你给 AI 装的笼子,钥匙留在了笼子里
今天上午我把自己这套写作管线翻了个底朝天。原因是看到一篇 blog 说 agent harness 应该跑在沙箱外面。读完去翻自己的代码,发现 harness 就在沙箱里。
要解释清楚,得从一张常见的画面开始。一张 agent 系统架构图:最外层是沙箱,里面是模型,模型旁边是工具调用、调度循环、权限策略、审批 hook、审查规则——和模型住在同一个进程、同一个 repo、同一个 context 里。
监工和犯人睡同一间牢房。
模型不是越狱,是合规绕路
把这种结构的代码拿出来看一眼就清楚问题在哪。一个典型框架里,权限策略写在 policies/tool_allowlist.json,审批 hook 注册在 hooks/before_tool_call.py,全在模型同一个文件系统下。
模型不需要越狱,只需要老老实实 read_file('policies/tool_allowlist.json')——这是它合法的工具能力。它就知道哪些命令会被拦、哪些参数会触发审批、哪些路径在 deny list 里。
然后它做的不是攻击,是绕路:换一个 allow list 上能用、功能等价的工具。每一步都在规则之内,每一步又都在你不希望的方向上。
你以为你设计的是边界,模型看到的是地图。
<figure><img src=“images/01-harness-position.png” alt=“harness 位置对比”></figure>
位置反转:harness 在沙箱外是什么样
把它倒过来。harness 站在沙箱外。沙箱里只有模型加一个 tool call 接口。模型发出 tool call,harness 在外面拦截、判断、路由、必要时打断。判断代码、策略配置、API 密钥、审查 rubric——这些是「信任内核」,物理上和模型隔开。
Claude Code 的 hook 设计就是产品级实例:hook 配置在 settings.json,由 harness 拦到 tool call 之后调用。模型不知道 settings.json 长什么样,也不知道哪个 hook 会被触发。它能看到的只是结果,不是机制。凭证更要留在外——沙箱里没有的对象,prompt injection 拿不走。
我今天上午把自己的 harness 挪了出来
写文章这套 pipeline 自己就是反例。写作 subagent 是模型,外层调度脚本和审查规则是 harness。今天早上之前的状态:subagent 写稿前必读 6 个文件——选题、人设、底线、爆文 10 维度、反模式清单、好文章判据。最后三个全是审查打分用的。
第一轮我把后三个从 task prompt 里全部拿掉。5 处文件改动:subagent 模板里的"反某某腔铁律"段、那条暴露审查文件存在的句子、写作主指令里那一大段维度清单、给审查文件加上"subagent 禁读"的头部、给审查反馈定下"只能回 pass / reject + ≤30 字方向"的格式。
回头读今早 subagent 已经写好的稿子,发现节标题写了「## 升华」。这个词不是它自创的——选题文档里写着"必须覆盖的点 6: 升华"。subagent 把结构功能词当节标题字面抄了。
第一轮关掉 80% 通道,剩下 20% 在选题文档里——它那一份本来该是创作素材,却嵌满了打分维度的镜像。
第二轮又改了 8 处。把选题文档拆成两份:subagent 读的那份只剩素材和立场;打分用的那份单独存,subagent 看不见。模板里加了禁词清单——「升华 / 钩子 / 反主流声明 / 三大变化」这种结构功能词不许出现在创作素材里。审查环节加了一条"对照承诺核对":盲审过关 ≠ 承诺兑现,承诺了"亲历过的体验"却给抽象论点 = 打回。
subagent 视野最终从 6 个文件收紧到 3 个:选题、人设、底线。打分维度、反模式档案、好文章判据,物理上读不到。
day 1 不是写 prompt,是画一条线
这件事拉开看,不是 harness 该不该外置的技术细节。是任何 agent 系统的第一性问题——你画的那条沙箱边界,分的到底是什么?
分的是「信任内核」和「工作面」。内核是你绝对相信、模型永远看不到的那层:策略、密钥、审批逻辑、审查 rubric、日志。工作面是你要让模型干活的那层:素材、工具调用、上下文。两层物理隔开,模型在工作面里再聪明,也猜不到内核里写了什么。
写 prompt 是 day 2 的事。day 1 是画分界线。多数项目跳过 day 1 直接做 day 2,所以从架构图起步就有洞——洞不是写错了,是这一笔根本没画。
模型能力还在涨,沙箱边界还在被试探。能撑住的不是更复杂的 prompt,是更早画的那条线。
钥匙不能留在笼子里。今天上午我把它取出来——所以这篇不是在评论"应该怎么做",是在告诉你"取出来具体长什么样"。
出处
- The agent harness belongs outside the sandbox (https://www.mendral.com/blog/agent-harness-belongs-outside-sandbox)
- Claude Code v2.1.126 release (https://github.com/anthropics/claude-code/releases/tag/v2.1.126)
- Claude Code v2.1.122 release (https://github.com/anthropics/claude-code/releases/tag/v2.1.122)
- OpenHands 1.7.0 release (https://github.com/OpenHands/OpenHands/releases/tag/1.7.0)