2026年10月8日 1 分钟阅读

AI Agent 不该拥有无限工具权限:Planlock 计划审批与 MCP 调用实战

tinyash 0 条评论

当 AI Agent 能调用退款、发邮件、修改脚本等工具时,常见方案只有两种:每次调用都让人点确认,或者让 Agent 在无人值守状态下拥有完整权限。前者很快变成“看到提示就点同意”,后者则把一次提示注入或错误推理变成真实的业务操作。

Planlock 提供了第三种路径:先让 Agent 写出执行计划,由人一次性批准;之后它作为 MCP 代理站在 Agent 与上游工具之间,只放行计划明确允许的调用。它是一个 MIT 许可证的 TypeScript 项目,仓库在 2026 年 10 月 7 日创建,当前仍是非常早期的工具,适合先做实验性验证,不应直接当成成熟的生产审计系统。

核心思路:批准约束,而不是批准一段话

Planlock 的关键不是让模型“保证自己会遵守计划”,而是把约束写进代理代码。一个计划可以规定:某个工具最多调用几次、参数必须等于什么值、数值上下限是多少、当前步骤允许哪些工具,以及上游脚本是否仍然是审批时的版本。

例如,一个客服 Agent 处理退款时,可以把计划拆成“查询订单→最多退款 30 欧元→发送确认邮件→关闭工单”。如果 Agent 尝试退款 300 欧元、换一个订单,或者在退款前先发邮件,代理会在请求到达 Windmill 等上游 MCP 服务之前拒绝调用。

这种设计还把“工具版本变化”纳入边界。README 展示的 pin 约束会在写操作前重新读取上游脚本的哈希;如果同事在审批之后修改了退款脚本,当前计划会进入 Hold,而不是继续执行未知版本的代码。

一次调用是怎样被拦截的

计划不是只保存自然语言描述,而是保存每一步的工具和参数限制。下面是官方 README 展示的约束结构的简化版本:

{
  "s-f_support_refund__customer": {
    "max_calls": 1,
    "args": {
      "order_id": { "eq": "4711" },
      "amount": { "min": 1, "max": 30 }
    },
    "pin": {
      "tool": "getScriptByPath",
      "args": { "path": "f/support/refund_customer" },
      "field": "hash",
      "eq": "APPROVED_SCRIPT_HASH"
    }
  }
}

实现层支持 eq、enum、min、max、max_length 和 any 等约束;未声明的参数也会被拒绝。调用失败、被 pin 拦截或跳过步骤,都可能让计划暂停。处于 Hold 时,Agent 本身不能自我批准,必须通过独立的审批通道由人处理。

这比在系统提示词中写“不要退款超过 30 欧元”更可靠,因为规则位于工具调用链路上。即便 Agent 读到了恶意文本,最多也只能尝试调用;越过参数、步骤或版本边界的请求不会抵达业务系统。

用 Docker 跑通官方演示

仓库提供了基于 Windmill 的退款示例。官方要求 Docker 和 Node.js 20+,在项目目录中可以按下面的流程启动:

npm ci
cp .env.example .env
# 在 .env 中设置 APPROVER_TOKEN

docker compose --env-file .env -p wm \
  -f examples/windmill/docker-compose.yml up -d
node examples/windmill/setup.mjs

docker compose --env-file .env -p wm \
  -f examples/windmill/docker-compose.yml \
  --profile guard up -d --build planlock

node examples/windmill/demo.mjs

演示会先尝试一个超出上限的退款,再执行批准范围内的退款,然后模拟同事修改上游脚本。后一个调用会因为哈希不一致而被阻断,计划进入 Hold。测试结束后可以清理环境:

docker compose --env-file .env -p wm \
  -f examples/windmill/docker-compose.yml \
  --profile guard down -v

如果只想测试代理本身,也可以使用仓库自带的 mock upstream:docker compose up --build,然后运行 npm run smoke。MCP 服务和审批通道在 README 给出的示例中分别监听本机的 3001 和 4001 端口;不要把这些开发端口直接暴露到公网。

它适合什么场景

Planlock 最适合“动作风险高,但计划边界相对清晰”的任务:客服退款、工单状态流转、受限的运维脚本、带金额或对象范围的业务操作。它也适合作为现有 MCP 服务的旁路保护层,不必重写每个上游工具。

但它不是万能沙箱。官方威胁模型明确指出:如果 Agent 同时能在宿主机执行命令、读取审批令牌或修改相关文件,这些保证就不成立;pin 检查与真正调用之间也存在竞态窗口。此外,示例状态默认保存在内存中,并且一个服务实例只处理一个 Agent。生产化前还需要补充持久化、身份认证、审计留存、密钥隔离和故障恢复设计。

因此更稳妥的落地顺序是:先接入只读工具,再启用参数严格的低风险写操作;把审批通道与 Agent 能看到的 MCP 工具分开;对每次 Hold 记录原因和上游实际状态;最后再评估是否需要接入真实业务系统。Planlock 的价值不是承诺 Agent 永远不会犯错,而是让错误在进入业务系统前有一个可执行、可测试的边界。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。