# Harness Engineering 101：300 行代码就能跑通 Agent，真沙箱却留成了课后作业

**Summary:** Harness Engineering 101 把 Agent 的控制流摊开给人看，代价是玩具之外的那个真沙箱，被作者留成了读者作业。要让我拿它处理正经工作，我会先把工具权限钉死，再检查任务结果到底对不对。

- Canonical: https://markhuang.ai/zh/news/harness-engineering-101-sandbox-homework
- Language: zh-CN
- Author: [Mark Huang](https://markhuang.ai/about)
- Published: 2026-10-19
- Section: News
- Tags: Harness Engineering, AI Agent, Python, 沙箱隔离, 工具权限, Agent 可靠性
- Source: [Harness Engineering 101 on GitHub](https://github.com/IsuruMaduranga/harness-engineering-101)
- License: https://creativecommons.org/licenses/by-nc/4.0/

---

![一座黄铜材质的 Agent 循环教学模型，装在尚未完工的玻璃外壳里，最后一块面板还搁在工作台上](https://cdn.markhuang.ai/news/harness-engineering-101-sandbox-homework/hero.webp)

*循环已经装好了，保护它的那层外壳还没完工。*

[Harness Engineering 101](https://github.com/IsuruMaduranga/harness-engineering-101) 讲 Agent 的方式，是跟着一个小 Python 程序走：每撞一次墙，就改一次代码。作者 Isuru Wijesiri 把这本书标为 1.0 版，时间写着 2026 年 9 月，用 16 章围绕一个三百行上下的练手 harness 展开。

我最在意的一个细节藏在[结语](https://github.com/IsuruMaduranga/harness-engineering-101/blob/main/src/16-epilogue-build-your-own.md)里：接上一个真正的沙箱，是留给你自己做的作业。作者把这道权限关卡称作“草图”，还列了一串生产环境里缺的东西，重试和上下文压缩都在其中。把 Agent 跑起来只是开始，真要我放心把活交给它，中间还差着不少东西。

我会拿这本书搞清一件事：Agent 的权限到底从哪来，然后再决定围绕它搭什么。代码量小，控制流一眼就能看完。我担心的是读者从这种“小”里推出来的结论：看懂了这个循环，不等于它就该拿到一台真机器的访问权。

## 每个功能背后，都是一次失败

README 给每章定了同一个套路：先出问题，再打个最小补丁，最后交代这个补丁的代价。功能之所以出现，是因为工具返回的结果太大、任务拖得比一次同步调用还久，或者信息已经塞不进对话里。这些都是很具体的理由，说明为什么值得往里面加东西。对刚上手的人来说，这也是一个去质疑框架功能清单的切入点。

在加记忆或委派之前，我想知道它修好的到底是哪个已经出现的失败，又会带来什么新的失败。所以这本书适合那种能调模型、但说不清 Agent 为什么卡住或丢上下文的开发者。程序足够小，这些决定在代码里都能一路跟下来。

[LangChain 报告过](https://blog.langchain.com/improving-deep-agents-with-harness-engineering/)，在模型不变的前提下，把自家的编程 Agent 在 Terminal Bench 2.0 上的成绩从 52.8% 提到 66.5%。这是厂商自己 Agent 的结果，跟这个仓库没有关系。它给了我一个去研究周边软件的理由，但“我自己的 harness 该怎么搭”，它没回答。

## 先读懂那道门，再决定信不信这个壳

我会把[玩具实现里的 `gate` 函数](https://github.com/IsuruMaduranga/harness-engineering-101/blob/main/src/harness/harness.py)和正文对着看。它会检查 `write_file` 和 `edit_file` 的受保护路径字符串，还要求先读过才能改。shell 命令走的是另一条分支：命令里命中某些子串，就会触发人工审批。再往下分发时，前台命令用 `subprocess.run`，还带着 `shell=True`。

顺着这段控制流看，就明白那个沙箱练习为什么重要。挂在文件编辑工具上的路径检查，管不到通过 shell 完成的文件改动。在说某项权限“已经强制执行”之前，我会先把所有能通向同一结果的路径都追一遍。识别命令里的某些字符串，和限制一个进程能碰到什么，是两套不同的控制。

作者对这条边界说得很清楚。[第 13 章](https://github.com/IsuruMaduranga/harness-engineering-101/blob/main/src/13-reflexes-and-guardrails.md)讲的是分层防御，包括限制工具、确定性检查、人工确认和沙箱。更强的那道边界，结语留给了读者自己去实现。这种坦率我挺喜欢，也会把这道练习当成正经干活之前必须过的一关。

> **Info:**
>
> 在加下一个 Agent 功能之前，我会先定义清楚：这个进程能读什么、能改什么、能连到哪。然后逐一验证这些限制在每个暴露出去的工具上都成立。

## 关得住，不等于做对了

一个被关得很好的 Agent，照样可能把任务做错。在 [Birgitta Böckeler 对 harness engineering 的分析](https://martinfowler.com/articles/exploring-gen-ai/harness-engineering.html)里，行动前的引导和行动后的反馈管的是两件不同的事。她还指出一个更硬的限制：当人自己都没说清想要什么行为时，检查也没法可靠地判断功能是否正确。

这也是我最认同的一条反驳：拿一个小循环去解释整个工程工作，是不够的。循环解释的是 Agent 怎么一直动下去；结果有没有解决用户的问题，还得有人来判断。沙箱限制的是后果，验收检查问的是这活有没有用。这两件事我都得提前算进成本。

[Hacker News 上关于这本书的讨论](https://news.ycombinator.com/item?id=50151390)里，有人夸这份材料好用，也有人不买它那套生物学比喻。当比喻开始代替解释，我也有同样的顾虑。回到这本书，我会去看代码：能不能找到那个拒绝执行的分支，并跟下去看结果怎么处理？能不能说清这次运行为什么停下？想清楚这些，比喻就没那么重要了。

## 我会先做的那道练习

我会从一个用完就扔的项目、一个不大不小的任务开始。跑之前先定好预期输出，再定一个这个进程绝对做不了的动作。然后给这个“拒绝”检查配一个必须成功的正常任务。要是什么都拦，我就看不出这条边界到底能不能用。

调试的时候，我会照[第 12 章那套抓请求的做法](https://github.com/IsuruMaduranga/harness-engineering-101/blob/main/src/12-debugging-the-array.md)，用合成输入去看真正送到模型面前的到底是什么。之后，等某次失败的运行给了我理由，再往上加功能。这跟我之前的观点是一致的：[harness 的每个组件都该自己挣来它的位置](https://markhuang.ai/news/stronger-coding-agents-fewer-tools)。

我推荐 Harness Engineering 101，因为它给出来的代码能从一次模型请求一路跟到一个动作。而那个沙箱练习，就是我会停下阅读、开始动手的地方。在把这个程序交给我在乎的任何东西之前，我要能说清它不能做哪些动作，以及是什么在守住这条线。
