内容提要
文章介绍用 Java 17 为 Agent 工具调用添加执行门禁:调用前校验工具白名单、金额合法性与累计预算,任一失败即拒绝并记录审计日志。示例中首笔通过,越权工具与超额调用被拒。强调执行权应在应用侧,预算分单次、任务、租户三层,生产环境需数据库事务、幂等键与人工复核。
延伸解读
执行权归属:应用侧而非模型
文章强调,Agent 工具调用的执行权必须掌握在应用手中,不能因为模型返回了函数名就默认批准。示例代码在调用前依次校验工具白名单、金额合法性和累计预算,任一失败即拒绝并记录审计日志。这提醒开发者,模型只负责提出计划,而批准与执行应由应用侧独立完成,避免将模型输出直接等同于系统授权。
预算分层与额度冻结机制
文章指出,实用的预算规则应分为单次调用、单个任务和租户日限额三层,分别控制爆炸半径、循环风险和总体风险。调用前需冻结额度,执行成功后确认,失败或取消后释放,以防止并发任务都读到余额充足。示例中的内存变量仅用于演示,生产环境必须使用数据库事务或带条件写入的额度账本,确保多实例下的数据一致性。
审计日志与常见错误规避
审计记录应包含请求 ID、模型版本、策略版本、决策、执行结果与操作者,但不应完整保存敏感提示词或凭据。文章列举了常见错误:仅限制工具名却不校验参数、把创建草稿和提交付款放在同一工具、重试时重复扣减、审计日志包含密钥。这些错误可能导致越权或数据泄露,需在设计中避免。
适用边界与工程化改进
该门禁方案适合低到中风险、规则清晰的流程,如采购草稿、工单变更、云资源申请,但不适合让模型自行决定付款、删库或人事处分。工程化改进包括租户隔离、幂等键、每工具限额和人工双人复核。若工具产生不可逆副作用,预算通过也不等于可以执行,界面还需显示工具名、参数摘要、预计金额和确认人。
Q&A
为什么不能把模型发来的函数名直接当作已批准执行?
因为真正的执行权应该在应用手里,模型只是提出调用建议,应用需要校验工具白名单、金额合法性和累计预算,任何一步失败都拒绝执行。
Java 17 实现 Agent 工具调用门禁时,approve 方法会检查哪三件事?
检查工具是否在白名单、金额是否为合法正数、累计预算是否还够;任何一步失败都不给执行器机会。
示例代码中三笔调用的预期输出是什么?为什么?
预期输出依次为 true、false、false。第一笔只创建草稿且金额 120 在预算内,通过;第二笔工具 wire_money 不在白名单,拒绝;第三笔累计金额 120+400=520 超过 500 限额,拒绝。
生产环境使用这种内存变量做预算控制有什么问题?应该怎么改进?
不能把内存变量直接用于生产,多实例服务必须用数据库事务或带条件写入的额度账本,并考虑租户隔离、幂等键、每工具限额和人工双人复核。
预算通常分为哪三层?各自的作用是什么?
分为单次调用限制爆炸半径、单个任务限制循环、租户日限额控制总体风险。调用前冻结额度,执行成功后确认,失败或取消后释放。
审计日志应该记录哪些信息?不应该记录什么?
至少包含请求 ID、模型版本、策略版本、决策、执行结果与操作者;不应完整保存敏感提示词或凭据。
这种门禁方案适合哪些场景?不适合哪些场景?
适合低到中风险、规则清晰的流程,如采购草稿、工单变更、云资源申请等有外部副作用的流程;不适合让模型自行决定付款、删库或人事处分。
上线后如何根据拒绝原因优化策略?
按拒绝原因统计:工具名频繁被拒说明能力设计要拆分;预算频繁被拒说明需要排队或重新分配额度,而不是悄悄调高阈值。