
1. 先聊聊一个人九个月20万行这件事到底意味着什么看到一个人、九个月、20万行代码、每月40亿token这组数字我第一反应不是惊叹而是想拆解它背后的工程结构。因为单纯堆代码量没有意义一个熟练的开发者用AI辅助九个月写出20万行并不稀奇——稀奇的是这些代码要能跑起来、要能维护、要能支撑一个Harness架构的应用持续运转。这才是真正值得聊的地方。先把这个项目的核心概念说清楚。所谓Harness架构你可以把它理解成给AI套上一副缰绳和马具。Harness这个词本身是马具的意思在AI工程语境里它指的是包裹在大模型外面的一整套控制层负责管理上下文、调度工具调用、维护记忆、处理错误重试、控制输出格式。模型本身是那匹力气很大但方向感不稳定的马Harness就是让它能拉着车稳稳走在路上的那套装备。这个项目做的事情就是一个人从零搭建了这样一套Harness并且用它驱动出一个完整的应用。九个月时间20万行代码平均每个月消耗40亿以上的token。这三个数字放在一起透露出的信息量非常大40亿token意味着大量的模型调用和反复的上下文处理20万行代码意味着这不是一个demo而是一个有完整模块划分的系统。我为什么对这个案例感兴趣因为现在市面上讲Agent开发的内容大多停留在调个API、写个prompt、串几个工具的层面。真正把Harness当成一个正经软件工程项目来做的人很少。大部分人做到一半就会发现上下文管理失控了、工具调用开始互相干扰、错误处理写不下去、成本像脱缰一样往上涨。这个项目能撑九个月还在迭代说明它在架构层面解决了一些根本问题。这篇文章我会围绕几个核心问题展开Harness架构到底要解决哪些工程难题、20万行代码大概花在了哪些地方、每月40亿token是怎么烧掉的以及怎么控制、Markdown和Obsidian这类工具在整条链路里扮演什么角色、以及一个人做这种项目时最容易踩的坑。适合正在做Agent开发、或者准备认真做一个AI应用的人参考。如果你只是想调个接口玩玩这篇可能有点重但如果你想做一个能长期活下去的AI产品这里面的经验应该对你有用。2. Harness架构到底在解决什么问题2.1 模型不是产品Harness才是很多人做AI应用时的思维定式是找一个最强的模型写好prompt产品就成了。这个思路在demo阶段没问题但一旦要上线、要面对真实用户的复杂输入立刻就会崩。原因很简单——模型是一个概率性的文本生成器它不负责状态管理、不负责错误恢复、不负责成本控制、不负责输出格式的稳定性。这些全是Harness的活。我打个比方。模型像一个非常有才华但记性很差、情绪不稳定的顾问。你每次问他问题他都能给出不错的答案但他不记得上次跟你聊了什么有时候会答非所问有时候会突然跑题有时候会编造事实。Harness就是那个坐在顾问旁边的项目经理提前把相关资料整理好递给他、把他跑题的话拉回来、把他编造的内容标记出来、把重要的结论记到本子上供下次使用。这个项目九个月20万行代码我判断绝大部分不是在写业务逻辑而是在写这个项目经理的各种能力。因为业务逻辑本身可能几万行就够了剩下的十几万行都是在处理上下文怎么裁剪、工具调用怎么编排、失败怎么重试、状态怎么持久化、多轮对话怎么保持一致性、输出怎么校验。2.2 Harness的五个核心模块根据我对这类架构的理解一个完整的Harness通常包含五个核心模块这个项目大概率也是围绕这些展开的上下文管理器。这是最复杂的一块。模型的上下文窗口是有限的但一个真实应用的对话历史、工具返回结果、检索到的文档加起来很容易超出窗口。你需要决定哪些内容保留、哪些压缩、哪些丢弃、按什么优先级排序。这里面的策略直接决定了应用聪不聪明。工具调度器。Agent要能调用外部工具——读文件、查数据库、发请求、执行代码。但工具不是随便调的你需要处理什么时候该调、调哪个、参数怎么填、返回结果怎么解析、调用失败了怎么办、多个工具能不能并行。这一块的代码量通常很大。记忆系统。短期记忆是当前对话长期记忆是跨会话的知识。记忆的写入、检索、更新、淘汰每一个环节都有讲究。做得粗糙Agent就会失忆或者记错。输出控制器。模型输出的是自然语言但你的下游系统可能需要结构化数据。怎么让模型稳定输出JSON、怎么校验、校验失败怎么修复这是一整套工程。可观测性层。日志、追踪、成本统计、性能监控。没有这一层你根本不知道系统在干什么、钱花在哪了、哪里出了问题。这五个模块加起来20万行代码是完全合理的。而且这还只是骨架每个模块内部还有大量的边界情况处理。2.3 为什么不用现成的框架有人会问LangChain、LlamaIndex这些框架不是现成的吗为什么要自己写20万行这个问题我在实际项目里也纠结过。现成框架的好处是上手快但坏处是当你的需求稍微偏离框架的设计假设时你就要跟框架搏斗。而且框架的抽象层往往很厚出了问题很难定位性能开销也不可控。这个项目选择自研Harness我推测核心原因是它需要对自己的上下文策略、工具协议、记忆机制有完全的控制权。用现成框架你只能在其提供的抽象里做文章自研的话每一个字节的上下文怎么用、每一次工具调用怎么编排都是你自己说了算。对于一个月烧40亿token的应用来说这种控制权直接关系到成本和效果。当然自研的代价就是工作量大。20万行代码里估计有相当一部分是在重复造轮子。但对于一个要长期迭代的项目这个投入是值得的——因为轮子是你自己的你想怎么改就怎么改。3. 每月40亿token是怎么烧掉的3.1 先算一笔账40亿token一个月平均到每天大概是1.3亿。这个量级听起来吓人但拆开看就合理了。假设你的应用每次交互平均消耗2万token包括系统提示、上下文、工具返回、模型输出那么一天1.3亿token对应大约6500次交互。对于一个有一定用户量的应用来说这个数字并不夸张。如果每次交互消耗更高比如5万token那一天就是2600次交互。关键在于单次交互的token消耗是可以优化的而且优化空间巨大。我见过很多项目单次交互动辄十几万token其中一大半是浪费的——重复的系统提示、冗余的历史记录、没必要的工具返回全文。3.2 token消耗的三个大头根据经验token消耗主要集中在三个地方系统提示和上下文注入。每次调用都要带上系统提示、角色设定、工具定义、当前状态。这部分如果写得太啰嗦每次都是固定开销。一个精心精简的系统提示可能只要2000token一个没优化的可能要8000token差4倍。历史对话。多轮对话里历史记录会不断累积。如果不做裁剪和压缩第20轮对话可能带着前19轮的全部内容token量线性增长。工具返回结果。工具调用返回的内容往往很长——一个文件的内容、一次搜索的结果、一段数据库查询的输出。如果原样塞进上下文很快就会撑爆窗口。3.3 控制成本的具体手段这个项目能把成本控制在可接受范围我推测用了以下几类手段分层上下文策略。不是所有历史都平等对待。最近的对话保留原文较早的对话做摘要压缩更早的只保留关键结论。这样既保持了连贯性又控制了长度。工具结果的按需加载。工具返回的长内容不直接进上下文而是先存起来只把摘要或索引给模型。模型需要细节时再按需取用。这个思路类似操作系统的虚拟内存。缓存复用。很多模型服务支持prompt caching相同的系统提示和前缀部分可以缓存重复调用时只计算新增部分。对于高频调用的应用这个能省下大量成本。模型分级。不是所有任务都需要最强的模型。简单的分类、格式化、提取任务用小模型复杂的推理和生成用大模型。这个项目每月40亿token如果全部用最贵的模型成本会非常吓人分级之后实际支出可能只有几分之一。输出长度控制。明确告诉模型输出多长避免它啰嗦。这个看似简单但效果显著。提示token成本控制不是一次性的工作而是要持续监控和调优。建议从第一天就建立成本追踪按功能模块、按用户、按调用类型分别统计这样才能找到优化重点。3.4 40亿token背后的迭代成本还有一点容易被忽略这40亿token里有相当一部分是开发过程中的消耗。一个人开发九个月每天要反复测试、调试、验证这些调用也是要花钱的。尤其是做Harness这种底层架构你需要大量实验来验证上下文策略、工具协议、错误处理是否有效。这些实验的token消耗可能占到总量的两三成。所以40亿这个数字既是运行成本也是研发成本。理解这一点对评估一个AI项目的真实投入很重要。4. 20万行代码的分布与工程取舍4.1 代码量的合理分布20万行代码如果按模块拆我估计大致是这样的分布模块预估占比主要工作上下文管理20%裁剪、压缩、排序、缓存工具系统25%工具定义、调度、参数校验、结果解析记忆系统15%存储、检索、更新、淘汰输出控制10%格式约束、校验、修复可观测性10%日志、追踪、成本统计业务逻辑15%具体应用功能基础设施5%配置、部署、测试这个分布说明一个事实做AI应用大部分代码不是在用AI而是在伺候AI。真正调用模型的那几行代码很简单难的是让模型在正确的上下文里、用正确的工具、输出正确格式的结果。4.2 为什么代码量会膨胀一个人九个月写20万行平均每天700多行。这个速度在有AI辅助的情况下是可能的但前提是代码要能持续维护。代码量膨胀通常有几个原因边界情况处理。每一个功能正常路径可能只要几十行但异常路径要几百行。网络超时、返回格式不对、参数缺失、权限不足、并发冲突……这些加起来是正常逻辑的好几倍。抽象层的反复调整。做Harness这种底层架构抽象设计很难一次到位。你可能先设计了一套工具接口用了一段时间发现不够灵活重构又设计了一套上下文策略发现效果不好再重构。每次重构都会增加代码量。测试和验证代码。要保证Harness稳定需要大量的测试。单元测试、集成测试、端到端测试还有各种模拟场景的验证脚本。这部分代码量不小。配置和适配。不同的模型服务、不同的工具、不同的部署环境都需要适配代码。这些代码单独看不多加起来很可观。4.3 自研Harness的取舍自研20万行值不值我的看法是取决于你的项目是否把Harness本身当成核心竞争力。如果你的应用只是调用模型简单工具那用现成框架完全够自研是浪费。但如果你的应用效果高度依赖于上下文策略、工具编排、记忆机制的精细控制那自研就是必要的。因为这些东西是框架给不了的你必须自己掌握。这个项目显然属于后者。它把Harness当成了产品的核心所以愿意投入20万行代码去打磨。这个选择对不对最终要看产品效果但从工程逻辑上是自洽的。注意自研Harness的一个常见陷阱是过度设计。一开始就想着要支持所有可能的场景结果抽象层做得极其复杂实际用到的功能只有一小部分。建议从最小可用版本开始遇到真实需求再扩展。5. Markdown、Obsidian与Agent的协作链路5.1 为什么Markdown是Agent的天然搭档在这个项目的技术栈里Markdown和Obsidian被反复提及这不是偶然。Markdown对Agent应用来说有几个天然优势结构化但不过度。Markdown有标题、列表、表格、代码块这些结构但语法足够简单模型生成起来很稳定。相比之下让模型生成严格的JSON或XML出错率会高很多。人类可读。Agent的中间产物、记忆内容、日志用Markdown存储人可以直接看懂。这对调试和审查非常重要。工具生态成熟。Markdown的解析、渲染、转换工具非常丰富几乎每种语言都有成熟的库。这意味着Harness处理Markdown内容的成本很低。版本友好。Markdown是纯文本天然适合版本控制。Agent的记忆和知识库用Markdown存储可以追踪每一次变化。5.2 Obsidian在链路中的角色Obsidian是一个基于本地Markdown文件的知识管理工具。它在这个项目里的角色我推测是作为人类与Agent共享的知识层。具体来说人用Obsidian整理笔记、文档、知识这些内容以Markdown文件形式存在本地。Agent通过Harness读取这些文件作为上下文的一部分。Agent产生的新内容也可以写回Markdown文件人在Obsidian里查看和编辑。这种设计的妙处在于人和Agent操作的是同一份数据没有同步问题。不需要数据库导入导出不需要格式转换就是一堆Markdown文件。人改了什么Agent下次读取就能看到Agent写了什么人打开Obsidian就能看到。5.3 实际协作中的几个细节在实际操作中这种协作模式有几个需要注意的地方文件组织要清晰。如果Markdown文件散落在各处Agent检索起来会很困难。建议按主题分目录用一致的命名规范必要时加索引文件。内容粒度要合适。一个文件太大Agent读取时token消耗高太小又会产生大量文件。一般建议单个文件控制在几百到几千字一个主题一个文件。元数据要规范。在Markdown文件头部用YAML front matter记录元数据标签、日期、来源等方便Agent按条件筛选。换行和格式要统一。Markdown的换行在不同解析器里行为不一致团队协作时最好约定统一规范避免Agent解析出错。提示如果你的Agent需要处理大量Markdown建议在Harness里内置一个Markdown解析和索引模块把文件内容结构化后再给模型而不是把原始Markdown直接塞进上下文。这样能显著降低token消耗提高检索精度。5.4 从Markdown到结构化数据的转换Agent处理Markdown时经常需要把内容转成结构化数据。比如把Markdown表格转成JSON、把列表转成数组。这个转换过程有几个坑表格转换时要注意单元格里的换行、转义字符、空单元格。列表转换时要注意嵌套层级和有序无序的区别。代码块要单独处理不能当普通文本解析。这些转换逻辑在Harness里应该封装成独立的工具让模型按需调用而不是每次都在prompt里让模型自己解析。模型解析结构化文本的能力不稳定交给代码处理更可靠。6. 一个人做这种项目的真实体验与避坑6.1 孤独是最大的敌人一个人做九个月技术难度是一方面心理压力是另一方面。没有同事讨论、没有代码review、没有及时反馈很容易陷入自我怀疑。我自己的经验是必须建立外部的反馈循环。可以是找几个同样在做AI应用的朋友定期交流可以是在社区里分享进展可以是写开发日志。关键是要有人知道你做了什么、遇到了什么问题。完全闭门造车很容易在某个死胡同里卡很久。6.2 上下文策略是最容易翻车的地方我见过太多项目在上下文管理上翻车。表现是早期效果很好随着对话变长或数据变多效果急剧下降。根本原因是上下文策略没有设计好。几个具体的坑无脑截断。简单地把超出窗口的部分砍掉会导致关键信息丢失模型答非所问。摘要失真。用模型压缩历史对话压缩过程中会丢失细节多次压缩后误差累积。检索不准。从知识库检索相关内容时如果检索算法不好会召回无关内容干扰模型判断。优先级混乱。系统提示、历史对话、工具结果、检索内容这些在上下文里的优先级和位置安排直接影响模型的表现。这个项目能撑九个月说明它在这些方面做了大量实验和调优。这也是20万行代码的主要去向之一。6.3 工具调用的可靠性问题Agent调用工具看起来简单实际非常容易出问题参数错误。模型生成的工具参数格式不对、类型不对、缺字段。需要在Harness里做严格的校验和修复。调用循环。模型反复调用同一个工具陷入死循环。需要设置调用次数上限和循环检测。结果解析失败。工具返回的内容格式和预期不符解析报错。需要容错和降级处理。并发冲突。多个工具调用同时操作同一资源产生冲突。需要加锁或串行化。这些问题每一个都需要专门的代码来处理。20万行里工具系统占25%很大一部分就是在处理这些可靠性问题。6.4 成本失控的预警信号每月40亿token如果没有好的监控很容易失控。几个预警信号单次交互token消耗持续上升某个功能的调用频率异常高错误重试导致的重复调用增多上下文长度接近窗口上限的调用占比上升一旦发现这些信号就要立刻排查。成本控制不是月底看账单而是每天盯指标。6.5 关于九个月这个时间九个月做出一个能跑的Harness应用节奏是合理的。前三个月大概在搭骨架、验证核心思路中间三个月在填功能、处理边界情况后三个月在优化、调优、补测试。如果有人说三个月就能做出同等复杂度的东西要么是简化了需求要么是没算上后期的打磨。一个人做项目最大的优势是决策快、没有沟通成本最大的劣势是精力有限、容易钻牛角尖。我的建议是把时间花在核心链路上非核心的部分能用现成的就用现成的。比如日志、监控、部署这些没必要自己造。7. 这套架构能复用到哪些场景7.1 适合复用的场景特征这套Harness架构不是万能的它适合的场景有几个特征需要长期记忆。应用要记住用户的历史、偏好、上下文跨会话保持连贯。需要调用多种工具。不只是聊天还要读文件、查数据、执行操作。对输出格式有要求。下游系统需要结构化数据不能只是自然语言。成本敏感。调用量大必须精细控制token消耗。需要可观测。要能追踪每次调用的来龙去脉方便调试和优化。7.2 具体可以落地的方向基于这些特征这套架构可以复用到个人知识助手。结合Obsidian这类本地知识库做一个能理解你全部笔记、帮你检索和整理的助手。自动化工作流。把重复性的工作数据整理、报告生成、信息提取交给AgentHarness负责调度和容错。代码辅助工具。类似Claude Code这样的工具核心也是Harness——管理代码上下文、调度文件操作、控制输出。客服和咨询系统。需要长期记忆、多工具调用、稳定输出的场景。7.3 复用时需要调整的部分直接照搬肯定不行复用时需要调整工具集要换。不同场景需要的工具完全不同工具系统要重新配置。上下文策略要调。知识助手和客服系统的上下文重点不一样策略要相应调整。成本模型要重算。不同场景的调用频率和token消耗差异很大成本控制策略要重新设计。输出格式要定。下游系统需要什么格式输出控制器就要支持什么格式。8. 一些实操层面的经验补充8.1 开发顺序的建议如果让我重新做一遍我会按这个顺序先把最简单的模型调用单工具跑通验证基本链路加上上下文管理处理多轮对话扩展工具系统支持多工具调度加入记忆系统支持跨会话完善输出控制和可观测性最后做成本优化和性能调优这个顺序的好处是每一步都有可运行的成果不会一开始就陷入复杂架构里出不来。8.2 测试策略Harness的测试比普通应用难因为涉及模型的不确定性。我的建议是单元测试覆盖确定性逻辑。上下文裁剪、参数校验、结果解析这些输入输出确定可以正常写测试。集成测试用固定模型响应。把模型的响应mock掉测试Harness的处理逻辑。端到端测试用真实模型但限定场景。选几个典型场景用真实模型跑人工评估结果。回归测试要持续跑。每次改动后跑一遍典型场景确保没有退化。8.3 关于模型选择不要迷信最强模型。实际项目里模型选择要考虑任务复杂度简单任务用便宜模型响应速度实时交互场景要选快的成本高频调用要算清楚单位成本稳定性生产环境要选服务稳定的这个项目每月40亿token如果全部用最贵的模型成本会高到无法承受。分级使用是必然选择。8.4 最后分享一个小心得做Harness这种底层架构最容易犯的错是过早优化。一开始就想着要支持所有场景、要处理所有边界情况结果架构做得极其复杂实际用到的功能很少。我的经验是先让它跑起来再让它跑得稳最后让它跑得省。顺序不能反。先跑起来你才知道真实需求是什么跑稳了你才有余力去优化优化的时候你才知道哪些地方值得优化。九个月20万行听起来很吓人但拆解到每一天其实就是持续地解决一个又一个具体问题。没有什么神奇的技巧就是把每个环节都做扎实然后坚持下去。