乐于分享
好东西不私藏

让 AI 编码 Agent 可靠干活的工程框架

让 AI 编码 Agent 可靠干活的工程框架

模型越来越强,但光靠模型解决不了长任务跑偏、代码库迷路这些问题。
真正起作用的是套在模型外面那层工程结构——Harness。

2026-05-17阅读约 10 分钟

我用 Claude Code 写了大半年代码,有一个感受越来越深:决定 Agent 能不能干活的因素,模型能力大概只占一半,另一半全看你怎么配。

这个"怎么配"的东西,现在有个统一的名字叫 Harness。我把最近学到的一些 Harness 工程实践整理了一下,主要聊两个问题:

  • 长任务怎么管住目标——跑着跑着 Agent 说"差不多了"然后停下来,怎么办?
  • 大型代码库怎么不迷路——百万行代码,Agent 怎么找到对的地方?
目标

1Agent 的目标不能只活在聊天里

我之前给 Agent 布置任务,最常见的一个翻车场景是这样的:

我说"把这个模块重构完",Agent 跑了几轮,改了几个文件,然后告诉我"核心路径已经迁移完成,主要功能正常"。我一看,公共 API 被改了,测试里删了几条断言,文档也没更新。

它不是故意偷懒。问题是目标太模糊了。"重构完"到底什么算完?哪些东西不能碰?用什么来证明做完了?这些如果不说清楚,Agent 在长上下文里会不断把局部成功当成全局完成。

最近行业在往一个方向收敛

2026 年 4、5 月间,几个主流 AI 编码工具几乎同时推出了/goal命令。OpenAI 的 Codex、Anthropic 的 Claude Code、Nous Research 的 Hermes,做法各异,但解决的是同一个问题。其中 Codex 的实现最早,其概念来自 Eric Traut(OpenAI)设计的 Codex CLI 0.128.0 中的 "Ralph loop"——一个内部评审循环,Hermes 文档也明确标注了这一点[4]。

我把它们理解为三种不同的思路:

Codex:把目标变成一个控制台

目标存进数据库,有完整的状态管理。你可以暂停、恢复、清除。运行时还管 token 预算和时间预算,到点了自动收束。目前标注为实验性功能,需要通过 config.toml 手动启用[1]。

适合代码迁移、大型重构这类一跑就几十轮的任务。

重但完整

Claude Code:请一个独立验收员

思路轻巧:主模型干活,每轮快结束时,另一个独立的 evaluator 看看对话里的证据,判断目标达成了没。没达成就拉回来继续。这个 evaluator 默认用的是 Haiku——一个轻量快速的模型,不浪费主力模型的 token[2]。

目标描述上限 4,000 字符,要求写清楚范围、成功条件、不变量和收束方式。另外,如果配置了disableAllHooks,/goal 会直接不可用——它本质上还是跑在 Hook 机制上的[2]。

解决了最常见的 Agent 失败模式——不是不会干,是干到一半说"行了"。

轻而实用

Hermes:目标跟着你走

目标不绑定某个终端窗口。你在命令行开始的任务,切到 Telegram 或 Slack 上还能接着看进度。底层靠 SessionDB 的 state_meta 字段持久化目标状态,所以跨 gateway 是天然支持的[4]。

有个 fail-open 的评估机制——评估器自己出错不会把整个过程搞崩,有 turn budget 兜底。默认 turn budget 是 20 轮,到点就停[4]。

跨平台

写好一个目标,至少要想清楚五件事

不管用哪个工具,我自己现在写目标时会过一遍这五个清单:

  1. 范围— 到底改哪几个文件、哪个模块。不说清楚,Agent 会顺手"优化"周边代码。
  2. 不变量— 什么东西绝对不能碰。公共 API、现有断言、数据结构,写出来。
  3. 验证证据— 不接受"测试应该没问题"这种说法。要写清楚跑哪条命令、看哪个输出。
  4. 预算— 最多跑多少轮。到点了是继续硬跑,还是停掉整理现场。
  5. 收束— 做不完的时候留什么。已完成的、失败的、下一步建议,让别人能接着干。

举个例子,我不会再说"帮我修一下 auth 的测试",而是这样写:

/goal 修复 test/auth 下所有失败测试,保持 src/auth 的 public API 不变

范围:只改 src/auth、test/auth 和必要的测试辅助文件
不变量:不删除现有断言,不改公共 API
验证:每轮跑 npm test -- test/auth,完成前跑 lint 并报告 git diff
预算:20 turns 后停止新增改动
收束:整理已通过项、剩余失败项、失败命令和下一步建议

比之前那种一句话的写法,靠谱一个数量级。

一个认知纠正:Agent 更自主不等于更放任。恰恰因为要让 Agent 更自主地干活,才需要给它立更清楚的护栏。长任务 Agent 和长期运行的后端服务一样——需要健康检查、超时、重试、回滚。
代码库

2百万行代码库,Agent 怎么不迷路

解决了"目标怎么管"的问题,下一个坑是"代码怎么找"。

我的 demo 目录下有十几个子项目,已经不算小了。但比起那些百万行的 monorepo、跑了几十年的遗留系统,根本不算什么。在这种代码库里,Agent 如果不知道往哪看,要么找不到东西,要么找到过期的信息。

RAG 有个硬伤

主流 AI 编码工具用的是 RAG 方案:先把代码库全部嵌入,查询时检索相关片段。听起来很美,但在活跃开发的代码库里有个致命问题——索引跟不上代码变化的速度

你检索到一个函数定义,但那是两周前的版本,函数早就改名了。或者你查到一个模块的文档,但这个模块在上次提交里已经被删了。RAG 不会告诉你这些信息过期了。

Claude Code 走了另一条路:不建索引,像工程师一样遍历文件系统、grep、跟踪引用。每个实例直接读实时代码库,不存在"索引过期"的问题。

但这有个代价——Agent 得知道往哪找。你如果让它在一个十亿行代码库里"找一个模糊的模式",还没开始干就撞上上下文窗口的上限了。所以代码库的配置质量,直接决定了 Agent 的表现。

Harness:比模型更重要的东西

很多人以为 Claude Code 厉不厉害全看模型版本,其实不是。围绕模型的工程框架——Anthropic 叫它 Harness——对最终效果的影响可能更大。

Harness 由好几个层组成,每层干不同的事:

组件干什么容易犯的错
CLAUDE.md每次会话自动加载的规则塞太多东西,拖慢每次会话
Hooks在特定时机自动执行的动作只用来防错,忽略了自动改进
Skills按需加载的专业知识把所有知识塞进 CLAUDE.md
Plugins把 Skills + Hooks 打包分发好的配置只在少数人手里
LSP像 IDE 一样跳转定义和引用只靠 grep,同名函数分不清
MCP Servers连接内部工具和 API手动复制数据而不是直连
Subagents隔离上下文的子任务所有工作挤在主上下文里
构建有先后:先配好 CLAUDE.md,再加 Hooks,然后是 Skills、Plugins、LSP、MCP,最后才是 Subagents。每层建在前一层上面,跳级没什么好处。

Hooks 的用法比你想的要多

Claude Code 的 Hooks 有五种触发方式:command(命令行)、HTTP、MCP tool、prompt 和 agent[3]。大部分人理解的 Hooks 是"别让 Agent 犯错"。但更有价值的用法是让系统自己变好

Stop Hook:会话结束时的复盘
Agent 刚跑完一个长会话,上下文还新鲜。这时让 Hook 回顾一下:这次哪些地方反复踩坑?CLAUDE.md 里是不是该加条规则?下次就不会重蹈覆辙。
Startup Hook:自动适配当前模块
你在支付服务目录下打开 Claude Code,它自动加载支付相关的配置和约定。切到用户模块,配置跟着变。不用手动切。
用 Hook 做确定性执行
lint、格式化、类型检查这些东西,让 Hook 来做,比让 Agent "记住要跑 lint"靠谱得多。Agent 记性不靠谱,脚本靠谱。

让代码库对 Agent 可读

根据我的实践经验,有几个配置对效果影响特别大:

  1. CLAUDE.md 要分层。根目录只放总览和关键约束,子目录放各自模块的约定。别把所有东西堆在根目录——每次会话都会加载它,内容越多越慢。
  2. 在子目录里启动。不要在代码库根目录打开 Claude Code,进到你要改的那个模块目录里再启动。范围越小,Agent 越专注。
  3. 测试命令限定在子目录。改一个服务就跑那个服务的测试,别跑全量。不然超时浪费 token。
  4. 用 .ignore 排除噪音。构建产物、node_modules、自动生成的代码,把这些排除掉。最好把排除规则提交到版本控制里,团队每个人都能享受降噪效果。
  5. 代码库地图。如果目录结构比较乱,在根目录放一个 markdown 文件,简单描述一下每个顶层文件夹是干什么的。Agent 打开文件之前可以先扫一遍目录。
  6. 配 LSP。如果代码库超过几万行,LSP 的投入产出比非常高。grep "handleClick" 可能返回几百个结果,LSP 只返回同一个函数的引用。
一个容易忽略的事:CLAUDE.md 是写给当前模型的行为契约,不是一劳永逸的。模型在进化,半年前写的规则可能现在反而是限制。比如旧模型需要被要求"每次只改一个文件",新模型已经能做跨文件编辑了,这条规则反而会拖慢它。建议每几个月审一遍。
全局

3把零散的东西串成一条线

目标管理和代码库导航,其实是同一个问题的两面:怎么让 Agent 在大规模场景下可靠地完成工作

把它们放在一起看,一个成熟的长任务 Agent 工作流大概是这样:

CLAUDE.md 规则Skill 流程/goal 目标Hooks 检查Memory 记录CI 验证

CLAUDE.md 让 Agent 懂规矩,Skill 告诉它流程,/goal锁定目标和停止条件,Hooks 在关键节点做确定性检查,Memory 留下阶段性成果,CI 做最终交付验证。

这个过程不像什么颠覆性创新,更像是把软件工程的基本原则搬到了 Agent 上面。想想看,后端服务上线需要什么?健康检查、超时、重试、幂等、限流、告警、回滚。Agent 干长任务,需要的控制面是一样的。

我的几个实操建议,都是踩过坑之后总结的:

  • 写目标时过五字段清单。范围、不变量、验证证据、预算、收束。花两分钟写清楚,省掉后面无数轮的来回。
  • CLAUDE.md 要精简。只放广泛适用的内容。越精简,每次会话加载越快,Agent 注意力越集中。
  • Hooks 优先用于改进而非防错。Stop Hook 自动建议更新 CLAUDE.md,比什么都有效。
  • 配 LSP。如果你的代码库不是玩具项目,这个投入不会亏。
  • 定期审视配置。模型在变,工具在变,三个月前的好配置可能现在是负担。

最后说一点我的观察。Agent 编码工具的演进,和很多基础设施的演进走的是同一条路:先是"能用就行"的野蛮生长阶段,然后是"稳定可控"的工程化阶段。我们正在经历从前者到后者的转变。Goal 从一句话变成运行时接口,Skills 从 Markdown 变成工作流包,Memory 从聊天上下文变成结构化存储——方向很清楚。

能让 Agent 多跑几轮,没问题。但别让目标只活在聊天里。

参考
  1. OpenAI Codex /goal 文档
    developers.openai.com/docs/guides/codex/goals
  2. Anthropic Claude Code /goal 文档
    code.claude.com/docs/en/goal
  3. Anthropic Claude Code Hooks 参考
    code.claude.com/docs/en/hooks
  4. Nous Research Hermes Persistent Goals 文档
    hermes-agent.nousresearch.com/docs/features/persistent-goals