上一集把判断"交出去",这一集把活"派出去"。给你的 agent 装上委派能力:把一块活丢给一个独立的子 agent 去干,它在自己的进程里跑、干完只把结论交回来。重点不在"能派",在"派了怎么还安全"——答案是能力围栏:不靠每一步拦着问,靠事前只给它够用的工具。你会亲眼看到同一句"删掉这个文件",派侦察兵它做不到、派执行工它真删了。这一集不写代码,只写两个配置文件。
上一集我们把判断交出去(handoff);这一集把活派出去(subagent)。这俩是两种不同的委托——交出去是控制权转移,派出去是你始终主导、分身干完把结论交回来。忘了的话回看课②那张对比图。
这一集给你的 agent 装上委派能力。但重点不在”能派”,在一个更要紧的问题上:
让一个 agent 自主替你跑,怎么还不让它瞎搞?
答案就是这一集的主心骨——能力围栏(capability fence):不靠每一步拦着问,靠事前只给它够用的工具。
而且好消息:这一集不写一行代码,只写两个配置文件。 pi 官方自带一个 subagent 扩展,我们原样用,一个字都不改 pi。
一、派个分身出去:它在自己的进程里跑
pi 官方的 subagent 扩展,让主 agent 把一块活派给一个独立的子 agent——独立进程、独立上下文,干完只把结论交回来。
我派一个叫 scout 的分身,去读 pi 自己那份 792 行的 agent-loop.ts、总结它的结构:

它干得漂亮。但最值得看的是那行账:↑11k ↓1.4k——
scout 往上吃了 11k token(那 792 行文件,是在它自己进程里读的),往下只吐回 1.4k(一段摘要)。那 11k 的原文,没进你的主会话。
而且这不是”涨得少”——分身交回来的结果里根本没带 token 账,所以它花的那 11k,连你主会话的用量统计都进不去。隔离是结构性的,不是”碰巧省”。
这就是 subagent 最实在的价值:不是”更聪明”,是”更省 context”。 读一堆文件、翻一堆日志这种又脏又占地方的活,丢给分身在它自己的上下文里干完,你的主线只拿回一小段结论——主会话不被中间过程撑爆。
二、围栏是真的:scout 删不掉文件
现在见真章。我派同一个 scout,去删一个文件(先 touch /tmp/试验品.txt 造个试验品,别拿真文件练手):

我只有只读工具(read/grep/find/ls),没有删除文件的能力,做不到。
这一句,是全课最该说透的地方:
它不是”被拦下来了”,是手里压根没有能删文件的刀。
scout的围栏是read, grep, find, ls——没有bash、没有edit、没有write。 事前给得少,事中就不需要拦。
这就是”能力围栏”和”人来把关(HITL)“的根本差别:
| 人来把关(HITL) | 能力围栏 | |
|---|---|---|
| 时机 | 事中,每个危险动作停下问你 | 事前,压根不给它那把刀 |
| 靠什么挡住 | 你在旁边点”拒绝” | 它手里没有那个工具 |
| 适合 | 你盯着的单会话 | 自主委派、无人值守 |
三、围栏不是”一律只读”,是”按任务给刀”
要是分身只能读,那写代码的活谁干?围栏的正确含义是最小权限——给这个任务够用的工具,不多给一件。 读的活给读的刀,写的活就得给写的刀。
我另建了一个叫 worker 的分身,它的档案故意不写 tools 字段。同一句”删掉 /tmp/试验品.txt”,这回派 worker:

真删了。 同一个扩展、同一句话,只是换了个档案——
证明围栏是”按任务给刀”,不是”subagent 天生只读”。
worker 那个”不写 tools”是刻意的:没声明 tools,扩展就不传 --tools,子进程拿到默认全套(read, bash, edit, write)。写代码的活,本来就该给 write。 围栏的松紧,跟着任务走。
四、最要紧的一层:谁定围栏,比围栏能锁多细更根本
到这儿你可能想:那让模型委派时自己挑工具,不就行了?
恰恰不行。 如果”给哪些工具”是模型自己能填的参数,那不叫围栏,叫自助餐——它想删文件,自己给自己配把刀就是了。
官方的做法很讲究:围栏写在人维护的 agent 档案里,模型只能选”用哪个 agent”,改不了围栏本身。
# ~/.pi/agent/agents/scout.md —— 这是人写的,模型碰不到
---
name: scout
description: 只读侦察兵。读文件、搜代码、列目录,产出摘要。不做任何修改。
tools: read, grep, find, ls ← 围栏在这儿,人定的
---
你是一个只读侦察兵……
模型委派时,只能说”派 scout”或”派 worker”——它选笼子,你造笼子。 这就是这一课最该带走的一句:
围栏能锁多细,不是终点。终点是——这把锁,谁能改。
(诚实一句:围栏管到”工具”这一层。再往下的硬隔离——把整个文件系统、网络都关起来——是沙箱那一层的事,那是另一集。)
动手做:就两个配置文件
这一集的”改造”,不是改代码,是写两个 agent 档案给你的分身划围栏:
📦 想自己跑一遍? 两个档案(
scout.md只读 /worker.md可写)+ 完整照跑步骤,都在配套练习仓库: github.com/pkm365/lucid-learn-agent 官方subagent原样-e加载,不用装依赖、不改一行 pi。
⚠️ 一个一定会踩的坑:agent 档案的 frontmatter 缺
name或description会被静默跳过——不报错、不警告,只表现为”没有这个 agent”。问一句”有哪些可用的 agent?”要是列不全,先回去检查这两个字段。
三段教学坐标(不用读那 1141 行,命根子就三处;基线 pi 936aff009,认符号名别认行号):
| 讲什么 | 位置 | 重点 |
|---|---|---|
| 注册成工具 | pi.registerTool({ name: "subagent" … }) | tools 不在参数里——模型只能选 agent,改不了围栏 |
| spawn 时围栏怎么焊上 | args 组装 → getPiInvocation → spawn | --tools 的值来自 agent 档案的 frontmatter,不来自模型 |
| 结果怎么回流 | getFinalOutput → 返回 { content, details } | 子进程吐事件流 → 抽最终文本 → 变一条 toolResult 进父账本 |
带走这一句
给 agent 装”委派”很容易,难的是让它自主又不失控。答案是能力围栏:把活派给一个独立的子 agent,而它能干什么,由你事前在 agent 档案里划定——只读的侦察兵删不掉文件,不是被拦住,是手里没那把刀;要写的活,就派给带写权限的执行工。围栏不是”一律只读”,是”按任务给刀”;而最要紧的不是围栏锁多细,是围栏由谁定、谁能改。分身还顺手帮你省 context——脏活在它自己进程里干完,主线只拿回一段结论。
下一集
围栏管到”工具”这一层——它能挡住”没给的工具”,挡不住更底层的东西(比如一个有写权限的分身,在你没预期的目录里写)。要把整个环境都关进笼子——文件系统只读、网络切断——那是沙箱那一层。下一集我们就看 pi 怎么把危险动作关进一个 OS 级的笼子里跑。