跳转至

工具、权限与执行边界:模型提出动作之后发生什么

上一篇:一次任务怎样形成 Agent Loop · 返回学习入口 · 下一篇:Session、Context、Memory 与恢复

工具可见、策略、批准与隔离的分层

工具让模型能读取和改变外部世界,也因此把模型不确定的输出接上了真实副作用。读源码时,你得分开查四件事:请求里有没有工具,策略放不放行,用户批不批准,操作系统最后有没有执行成功。它们分属不同层,不能压成一个布尔值,各层的失败也不能统统算成「执行失败」。

同一个动作经过五道边界

回到运费案例,这次模型想要跑测试。

{
  "name": "run_command",
  "arguments": {
    "command": "npm test -- tests/shipping.test.ts"
  }
}

命令真正跑起来以前,这个请求至少要过五道关。

  1. 工具可见性:模型输入中是否声明了 run_command
  2. 协议校验:工具名和参数是否符合 Schema;
  3. 产品策略:当前模式和规则是否允许运行该命令;
  4. 用户确认:风险达到阈值时是否获得即时授权;
  5. 执行环境:宿主、Sandbox 或远程运行器是否真的能执行。

前四道关只在审查请求有没有资格进入执行环境,第五步才会真正启动进程,产生副作用。

工具可见不等于可以自动执行

工具定义通常会告诉模型,这个工具叫什么、用来做什么,参数又该怎么填。

{
  "name": "run_command",
  "description": "在当前工作区运行命令并返回退出码和输出",
  "input_schema": {
    "type": "object",
    "properties": {
      "command": {"type": "string"}
    },
    "required": ["command"]
  }
}

把工具告诉模型,只是允许模型照这套协议生成请求。请求能不能自动执行,还要继续查权限模式、命令内容、路径范围、网络需求和用户选择。看得见工具,不等于已经拿到权限。

反过来,工具没写进模型输入,模型即使猜到系统支持终端,也没法按约定协议发出请求。有些 Agent Harness(智能体框架)会根据当前模式筛选工具,另一些会始终把工具告诉模型,等请求出现后再按策略拒绝。下文把 Agent Harness 简称为 Harness。两种写法会用不同方式影响模型行为和 Token 用量,你得分开追。

Schema 校验保护协议,不保护业务安全

Schema 能拦下缺少 command、类型错误或带有未知字段的请求,却判断不了命令会不会带来危险。

npm test -- tests/shipping.test.ts    结构合法,通常低风险
删除整个工作区                         结构同样可能合法,风险完全不同

参数合法,只说明 Harness 看得懂这个请求,并没有说它应当获准,因此参数校验和权限策略必须分开判断。合法不等于安全。

请求进入执行环境前,Harness 还可能给它补上工作目录、超时、环境变量和输出上限。所以正文要讲清原始参数经过了哪些改写,最后又变成什么。否则审计者只能看见模型最初吐出的文本。

产品策略怎样作决定

权限策略作决定时,可能会读下面这些信息。

  • 工具名称;
  • 命令和参数;
  • 当前工作区;
  • Session 模式;
  • 用户或组织规则;
  • 请求来源;
  • 是否已有同范围授权;
  • 动作是否可逆。

如果策略只返回 truefalse,你就不知道它为什么放行或拒绝。返回值还得带上能说清原因的理由。

{
  "decision": "ask",
  "reason": "命令会启动本地进程",
  "scope": "本次调用",
  "final_arguments": {
    "command": "npm test -- tests/shipping.test.ts",
    "timeout_ms": 120000
  }
}

不同项目会用 allow、deny、ask、always allow、workspace scope 或模式枚举来表达结果,名字像,语义却不一定一样。真要比较时,你得追到每个选项实际排在什么优先级,授权又会存多久、管多大范围。

用户确认是策略的一部分,不是 Sandbox

用户点下「允许」,只是表示他当下同意这个请求。这一点击扩大不了操作系统权限,也证明不了命令本身安全。确认界面可能跑在 CLI、IDE(集成开发环境)、桌面端或远程客户端,这些界面未必都能用同一种方式向用户询问。批准穿不过系统边界。

无头模式如果没有确认通道,Harness 就得明确选一条路:直接拒绝,使用事先配好的策略,或把请求交给外部审批者。如果它不出声就自动放行,安全边界就已经变了,文章必须把这个选择讲出来。

保存确认结果时,要同时绑定调用 ID 和授权范围。如果只留一句宽泛的「用户曾经允许 run_command」,后面一条完全不同的命令就可能错用这份旧授权。

Sandbox 限制已经获准的动作

Sandbox 管的是动作真正执行时,进程究竟能碰到什么。

  • 哪些目录可读写;
  • 是否能够访问网络;
  • 能否看到宿主凭据;
  • CPU、内存、磁盘和时间限制;
  • 子进程和系统调用范围;
  • 执行完成后是否保留工作区。

有的项目会很细致地询问权限,却默认让命令在宿主进程里跑。另一个项目可能把所有命令都放到远程隔离环境,产品策略却放得很宽。两种设计在防不同的风险,不能拿一把尺子量。

在运费案例里,测试命令就算获准,Environment(运行环境)仍可能返回下面的结果。

{
  "status": "failed",
  "exit_code": 127,
  "stderr": "npm: command not found",
  "executed": true
}

这里失败的是执行,权限并没有拒绝。模型只有看到准确错误,才能换成仓库支持的测试命令,或者如实告诉用户:环境有问题。

工具结果怎样安全地回到模型

工具吐出的内容可能很长,也可能夹着二进制内容或敏感数据。Harness 把结果交回模型前,通常要做下面这些处理。

  • 保存退出码和错误类型;
  • 截断过长输出并提供完整结果位置;
  • 标记 stdout 与 stderr;
  • 过滤不应进入模型的敏感字段;
  • 保留原调用 ID;
  • 说明动作是否实际执行;
  • 把结果转换成 Provider 接受的消息格式。

只回一句「工具失败」,模型就没有线索去修正。可要是把几万行日志全部塞回上下文,Token 预算又会很快被吃光。信息太少和太多都要付出代价。Harness 得决定保留什么、截掉什么,才能让模型有足够信息继续工作,又不把上下文挤满。

四条失败路径

路径 executed 应记录什么 模型下一轮可以做什么
未知工具 false 工具名和可用工具提示 改用现有工具
参数不合法 false Schema 错误和字段位置 修正参数
策略或用户拒绝 false 决定来源、理由和范围 选择低风险替代方案
环境执行失败 true 或状态未知 退出码、错误、部分输出 修正命令或报告阻塞

如果这四条路都被压成同一个 error,恢复逻辑、审计者和 Eval(评测)就都判断不了副作用究竟发生过没有。

恢复时最危险的情况

工具已经开始执行,进程却突然崩了,Session 里就可能只有「开始」事件,没有与它配对的「结束」事件。这时别自动假定工具没执行过。写文件、发消息、支付和部署都会留下副作用,盲目重跑很可能把同一件事做两遍。

想让恢复更安全,记录里至少要留下这些信息。

  • 稳定调用 ID;
  • 审批后冻结参数;
  • 开始执行时间;
  • 执行环境标识;
  • 完成、失败、取消或未知状态;
  • 可用于查询或补偿的外部操作 ID。

这些记录齐了,恢复逻辑才能看工具的性质,决定去查状态、做补偿、重新执行,或者把无法自动确认的情况交给人来判断。

在真实源码中怎么找

读真实源码时,不要只搜 permission。找到工具请求的数据类型,再沿着它一路追下去。

  1. 工具定义在哪里进入模型请求;
  2. 模型响应怎样解析成内部 ToolCall;
  3. 工具注册表怎样从名称找到实现;
  4. 参数在何处校验或改写;
  5. 策略与用户确认的调用顺序;
  6. 执行器使用宿主、Sandbox 还是远程环境;
  7. 结果怎样转换并回到消息流;
  8. 拒绝、取消、超时和未知状态有哪些测试。

读 Claude 课程时,还要额外核对证据到哪里为止。公开 SDK 可以让我们看到回调和控制协议,但它证明不了 Claude Code 内部所有策略和执行细节都已经公开。

回到运费案例

读源码、改比较符和跑测试,可能各自落在不同的风险级别。一套合理流程可以自动放行工作区内的读取,动手编辑前先把差异给用户看,遇到命令再按策略判断要不要询问。真正执行时,范围始终要卡在工作区内。

「所有工具都获准」证明不了任务做对了。真正的证据是:危险请求没有越界,必要动作确实执行了,覆盖边界值的目标测试也最终通过。

练习:判断阻断发生在哪一层

请你给下面四种失败分层:工具名称不存在、命令被策略拒绝、用户取消确认,以及进程在 Sandbox 里读不了工作区外的文件。再说说为什么它们不能统一返回「执行失败」。

查看核对要点 它们依次属于工具解析或注册、产品策略、交互批准和执行环境能力。如果都压成「执行失败」,模型可能会反复重试一个永远不会获准的动作。恢复逻辑也判断不了副作用究竟发生过没有。

现在应该能解释

工具是否可见、Schema 是否合法、策略是否放行、用户是否批准,以及系统最后是否执行,要分成五次判断。权限管产品愿不愿意做,Sandbox 管进程真正能做到什么。工具结果还得准确写明副作用有没有发生,下一轮才能正确处理,恢复时也才不会盲目重跑。

下一篇:Session、Context、Memory 与恢复