Agent 不是看见所有 API 才更聪明:为什么工具暴露必须显式 opt-in?
关键词:Agent 工具白名单、Agent 越权调用工具、OpenAPI 直接给大模型、AI Agent 权限控制、工具可见性
一套运行多年的业务系统,通常不会只有几个接口。
以商城后台为例,它可能同时存在:
GET /orders 查询订单
POST /refunds 创建退款
PATCH /inventory/{sku} 调整库存
DELETE /staff/{id} 删除员工
PUT /billing/config 修改结算配置
POST /notifications/batch 批量发送通知
当团队准备接入 Agent 时,一个很自然的做法是:读取整份 OpenAPI,把每个 operation 转成模型可以调用的工具。
接口已经有名称、描述和参数 Schema,模型也能根据用户意图选择工具。既然如此,为什么还要额外维护工具白名单?把更多 API 交给模型,不是能让 Agent 更聪明、更万能吗?
真正进入生产环境后,团队往往会发现:
Agent 的能力,不取决于它能看见多少工具,而取决于它在当前场景中只看见正确的工具。
工具可见性不是单纯的体验配置,而是 Agent 行动链路中的第一道安全边界。
1. “系统里有这个 API”和“Agent 应该看见它”是两回事
传统后台中的 API,原本可能只服务于:
- 一个受控的管理页面;
- 一段固定的后端流程;
- 内部定时任务;
- 只有管理员才能进入的运维入口;
- 其他经过身份和权限校验的服务。
接口存在,并不意味着它已经准备好进入模型的工具候选集。
Agent 的调用方式发生了变化:用户给出的往往不是一条确定指令,而是一个自然语言目标;模型需要理解目标、选择工具并生成参数。只要一个操作进入可见工具集合,它就可能被模型选中,也可能受错误上下文、模糊表达或提示注入影响而被错误触发。
因此,至少需要区分四个问题:
| 问题 | 回答的是什么 |
|---|---|
| 业务 API 是否存在并可访问? | 接口与网络可用性 |
| 这项能力是否允许进入 Agent 的可见范围? | Agent-facing 能力声明 |
| 当前路由或场景是否需要这项能力? | 运行时工具白名单 |
| 当前主体此刻是否有权操作具体对象? | 业务系统最终授权 |
这四件事不能用一个“接口已经鉴权”合并掉。
2. 工具越多,模型选择未必越准确
假设客服助手只需要:
order.read
order.logistics.read
ticket.create
如果运行时把退款、库存调整、员工管理、结算配置和批量通知也全部交给模型,首先出现的未必是攻击,而可能只是普通的选择错误:
order.cancel和refund.create的描述相似;staff.disable和staff.delete都能让员工停止使用系统;inventory.adjust和inventory.overwrite都能改变库存;- 同一业务动作存在旧接口、新接口和内部接口。
工具数量增加后,模型需要在更大的候选集合里消歧。描述稍有重叠,就可能选中“看起来能完成目标”、但后果完全不同的操作。
所以工具白名单同时改善两件事:
- 降低行动范围:模型无法选择没有进入当前候选集的能力;
- 提高选择质量:减少无关和相似工具带来的歧义。
最小能力集合不是在限制模型智力,而是在为当前任务提供更清晰的行动空间。
3. 提示词不能代替工具可见性控制
一种常见方案是把所有工具交给模型,再在系统提示词中写:
你是客服助手,只能查询订单和创建工单。
不要退款,不要修改库存,不要操作员工账号。
这段提示当然有价值,但它属于模型行为引导,不是可靠的执行边界。
原因很简单:
- 提示词可能被后续上下文稀释;
- 用户输入或外部内容可能包含提示注入;
- 模型可能误解“只能查询”的语义;
- 不同模型或版本对同一提示的服从程度不同;
- 工具调用链路最终仍然看到了那些高后果操作。
如果某个工具在当前场景下绝不应该被调用,更可靠的做法不是反复要求模型“不要选”,而是根本不把它放进候选集合。
提示词负责帮助模型正确行动;工具可见性负责限定模型最多可以尝试什么。
4. 同一套 API,在不同 Agent 场景中应该呈现不同能力
业务系统通常只有一套 API,但 Agent 入口可能有很多:
| Agent 场景 | 合理的能力范围 |
|---|---|
| 匿名网页助手 | 商品查询、帮助中心搜索 |
| 登录后的客户助手 | 本人订单查询、售后申请 |
| 商家运营助手 | 商品维护、库存调整、订单处理 |
| 财务助手 | 对账查询、退款审批相关能力 |
| 内部 HR 助手 | 员工查询、状态变更 |
如果工具集合只在全局维护一份,就会出现两个极端:
- 为了安全,只开放少量只读接口,Agent 永远无法进入真实业务;
- 为了能力完整,把大量后台 API 全部暴露给每一个 Agent 场景。
更合理的模型是取交集:
当前可见工具
= 显式声明允许面向 Agent 的能力
∩ 当前路由或场景的 allowlist
∩ 当前运行时策略允许的范围
∩ 已满足主体等前置要求的能力
任何一层不满足,能力都不应该进入模型的工具列表。
5. 显式 opt-in 到底声明了什么
显式 opt-in 的意思不是“这个 API 已经完成最终授权”,而是:
API 所有者明确确认,这个 operation 可以作为一项 Agent-facing 能力被兼容运行时读取。
在 ACC v1 的 OpenAPI 绑定中,可以这样声明:
paths:
/orders/{id}:
get:
operationId: order_get
summary: Query one order by ID.
x-agent-capability:
version: 1
enabled: true
scope: order.read
risk:
level: low
subject:
required: true
execution:
readonly: true
idempotent: true
这里有两个容易误解的字段。
enabled 不是服务启停开关
enabled: true 表示该 operation 显式加入 Agent-facing 能力候选范围。
enabled: false 表示运行时不得把它暴露成 Agent 可调用能力。它不等于 HTTP API 下线,也不影响传统后台继续调用这个接口。
scope 不是最终业务权限
scope: order.read 提供一项稳定的能力标识,让路由 allowlist 和治理策略可以引用它。
它不表示“任何看到 order.read 的用户都可以读取任何订单”。当前用户能否查询这个订单,仍然必须由业务系统根据登录身份、租户归属、数据权限和实时状态判断。
ACC 管的是 Reach:这项能力是否可以进入 Agent 的触达范围。
业务系统保留 Authority:当前主体是否真的可以完成这次具体操作。
6. 为什么默认不暴露比默认全部暴露更合理
如果系统采用“OpenAPI 中的 operation 默认都能成为工具”,每新增一个后台接口,就可能无意间扩大 Agent 的行动范围。
这种变化很隐蔽:
- 业务团队新增一个内部管理接口;
- OpenAPI 自动更新;
- 工具生成器重新编译;
- 新工具悄悄进入模型候选集;
- Agent 的能力边界在没有安全评审的情况下发生变化。
显式 opt-in 把流程反过来:
- API 可以正常开发和发布;
- 只有完成 Agent-facing 评审的 operation 才增加声明;
- 运行时只读取显式启用且具有有效
scope的能力; - 当前路由再用 allowlist 缩小范围;
- 业务系统继续执行最终授权。
这使“新增 API”和“扩大 Agent 能力”成为两个独立动作。后者必须被明确看见、审查和记录。
7. 一份可以直接落地的最小检查表
准备把 OpenAPI 编译成 Agent 工具时,可以先检查:
- 是否只有显式 opt-in 的 operation 才能成为工具?
- 当前 Agent 场景是否有独立的 scope allowlist?
- 未知或缺少治理声明的接口是否默认跳过?
- 没有可信主体时,要求主体的能力是否会被隐藏?
- 模型提示词是否只承担引导,而不承担安全边界?
- 即使绕过工具列表直接请求 API,业务系统是否仍会做最终授权?
- 新增 OpenAPI operation 时,是否不会自动扩大 Agent 权限?
- 日志能否说明某个工具为什么被暴露或跳过?
如果这几个问题没有明确答案,“把 OpenAPI 全量转成工具”就不应该直接进入生产环境。
8. 工具白名单不是终点,但它是必要的起点
工具可见性无法替代身份认证、参数校验、审批、审计和业务授权。一个工具被隐藏,也不意味着业务 API 可以放弃自己的权限校验。
但反过来,业务系统有权限校验,也不意味着 Agent 应该看到全部 API。
两层防线解决的是不同问题:
- 可见性控制减少 Agent 可以尝试的行动范围;
- 业务授权决定当前主体是否真的可以执行。
当 Agent 开始操作真实订单、库存、员工和资金时,第一步不是把所有接口交给模型,再期待它一直做出正确选择。
第一步应该是明确:
哪些业务能力经过主动评审后,才允许进入当前 Agent 的视野。
这就是显式 opt-in 的价值。它很小,却决定了 Agent 的行动边界从哪里开始。
延伸阅读
- ACC 规范与示例:https://agentcapability.org/docs/
- ACC GitHub:https://github.com/agent-capability/agent-capability-contract
- BailingHub:https://github.com/bailinghub/bailinghub
BailingHub 是一个实现 ACC 的开源控制面示例;ACC 本身保持实现中立,其他运行时、网关和工具平台也可以独立实现相同的声明语义。
更多推荐


所有评论(0)