首页/新闻资讯/正文详情

双层Harness:让Coding Agent连续70轮自主开发

发布时间:2026/9/26 3:34:16 来源:云帆数科 栏目:资讯中心
双层Harness:让Coding Agent连续70轮自主开发
如果你自己动手跑过 Coding Agent八成有过这种体会单独让它写个函数、补个测试速度确实快可一旦把“把这个项目做完”这种大目标扔给它它很快就原形毕露——写了一半忘掉原始需求、跑挂了测试不修还要往下写、改数据库结构都不提前吱一声。更别说连续跑几十轮基本上十轮以内就得人工介入一次。最近上海 AI Lab 公开分享的“Harness 套 Harness”方案核心思路就是给 Coding Agent 套上两层工作流框架用严格的编排和验收规则约束它让它连续自主执行 70 轮任务环境搭建、代码生成、测试修复、文档汇总一条流水线从头跑到尾。这篇博文把这一思路的原理解析、复现路径和踩坑记录完整写出来适合正在做 Agent 开发、AI 辅助编程或者想给团队搭一套“自动开发流水线”的工程师参考。1. 核心思路拆解为什么要“Harness 套 Harness”1.1 先想清楚一个基础问题Harness 到底是干什么的很多第一次接触“Harness”的人都会把它当成某种新模型或者新语言实际上它跟模型完全是两码事。Harness 这个词本身是“安全带、工具架”的意思在 AI Agent 开发里它指的是独立于模型之外的工作流编排与行为约束层。我习惯用一个类比来讲这件事如果你把 Coding Agent 当成一个业务能力很强但完全不懂公司规矩的实习生那模型是“聪明的大脑”Harness 就是“工牌、作业指导书和打卡机”。Agent 负责想、负责做Harness 负责规定它应该做什么、按什么顺序做、做到什么程度算完、出问题谁说了算。两者的职责对比如下角色对应物核心职责Agent干活的实习生基于模型做决策调用工具产出代码和文本Harness工牌 作业指导书 审批流管理任务状态约束行为边界控制轮次执行验收这个区分非常重要。很多人用 Agent 翻车不是模型不行而是没有 Harness 管住它。模型给了一段“看起来合理”的回答Agent 就真的去执行了哪怕这段回答跟实际项目状态完全脱节。Harness 存在的意义就是把这个“看起来合理”变成“经过校验的合理”。1.2 “套两层”的真正含义项目经理 实施小组单层 Harness 已经能约束单个 Agent为什么还要套两层这是这套方案里我觉得最关键的设计。在处理复杂开发任务时单层 Harness 会碰到两个现实问题。第一个问题是上下文长度。一个 Agent 的上下文窗口是有限的你要它同时记住原始需求、技术方案、当前文件内容、最近的测试输出还要它处理几十个子任务跑到后半程上下文必然溢出模型开始“选择性失忆”。第二个问题是任务间的耦合。一个开发任务往往包含多个阶段环境搭建完之后才能写代码代码写完之后才能跑测试测试挂了又得回头改代码。如果所有阶段都挤在一个 Harness 里任何一步出问题整条流水线就得回滚重来状态管理会非常混乱。“Harness 套 Harness”就是把这些问题分层处理。外层 Harness 充当项目经理负责把大需求拆成子任务、维护任务队列、判断子任务验收是否通过、决定什么时候进入下一轮内层 Harness 充当实施小组每个子任务内部有一个独立的 Coding Agent 专注当前这一件事它不需要关心全局只需要在给定的小范围内完成编码、编译、测试这个小循环。外层的状态空间很小只关心“任务做到哪了、有没有达标”内层的上下文很干净只关心“当前这个模块怎么实现”。两者解耦之后70 轮连跑才不会演变成上下文灾难。1.3 连续 70 轮到底意味着什么70 轮这个数字第一次看到会觉得夸张但拆开看其实就是一整个开发任务的生命周期。我复现的时候大致按这种比例分配过需求解读与任务拆解约 5 轮环境准备与依赖管理约 8 轮项目骨架与接口设计约 10 轮核心逻辑实现与模块联调约 22 轮测试编写与缺陷修复约 15 轮文档生成与收尾检查约 10 轮合计正好 70 轮附近。所以说“让 Agent 连续干 70 轮”并不是刻意刷数字而是把原本需要人类开发者在 IDE 里来回切换、举棋不定、反复 debug 的整个过程用一套可编排的工作流交给 Agent 自治完成。这种长时自治任务还有一个隐性价值每一轮的结果都是结构化的、可回溯的。人工开发时“我当时是怎么想到这个方案的”往往说不清Agent 跑完 70 轮每一轮的任务、动作、产物、验收结论全部有日志这本身就是一个极好的项目资产。2. 支撑 70 轮连跑的关键设计细节2.1 任务拆解与验收标准每个子任务都必须带退出条件我见过很多失败的 Agent 工作流问题根源不是模型智商不够而是任务定义不清晰。开发者只告诉 Agent“写一个用户登录模块”Agent 就按照自己对“登录模块”的理解开工了写完说一声“完成”就退出。至于登录需不需要 token 刷新、需不需要验证码、数据库表结构怎么设计通通没有约束。外层 Harness 的首要职责就是把这些模糊需求转成一张带退出条件Definition of Done的任务卡片。每个子任务至少要包含四件事目标描述这个子任务要交付什么输入清单依赖哪些文件、哪些上游任务产物动作约束允许改哪些文件、不允许动哪些范围验收标准用什么命令、什么断言来判断“真的做完了”我自己的经验是验收标准必须写成可执行的形式比如“运行pytest tests/test_login.py全部通过”而不是“代码质量良好”。因为 Agent 对“良好”的理解跟人的理解永远有差距但命令行输出的 0 和 1 是没有歧义的。哪怕多花几轮在任务拆解上也比后期花十几轮返工划算。2.2 状态管理与跨轮记忆最容易被低估的工程点70 轮任务里Agent 要跨过几十次“遗忘点”。如果每轮都把所有对话历史塞给模型token 成本爆炸不说模型还会被早期过时的信息污染。我在实操中把记忆拆成了三层这算是这套方案里最实用的部分短期记忆内层 Agent 在当前子任务内的完整对话上下文子任务结束就清空中期记忆每一轮产出的文件清单、测试结果、关键报错摘要长期记忆项目原始需求、技术选型决策、全局接口约定这些只在必要时注入简单说就是“该忘的让它彻底忘该记的用结构化方式留住”。内层 Agent 每完成一个子任务外层 Harness 做的不是把完整日志装入下一个任务而是提炼一张“产物清单风险摘要”传给下一轮。这种做法的直接效果是跑到第 60 轮时Agent 对需求的理解依然跟第 1 轮一致而不是被中间二三十轮的错误信息带偏。2.3 Coding Agent 的动作闭环写码、执行、看错、再改内层 Coding Agent 的能力核心是构建一个紧凑的“开发-执行-反馈”循环。这个循环在代码里本质上是多轮工具调用每轮包含四个动作生成本轮要写入文件的代码片段、调用文件写入工具落盘、调用 shell 工具运行程序或测试、读取输出结果作为下一轮的决策依据。工具列表我建议至少包含四类tools [ FileReadTool(max_content20000), # 读文件限制最大长度防止溢出 FileWriteTool(), # 写文件 ShellTool(timeout30, max_output8000), # 执行命令超时截断 TestRunnerTool(timeout60), # 跑测试单独做超时控制 ]这里有个细节值得单独说所有工具都要做输出截断。Agent 连续跑几十轮时经常会出现一条命令打印几千行日志如果不截断下一轮模型的输入会瞬间膨胀把有效的决策上下文挤掉。截断之后Agent 看到的是“前 2000 字 后 2000 字”中间被省略的信息对它做决策基本没有影响。内层 Harness 的 System Prompt 里我还会固定一段约束文字你的每一次回应都必须按以下格式输出决策依据、本轮动作、预期结果。动作类型只能是 read_file、write_file、run_command、run_test 四种之一。如果测试失败你必须先用 read_file 查看相关代码再修改禁止盲目重试。这段约束的价值在于它把 Agent 的思考过程从“自由发挥”改成了“结构化推进”既方便外层 Harness 解析中间状态也变相逼着 Agent 每次修改前先看一下真实代码而不是凭“记忆”乱猜。实测下来盲目重试的比例至少下降一半。2.4 安全阀与人机协作边界自治不等于失控连续 70 轮的自治执行听起来很爽但工程上必须面对一个灵魂拷问万一它第 30 轮把整个项目的公共接口全改了呢所以这套工作流里必须有安全阀。我不建议让 Agent 拥有完全自由的文件操作权限而是按动作风险分三级低风险读写指定目录下的普通源码文件、运行测试直接放行中风险修改依赖清单、修改配置项需要记录并通知人工高风险删除文件、变更数据库结构、发布构建产物默认挂起等待人工确认另外一个非常实用的机制是单子任务失败次数熔断。我发现大多数任务在 3 到 5 次迭代内都能解决如果内层 Agent 连续失败超过 5 次基本可以判定当前任务描述有歧义或者存在前置依赖问题继续重试只是烧钱。这时候外层 Harness 应该把任务标记为 blocked暂停整条流水线把上下文摘要提交给人类开发者而不是让 Agent 继续硬闯。安全阀不会拖慢多少速度因为 70 轮里真正需要人工确认的高风险动作通常只有三四个但这三四个确认能避免大量灾难性的返工。3. 实操从零搭建一套“70 轮连跑”的 Harness 工作流3.1 选型LangGraph 做外层编排DeepSeek 系模型打底搭建这类工作流选型是第一步。外层 Harness 我选了 LangGraph。原因很简单它原生支持有状态图StateGraph节点之间可以显式定义状态转换和分支条件正好对应外层 Harness 的“任务排队-执行-验收-下一步”调度逻辑。对比之下LangChain 虽然生态成熟但在多轮状态管理上表达能力弱一些完全自研调度器也行但需要处理图形状态流转、持久化、日志回放这些底层问题开发量明显变大。模型部分在我复现的实践中DeepSeek 系模型包括其 API 或本地部署版本是性价比很稳的选择。70 轮任务跑下来 token 消耗很大模型价格直接决定这个方案能不能量产同时 Coding Agent 需要较强的代码理解与长上下文保持能力DeepSeek 这两块的表现在同价位里属于能打的那一档。当然你完全可以用其他长上下文模型替换核心不依赖具体厂商。3.2 环境准备沙箱隔离 基础依赖第一步是准备一个干净的沙箱目录。强烈建议给 Agent 单独开一个工作目录里面放一个requirements.txt和一个空的项目骨架不要让 Agent 直接在你的真实项目里乱跑。这不是不信任模型而是工程上必须保证“Agent 的破坏半径有限”。安装依赖很简单python -m venv .venv source .venv/bin/activate pip install langgraph langchain openai如果你用的是 DeepSeek 的 API可以按 OpenAI SDK 兼容的方式配置 base_url 和 api_key。模型参数我建议 temperature 调到 0.2 左右max_tokens 给足但别用默认值让 Agent 无限生成长文——它很可能在写日志上比写代码热情高得多。3.3 内层 Coding Agent最小可用的实现我先构建内层 Agent 的状态节点让它接收“任务编号、任务描述、工作目录、验收命令”这几个输入然后进入工具调用循环。核心逻辑类似下面这样from langgraph.graph import StateGraph, END from typing import TypedDict class CodingState(TypedDict): task_id: str task_desc: str work_dir: str accept_cmd: str attempts: int def run_inner_agent(state: CodingState): # 在这里调用 LLM tools执行写码、跑测试的循环 # 每次工具调用后检查 attempts超过 max_attempts 直接返回失败 return {attempts: state[attempts] 1} graph StateGraph(CodingState) graph.add_node(coding, run_inner_agent) graph.add_edge(coding, coding) # 循环直到满足退出条件关键在于退出条件的判断测试命令返回 0才算任务完成其他任何“我觉得完成了”都不算数。内层 Agent 不需要知道全局任务有多宏大它只需要对这个子任务负责。3.4 外层 Harness调度循环与轮次控制外层 Harness 的逻辑反而比内层更简单但它决定了 70 轮怎么组织。核心就是一个调度循环每次从任务队列里取出一个当前依赖都满足的任务交给内层 Agent 去执行然后根据验收结果更新队列状态同时把轮次数加一。task_queue build_tasks_from_requirement(raw_requirement) harness_round 0 while task_queue and harness_round 70: task select_next_task(task_queue) # 按依赖拓扑选一个可执行任务 result run_inner_agent(task) if verify_acceptance(task, result): mark_done(task, result) else: mark_blocked(task) task_queue update_dependencies(task_queue, task) harness_round 1这个循环里还藏着一个容易被忽略的细节每轮结束时把该轮的决策摘要写入审计日志。审计日志不需要很长只要记录轮次、任务编号、Agent 执行的动作类型、关键输出文件、验收结果这几项就够了。我后面排查问题靠的全是这份日志。3.5 一轮执行日志的真实样貌跑完整套流程后外层 Harness 会生成类似下面这样的轮次记录。我抽三行典型日志贴出来轮次任务编号Agent 动作关键输出验收结果18TASK-014write_file run_testsrc/auth/token.py实现 refresh_token 逻辑2 个测试通过45TASK-031read_file run_test修复tests/test_checkout.py中 timezone 相关断言1 个之前失败的测试通过69TASK-048write_file生成README.md和API.md文档校验通过第 45 轮是我印象很深的一轮Agent 第一次跑测试失败后没有盲目重试而是先 read_file 打开了测试文件发现时间固定写法有问题然后针对性修改。这说明前期的系统提示词约束和内层小上下文设计真的起了作用。4. 常见问题与排查技巧实录4.1 跑着跑着就“幻觉”上下文污染是头号杀手症状是跑到第 30 轮以后Agent 突然开始引用一个十几轮之前的文件路径或者把上一个子任务的测试报错当成当前任务的障碍。原因基本是上下文里混入了过期的状态信息。排查方法是先看审计日志里 Action 的输入输出确认它引用的文件路径、时间戳是否和当前任务对得上。解决办法有两个一个是在子任务之间强制清空内层上下文只把结构化摘要传给下一轮另一个是让 Agent 每次修改代码之前必须 read_file 当前实际内容禁止直接根据记忆生成修改后的完整文件。这两招一起上幻觉问题能压到很低。4.2 工具卡死没有超时的工具会拖垮整条流水线连续跑 70 轮的时候某些命令会意外地一直挂住比如一个没写退出条件的脚本、一个启动后不结束的本地服务。如果工具的 timeout 参数设置得太大或者没设外层 Harness 就会卡死在那一轮后面的任务全部排队等候。我的做法是所有 shell 类工具强制超时 30 秒测试类工具 60 秒超时直接杀掉进程并把 stdout 尾部内容作为结果回调给 Agent。如果同一个任务连续三次超时不再重试直接把任务标记 blocked 转人工。实测下来这一条规则保证了整条 70 轮流水线能从头跑到尾而不是在某个死循环里干瞪眼。4.3 嵌套状态同步丢失内层改了外层不知道“Harness 套 Harness”最隐蔽的坑是状态同步。外层 Harness 维护全局任务状态内层 Coding Agent 执行时会修改文件但内层如果需要把某些信息回写比如“我新建了一个配置文件后续任务要用”通过返回值省略掉的话外层就完全不知情后续任务就会因为找不到文件而失败。解决办法很简单内层 Agent 每轮结束必须把“本轮新增或修改的文件路径”显式写入摘要外层 Harness 再把这个摘要合并进任务队列的输入清单。注意传递状态时用拷贝而不是引用防止内层不小心直接改掉外层状态的原始对象。这些小问题单独看都不起眼但在 70 轮的长跑里会被放大成致命故障。4.4 token 成本失控长任务钱包告急70 轮不是免费的。我按一轮平均输入 2 万 token、输出 3000 token 来算整条流水线大概要消耗 150 万到 200 万 token。这个量级下模型单价差的就很明显了这也是我推荐长上下文 低价模型作为默认的原因。省成本的技巧有三个第一内层子任务之间的历史不传递只传摘要第二工具输出强制截断长日志只保留头尾第三对低风险的收尾任务比如生成 README可以用更小的模型。做完这三件事整体 token 消耗能比朴素做法省下差不多一半而且 Agent 的表现几乎不受影响。我自己跑这种超长 Harness 工作流最大的体会是“先把节奏慢下来”。前 10 轮宁可在任务拆解和验收标准上多花些时间后面六十几轮反而会非常顺反过来前面图快让 Agent 直接开写后面至少有二十轮在给前面的模糊需求擦屁股。最后再分享一个小技巧让外层 Harness 每轮都把 Agent 产生的 diff 文件名写进审计日志这比任何监控面板都实在项目一旦出了幺蛾子你能直接定位到是第几轮、哪个文件被哪次修改改崩的回溯成本几乎为零。

相关推荐

Manus逆向工程:用Python拆解AI智能体的ReAct与Plan-Execute
Manus逆向工程:用Python拆解AI智能体的ReAct与Plan-Execute

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 3:34:16

微信小程序全局自定义分享:从配置到实现一文搞定
微信小程序全局自定义分享:从配置到实现一文搞定

1. 全局自定义分享的需求分析与方案选型做微信小程序开发的朋友一定都遇到过这个尴尬场景:用户在小程序里看到一篇好内容,想转发给微信好友,结果随手一点右上角的菜单,默认分享卡片只有小程序首页的截图和一行系统自动生成的标题&… · 2026/9/26 3:34:16

Oracle 基础积累:update 语句执行报错时,如何用 TaoToken 统一 Key 排查配置链路
Oracle 基础积累:update 语句执行报错时,如何用 TaoToken 统一 Key 排查配置链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 3:34:10

内容安全与合规:博文创作中的审核与规范
内容安全与合规:博文创作中的审核与规范

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 4:20:50

大型前端项目的自动化依赖治理与版本锁死
大型前端项目的自动化依赖治理与版本锁死

大型前端项目的自动化依赖治理与版本锁死在拥有数百名前端开发者、数十个业务线协同的大型企业级代码库(Monorepo 或多仓库架构)中,依赖管理往往是滋生偶发 Bug 与安全漏洞的温床: 开发者 A 在 package.json 中写了 "lodash&… · 2026/9/26 4:20:50

CLI-Anything:Agent-Native命令行工具的设计哲学与工程实践
CLI-Anything:Agent-Native命令行工具的设计哲学与工程实践

1. 从"CLI-Anything"说起:命令行工具正在经历一场静默革命第一次看到"CLI-Anything"这个提法,我脑子里蹦出来的不是某个具体工具,而是一种趋势判断——命令行界面(Command Line Interface)正在从&… · 2026/9/26 4:20:44

MySQL跨表DELETE避坑指南:语法、误删与分批删除实践
MySQL跨表DELETE避坑指南:语法、误删与分批删除实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 4:20:44

PCG 资产随机种子 (Seed) 跨平台一致性验证与排查
PCG 资产随机种子 (Seed) 跨平台一致性验证与排查

PCG 资产随机种子 (Seed) 跨平台一致性验证与排查在基于程序化内容生成(PCG)的开放世界或 Roguelike 游戏中,“相同种子必定生成完全相同的关卡世界”是跨平台联机同步、异步对抗和玩家社区分享(Seed Sharing)的基石。… · 2026/9/26 4:20:44

Claude Code最佳实践详解:从CLAUDE.md到生产级AI编程工作流
Claude Code最佳实践详解:从CLAUDE.md到生产级AI编程工作流

1. 项目总览:Claude Code“最佳实践”到底在讲什么Claude Code 这个词最近在各技术群里出现的频率高得吓人。作为长期折腾 AI 编程工具的人,我前后试过 GitHub Copilot、Cursor、Aider,最后在 Claude Code 上投入的时间最多。原因不复杂&… · 2026/9/26 4:20:44

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码