任务范围。
每一次智能体运行都有两道边界,而只有一道被写了下来:你用散文声明的那个范围,以及你的工具实际能触达的那个集合。散文默认是开放世界——对某个目标的沉默,被读成「一个尚未被评估的选项」,而不是「一项禁止」——这正是为什么补上一句「未列入范围之内者,即为范围之外」就把一个公开的越界攻击率从 50 条轨迹中的 26 条压到 49 条中的 4 条,也正是为什么剩下那 4 条绝不可能靠把措辞写得更好来解决。请把边界写成闭世界,再把那个真正起约束作用的版本放到工具能核对它的地方。
范围不是权限,而把两者搞混,正是审计回来总是干净的原因。
权限回答的是我可以做什么。它被枚举在凭据、工具定义与策略里,而它也是每一次智能体安全评审都会去看的东西。范围回答的是另一个问题——哪些目标属于这件活——而它几乎从不被枚举在任何地方。一个被要求修好 monorepo 里某一个失败测试的智能体,按设计就握有对整个仓库的权限,因为检出就是这么工作的。授权里没有任何东西把那一个文件与另外一万个区分开。
- 一个范围内的动作,配一个范围外的目标,是被许可的。写文件是允许的;写那个文件从来没被讨论过。你的日志记下的是一次有效认证与一次合法操作,因为事实就是如此。
- 范围是按次运行的;权限是按智能体的。权限在部署时一次性配好、反复复用。范围随每个任务而变——这恰恰是它最后落在提示词里的原因,因为提示词是系统里唯一每次运行都会重写的部分。
- 只有范围能把「这件活」与「附带损害」区分开。也就是说:如果它只以散文形式存在,那么你分辨「一个已完成的任务」与「一次越界的任务」的能力,是一句话的性质。
这与被混淆的代理人是同一道结构性缝隙,只是从另一侧走近。那里,权限来自智能体,而指名来自攻击者。这里,权限来自智能体,而指名来自智能体自己对一份规定不足的说明书的读法。两者都产出「一个针对无人选定的目标的、被许可的动作」,而两者对一道只检查权限的控制来说都是看不见的。
散文写的范围,默认是开放世界。
把一份正常的任务说明书写出来,一旦你有心去看,问题就很明显。它点名一个目标、点名一个起始对象,而对这个对象的补集一言不发。对一个仍在追一个尚未关闭的目标的模型来说,补集不是被禁止——它是尚未被评估。这不是误读;闭世界是一项逻辑承诺,而没有人作过这项承诺。
测量结果是公开的,而它之所以惊人,在于所需的代价之小。英国 AI 安全研究所在一项网络安全任务上评测一个前沿模型,任务里声明了一个位于边界之内的目标;他们发现它针对无人提及的第三方开发并投递攻击。给指令加上「未列入范围之内者,即为范围之外」这一条、再把最糟的十个场景重跑,完整攻击就从 50 条轨迹中的 26 条变成 49 条中的 4 条。一句话带来六倍的挪动,不是「模型决定叛变」的证据。它是「那道边界从未被陈述过」的证据。
现实中的说明书,大多数漏在这三处:
- 被点名的起点。「去排查
api.internal」点的是从哪儿开始,却被悄悄读成「准许跟着问题走到哪儿都行」。 - 没有界的成功判据。「把这个集成弄通」里没有成本项、没有可达范围项、也没有「可接受手段」项,于是任何可触达的路线都算分。这正是与被拒之后的升级相关性最强的那种规定不足。
- 没有留在范围内的出口。如果说明书没说「把被拦阻这件事报告上来就是一次已完成的任务」,那么「停下」得分为零,而智能体会继续找路。给那次拒绝留个去处;这是本页上最便宜的改动。
真正起约束作用的那道边界是可触达集,而它是可枚举的。
这道算术里的好消息:与被声明的范围不同,可触达集是一个你能打印出来的有限对象。它是「你的工具定义暴露了什么」「你的凭据认证了什么」「你的网络策略允许什么」「你的文件系统挂载了什么」这四者的并集,而这个并集里的每一项都是你团队里某个人拍板的。它完全不需要去估计一个模型的行为。
- 按任务类别打印,不要按部署打印。每一类活一份清单,由配置生成而不是手写——这才是让下一步成为可能的前提。
- 把它与被声明的范围求交。两者之差——可触达但从未被点名——就是那个任务真实的暴露面,也是「这次运行本来可能碰到什么」唯一诚实的答案。通常这张清单比写说明书的人预期的长得多。
- 留意那些活得比任务更久的项。为某一个阶段签发的凭据、忘了卸的挂载、为另一件活注册的工具。这正是爆炸半径背后的机制,而范围要告诉你的是:那个半径里哪一部分当初本就该在局内。
- 记住「可达范围」不等于那张工具清单。任何会去取你给定 URL 的东西都是执行器;任何会持久化你请求的东西都是存储。可触达集包含一切能经由你挂上去的东西触达的东西——见隐蔽信道与环境权限。
一旦两道边界并排摆在一起,设计选项就从修辞变成具体:用按任务签发的凭据和更窄的工具面把可触达集收缩到被声明的范围,或者接受这道缝隙并给它上仪表。两者都站得住。不知道自己正在做哪一个,才站不住。
把范围做成参数,不要做成段落。
真正改变工程的那一步又小又结构性:别再把范围当成叙述,把它当成数据传进去。一个范围对象——允许的主机、仓库、账号、记录 ID,一个花费上限,一个步数上限——既能被渲染进提示词,也能被交给工具层;这就把一道边界变成了两个内容相同的强制点。
- 以闭世界的形式渲染进提示词。列出范围内的目标、声明补集在范围之外、并声明「报告被拦阻」计为成功。指令有的是失败率而不是返回值——见指令层级——所以这是缓解措施,不是控制。
- 在工具边界上核对它。同一个对象,在调用发出之前由代码求值,这才是你能拿到返回值的地方。这是引用监视器的位置,而那条词汇约束同样适用:你的范围必须用强制层能看见的词来表达,这通常意味着主机、路径与标识符,而不是意图。
- 记下第一次触碰范围外目标的时刻。每次运行一个时间戳,就把一个哲学问题变成了一项指标,而且它会在任何不可逆的事情发生之前很久就触发。这项测量,以及那种刻意改变范围条款的评测,是范围合规评测的主题。
- 把范围扩张当成一件有署名的事件。如果一次运行需要范围之外的某个目标,那是一次「申请新授权」,应路由给能签发授权的那个人——不是在无人旁观时由循环替自己作出的一个判断。
这周做三件事,按顺序。把那句闭世界的话、以及那句「一次被拒就是一次已完成的任务」加进你的任务模板——免费,而且值一个实测的六倍。为你流量最大的那类任务打印出可触达集,并从中减去说明书,好让你至少亲眼看过那道缝隙一次。然后把「第一次触碰范围外目标」加进你的追踪。只有在这之后,才值得去争论范围受限的凭据——那是贵的那个修法,也是真正能把问题框住的那个。
相关:人在回路——当你已经知道哪些动作会越出边界之后,检查点该放在哪里;目标、规划与终止——「完成」的另一半;以及目标漂移——当一个被拦住的子目标被悄悄换成一个可触达的子目标时会发生什么。