知识点思维导图
17 个知识节点
Harness Engineering(03) - 构建最小可运行 Harness
读完后,你应能完成以下任务:
- 绘制“Harness Engineering(03) - 构建最小可运行 Harness / 我们要造什么”的关键对象与数据流,解释“" 它会自己列目录、挑文件、读内容、给你答案——这就是个超迷你版的 Claude Code。”,并用源码位置、日志或 Trace 标注证据。
- 为“Harness Engineering(03) - 构建最小可运行 Harness / 动手前:装好家伙”设计正常与异常输入,验证“没有 Key 也没关系,直接跳到 demo 跑 mock 版,照样能看到完整效果。”,输出首个偏差位置与回归测试结果。
- 实现“Harness Engineering(03) - 构建最小可运行 Harness / 一步步搭(每块都解释为什么)”的最小代码或配置,检验“所以要给每个工具写一份"说明书"(schema),告诉模型:这个工具叫什么、干嘛用的、要传什么参数。”,输出命令、结果与 Diff,并说明不适用边界。
前两章讲完了"是什么"和"怎么转",现在该动手了。 这一章的目标只有一个:让你亲手敲出一个真能跑、能操作真实文件的 Agent,并获得"我造出来了"的成就感。 核心代码不到 50 行。
一、我们要造什么
一个能在终端里对话的 mini Agent,它有两个工具:
list_files(dir):列出某个目录下的文件read_file(path):读取某个文件的内容
然后你就能问它:"这个项目里有哪些 Python 文件?挑一个告诉我它在干嘛。" 它会自己列目录、挑文件、读内容、给你答案——这就是个超迷你版的 Claude Code。
本章正文用真实 Anthropic SDK 讲解(这是真本事);配套 demo 同时提供 mock 离线版,没 API Key 也能跑。
二、动手前:装好家伙
pip install anthropic
export ANTHROPIC_API_KEY="你的key" # Windows 用 set
没有 Key 也没关系,直接跳到 demo 跑 mock 版,照样能看到完整效果。
三、一步步搭(每块都解释为什么)
3.1 第 1 块:定义工具(Agent 的"手")
先写两个普普通通的 Python 函数。注意——它们就是普通函数,没有任何"AI 魔法":
3.2 第 2 块:把工具"描述"给模型看
模型不会读你的 Python 代码,它只能读文字描述。所以要给每个工具写一份"说明书"(schema),告诉模型:这个工具叫什么、干嘛用的、要传什么参数。
💡 这份 schema 是模型选工具的唯一依据。description 写得含糊,模型就会选错工具——这点第 04 章会专门展开。
3.3 第 3 块:核心循环(把第 02 章的骨架变成真代码)
3.4 第 4 块:加个对话入口
就这些。 把这四块拼起来,一个真能干活的 Agent 就诞生了。核心循环部分(第 3 块)满打满算不到 30 行。
四、它跑起来是什么样
🤖 Mini Agent 已启动(输入 quit 退出)
👤 你:这个目录里有哪些文件?挑个 .py 告诉我它在干嘛。
[模型调用 list_files(directory=".")]
[模型调用 read_file(path="agent.py")]
🤖 这个目录里有 agent.py、mock_llm.py、README.md。
其中 agent.py 是核心,它定义了两个工具并实现了一个带轮次上限的 Agent 循环……
你让它做的只是一句话,它自己列了目录、挑了文件、读了内容、给了答案——转了好几圈循环,全程没有一步是你写死的。回头看第 02 章那张循环图,是不是一下就对上了?
五、常见错误(新手 100% 会踩)
❌ 错误 1:忘了把模型的回复 append 回 messages。
很多人执行完工具就直接喂结果,漏了先把 assistant 的回复(含 tool_use 请求)加进去。结果 API 报错"tool_result 找不到对应的 tool_use"。顺序必须是:先 append 模型回复,再 append 工具结果。
❌ 错误 2:tool_use_id 没对上。
工具结果必须带上对应请求的 id(tool_use_id)。模型一圈可能调多个工具,靠这个 id 才能把"哪个结果对应哪个请求"对上号。复制粘贴时最容易把这个搞丢。
❌ 错误 3:工具函数抛异常,整个程序崩了。
比如模型让你 read_file("不存在.txt"),函数直接抛 FileNotFoundError,程序当场退出。正确做法是把异常捕获、当成普通结果喂回去("读取失败:文件不存在"),让模型自己换条路。demo 里演示了这种写法。
❌ 错误 4:stop_reason 判断写错。
得用 resp.stop_reason == "tool_use" 来判断"模型还想调工具"。判断条件写反,要么死循环,要么工具永远不执行。
六、最佳实践
✅ 从最小开始,能跑了再加。 先让两个工具跑通,再考虑加 write_file、run_command……一上来堆十个工具,出了 bug 都不知道在哪。
✅ 工具函数里做好异常处理,把错误转成给模型看的文字,而不是让程序崩溃。这是 demo 到产品的第一道分水岭。
✅ 打印工具调用过程(哪怕只是简单 print)。看不见 Agent 在调什么工具,调试就是抓瞎。
✅ 给工具描述(description)写清楚"什么时候该用我",而不只是"我是什么"。模型选不选你这个工具,全看这句话。
七、动手实践:最小 Harness:50 行跑通第一个 Agent
它有两个工具:list_files(列目录)和 read_file(读文件)。你用一句话提需求,它会自己列目录、挑文件、读内容、给答案。
7.1 两个版本
| 文件 | 说明 | 是否需要 API Key |
|---|---|---|
agent_mock.py |
离线 mock 版,逻辑结构和真实版完全一致 | ❌ 不需要,直接跑 |
agent.py |
真实 Anthropic SDK 版,真·调用大模型 | ✅ 需要 ANTHROPIC_API_KEY |
7.2 怎么跑
离线版(推荐先跑这个):
python agent_mock.py
会自动用一个内置任务演示完整流程,打印每次工具调用。
真实版:
pip install anthropic
export ANTHROPIC_API_KEY="你的key"
python agent.py
# 然后输入:这个目录里有哪些文件?挑个 .py 告诉我它在干嘛。
7.3 看点
- 四块结构:工具函数 / 工具 schema / 核心循环 / 对话入口——对照第 03 章正文逐块看。
- 异常处理:故意让工具捕获异常并把错误当结果喂回(见
read_file),试着读一个不存在的文件,看 Agent 不崩还能自己应对。 - 对比两个文件:
agent.py和agent_mock.py的循环骨架几乎一模一样——这说明 harness 逻辑和具体模型是解耦的,换模型不用改循环。
八、总结
- 我们要造什么:" 它会自己列目录、挑文件、读内容、给你答案——这就是个超迷你版的 Claude Code。
- 动手前:装好家伙:没有 Key 也没关系,直接跳到 demo 跑 mock 版,照样能看到完整效果。
- 一步步搭(每块都解释为什么):注意——它们就是普通函数,没有任何"AI 魔法":
- 它跑起来是什么样:你让它做的只是一句话,它自己列了目录、挑了文件、读了内容、给了答案——转了好几圈循环,全程没有一步是你写死的。
- 常见错误(新手 100% 会踩):顺序必须是:先 append 模型回复,再 append 工具结果。
- 最佳实践:✅ 工具函数里做好异常处理,把错误转成给模型看的文字,而不是让程序崩溃。
学完自测
选择所有正确答案;提交后逐项核对判断依据。