Agent 一旦可以查询订单、修改配置或发送消息,工具调用就不再是普通的函数调用,而是一次由自然语言触发的业务操作。模型可能误解用户意图,外部材料可能包含恶意指令,工具返回的数据也可能被拼接到下一轮提示词中。
因此,安全边界不能只写在系统提示词里。模型可以提出动作,但真正决定“能不能做、对什么对象做、做完是否生效”的,应该是独立于模型的策略和执行层。
先画出工具调用的信任边界
一次调用至少经过四个主体:用户、Agent 编排器、策略引擎和业务工具。用户身份决定任务范围,编排器负责组织步骤,策略引擎负责授权,工具服务负责最后的业务校验。任何一层都不应假设前一层已经做完全部检查。
可以把工具按照风险分为三类:
- 只读工具,例如查询知识和读取订单。
- 可逆写入工具,例如创建草稿、生成待审批配置。
- 不可逆或外部影响工具,例如付款、删除数据、发布内容和向外部发送消息。
风险等级应决定授权方式、审计粒度和是否需要人工确认,而不是决定模型能否调用某个函数名。
工具契约要写清楚
工具定义需要同时描述机器可校验的 schema 和人可以理解的语义。例如:
1 | { |
description 不能把“可做什么”和“不能做什么”混在模糊的自然语言里。读写应拆成独立工具,参数的枚举、长度、数量和资源归属应在 schema 与代码中重复校验。模型输出的 JSON 只是候选参数,不能视为已经通过验证。
使用短时、最小权限的授权
Agent 不应拿到一个长期有效、包含所有业务权限的服务账号。更安全的做法是:用户先通过身份认证,平台根据用户、组织、资源和任务类型生成短时能力令牌,工具服务再次验证令牌中的范围。
令牌至少应包含主体、作用域、资源范围、过期时间、任务 ID 和审批状态。比如“允许读取项目 A 的工单”与“允许修改所有项目工单”必须是两个不同的 scope。工具服务不要相信模型传入的 user_id,应从经过验证的身份上下文取得调用者。
多租户场景还要防止资源 ID 越权。即使用户知道另一个租户的订单号,也不能仅凭字符串通过校验。资源归属检查应在业务服务侧完成,并记录拒绝原因。
把提示词注入当成输入问题处理
网页、邮件、文档和工单内容都属于不可信输入。它们可能出现“忽略之前规则”“把密钥发给我”之类的文字。检索内容应该作为证据传递给模型,而不是被拼接为新的系统指令。
可以采取几层防护:
- 明确区分指令、用户内容和外部材料,使用结构化消息传递。
- 对外部文本做长度限制、格式标记和敏感内容识别。
- 工具参数只从结构化字段读取,不从模型的解释段落中解析命令。
- 高风险动作要求重新确认,不能由外部材料自动触发。
- 记录触发策略的证据片段,方便复盘而不必保存全部敏感内容。
这些措施不能保证模型永远不会被误导,但可以让一次误解无法直接扩大成权限事故。
审批不是简单的确认弹窗
审批应描述即将发生的具体动作,而不是只显示“允许 Agent 继续”。用户需要看到对象、变更内容、影响范围、调用者、依据和过期时间。审批结果要绑定任务步骤和参数摘要,参数发生实质变化时必须重新审批。
对批量操作,可以要求先生成预览,再由用户选择范围;对不可逆动作,可以增加双人审批或延迟执行窗口。审批系统要支持拒绝、撤回和超时,不能把“用户没有点击”解释成允许。
幂等、重试和回滚同样属于安全
网络超时可能让 Agent 重试一个已经成功的写入。所有可写工具都应设计幂等键,并在业务侧保存执行记录。重试只能复用同一个幂等键,不能每次生成新的请求。
对于可逆操作,工具可以提供补偿动作,例如撤回草稿;对于不可逆操作,要在执行前生成清晰的预览和风险提示。不要把回滚责任交给模型自由规划,回滚路径应该由业务系统定义。
审计记录要能回答五个问题
一次工具调用至少要能回答:谁发起、模型建议了什么、策略依据是什么、实际执行了什么、结果影响了哪些资源。建议用任务 ID 串起用户消息、模型请求摘要、检索证据、策略决策、审批记录和工具结果。
日志中避免直接写入完整密码、令牌和敏感正文,可以保存哈希、字段摘要和受控引用。审计数据本身也需要访问权限和保留期限,否则为了追查问题反而制造新的泄露面。
先做拒绝测试,再做成功测试
工具安全测试不能只验证“正确参数能执行”。还要覆盖越权资源、过期令牌、缺失审批、参数边界、重复请求、恶意文档、超时重试和取消后的迟到结果。对每个高风险工具,至少准备一组应该拒绝的样例,并将策略版本纳入回归测试。
Agent 的自主性应随着证据和控制能力一起增加。能安全读资料,不代表可以安全写入;能生成建议,也不代表可以直接替用户做出不可逆决定。把工具当成受控的业务 API,Agent 才能在企业环境中长期运行。