1. 一个人九个月二十万行代码,这件事到底在说什么
先把数字摊开来看。九个月,按每月22个工作日算,大概198天。20万行代码,平均每天要产出1000行左右。这个量级放在任何团队里都不算小,何况是一个人。更关键的是后面那个数字——每个月烧掉40亿以上的token。这个消耗量说明它不是靠手写堆出来的,而是大量借助了AI Agent来生成、修改、重构代码。
这个项目的核心,是造一款基于Harness架构的应用。Harness这个词在AI Agent圈子里最近被反复提起,它指的是一套让Agent能够稳定、可控、可复用执行任务的工程化外壳。你可以把它理解成给大模型套上一副"骨架"和"缰绳"——骨架负责定义它能做什么、怎么调用工具、怎么管理上下文;缰绳负责约束它别乱跑、别把上下文撑爆、别在关键步骤上翻车。
为什么一个人能在九个月里推进这么大的工程量?答案不在于这个人有多能敲键盘,而在于他把大量重复性、结构化的编码工作交给了Agent,自己专注于架构设计、任务拆解和质量把关。这背后涉及几个关键词:Harness架构、Agent开发、Claude Code、Markdown、Obsidian。这几个词串起来,其实就是一条完整的个人开发工作流——用Obsidian管理知识和任务,用Markdown做统一的中间格式,用Claude Code这类Agent工具执行具体编码,用Harness架构把整个流程串成可复用的系统。
这篇文章适合谁看?如果你是一个独立开发者,或者小团队里负责技术方案的人,正在琢磨怎么用Agent把开发效率拉起来,那这篇内容会对你有直接参考价值。如果你只是听说过Harness但不知道它具体解决什么问题,我也会从最基础的概念讲起。整篇内容会围绕这个项目的架构思路、核心实现、实操细节和踩坑经验展开,尽量把"为什么这么做"讲透,而不是只丢一堆结论。
2. Harness架构到底解决了什么问题
2.1 从"裸用大模型"到"给模型装骨架"
大部分人最开始用大模型写代码,方式很直接:打开对话框,把需求描述一遍,等它吐代码,复制粘贴,跑一下,报错了再贴回去让它改。这个方式在单文件、小脚本场景下还能凑合,一旦项目规模上去,问题立刻暴露。
第一个问题是上下文管理。一个20万行的项目,你不可能每次都把全部代码塞进对话里。模型的上下文窗口再大也有上限,而且塞得越多,注意力越分散,输出质量反而下降。第二个问题是任务一致性。你今天让它按A方案写了一个模块,明天换个对话让它写关联模块,它可能就按B方案来了,两边的接口对不上。第三个问题是可追溯性。对话一关,之前怎么改的、为什么这么改,全丢了。
Harness架构要解决的就是这三件事。它的核心思路是:不让模型直接面对整个项目,而是给它一个受控的执行环境。这个环境里定义了工具集(读文件、写文件、执行命令、搜索代码等)、上下文注入策略(每次只给它当前任务相关的代码片段)、以及任务的状态管理(当前做到哪一步、下一步该干什么)。
打个比方,裸用大模型就像让一个刚入职的工程师直接进机房随便改配置,而Harness架构相当于给他配了工单系统、权限控制、操作日志和代码审查流程。模型还是那个模型,但行为变得可控了。
2.2 Harness的三个核心组成
一个能跑起来的Harness,通常包含三个部分。
工具层。这是Agent的手和脚。最基础的工具包括文件读写、目录遍历、命令执行、代码搜索。进阶一点的有Git操作、测试运行、依赖安装。工具的定义要足够清晰——每个工具叫什么、接受什么参数、返回什么格式,都要写死。模型通过调用这些工具来和真实项目交互,而不是靠"想象"。
上下文层。这是Agent的眼睛和记忆。它负责在每次调用模型之前,把当前任务需要的信息组装好塞进去。比如当前要改的文件内容、相关的接口定义、最近的报错信息、项目的编码规范。这一层的设计直接决定了Agent的输出质量。塞少了它不知道背景,塞多了它抓不住重点。
编排层。这是Agent的大脑。它决定任务的执行顺序:先读哪个文件、再改哪里、改完跑什么测试、失败了怎么回滚。编排逻辑可以很简单,比如"读文件→改文件→跑测试"的固定流程;也可以很复杂,带条件分支和循环重试。
这三层配合起来,才能让Agent在真实项目里稳定干活。缺了工具层,它只能空谈;缺了上下文层,它瞎猜;缺了编排层,它干一步停一步。
2.3 为什么这个项目选了Harness而不是别的方案
市面上做Agent的方案不少,有偏对话式的,有偏工作流式的,也有偏多Agent协作的。这个项目选Harness架构,我推测有几个现实考量。
一是单人开发的场景。一个人做项目,最缺的是"稳定的执行力",而不是"创意"。Harness的强项正好是把确定性的任务交给Agent稳定执行,人只需要在关键节点做决策。二是20万行的规模。这个体量下,任何靠"每次重新描述需求"的方式都会崩溃,必须有持久化的任务状态和上下文管理。三是token消耗量。每月40亿token意味着大量调用,Harness的上下文裁剪策略能有效控制单次调用的token量,不然成本会失控。
提示:选架构之前先想清楚你的瓶颈在哪。是缺创意、缺执行力,还是缺上下文管理能力?不同瓶颈对应不同方案,别一上来就堆最复杂的。
3. 核心细节拆解:Markdown、Obsidian与Agent的配合
3.1 为什么用Markdown做统一中间格式
这个项目里Markdown出现的频率很高,不是偶然。Markdown的好处在于它既是给人看的,也是给机器读的。人看它排版清晰,机器读它结构简单——标题、列表、代码块、表格,都有明确的语法标记。
在Agent工作流里,Markdown承担了几个角色。第一是任务描述。你把要做的事写成Markdown文档,Agent读进去就能理解任务边界。第二是知识沉淀。项目里的架构决策、接口约定、踩坑记录,都用Markdown存下来,Agent需要时直接检索。第三是输出格式。Agent生成的分析报告、修改说明,也用Markdown输出,方便人快速扫读。
相比JSON或YAML,Markdown对人多了一层可读性;相比纯文本,它对机器多了一层结构。这个平衡点让它成为Agent工作流里的通用货币。
3.2 Obsidian在项目里扮演什么角色
Obsidian本质上是一个基于本地Markdown文件的知识管理工具。它的价值在于双向链接和图谱视图——你可以把项目里的各个知识点连起来,形成一个网络。
在这个项目里,Obsidian大概率被用作"项目大脑"。所有的任务卡片、架构文档、决策记录、问题追踪,都以Markdown文件的形式存在Obsidian库里。Agent通过文件系统访问这些内容,人通过Obsidian的界面浏览和编辑。这样做的好处是数据和工具解耦——就算哪天不用Obsidian了,这些Markdown文件还在,换个工具照样能用。
具体用法上,可以给每个功能模块建一个笔记,笔记里写清楚这个模块的职责、依赖、接口、待办事项。Agent接到任务时,先读对应笔记,理解上下文,再动手改代码。改完之后,把变更记录写回笔记。这样人和Agent共享同一份"项目记忆"。
3.3 Agent如何读取和写入这些内容
Agent访问Obsidian库,走的是文件系统这一层,不需要Obsidian本身提供API。因为Obsidian的库就是一堆Markdown文件加一个配置目录,Agent用普通的文件读写工具就能操作。
读取时,Agent按路径找到对应文件,解析Markdown结构,提取需要的信息。写入时,Agent按约定的模板生成Markdown内容,追加或覆盖到文件里。这里有个细节要注意:Obsidian有自己的链接语法,比如双方括号包裹的链接。Agent在写入时要么遵守这个语法,要么干脆不用链接,避免破坏Obsidian的解析。
注意:让Agent直接改Obsidian库里的文件时,最好先做备份或者用Git管理。Agent偶尔会误删内容或者写坏格式,有版本控制能随时回滚。
4. 实操过程:从零搭一套能跑的Agent工作流
4.1 环境准备与工具选型
先说工具链。核心是Agent执行工具,Claude Code是这类工具里比较有代表性的一个,它能读文件、写文件、跑命令,并且有相对完善的权限控制。配套的还需要一个代码编辑器(VS Code足够)、一个版本控制工具(Git)、以及Obsidian作为知识库。
安装Claude Code的流程不复杂,大致是先在系统里装好Node.js环境,然后通过包管理器安装命令行工具,最后配置好API访问凭证。VS Code里可以装对应的扩展,这样能在编辑器内直接调用Agent能力。具体命令各平台略有差异,装完之后用--version验证一下是否可用。
Obsidian的安装更简单,官网下载对应平台的安装包,装完创建一个库(Vault),指定一个本地目录作为库的根路径。这个目录就是后续Agent要访问的地方。
4.2 目录结构设计
目录结构决定了Agent能不能快速找到它需要的东西。我建议按职责划分,而不是按文件类型划分。一个参考结构是这样的:
project-root/ vault/ # Obsidian库 tasks/ # 任务卡片 docs/ # 架构与决策文档 logs/ # 执行日志 src/ # 源代码 tests/ # 测试代码 harness/ # Agent配置与工具定义 tools/ # 工具定义文件 prompts/ # 提示词模板 config.yaml # 全局配置这样分的好处是,Agent的配置和项目代码分开,互不干扰。任务和文档放在vault里,人用Obsidian看,Agent用文件系统读。日志单独放,方便排查问题。
4.3 工具定义与提示词编写
工具定义要写清楚三件事:工具名、参数、返回值。比如一个"读取文件"的工具,参数是文件路径,返回值是文件内容。定义要足够精确,模型才能正确调用。
提示词模板是另一个重点。每个任务类型对应一个模板,模板里包含任务描述、上下文占位符、输出格式要求。比如"修改代码"的模板,会要求Agent先读文件、再输出修改后的完整内容、最后说明改了什么。模板写得好,Agent的输出就稳定;模板写得含糊,Agent就开始自由发挥。
这里有个经验:提示词里要明确"不要做什么"。比如"不要修改无关文件"、"不要引入新依赖"、"不要改变现有接口"。负面约束往往比正面要求更能防止Agent跑偏。
4.4 任务执行与状态管理
任务执行的核心是状态机。每个任务有明确的状态:待处理、进行中、待验证、已完成、失败。Agent每完成一步,更新状态。人可以在Obsidian里看到所有任务的状态,随时介入。
状态管理用文件实现就够了。每个任务一个Markdown文件,文件头部用YAML front matter记录状态、负责人、创建时间等元数据。Agent读写这个文件来更新状态。简单、透明、可追溯。
执行日志要详细记录。每次Agent调用工具、每次模型输出、每次测试结果,都记下来。出问题时,翻日志就能定位是哪一步出的错。日志按日期分文件,避免单个文件过大。
5. 常见问题与排查技巧实录
5.1 Agent执行中断与错误处理
Agent执行过程中最常见的报错是"execution terminated due to error"这类中断。原因通常有几类:工具调用参数格式不对、访问了不存在的文件、命令执行超时、上下文超出限制。
排查思路是从日志入手。先看最后一次成功的工具调用是什么,再看失败的那次调用参数是什么。如果是参数问题,检查工具定义是否清晰;如果是文件问题,检查路径是否正确;如果是超时,考虑给命令加超时限制或者拆分任务。
处理策略上,建议给每个工具调用加try-catch,失败时记录详细错误信息,并让Agent有机会重试。重试次数要设上限,避免死循环。连续失败三次就停下来,等人介入。
5.2 上下文超限与token控制
每月40亿token的消耗量,说明token控制是这个项目的生命线。上下文超限的表现是模型开始"遗忘"前面的内容,或者输出质量明显下降。
控制手段有几个。一是上下文裁剪,每次只注入当前任务相关的代码片段,而不是整个文件。二是摘要压缩,把长文档压缩成要点再注入。三是分步执行,把大任务拆成小任务,每个小任务独立调用模型。四是缓存复用,相同的前缀内容可以缓存,减少重复计算。
实测下来,上下文裁剪的效果最明显。一个2000行的文件,如果只注入相关的200行,token消耗能降到十分之一。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决建议 |
|---|---|---|---|
| Agent执行中断 | 工具调用失败 | 查看最后成功调用 | 检查参数格式与路径 |
| 输出质量下降 | 上下文超限 | 统计单次token量 | 裁剪上下文或拆分任务 |
| 修改了无关文件 | 提示词约束不足 | 检查提示词模板 | 增加负面约束 |
| 任务状态混乱 | 状态更新遗漏 | 检查状态文件 | 统一状态更新入口 |
| 重复执行同一任务 | 状态未持久化 | 检查状态读写 | 确保状态落盘 |
| 命令执行超时 | 任务粒度过大 | 查看命令耗时 | 拆分任务或加超时 |
5.4 几个踩过的坑
第一个坑是过度信任Agent的输出。早期我让它直接改代码,不做验证,结果它改了一个函数签名,调用方全挂了。后来改成"改完必须跑测试",问题少了很多。
第二个坑是提示词写得太长。以为写得越详细越好,结果模型抓不住重点,反而容易跑偏。后来精简到只保留关键约束,效果反而更好。
第三个坑是忽略日志。出问题时第一反应是重新跑一遍,而不是看日志。后来养成习惯,先看日志定位问题,再决定怎么处理,效率高很多。
提示:Agent工作流里,日志的价值被严重低估。花点时间把日志做好,后面排查问题能省大量时间。
6. 这套工作流的扩展方向
跑通基础流程之后,可以往几个方向扩展。
一是多Agent协作。把不同职责拆给不同Agent,比如一个负责写代码,一个负责审查,一个负责写测试。它们通过共享的任务文件来协调。这样能进一步提升吞吐量,但协调复杂度也上去了。
二是知识库自动更新。让Agent在完成任务后,自动把经验教训写回Obsidian库。时间长了,这个库就成了项目的"活文档",新人接手时能快速上手。
三是质量门禁。在Agent提交代码前,自动跑一遍静态检查、单元测试、格式校验。不通过就打回重做。这样能把质量问题挡在前面,减少人工审查的负担。
四是成本监控。统计每个任务的token消耗,找出消耗大户,针对性优化。比如某个任务总是消耗大量token,可能是上下文注入策略有问题,或者任务拆分不够细。
这套东西说到底,核心不是技术多先进,而是把"人做决策、Agent做执行"这个分工落到实处。一个人九个月20万行代码,靠的不是手速,是把重复劳动交出去,把精力留给真正需要判断的地方。我在实际使用中最大的体会是:别指望Agent一次做对,要设计好让它能试错、能回滚、能积累经验的机制。机制搭好了,效率自然就上来了。