1. 先搞清楚这个项目到底在做什么
一个人,九个月,20 万行代码,每个月消耗 40 亿以上的 token,最终交付的是一款基于 Harness 架构的应用。这几个数字放在一起,第一反应大概率是"这不可能",第二反应是"就算可能,代码质量能看吗"。我一开始也是这个反应,直到我把这套东西的架构思路、工具链和实际运行方式完整拆了一遍,才发现它背后的逻辑其实非常清晰——它不是靠一个人硬写 20 万行,而是靠一套高度工程化的 Agent 流水线,把"写代码"这件事本身变成了可编排、可复用、可观测的流程。
先把核心概念对齐一下,不然后面全是雾水。Harness在这个语境里不是某个具体产品名,而是一种架构范式:它指的是把大模型能力、工具调用、上下文管理、任务编排、结果校验这几件事,用一个统一的"骨架"串起来,让 Agent 能在一个受控的运行时里持续干活。你可以把它理解成给 AI 装了一个"工作台"——模型是工人,Harness 是工作台加流水线加质检员。而Agent是跑在这个工作台上的具体执行单元,它有自己的目标、工具集和记忆。两者的区别用一句话说:Harness 是场地和规则,Agent 是场上踢球的人。
这个项目之所以值得拆,是因为它踩中了当前 AI 工程化最真实的一个痛点:单次对话能解决的问题早就解决了,真正难的是让 AI 连续九个月、跨几十万行代码、保持上下文一致地干活。这中间涉及 token 成本控制、上下文压缩、Markdown 作为中间表示层、Claude Code 作为执行入口、Obsidian 作为知识库底座等一系列具体工程决策。适合谁来参考?如果你正在做 AI Agent 相关的项目,或者想搞清楚"一个人怎么用 AI 撑起一个中型项目",这篇内容基本能给你一套可抄的作业。
我下面会按"整体设计思路 → 核心细节 → 实操落地 → 踩坑排查"这个顺序展开,中间会穿插大量参数选择、成本计算和实际配置,尽量做到你看完能直接上手改自己的项目。
2. 整体架构设计与关键选型逻辑
2.1 为什么是 Harness 架构而不是裸调 API
很多人做 AI 项目的第一反应是直接调模型 API,写个循环就完事。这个做法在 demo 阶段没问题,但一旦项目周期拉长到几个月,问题会集中爆发:上下文窗口爆掉、工具调用状态丢失、错误无法回溯、成本失控。Harness 架构的核心价值就是把这些"脏活"从业务逻辑里剥离出来,做成一层稳定的运行时。
具体来说,这套架构通常包含四个层次。最底层是模型接入层,负责统一不同模型的调用接口和重试策略;往上是上下文管理层,处理历史消息的压缩、摘要和检索;再往上是工具执行层,管理 Agent 能调用的所有工具(文件读写、命令执行、搜索等);最顶层是任务编排层,决定什么时候调哪个 Agent、传什么上下文、怎么校验结果。这四层分开之后,每一层都可以独立优化,比如你想换模型,只动接入层;想改压缩策略,只动上下文层。
提示:Harness 架构最大的坑是"过度设计"。我见过有人一上来就搭四层,结果项目还没跑起来,光架构代码就写了上万行。建议先用最简版本跑通一个完整任务,再逐层加。
2.2 20 万行代码是怎么"长"出来的
这里必须澄清一个误解:20 万行不是手写的,也不是模型一次性生成的,而是在九个月里通过数千次 Agent 任务累积出来的。每一次任务可能生成几十到几百行,经过校验后合入代码库。按九个月 270 天算,平均每天新增约 740 行,这个量级对一个持续运行的 Agent 流水线来说完全合理。
关键在于每次任务的粒度控制。粒度太粗,模型容易跑偏,生成一堆用不上的代码;粒度太细,任务调度开销会吃掉大部分收益。实践中比较稳的做法是:单个任务对应一个明确的函数或一个独立模块,输入输出都有清晰契约。这样即使某次生成质量差,影响范围也可控,回滚成本低。
2.3 每月 40 亿 token 的成本账怎么算
40 亿 token 听起来吓人,但拆开看就清楚了。假设九个月里平均每月有 20 个工作日,每天跑 200 次 Agent 任务,每次任务平均消耗 10 万 token(包含上下文、工具返回、生成内容),那一天就是 2000 万 token,一个月 4 亿,九个月 36 亿——和 40 亿基本吻合。所以这个数字不是"烧钱",而是高频小任务的自然累积。
成本控制的核心不在单次调用省钱,而在减少无效调用。我实测下来,最有效的三个手段是:第一,给每个任务设置明确的终止条件,避免 Agent 无限循环;第二,上下文压缩要激进,历史消息超过阈值就摘要,别舍不得;第三,工具返回结果要裁剪,比如读文件只返回相关片段,不要整个文件塞回去。这三条做好,token 消耗能降 40% 以上。
| 成本控制手段 | 预估节省比例 | 实施难度 |
|---|---|---|
| 任务终止条件 | 15%-25% | 低 |
| 上下文激进压缩 | 20%-30% | 中 |
| 工具返回裁剪 | 10%-20% | 低 |
| 模型分级调用 | 15%-30% | 中 |
2.4 Markdown 为什么成了中间表示层
这个项目里 Markdown 不只是文档格式,而是Agent 之间传递信息的通用语言。原因很实际:Markdown 结构清晰、模型理解成本低、人类也能直接读、还能被 Obsidian 这类工具直接索引。Agent 生成的任务计划、执行日志、代码说明、知识沉淀,全部用 Markdown 存,形成了一条从"临时上下文"到"长期知识库"的通路。
这里有个细节值得说:Markdown 的换行和表格语法在不同解析器里行为不一致,Agent 生成时如果不管这个,后续解析会出各种幺蛾子。我的做法是统一用一套严格的 Markdown 规范,比如表格必须对齐、换行统一用空行分隔、图片路径统一用相对路径。这套规范写进 Agent 的 system prompt 里,生成质量会稳定很多。
3. 核心工具链的配置与实操要点
3.1 Claude Code 作为执行入口的配置细节
Claude Code 在这个项目里承担的是"手"的角色——Agent 想好了要做什么,具体执行靠它。安装和配置这块,不同系统差异不小。Ubuntu 下相对简单,装完 Node 环境后直接全局安装即可;Windows 下建议走 WSL,原生环境的路径和权限问题会浪费你大量时间。
配置的核心是权限边界。Claude Code 默认会问你很多确认,这在交互式使用时没问题,但在 Agent 自动运行时会把流程卡死。我的做法是预先配置好允许的操作白名单,比如允许读写项目目录、允许执行特定命令,其他一律拒绝。这样既保证自动化流畅,又不至于让 Agent 乱动系统文件。
# 典型的项目级配置思路(示意) # 允许的操作范围限定在项目目录内 # 命令执行限定在白名单内 # 网络访问默认关闭,按需开启注意:卸载 Claude Code 时记得清理配置目录,否则残留的配置会影响下次安装。这个坑我踩过,重装后行为诡异,排查了半天才发现是旧配置没清干净。
3.2 Obsidian 知识库的搭建思路
Obsidian 在这里的作用是长期记忆的载体。Agent 每次任务产生的有价值信息,会被整理成 Markdown 笔记存进 Obsidian 库,下次任务需要时再检索出来。这就解决了大模型"记不住"的问题——不是靠模型记,而是靠外部知识库记。
搭建时几个关键点。第一,目录结构要提前规划好,建议按"项目 / 模块 / 主题"三级划分,别一股脑全堆根目录。第二,插件选择要克制,Git 插件用于版本管理是刚需,其他花哨的插件能少则少,插件越多启动越慢、冲突越多。第三,笔记命名要有规范,建议用"日期-主题-状态"的格式,方便检索和排序。
Obsidian 的 docxer 这类插件用于格式转换时,要注意中英文混排的序号问题,自动编号经常乱。我的经验是转换前先把 Markdown 里的列表结构规整一遍,转换后再人工过一遍,别指望全自动。
3.3 Markdown 作为 Agent 通信协议的规范设计
前面提到 Markdown 是中间表示层,这里展开说规范怎么定。核心原则是机器可解析优先,人类可读其次。具体包括:标题层级严格用##和###,不用#;表格必须有表头分隔行;代码块必须标注语言;链接和图片用标准语法;不用 HTML 混排。
为什么这么严?因为 Agent 之间传递信息时,解析失败会导致整个任务链断掉。我遇到过因为一个表格少了分隔行,导致下游 Agent 把整个表格当成普通文本处理,结果数据全丢的情况。规范定好之后,这类问题基本绝迹。
3.4 工具选型对比:为什么是这套组合
| 工具 | 承担角色 | 选它的理由 | 替代方案 |
|---|---|---|---|
| Claude Code | 执行入口 | 工具调用能力强,生态成熟 | 其他 CLI Agent 工具 |
| Obsidian | 知识库 | 本地 Markdown,可 Git 管理 | 其他本地笔记工具 |
| Markdown | 通信协议 | 通用、可读、易解析 | JSON、YAML |
| Harness 架构 | 运行时骨架 | 分层清晰,可独立优化 | 自研单体框架 |
选型逻辑其实就一条:每一层都选最成熟、最不容易出意外的方案。一个人做项目,没有团队帮你兜底,稳定性比先进性重要得多。
4. 完整实操流程与关键环节实现
4.1 从零搭建 Harness 运行时的步骤
第一步,搭最小可运行版本。不要一上来就搞四层架构,先写一个能跑通"接收任务 → 调模型 → 执行工具 → 返回结果"的单文件脚本。这个脚本可能只有一两百行,但它是后面所有扩展的基础。
第二步,加上下文管理。当单次任务能跑通后,你会发现多轮任务之间上下文会丢。这时候引入一个简单的上下文存储,可以是内存里的字典,也可以是文件。关键是让 Agent 能"记得"上一次做了什么。
第三步,加任务编排。当你有多个 Agent 需要协作时,需要一个调度器决定谁先谁后、传什么参数。这一步最容易过度设计,建议先用最简单的顺序执行,跑通了再考虑并行和条件分支。
第四步,加结果校验。Agent 生成的东西不能直接用,必须有校验环节。校验可以是规则校验(比如代码能不能编译),也可以是模型校验(让另一个 Agent 检查)。这一步是保证 20 万行代码质量的关键。
4.2 单次 Agent 任务的完整生命周期
一次典型任务从触发到结束,大概经历这几个阶段。任务解析:把自然语言需求转成结构化任务描述。上下文组装:从知识库和最近历史里捞出相关信息,拼成 prompt。模型调用:发给模型,拿到生成结果。工具执行:如果模型要求调工具,执行并返回结果,可能需要多轮。结果校验:检查生成内容是否符合预期。知识沉淀:把有价值的信息写回 Obsidian。状态更新:记录任务完成情况,供后续任务参考。
这个流程里最容易出问题的是上下文组装和结果校验。上下文组装不好,模型会答非所问;结果校验不严,错误会累积。我的做法是给这两个环节单独写测试用例,每次改架构都跑一遍,确保不退化。
4.3 参数选择与成本计算的实际过程
以一次代码生成任务为例,算一下 token 消耗。假设 system prompt 2000 token,任务描述 500 token,检索到的相关知识 3000 token,最近历史 2000 token,工具定义 1500 token,合计输入约 9000 token。模型生成代码平均 1500 token,如果触发两轮工具调用,每轮工具返回约 1000 token,那总消耗约 9000 + 1500 + 2000 + 1500 = 14000 token。按每天 200 次任务算,一天 280 万 token,一个月约 5600 万,九个月约 5 亿——这比 40 亿少很多,说明实际任务比这个复杂,或者任务次数更多。
反推一下,要达到 40 亿,要么任务次数是每天 1500 次左右,要么单次消耗是 14 万 token 左右。结合"20 万行代码"这个产出,我倾向于认为单次任务消耗更高,因为复杂任务的上下文和工具调用轮次都会显著增加。这个计算过程的意义在于:你得知道自己项目的 token 花在哪,才能优化。
4.4 知识沉淀与检索的实现细节
Obsidian 库里的笔记怎么被 Agent 用起来?核心是检索。最简单的做法是关键词匹配,但效果一般。好一点的做法是把笔记做向量化,用语义检索。再进一步是混合检索,关键词和语义结合。
我的实践经验是:笔记数量在几千条以内时,关键词加简单语义检索就够了,不用上复杂的向量数据库。笔记数量上万后,才需要考虑专门的检索方案。另外,笔记的更新策略很重要——过时的笔记要及时标记或删除,否则会污染检索结果。我一般给每条笔记加一个"最后验证日期",超过三个月的笔记检索时降权。
5. 常见问题与排查技巧实录
5.1 Agent 执行中断的典型原因
"agent execution terminated due to error" 这个报错我见过太多次,原因五花八门。最常见的是工具调用超时,比如执行一个耗时命令,超过了设定的超时阈值。其次是上下文超限,prompt 太长被模型拒绝。还有权限不足,Agent 想读写某个文件但被系统拦了。
排查思路是分层看:先看错误发生在哪个阶段(模型调用、工具执行、结果校验),再看具体错误信息。我一般会在 Harness 里加详细的日志,每个阶段进出都记一笔,出问题时能快速定位。没有日志的 Agent 系统,排查起来就是盲人摸象。
5.2 上下文丢失与记忆错乱的解决
多轮任务跑久了,Agent 会"忘记"之前做过什么,甚至把不同任务的信息混在一起。这是上下文管理的经典问题。解决办法有三层:短期靠上下文窗口内的历史,中期靠任务级的摘要,长期靠 Obsidian 知识库。
关键是摘要的质量。摘要太简,信息丢失;摘要太详,等于没压缩。我的经验是摘要保留"做了什么、为什么这么做、结果如何"三要素,具体代码和细节不放摘要里,需要时从知识库检索。这样摘要能压缩到原文的 10% 左右,效果还不错。
5.3 Markdown 解析异常的排查清单
| 异常现象 | 可能原因 | 解决方法 |
|---|---|---|
| 表格解析错乱 | 缺少表头分隔行 | 强制生成分隔行 |
| 换行丢失 | 用了单换行 | 统一用空行分隔 |
| 代码块未识别 | 未标注语言 | 强制标注语言 |
| 图片路径失效 | 用了绝对路径 | 统一相对路径 |
| 列表嵌套错乱 | 缩进不一致 | 统一缩进规范 |
这张表是我踩坑踩出来的,基本覆盖了 90% 的 Markdown 解析问题。建议把它写进 Agent 的 system prompt,让生成时就规避。
5.4 成本失控的预警与止损
成本失控通常不是突然发生的,而是慢慢涨上去的。预警信号包括:单次任务 token 消耗持续上升、任务重试率变高、上下文长度接近上限。发现这些信号就要及时干预。
止损手段我按优先级排:先砍掉不必要的工具调用,再压缩上下文,再降低模型规格,最后才是减少任务量。前三个手段通常能解决问题,不用走到最后一步。另外建议设置每日 token 预算,超了就暂停,避免一觉醒来账单爆炸。
5.5 一个人维护大项目的经验教训
九个月一个人扛下来,最大的体会是自动化程度决定可持续性。凡是需要手动做的事,迟早会成为瓶颈。测试要自动跑,部署要自动做,知识沉淀要自动写,连代码审查都要尽量让 Agent 先过一遍。
第二个体会是文档比代码重要。20 万行代码,三个月后你自己都记不清某段是干嘛的。所以每个模块必须有说明,每个决策必须有记录,这些文档就存在 Obsidian 里,随时能查。
第三个体会是别追求完美。一个人做项目,资源有限,该妥协就妥协。代码能跑就行,架构够用就行,别为了优雅把项目拖死。我见过太多人卡在"重构"上,最后项目黄了。
最后分享一个我一直在用的小技巧:每周花半小时回顾 Agent 的执行日志,找出最常失败的任务类型,针对性优化。这个习惯坚持下来,系统的稳定性会肉眼可见地提升。项目后续如果要扩展,我建议优先做两件事——把知识库检索做得更智能,以及把任务编排做得更灵活,这两块是当前最影响效率的瓶颈。