type
Post
status
Published
date
Apr 3, 2026
slug
Harness-Engineering-002
summary
搭建Mini Harness
tags
Agent
category
Harness Engineering
icon
password
😀
 

手搓 Mini Harness:用 11 个机制从零搭建一个生产级 AI Agent 控制框架

不用 LangChain,不用 LangGraph,不用任何 Agent 框架。用最裸的 Python + OpenAI SDK,从零搭建一个包含 11 个安全机制的 AI Agent 控制平面,并诚实回答一个问题:Harness 到底值不值?

一、背景:Agent 不是智能体,是一个脆弱的循环

一个基本事实:AI Agent 不是智能实体,而是一个由代码组成的、可以反复调用 LLM 的 while 循环。 这个循环本身非常脆弱——它会循环失控、会吞掉工具报错、会在长会话中把自己搞傻、会无声无息地烧掉你的钱。
这些脆弱点被归纳为 八大故障模式
编号
故障模式
典型表现
循环失控
Agent 陷入无限循环,反复调用同一个工具
Context 溢出
长会话中上下文窗口被撑爆
Cache Miss
重复计算导致成本飙升
Tool 错误吞
工具执行失败被静默忽略,Agent 基于错误结果继续推理
状态丢失
任务中断后无法续跑,前功尽弃
缺权限闸
Agent 可能执行危险命令(如 rm -rf
缺自动化评审
LLM 自审等于作者自审,天然有偏差
成本失控
异常循环导致 API 费用无限增长
针对这八大故障模式,Harness Engineering 使用了 11 个机制(8 核心 + 3 扩展)
编号
机制
救的故障模式
实现文件
Agent Loop
① 循环失控
core.py
Tool Use
④ tool 错误吞
core.py
Progress Tracking
⑤ 状态丢失
progress.py
Context Management
② context 溢出 / ③ cache miss
context.py
Feature List
② context 溢出(源头防控)
planner.py
Verification Loop
④ tool 错误吞(下游验证)
verifier.py
Subagents
② context 溢出 / ⑧ 成本失控
subagent.py
Generator-Evaluator
⑦ 缺自动化评审
evaluator.py
Permission Gate
⑥ 缺权限闸
permission.py
Hooks
贯穿所有机制的事件挂钩基础设施
hooks.py
Token Budget
⑧ 成本失控
budget.py
本文将逐一拆解这 11 个机制的核心实现,并在最后用一组真实的 E2E 对比数据来回答那个核心问题。

二、项目骨架:11 个文件 = 1 个配置中心 + 10 个机制模块

整个 Mini Harness 刻意不使用任何 Agent 框架——目的不是省事,而是看清裸骨架:每一块肌肉是什么、做什么、怎么连接。框架会帮你隐藏复杂度,但代价是你不知道出了问题该去哪里找。

配置中心:HarnessConfig

所有 11 个机制共享一个配置对象,避免参数散落各处:
注意 max_steps=50——它是机制①防止循环失控的硬刹车。

三、核心机制详解

机制①②:Agent Loop + Tool Use(core.py

这是整个 Mini Harness 的心脏。Agent Loop 的本质是一个 while 循环,Tool Use 是循环体内的工具调度器。

Agent Loop 核心结构

关键设计点:
  • max_steps 硬刹车while steps < config.max_steps 确保循环不会无限执行
  • BudgetExceeded 优雅终止:token 超限时抛异常,由外层 try/except 捕获
  • Permission Gate 挂载点trigger_gate("pre_tool_use") 在工具执行前拦截危险命令

Tool Use:自动反射 + 结构化错误回传

传统做法需要开发者手工维护一份 JSON Schema 配置文件,极易与代码脱节。Harness 使用 Python 的 inspect.signature 做运行时反射,自动从函数签名生成 tool schema:
核心收益:业务源码与调用契约 100% 自动同源同步。你在 Python 里增删一个参数,给大模型的 JSON 契约瞬间自适应改变。
工具执行层的 dispatch_tool 是另一个关键设计——绝不吞报错
传统做法要么让程序崩溃(Agent 死机),要么 try...except: pass 吞掉异常(LLM 产生幻觉)。dispatch_tool 走第三条路:将错误包裹成结构化 JSON 回传给 LLM,让 LLM 自己读错误信息、修正参数、重新调用。这是 Agent 自我纠偏的核心枢纽。

机制③:Progress Tracking(progress.py

故障模式⑤(状态丢失)的解药。ProgressTracker 通过 HookManager 的三个事件点把会话过程记录到 progress.md
核心 API 是一行 tracker.register_to(agent.hooks)——零侵入接入,不需要改动 run_agent 内部任何代码。

机制④:Context Management(context.py

故障模式②(context 溢出)和③(cache miss)的解药。核心策略:不改 toolset、不改 memory、不改 system prompt(三铁律),只对 messages 做结构化压缩。
三铁律的出处是 AGENTS.md 规范——压缩时绝不能改变 agent 的能力边界(toolset)、已有知识(memory)和行为规范(system prompt)。

机制⑤:Feature List(planner.py

故障模式②(context 溢出)的源头防控。核心思想:用一个外部数据结构承载任务状态,把"全局规划的复杂性"从 LLM 的 context 里剥离出去。
三种模式对应任务生命周期的三个阶段:
  • 替换模式merge=False):任务开始时创建清单
  • 合并模式merge=True):执行过程中更新状态(pending → in_progress → completed
  • 查询模式todos=None):任务完成前检查是否全部完成
在 E2E demo 的 7 步任务中,有 5 步是 todo 操作。这不是低效,而是刻意设计:每步只做一件事的纪律,是防止 context 溢出的源头防控。

机制⑥:Verification Loop(verifier.py

故障模式④(tool 错误吞)的下游验证。核心原则:验证必须由工具完成,而不是由 LLM 完成。 LLM 的自我确认没有验证效力——它倾向于说"我检查过了",但无法真正运行自己生成的代码。
两层验证架构:
第一层(引导层):通过 system prompt 植入验证思维:
第二层(执行层):用真实工具验证——例如通过 subprocess 调用 pytest 验证生成的代码是否真的能跑通。工具返回的确定性结果(pass/fail)比 LLM 的自我确认可靠得多。
与第二章错误回传的本质区别:
机制
触发时机
验证主体
作用
结构化错误回传
工具调用本身出错时
工具执行层
确保错误不被吞掉
Verification Loop
工具调用成功后
独立验证工具
确保结果本身是正确的

机制⑦:Subagents(subagent.py

故障模式②(context 溢出)和⑧(成本失控)的解药。核心设计:子 agent 拥有完全独立的 messages 列表,父 agent 的对话历史对子 agent 不可见。
父子迭代预算不是加法,是乘法。 假设父 agent max_steps=50,每步都 spawn 一个子 agent(max_steps=50),最坏情况是 50 × 50 = 2500 步。这是 Manus 早期版本的真实教训。
三条子 agent 设计铁律:
  1. 独立迭代上限:子 agent 步数上限必须比父更小(推荐父 50 / 子 10)
  1. 结果长度上限:子任务返回内容必须截断,防止撑爆父 context
  1. 成本上限:子任务必须设置 Token Budget,达到阈值强制终止

机制⑧:Generator-Evaluator(evaluator.py

故障模式⑦(缺自动化评审)的解药。核心思想:生成和评估分离,用独立 context 的另一个 LLM 做客观审查。
为什么 LLM 自审不可靠?LLM 在生成内容时,注意力已被当前推理路径"锚定"。当被要求"检查自己的输出"时,它倾向于沿着相同的推理路径再走一遍,而不是真正以批判视角重新审视。生成者和审查者读的是同一份 messages 历史,思维起点相同,盲点也相同。
两个关键设计:
  • temperature=0.3:评审需要稳定性和一致性,低温度保证同样的候选方案每次评审得分接近
  • Evaluator 的 system prompt 完全独立:它不知道 Generator 的内部推理过程,只看最终输出
与 Verification Loop 的关系:两者可以组合使用——先用 Verification Loop 做客观验证(pytest),再用 Generator-Evaluator 做主观质量评审,构成双重质量保障。

四、三个生产级扩展机制

机制⑩:Hooks 事件总线(hooks.py

Hooks 本身不直接救任何一条故障模式,而是为 Permission Gate、Progress Tracker 和 Budget Guard 提供挂载基础设施。它是整个 Harness 的"神经系统"。
六大标准事件
HookManager 提供两类接口:
  • trigger(event):普通事件,顺序调用所有 handler,单个失败不影响其他
  • trigger_gate(event):门控事件,任一 handler 返回 (False, reason) 则立即 veto
关键安全策略:普通事件 handler 失败只记录不中断;门控事件 handler 失败视为拦截——因为允许一个"门坏了"的危险命令执行比多记录一条日志严重得多。

机制⑨:Permission Gate(permission.py

故障模式⑥(缺权限闸)的解药。挂在 pre_tool_use gate 事件上,在执行前拦截危险命令。
核心实现是一个正则黑名单,包含 14 条危险模式(如 rm -rfsudochmod 777curl | bash 等)。任何匹配的工具调用参数都会被 veto,返回 (False, reason) 阻止执行。

机制⑪:Token Budget(budget.py

故障模式⑧(成本失控)的解药。BudgetGuard 在每次 LLM 调用后累计 token 消耗,超限时抛出 BudgetExceeded 异常,由 run_agent 的 try/except 捕获后优雅终止。

五、E2E 真实数据:Harness 到底值不值?

以下是 2026-04-22 真实跑通的数据(模型:deepseek-chat,任务:分析 main.py 的重复代码并给出重构建议):
维度
Baseline(单轮调用)
Full Harness(8 机制)
倍率
步骤数
1
7
耗时
35.45 s
94.02 s
2.65×
总 tokens
1,104
15,053
13.6×
答案字符数
2,498
2,819
+13%
成本 (USD)
$0.0697
预算上限
$0.50
Permission 拦截
0
0(本次无危险命令)
已落盘(7 条记录)
13.6× tokens,2.65× 耗时。 这不是 Harness 效率低,而是它的成本结构。你用 13 倍的 tokens 换来了三个用单轮调用永远买不到的属性:
  • 可观察性progress.md 落盘了 7 条记录,每一步做了什么、调用了哪个工具、结果是什么,全程可追溯。Baseline 跑完了,你只能看到最终答案。
  • 可干预性:Permission Gate 就绪,任何危险命令都会被在执行前拦截。Baseline 里 agent 直接执行任何工具,包括 rm -rf——你没有机会干预。
  • 可控性:Token Budget 守住了整个任务,$0.0697 < $0.50 上限。如果任务出现异常循环,Budget 会触发优雅终止而不是无限烧钱。

六、三条核心结论

结论一:Harness 的 13× tokens 换的是"三性",不是低效

成本直觉建立后,你才能判断"这个任务值不值得上 Harness"——不是所有任务都需要,但凡是你需要追溯、拦截、兜底的任务,这个成本就是必要的。

结论二:Harness 与底层模型解耦

Mini Harness 基于 OpenAI Python SDK 写成,但每个机制都能在 Claude Code、Codex 里找到对应实现。如果把 core.py 的主循环换到 Anthropic SDK,只需要动 API 调用、循环结束判断、tool call 位置、结果回写格式、tool schema 字段这 5 处——Context Management、Progress Tracking、Permission Gate 等深层机制一行代码都不需要动。Harness 的架构逻辑与模型提供商是完全解耦的。

结论三:Harness 会 go stale,它是工具不是信仰

Anthropic 在 2026-03-24 的博客中坦率承认:"Every component in a harness encodes an assumption about what the model can't do on its own"。今天你为 agent 加 Permission Gate,是因为模型可能误执行危险命令;如果未来模型默认就能做到"不执行危险命令",这个组件就可以从 Harness 里移除。随着模型能力提升,Harness 的组件会慢慢过时——这不是劝退,是让你建立正确的成本直觉。

七、Mini Harness vs 生产级工具对照

机制
Mini Harness
Claude Code 生产版
OpenAI Codex 生产版
Agent Loop
while + max_steps=50
多层事件驱动
App Server JSON-RPC
Context
head(2)+tail(6)+middle summary
5 层 compaction pipeline
AGENTS.md 渐进披露
Progress
progress.md 追加写
claude-progress.txt + git
待补充
Feature List
todo_tool JSON 状态机
200+ 项结构化清单
PLANS.md 持久化
Verification
pytest subprocess
Puppeteer MCP 真机
structural test
Subagents
delegate 递归隔离
/agent + 独立 workflow
待补充
Permission
正则黑名单 14 条
27 个 hook + 规则矩阵
sandbox policy
Hooks
HookManager 6 事件
Claude Code 27 事件
middleware 3 hook
Budget
BudgetGuard + BudgetExceeded
token budget + iteration cap
per-model quota
Mini Harness 是"裸骨架"——功能极简,但结构透明;生产工具是成熟系统——功能丰富,但内部封装。学完骨架,以后读生产工具的源码时,你会认出每一块肌肉。

附录:关键术语快速检索

术语 / 机制
核心文件
关键函数 / 类
Agent Loop
core.py
run_agent, while steps < config.max_steps
Tool Use
core.py
dispatch_tool, _build_tool_schemas
Progress Tracking
progress.py
ProgressTracker.register_to
Context Management
context.py
compress_if_needed, estimate_tokens
Feature List
planner.py
todo_tool(替换/合并/查询三模式)
Verification Loop
verifier.py
verify_by_pytest
Subagents
subagent.py
delegate
Generator-Evaluator
evaluator.py
evaluate, temperature=0.3
Hooks
hooks.py
HookManager, trigger_gate
Permission Gate
permission.py
PermissionGate.check, 14 条黑名单
Token Budget
budget.py
BudgetGuard.add, BudgetExceeded

参考引用

来源
日期
URL
Anthropic · Effective Harnesses for Long-Running Agents
2025-11-26
Anthropic · Harness Design for Long-Running Apps
2026-03-24
OpenAI · Unlocking the Codex Harness
2026-02-04
Phil Schmid · The Importance of Agent Harness in 2026
2026-01-05
AGENTS.md 规范

本文基于 2026 年 4 月技术状态编写,使用 deepseek-chat 模型验证 E2E demo。依赖版本:openai==2.26.0python-dotenv==1.2.2pytest==9.0.3httpx==0.28.1
 
 

📎 参考文章

 
💡
欢迎您在底部评论区留言,一起交流~
 
上一篇
第一节 大脑:重新认识你自己
下一篇
Harness Engineering - 搭建Mini Harness
Loading...