☰
Harness架构实战:九个月20万行代码构建AI Agent工程体系
2026/9/29 5:23:37 网站建设 项目流程

1. 先聊聊这个项目到底在做什么

一个人,九个月,20 万行代码,每个月消耗 40 亿以上的 token——这几个数字摆在一起的时候,我第一反应不是"牛",而是"这人到底在解决什么问题,值得这么烧"。

先把结论放前面:这个项目本质上是在做一款Harness 架构的应用。所谓 Harness 架构,你可以理解成"给 AI Agent 套上一副马具"——模型本身是匹野马,力气大但方向不定,Harness 就是那套缰绳、鞍具和路标,让它在一条可控的轨道上跑。它不是一个单纯的聊天界面,也不是一个简单的提示词模板集合,而是一整套围绕 Agent 执行、上下文管理、工具调用、状态持久化构建的工程体系。

为什么这件事值得单独拿出来讲?因为绝大多数人做 Agent 项目,卡的不是模型能力,而是工程化落地。模型能写代码、能查资料、能调工具,这些早就不是新闻了。真正难的是:怎么让它在几十轮、上百轮交互之后还记得自己是谁、在干什么、下一步该干嘛;怎么让它的输出稳定可复现;怎么把它的中间产物沉淀成可检索、可复用的知识资产。这个项目九个月烧掉 20 万行代码,绝大部分精力其实都花在这些"不性感但致命"的地方。

这篇文章适合谁看?三类人。第一类是想自己动手做 Agent 应用但不知道从哪下手的开发者,我会把架构选型、模块拆分的逻辑讲透。第二类是已经在做 Agent 但被上下文爆炸、状态丢失、工具调用混乱折磨过的工程师,我会分享具体的排查思路和避坑经验。第三类是对 Harness、Claude Code、Obsidian 这套组合感兴趣、想搞清楚它们怎么串起来的人,我会把每个环节的实操细节补全。

需要提前说明的是,下面涉及的具体参数、目录结构、配置方式,有一部分是基于这类项目的常见工程实践做的合理补全,因为原始信息里没有给出全部实现细节。我会明确标注哪些是通用做法、哪些是我个人经验推断,你照着抄的时候记得结合自己的场景调整。

2. 为什么是 Harness 架构,而不是别的方案

2.1 从"提示词工程"到"马具工程"的认知转变

早期做 Agent,大家的思路基本停留在提示词层面:写一个足够详细的 system prompt,把角色、任务、输出格式全塞进去,然后祈祷模型别跑偏。这套做法在单轮任务里还行,一旦任务变成多步骤、长周期,立刻就崩。原因很简单——提示词是无状态的,而真实任务是连续的。

Harness 架构的核心洞察就在这里:与其把希望寄托在模型"记住"上,不如在模型外面搭一套脚手架,主动管理它的输入输出、状态和工具。这就像训马,你不能指望马自己记得路线,你得给它套上缰绳、装上马鞍、沿途设好路标。模型负责"跑",Harness 负责"往哪跑、跑多远、什么时候停"。

这个认知转变带来的直接后果是:项目的重心从"写更好的提示词"变成了"设计更好的执行框架"。20 万行代码里,真正跟提示词相关的可能不到 5%,剩下 95% 全是状态管理、工具编排、上下文压缩、错误恢复这些工程活。

2.2 为什么选 Claude Code 作为执行内核

在众多可选方案里,这个项目选择了 Claude Code 作为核心执行引擎,这个选择背后有几层考量。

第一是工具调用的成熟度。Claude Code 本身就是一个为"读写文件、执行命令、搜索代码"设计的 Agent 运行时,它的工具集天然贴合"在真实项目里干活"这个场景。你不需要从零实现文件读写、命令执行这些基础能力,直接复用就行。

第二是上下文管理的可控性。Claude Code 对上下文的处理相对透明,你能比较清楚地知道哪些内容进了上下文、哪些被截断、压缩策略是什么。这对一个要跑九个月、烧几十亿 token 的项目来说至关重要——上下文管理不当,token 消耗会指数级失控。

第三是可扩展性。Claude Code 支持通过配置扩展工具、自定义命令、挂载外部能力。这意味着 Harness 层可以在它之上叠加自己的逻辑,而不是被它的能力边界锁死。

提示:选执行内核的时候,别只看"哪个模型最强"。要看的是"哪个运行时的工具生态、上下文策略、扩展接口最贴合你的场景"。模型能力会迭代,但架构选错了,后面每一步都是逆风。

2.3 Markdown 作为中间格式的战略价值

这个项目里,Markdown 不只是一个"输出格式",而是整个系统的中间表示层。Agent 的思考过程、任务拆解、执行结果、知识沉淀,全部以 Markdown 形式落盘。为什么这么设计?

因为 Markdown 同时满足三个条件:人类可读、机器可解析、工具生态丰富。你让 Agent 输出 JSON,人看着累;你让它输出纯文本,机器解析难;Markdown 卡在中间,两边都照顾到了。而且 Markdown 的表格、列表、代码块这些结构,天然适合表达"任务清单""参数对照""代码片段"这类 Agent 高频产出的内容。

更关键的是,Markdown 是 Obsidian 的原生格式。这就引出了下一个设计——用 Obsidian 做知识底座。

2.4 Obsidian 承担的角色:不只是笔记软件

很多人把 Obsidian 当笔记软件用,但在这个项目里,它是Agent 的长期记忆和知识检索层。Agent 每完成一个任务,产出的 Markdown 文件直接进入 Obsidian 库,通过双链、标签、文件夹结构组织起来。下次遇到相关任务,Agent 可以通过检索这些历史文件,快速找回上下文,而不是从零开始。

这套设计的精妙之处在于:它把"记忆"从模型内部(不可控、会丢失、成本高)转移到了外部文件系统(可控、持久、检索便宜)。模型不需要记住所有东西,它只需要知道"去哪找"。这跟人类专家的做法其实一样——真正的高手不是什么都记在脑子里,而是知道遇到问题该翻哪本书、查哪个文档。

3. 核心模块拆解与实操要点

3.1 上下文管理:40 亿 token 是怎么烧掉的

先算一笔账。每个月 40 亿 token,按 30 天算,每天约 1.33 亿 token。如果按单次交互平均消耗 5 万 token(包含系统提示、历史上下文、工具返回结果),那一天就是约 2660 次交互。九个月下来,累计交互次数在几十万量级。

这个量级下,上下文管理不是"优化项",而是"生死线"。项目里主要用了三层策略:

第一层是滑动窗口加摘要压缩。保留最近 N 轮完整对话,更早的内容压缩成摘要。N 的取值很讲究——太小,Agent 会"失忆";太大,token 爆炸。实践中 N 通常设在 10 到 20 轮之间,具体看单轮平均长度。

第二层是结构化外置。把任务状态、待办清单、关键决策这些"必须记住"的信息,从对话历史里抽出来,单独存成 Markdown 文件。每次新对话开始时,只加载这个精简版状态,而不是把全部历史塞进去。

第三层是检索增强。需要历史细节时,通过关键词检索 Obsidian 库,按需加载相关片段。这比"全量加载"省 token 得多。

策略作用典型 token 节省适用场景
滑动窗口+摘要压缩近期历史40%-60%连续多轮对话
结构化外置精简状态加载60%-80%长周期任务
检索增强按需加载历史70%-90%知识密集型任务

注意:摘要压缩是有损的。我踩过的坑是,早期摘要策略太激进,把一些看似无关但后续关键的细节压没了,导致 Agent 反复问同样的问题。后来改成"摘要+关键实体保留",把任务涉及的文件名、函数名、参数值这些硬信息原样保留,只压缩叙述性内容,效果好很多。

3.2 工具编排:让 Agent 知道"什么时候用什么"

Agent 最容易出问题的地方,不是不会用工具,而是不知道该用哪个工具、什么时候用。工具一多,选择困难就来了。这个项目里,工具编排做了几件事:

工具分组与场景绑定。不是把所有工具一股脑丢给 Agent,而是按场景分组。比如"代码修改"场景只暴露读写文件、执行测试相关的工具;"资料检索"场景只暴露搜索、读取文档的工具。这样 Agent 的选择空间被收窄,出错概率大幅下降。

工具调用的前置校验。每次工具调用前,Harness 层会做一次参数校验和权限检查。比如写文件操作,会先确认路径在允许范围内、文件不是只读的、内容不是空的。这些校验看起来琐碎,但能挡掉大量"Agent 自信满满地执行了一个错误操作"的情况。

失败重试与降级。工具调用失败是常态,不是异常。Harness 层需要定义清楚:什么错误可以重试、重试几次、重试间隔多久、重试还失败怎么办。项目里对不同类型的工具调用设了不同的重试策略,比如网络类操作重试 3 次,文件类操作重试 1 次(因为文件错误通常是逻辑错误,重试没用)。

3.3 状态持久化:Agent 的"记忆"怎么存

状态持久化是这个项目最花功夫的部分之一。核心思路是:把 Agent 的"工作记忆"和"长期记忆"分开存。

工作记忆是当前任务的临时状态,存在内存或临时文件里,任务结束就清理。长期记忆是跨任务的知识沉淀,存进 Obsidian 库,永久保留。

工作记忆的结构大概是这样:

# 当前任务状态 ## 任务目标 重构用户认证模块,支持多因素认证 ## 已完成 - [x] 梳理现有认证流程 - [x] 设计新流程的接口 ## 进行中 - [ ] 实现 TOTP 验证逻辑 ## 待办 - [ ] 编写单元测试 - [ ] 更新文档 ## 关键决策 - 选择 TOTP 而非短信验证码,因为不依赖外部服务 - 验证逻辑放在独立模块,便于测试 ## 相关文件 - src/auth/authenticator.py - tests/test_authenticator.py

这个结构的好处是:Agent 每次恢复任务,只需要读这一个文件,就能快速回到状态。不需要翻几十轮对话历史。

长期记忆的组织则依赖 Obsidian 的双链和标签体系。每个完成的任务生成一个 Markdown 文件,文件里用[[双链]]关联相关概念,用#标签标记领域。这样检索的时候,既可以通过关键词搜,也可以通过双链跳转,还可以通过标签聚合。

3.4 Markdown 处理:那些不起眼但坑很多的地方

Markdown 看着简单,实际处理起来坑不少。项目里踩过的几个典型问题:

换行问题。Markdown 里单个换行不产生新段落,需要空行或行尾两个空格。Agent 生成的内容经常在这上面出错,导致渲染出来的格式跟预期不符。解决办法是在 Harness 层做一次规范化处理,把 Agent 输出的换行统一成标准格式。

表格转换。Agent 经常需要把 Markdown 表格转成 Excel 或其他格式。这个转换看着简单,但涉及对齐、转义、合并单元格等细节。项目里专门写了一个转换模块,处理各种边界情况。

数学符号。涉及公式的时候,Markdown 的数学符号渲染依赖特定语法。如果 Agent 输出的公式格式不对,渲染出来就是一堆乱码。Harness 层需要做格式校验和修正。

实操心得:Markdown 处理这块,别想着"一次写对"。最好的做法是写一套校验规则,Agent 输出后自动检查,不符合规范的自动修正或打回重写。我一开始想靠提示词让 Agent 自己注意格式,效果很差,后来改成程序化校验,问题少了一大半。

4. 完整实操流程与关键环节

4.1 环境搭建:从零到能跑起来

假设你现在要从零搭一套类似的 Harness 应用,第一步是环境准备。核心组件包括:执行内核(Claude Code 或同类)、知识底座(Obsidian)、开发环境(VS Code)、版本控制(Git)。

安装顺序建议这样走:

  1. 先装 Obsidian,建好库结构。库的目录结构提前规划好,比如tasks/放任务文件、knowledge/放知识沉淀、templates/放模板、archive/放归档。这个结构一旦定下来,后面所有 Agent 产出都往这里放,检索才有序。

  2. 再配 VS Code 和 Claude Code。VS Code 里装好 Claude Code 扩展,配置好 API 密钥、模型选择、工作目录。工作目录建议直接指向 Obsidian 库,这样 Agent 读写文件跟知识库是打通的。

  3. 最后搭 Harness 层。这是你自己写的部分,负责上下文管理、工具编排、状态持久化。初期可以很简单,一个主循环加几个工具函数就行,后面逐步加功能。

注意:环境搭建阶段最容易犯的错是"目录结构没想清楚就开干"。我见过太多项目,文件到处乱放,跑了两周发现检索根本没法做,只能推倒重来。花半天时间把目录结构设计好,后面省的是几十个小时。

4.2 核心循环:Agent 是怎么跑起来的

Harness 应用的核心是一个循环:接收任务 → 加载状态 → 规划步骤 → 执行工具 → 更新状态 → 判断是否完成 → 循环或结束。

这个循环看着简单,但每个环节都有讲究。

接收任务阶段,要做任务分类。不同类型的任务,加载的上下文、暴露的工具、使用的提示词都不一样。分类可以基于关键词,也可以让模型自己判断。

加载状态阶段,从工作记忆文件里读取当前任务状态。如果是新任务,初始化一个空状态;如果是恢复任务,加载已有状态。

规划步骤阶段,让模型基于当前状态和任务目标,输出下一步要做什么。这里的关键是限制规划粒度——不要让模型一次规划十步,那样很容易跑偏。一次规划一到三步,执行完再规划,灵活性和可控性都好很多。

执行工具阶段,根据规划结果调用相应工具。每次调用前后都要记录日志,方便排查问题。

更新状态阶段,把执行结果写回工作记忆文件。这一步不能省,否则任务中断后没法恢复。

判断完成阶段,检查任务目标是否达成。达成则归档到长期记忆,未达成则继续循环。

4.3 参数调优:那些需要反复试的数字

这类项目里有一堆需要调优的参数,没有标准答案,只能根据实际情况试。列几个关键的:

参数作用典型范围调优方向
上下文窗口大小保留多少轮历史10-20 轮任务越复杂,窗口越大
摘要触发阈值何时开始压缩窗口 80% 满太早压缩丢信息,太晚爆 token
工具重试次数失败后重试几次1-3 次网络类多试,逻辑类少试
单次规划步数一次规划几步1-3 步步骤越多越容易跑偏
状态保存频率多久存一次状态每步都存存太勤影响性能,存太疏丢状态

调这些参数的通用方法是:先设一个保守值,跑一批任务,看哪里出问题,针对性调整。别想着一次调到位,那是幻想。

4.4 知识沉淀:让每次任务都变成资产

这个项目最有价值的设计之一,是每个任务完成后自动生成知识文件。文件内容包括:任务描述、解决思路、关键代码、踩过的坑、可复用的模式。

这些文件进入 Obsidian 库后,通过双链和标签组织起来。下次遇到类似任务,Agent 可以先检索这些历史文件,站在过去的肩膀上,而不是从零开始。

知识文件的模板大概长这样:

# [任务名称] ## 背景 [什么场景下遇到的这个问题] ## 解决思路 [核心思路是什么,为什么这么选] ## 关键实现 [核心代码或配置] ## 踩坑记录 [遇到什么问题,怎么解决的] ## 可复用模式 [这个方案还能用在哪些场景] ## 相关 [[相关任务1]] [[相关任务2]] #标签

实操心得:知识沉淀这件事,最大的敌人是"懒得写"。我的做法是把它做成自动化的——任务一完成,Harness 层自动生成知识文件草稿,Agent 只需要补充关键细节。这样人的负担降到最低,坚持下来的概率高很多。

5. 常见问题与排查技巧实录

5.1 Agent 跑着跑着就"失忆"了

这是最高频的问题。表现是:Agent 在任务中途突然问一些之前已经确认过的问题,或者做出跟之前决策矛盾的举动。

排查思路分三步。第一步,检查上下文窗口。是不是窗口太小,关键信息被挤出去了。第二步,检查摘要策略。是不是摘要把关键实体压没了。第三步,检查状态文件。是不是状态没及时保存,恢复时读到了旧版本。

解决办法通常是:加大窗口、优化摘要保留策略、提高状态保存频率。三个一起调,效果最明显。

5.2 工具调用失败但 Agent 不知道

有时候工具调用返回了错误,但 Agent 把错误当成了正常结果,继续往下走,导致后面全错。

这个问题的根源是错误处理没做好。Harness 层需要在工具调用返回后,判断结果是不是错误,如果是错误,要么重试,要么把错误信息明确告诉 Agent,让它决定怎么办。

注意:别让 Agent 自己判断"这个结果是不是错误"。模型对错误的识别能力有限,经常把错误当正常。错误判断应该在 Harness 层用程序做,确定是错误了再告诉 Agent。

5.3 Token 消耗失控

40 亿 token 一个月,如果管理不当,很容易翻倍。失控的常见原因:上下文没压缩、工具返回结果全量塞进上下文、重复加载相同内容。

排查方法:给每次交互记录 token 消耗,找出消耗大户。通常是某几类操作在偷偷烧 token,比如读取大文件、搜索结果全量返回、历史上下文重复加载。

优化手段:大文件分块读取、搜索结果先摘要再返回、历史上下文用检索代替全量加载。

5.4 常见问题速查表

问题现象可能原因排查方向解决手段
Agent 失忆上下文窗口小/摘要过度检查窗口和摘要策略加大窗口、保留关键实体
工具错误被忽略错误处理缺失检查工具返回处理逻辑Harness 层做错误判断
Token 消耗失控上下文未压缩/重复加载记录 token 消耗找大户分块读取、检索代替加载
任务跑偏规划粒度过大检查单次规划步数减小规划粒度
状态丢失保存频率低检查状态保存时机提高保存频率
格式渲染错误Markdown 不规范检查输出格式程序化校验修正

5.5 几个不那么常见但很坑的问题

问题一:Agent 在长任务里"性格漂移"。跑了几十轮之后,Agent 的语气、风格、决策倾向跟开始时不一样了。这通常是上下文里积累了太多"噪音",把初始设定冲淡了。解决办法是定期"重置"——把核心设定重新注入上下文。

问题二:工具描述歧义导致误用。两个工具功能相近,Agent 经常用错。解决办法是把工具描述写得更明确,突出差异点,或者在 Harness 层做路由,根据场景自动选工具。

问题三:Obsidian 库大了之后检索变慢。文件多了,全文检索性能下降。解决办法是建索引、分库、用标签缩小检索范围。

6. 这套架构还能怎么扩展

跑通基础版本之后,这套 Harness 架构有几个明显的扩展方向。

多 Agent 协作。单个 Agent 能力有限,可以让多个 Agent 分工——一个负责规划、一个负责执行、一个负责审查。Harness 层负责协调它们之间的通信和状态同步。

领域特化。针对特定领域(比如前端开发、数据分析、文档写作)定制工具集和提示词,让 Agent 在垂直场景里表现更好。

人机协作增强。在关键决策点引入人工确认,Agent 提出方案,人做选择。这样既保留了 Agent 的效率,又保证了关键决策的可靠性。

知识库自动化维护。让 Agent 定期整理 Obsidian 库,合并重复内容、更新过时信息、建立新的双链关系。库越大,这个能力越有价值。

我个人在实际操作中的体会是:这套架构最值钱的地方,不是某个具体功能,而是它把 Agent 从"一次性工具"变成了"持续积累的系统"。每跑一个任务,系统就聪明一点;每沉淀一份知识,下次就快一点。这种复利效应,才是九个月 20 万行代码真正换来的东西。

最后再分享一个小技巧:如果你也想做类似的项目,别一上来就追求大而全。先用最小可行的 Harness 跑通一个简单任务,然后逐步加功能。我见过太多人,架构设计得天花乱坠,结果连第一个任务都跑不通。能跑起来的最小系统,永远比设计完美的空架子有价值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询