一个人、九个月、20 万行代码、每个月烧掉 40 亿 token——造出一款Harness架构应用先说个让人有点羞耻的数字过去九个月我一个人蹲在工位上写了大概 20 万行代码每个月烧掉 40 亿 token。你没看错是亿不是万。这些 token 基本都是喂给了代码生成模型和配套的 Agent 流程用来帮我完成从需求拆解、接口设计到模块生成、测试修复的所有环节。说句实话九个月前我也觉得这是一场豪赌但最后不仅把东西造出来了还顺手提炼出一套我现在称之为Harness 架构的应用骨架。这篇文章就是想把这段经历拆开揉碎讲讲为什么必须给 AI 套上“缰绳”以及那 40 亿 token 到底烧得值不值。如果你正准备做一款以 AI 生成为核心、但又不希望被 AI 的不可控性拖垮的软件或者你也在为每天疯狂上涨的 token 账单发愁那这篇文章应该能给你一些参考。我不会只讲成功学更多是踩坑实录和工程取舍。适合独立开发者、小团队技术负责人以及所有对大模型驱动开发感兴趣的人。1. 为什么要给 AI 套上“缰绳”Harness 架构的起源1.1 让 AI 直接写整个项目的教训最开始我的想法特别天真既然大模型那么能写代码那就让它直接按需求生成一个完整应用好了。我试过用一种“终极提示词”的玩法把整个项目需求写成几千字的规格书然后让模型一口气输出几十个文件。结果怎么样第一天生成的三个核心模块到了第三天已经完全看不出它们在同一个系统里一个模块用 Python 写服务端逻辑另一个模块用 TypeScript 写云函数还有一个模块甚至自己发明了一个“ORM”连数据库连接方式都跟另外两个模块完全对不上。更崩溃的是调试环节。AI 生成的代码在单文件层面看起来有模有样但一旦有跨模块调用就会暴露出一堆“幻觉接口”和“命名漂移”。我数了一下光是修复一个简单的鉴权中间件就来回跟模型沟通了 17 轮token 消耗轻松突破 500 万最终产出的还是 600 行堆着一堆TODO的意大利面。那一刻我意识到问题不在模型能力而在架构失控。真正需要建设的不是“更聪明的提示词”而是一个能约束 AI 行为、规定输入输出、自动验证结果的运行框架。我当时给这种框架起了个名字——Harness。这个词的本意是“马具”或“保护绳”用来牵引与约束。Harness 架构的核心就是AI 模型不再是“自由编码员”而是框架驱动下的“生成引擎”。1.2 Harness 架构的三个设计目标所谓 Harness 架构本质上是一套围绕 AI 生成过程的控制层。它不是操作系统也不是微服务架构而是专门为“大模型参与代码生产”设计的一套工程治理体系。我给自己定了三个硬性目标确定性接口AI 只能按照预先定义的接口契约去生成实现不允许自行发明对外 API。可验证输出每次生成的结果必须经过编译、静态检查、单元测试三关卡任何一关失败都不得进入主分支。可审计操作AI 每一次“写文件”“改文件”“调用工具”的动作都记录在案出了问题可以追溯也可以回滚。听起来很像传统软件工程的 CI/CD但区别在于以前我们约束的是人写代码的“结果”Harness 约束的是 AI 生成代码的“全过程”。1.3 为什么传统架构撑不住 AI 生成式开发传统架构的根基是“可预测”。无论是单体、微服务还是 Serverless开发者都假设代码由人编写因此可以通过 Code Review、架构评审来卡质量。可当代码由模型自动生成时你会面临三个传统架构完全没处理过的新问题不确定性同一段输入今天生成的代码和明天生成的代码完全不同。无意识性AI 根本不知道“自己不知道”会一本正经地调用并不存在的库。规模化崩溃AI 生成代码的速度远超人的审查速度一旦批量生成问题会指数放大。这三个问题让我认识到不能用机械式地“审阅”来应对 AI 生成而是要从上游把生成行为“圈养”起来。于是我把整个项目的架构改成了以Harness 为核心引擎的形态。后续所有模块都先定义契约、再让 AI 填肉最后由 Harness 统一验证发布。这个决定让我从“被 AI 带着狂奔”的状态回到“骑在 AI 背上控制方向”的状态。2. 九个月烧掉 40 亿 token 的账单钱都花在哪了2.1 真实消耗拆解Token 不是花在“写代码”上四十亿这个数字太抽象我把它换算成具体的东西按一次请求平均 5000 字上下文、单轮生成约 2000 字输出算每月 40 亿 token 大约对应 50 万次 API 请求。这么多请求真正花在“生成最终代码”上的可能只占三成其余全浪费在沟通成本、纠错和上下文搬运上。我从埋点日志里拉了一份消耗分布大致是这样的消耗场景占比说明多轮上下文携带35%每次对话都要把系统提示、项目规则、相关代码片段重复发送Agent 工具调用上下文25%检索文件、执行命令、抓取错误信息等工具结果需要写回上下文直接生成代码与补全20%真正产生有效代码的部分错误修复循环15%编译失败、测试不通过后的反馈与再生成测试生成与解释5%生成测试用例和解释性文本看到没“写代码”本身只占两成剩下八成都是在解决“如何让模型知道更多信息”和“如何让模型忘记错误信息”。这就是为什么很多人觉得 token 烧得快真实原因不是模型变贵了而是整个生产链路太啰嗦。2.2 我为什么没有靠人肉优化来省 Token你可能会说省 token 还不简单少发几次上下文、精简提示词不就行了如果只是写几个脚本确实可以那么干。但我这个项目是 20 万行代码的规模模块之间彼此依赖AI 必须理解全局才能生成局部代码。我一开始试过“极简提示词”策略结果生成出来的东西完全丢掉了上下文接口风格混乱甚至引用已经删掉的历史文件。后来被迫走向另一个极端每次请求把整个项目的文档都塞进上下文效率是高了一点点但 token 消耗直接翻了三倍。那个月账单下来我手都在抖。真正有效的优化路径是围绕Harness 架构的分层上下文管理全局层只放项目全局规范和接口索引大约 2 万 token每次任务固定发送。局部层每个功能模块的详细设计和相关文件按需加载不参与无关任务。即时层当前编译错误或测试失败的日志短平快用后即焚。这样每一轮对话的平均上下文从 8 万 token 降到了 3 万左右而生成的代码质量和完整上下文时几乎一致。这一套分级管理是根治 token 浪费的关键。2.3 Token 消耗反逼出架构升级还有一个反直觉的收获高额 token 账单其实帮了我大忙。因为每个月的花费都在刺激我思考“这段 token 能不能不花”。比如我发现AI 在修复错误时经常反复犯同一个错因为它看不到上一次修复的完整“diff”。于是我在 Harness 里加了一块修复记忆区把过去的失败模式和对应补丁缩存到上下文里。这直接让错误修复循环的 token 消耗降低了 60%而且错误修复的成功率更高了。所以你现在看到的 Harness 架构一半是被 AI 能力推着走另一半是被每月 40 亿 token 的账单逼出来的。3. 20 万行代码的工程组织一个人如何不陷入代码泥潭3.1 二十万行到底是什么概念20 万行代码不是一个抽象数字。如果按平均每行代码 30 个字符算相当于六百万字符全部打印出来大概是 1200 页 A4 纸。一个人九个月写完这意味着哪怕不吃不喝纯手写也需要每天输出 700 行以上高质量代码——这几乎不可能。但借助 AI 生成一天生成几万行并不难。真正的瓶颈不在“写不写得完”而在“如何让写完的代码不会互相踩踏”。我在项目早期因为贪图速度让 AI 并行生成多个模块。结果两周后整个代码库里同时存在 4 套时间格式化工具、3 套 HTTP 客户端封装、2 个日志库的混用版本。后来我痛下决心用 Harness 架构强制统一。3.2 用“契约优先”来控制模块生成Harness 架构的模块开发流程和传统“先设计再实现”最大的区别在于设计文档不是给人看的而是给 AI 看的契约体。每个模块启动前我先用固定的模板定义好对外暴露的函数签名和数据类型依赖的第三方库及版本区间预期的时间和空间复杂度日志输出规范与错误码范围可接受的单元测试覆盖率阈值这些规则被写进 Harness 的全局配置里作为每次生成请求的前置上下文。AI 只能在这些契约的“笼子”里完成实现。一旦它尝试越界比如擅自引用一个不在白名单里的第三方库Harness 的静态扫描层会直接拦截并驳回这次生成。这样做的直接后果是代码库的模块边界极其清晰。哪怕 AI 生成的两个模块之间毫无交流它们也能通过统一风格的接口彼此兼容。偶尔需要跨模块调用我只需要生成一个遵循既定协议的函数签名。这种“契约优先”的开发方式让我一个人也能维持 20 万行代码的秩序。3.3 哪些代码必须自己写哪些可以放心交给 AI九个月里我逐渐总结出一个分工原则基础设施、核心数据结构、算法骨架这些是整个系统的“地基”我自己手写。胶水代码、样板代码、CRUD 操作这些逻辑高度重复适合完全交给 AI。测试用例让 AI 生成“常规路径”的测试边界条件和异常场景我手动补。构建脚本、部署配置AI 生成初稿我人工调整细节防止奇怪的组合。这样分工以后代码质量明显上去了一大截。最直观的对比是早期 100% 靠 AI 生成的分支bug 修复平均需要 7 轮对话后来 30% 手写 70% AI 生成的分支修复平均只需要 2 轮。不要以为 AI 会替你解决所有问题它解决的是“量”而“质”的底线需要靠人的架构判断守住。3.4 没有团队 Review就用自动化流水线兜底独立开发者最尴尬的是没有第二双眼睛盯着代码。我的解决办法是把 Code Review 的任务“翻译”成一系列自动化关卡语法检查 类型检查必过ESLint/ Ruff 等规则强制规则比团队标准还要严一倍单元测试覆盖率检查核心模块不得低于 90%圈复杂度检查超过阈值自动打回重写重复代码检测相似度大于 85% 必须重构任何一个 AI 生成的文件只要没通过五道关卡就进不了主干。Harness 会把失败原因压缩成一条 200 字以内的错误摘要重新发给生成模型让它带着问题重做。这个过程刚开始看着很傻但反复十几轮后AI 会逐渐“内化”这些规则生成的代码一次通过的比率从 35% 上升到 80%。4. Harness 架构的核心实现从提示词到代码的闭环4.1 五层结构的总体设计如果一句话概括 Harness 架构那就是让 AI 像车间工人一样在固定工位上加工固定零件而不是让它当自由建筑师。我的实现中有五个核心层契约层Contract定义输入输出、约束和校验规则。状态层State记录当前任务的进度、已完成步骤、待办事项和上下文压缩摘要。执行层Executor把任务拆解成可执行的小步骤并调用模型和本地工具完成。验证层Validator对生成代码执行编译、测试、静态分析等校验。审计层Audit记录每一次模型决策和文件变更支持回滚。严格来说Harness 架构的应用本身也是一个常规应用它有数据库、API、前端。但所有 AI 相关能力都被这五个层包裹起来。这就像一个“驾驶舱”大模型只是引擎而 Harness 是方向盘和刹车。4.2 一个简化版控制循环示例我用 TypeScript 写过一个简化原型感受一下核心逻辑class HarnessEngine { private contract: Contract; // 契约 private state: State; // 状态 private validator: Validator; // 验证器 private audit: Audit; // 审计 async run(task: Task): PromiseResult { // 1. 产出定义好的契约和局部上下文 const prompt this.buildPrompt(task, this.contract, this.state.getRelevantContext()); // 2. 调用模型生成代码 const rawCode await this.generateCode(prompt); // 3. 记录原始输出便于审计 this.audit.log(generate, task, rawCode); // 4. 验证层检查 const validation await this.validator.validate(rawCode, task.scope); if (!validation.passed) { // 5. 失败则把错误反馈给模型进入下一次生成 const feedback this.buildFeedback(validation.errors); this.state.appendFeedback(feedback); return this.run(task); // 重试有次数上限 } // 6. 通过验证则写入目标文件 this.applyPatch(task, validation.patch); this.state.markCompleted(task); return validation.patch; } }这个循环看着简单但真正要命的是细节。比如buildPrompt里如何压缩局部上下文、state.appendFeedback时如何避免上下文膨胀、validator.validate中怎样平衡速度与准确性。每一个细节都经历了无数次踩坑后面我会讲到。4.3 提示词的结构化告别自由对话很多人和 AI 协作时喜欢像聊天一样把事情丢给模型“帮我写个 Python 爬虫。”在 Harness 架构里这种对话方式是被禁止的。所有大模型的输入都必须遵循一个结构化的类型{ task: generate_implementation, scope: module/auth, contract: { function_name: authenticate, parameters: [username, password], return_type: JwtToken, dependencies: [crypto-library 2.0.0] }, code_snippets: [existing_base64_encoder, error_codes_from_api], constraints: [no_third_party_orm, must_pass_eslint_standard] }这个 JSON 就是 Harness 传给模型的“工单”。模型只需要根据工单产出代码不需要理解整个项目的宏大背景。经验是给 AI 的信息越结构化它的输出就越可控给它讲一堆模糊理念它给你返回一堆模糊代码。另外我发现把反例放进提示词里非常有效。比如在打回重试时把上一次的失败错误摘要直接拼接进反馈区然后附上一句话“下面是刚才的错误请不要重现它。”这种“负反馈”比单纯的强调“请正确”有用十倍。我们后面会提到的“token 失效”问题也是在一次聊天中因为上下文丢失导致模型重复报错最终靠这种反例提示解决的。4.4 验证层的设计AI 生成的代码如何确保可运行我遇到的第一个难题就是验证层的“尺度”。如果验证太严格AI 产生的代码经常被拒导致重试次数 skyrocketing如果验证太宽松垃圾代码混进来后期修复的成本更高。最终我采用“分阶段验证”策略第 0 级——静态检查毫秒级语法解析、文件格式、命名规范。第 1 级——类型检查秒级TypeScript 编译、mypy 等。第 2 级——单测验证分钟级针对当前模块跑单元测试快速判断业务逻辑是否符合契约。第 3 级——集成验证偶尔手动触发跨模块调用、API 联调不进入每次生成流程。大部分问题在 0/1 级就被拦下来不至于浪费 token 去“验证一个显然错误的实现”。但单测这关不能省很多 AI 代码“看着没问题”一跑就挂所以我坚持每个模块都必须有配套测试。Harness 会在验证不通过时把测试失败信息压缩成 JSON 里的feedback字段反馈给模型。这个反馈占用的 token 不多效果却极其出色。4.5 工具调用与外部 API 的“马具”避免 Token 失效悲剧Harness 架构除了控制代码生成还要管理所有外部调用包括大模型 API、文件服务、代码仓库等。这里面最烦人的就是token 失效问题。因为在长任务中一个访问令牌Access Token可能只有几十分钟的有效期而一个大而全的生成任务可能需要几个小时。如果任务执行到一半令牌过期之前所有生成和修改全部作废那种“一地鸡毛”的感觉比丢代码还难受。我在 Harness 的审计层里加了两个机制令牌生命周期巡检每次执行子任务前检查令牌剩余有效期低于阈值时先刷新。断点续跑把整个任务拆成多个“原子操作”每个原子操作完成后持久化当前状态。这样即使 token 在某个环节失效重启后也能从断点继续而不是全部重来。这两个机制帮我躲过了好几次大面积 token 失效事件。你去看那些错误日志经常会看到“token exchange failed: error sending request”这类报错。在我这个项目里这类错误被 Harness 拦截掉转换成可重试的队列消息等令牌刷新后再继续。这篇经验就是给那些正在被 token 相关错误折磨的开发者的——千万别让令牌过期毁掉你一整天的生成任务。5. 踩过的坑token 失效、上下文爆炸和不可控代码5.1 Token 失效与刷新机制一次差点毁掉一个模块的教训有一次我写了一个超大规模的模块生成任务预计要跑两个小时。当时没有断点续跑所有状态都存在内存里。任务跑到一半大模型 API 突然抛出一个refresh_token相关的错误——刷新令牌已过期无法换取新的访问令牌。结果整个进程崩溃已经生成的十几个文件虽然写入了磁盘但状态记录全丢了Harness 无法判断哪些文件是已完成的哪些是半成品。最终我不得不手动清理所有生成文件从头再来。这件事直接催生了 Harness 的“令牌巡检 断点续跑”机制。现在每一个左侧的小任务完成后都会把当前进度和上下文摘要持久化到本地文件。重启后Harness 会先检查本地是否有未完成的 checkpoint然后从最后完成的步骤继续。这个机制不仅省 token还大大提升了任务的成功率。5.2 上下文爆炸模型“忘了”你最开始的要求另一个高频坑是上下文窗口被塞满导致的“遗忘综合症”。在 Agent 多轮交互中每一轮工具调用的结果都会追加到上下文里。跑到第 30 轮时最开始的 2 万字项目规范已经被挤到窗口之外。模型开始胡编乱造甚至产生了“幻觉依赖”。我的解法是分层摘要。每完成一步就把当前对话中最重要的结论压缩成 200 字的摘要替换掉历史完整信息。实现方式是用一个独立的小模型做摘要成本很低但效果立竿见影。后来我发现很多企业级 AI 应用都需要类似机制否则长任务必然中途“失忆”。5.3 AI 生成代码的“风格漂移”与“可维护性陷阱”如果你让 AI 连续生成几万行代码它会表现出一种“风格漂移”——今天写的代码和下周写的代码变量命名习惯都能完全不同。甚至同一个模块里一会儿用getData一会儿用fetchData都指同一个函数。我最终靠三招遏制强制规则引擎通过 eslint/rubocop 等工具内置命名风格检查不通过直接打回。公共工具函数白名单所有通用能力必须调用 Harness 框架提供的工具函数AI 不允许自建“同名方法”。定期重构日每个月挑一天让 AI 针对生成的代码做统一重构输入当前模块最大文件的上下文要求其输出符合整体风格的版本。这还不够。更隐蔽的问题是 AI 会生成大量“隐性重复”代码比如两个模块各自写了一套二分查找。Harness 里加了一个重复代码检测器只要发现相似度超标的片段就会自动提取公共方法并生成补丁替换。这样到项目后期代码量虽然还有 20 万行但“有效差异行数”远比实际要少可维护性也大幅提升。5.4 第三方依赖“幻觉”AI 会用不存在的库最让人头大的一个坑是 AI 生成代码时随意引用根本不存在的第三方库。比如它可能觉得express-ratelimit-plus这个名字合理就拿来用结果npm install直接报 404。比报错更麻烦的是它可能引用一个真实存在但版本过老的库导致安全漏洞或者兼容问题。Harness 的解决方案是在依赖引用之前做一次存在性校验。我在 Validation 层挂了一个查询 npm/pypi registry 的进程把所有 AI 提议的依赖名和版本号发过去核对。如果名字不存在直接把错误信息加入反馈让模型改成白名单内的库。这个环节虽然多占了一点 token但彻底避免了“编译过了装不上”的低级事故。5.5 测试用例的盲区AI 永远不会测试它没想过的边界AI 生成的测试用例天然倾向于“顺着实现逻辑走”很少测试边界条件和异常路径。比如一个parseDate函数AI 可能会写十几个正常日期用例却不会测null、空字符串、闰年错误格式。Harness 里没有一个专门的“测试补全器”它把已有实现和测试代码发给模型然后强制生成至少 3 个边界用例和 3 个异常用例。刚开始 AI 经常拒绝生成“会让自己代码失败”的用例后来我发现只要把“确保测试能暴露失败”明确写进提示词它就能做得不错。这些坑几乎每一个都对应 Harness 架构的一次迭代。从最初只有“生成器验证器”的两层结构逐步演化成现在的五层结构是九个月里被现实一次次教育的结果。6. 一个人九个月做成这件事最后想说的几句大实话如果现在有人问我想不想再来一次我会说想但绝不想用同样的方式再来一次。这九个月里最大的收获不是那 20 万行代码也不是几十亿 token 烧出来的经验而是**“如何用框架去驾驭 AI 能力”的工程思维**。不要迷信“一个人 AI 无限生产力”。AI 是引擎但因为引擎更强大你对方向盘、刹车和悬挂系统的要求反而更高。Harness 架构说到底就是你自己给自己造的那套“方向盘、刹车和悬挂”。它不会让 AI 跑得更快但它能保证 AI 跑得再快也不会翻车。对于想走同样路线的朋友我给几个具体的建议都是拿真金白银换来的教训第一先设计契约再放开生成。没有契约的生成等于盲跑省下来的时间迟早会在回滚时加倍还回去。第二把上下文当黄金。每多塞一个词进上下文就多花一份钱、多一份失忆风险。好好设计分层上下文和压缩机制比任何提示词技巧都重要。第三永远留一条手动后门。核心组件、关键数据结构坚决自己写。AI 可以优化它们、重构它们但绝不能从零定义它们。第四对 token 消耗建立“护栏”。别因为生成质量好就无限跑循环。设置单任务重试上限、单日消耗上限节省的是你的时间和心情。第五及时写日志。不是给用户看的日志而是给 AI 看的“重新加载状态”日志。没有这些日志长任务一断就是灾难。最后再分享一个小技巧当 Harness 验证发现错误时不要直接调用模型“重试”而是让它先解释“错误可能在哪个环节产生”然后再给修复指令。这个“先解释原因再给出修复”的流程能让失败修复的 token 消耗再降一半。我试过很多次几乎每次都能稳定生效。说回开头那个数字——每月 40 亿 token。九个月下来我已经不会再因为巨大的数字而感到惊讶。真正让我感到惊讶的是在这个数字之上通过 Harness 架构一个人可以撑起一个原本需要一个小型团队才能维护的代码库。那种感觉大概就是“被 AI 套上缰绳”后的自由吧。