Java 17实现Agent工具调用的白名单、预算与审计门禁

Agent 能调用工具以后,最危险的误区是把"模型发来函数名"当作"系统已经批准执行"。真正的执行权应该在你的应用手里。下面这段 Java 17 代码为每次候选调用检查三件事:工具是否在白名单、金额是否为合法正数、累计预算是否还够;任何一步失败都不给执行器机会。它适用于采购草稿、工单变更、云资源申请等有外部副作用的流程。

OpenAI Function Calling 文档讲的是模型如何提出工具调用;它不替你完成组织权限、金额上限和审计。最新 GPT-6 产品与智能界面方向恰好提醒我们:把"计划"和"批准"做成用户可见的两个状态,而不是一键自动化。

flowchart LR A[模型提出tool call] --> B[白名单与参数验证] B --> C{预算/风险通过?} C -->|否| D[拒绝并记录原因] C -->|是| E[展示确认信息] E --> F[受控执行器] F --> G[审计账本]

环境与完整代码

保存为 BudgetGate.java,执行 javac BudgetGate.java && java BudgetGate。无第三方依赖,示例未在本次任务中实际调用模型或线上工具;请在你的 Java 17 环境先编译并运行,再接入实际执行器。

java 复制代码
import java.math.BigDecimal;
import java.util.*;

public class BudgetGate {
  record Call(String tool, String amount, String requestId) {}
  static final Set<String> ALLOW = Set.of("create_draft_purchase", "search_catalog");
  static final BigDecimal LIMIT = new BigDecimal("500.00");
  static BigDecimal spent = BigDecimal.ZERO;
  static final List<String> audit = new ArrayList<>();

  static boolean approve(Call c) {
    if (!ALLOW.contains(c.tool())) return deny(c, "工具不在白名单");
    final BigDecimal cost;
    try { cost = new BigDecimal(c.amount()); }
    catch (NumberFormatException e) { return deny(c, "金额格式错误"); }
    if (cost.signum() < 0) return deny(c, "金额不能为负");
    if (spent.add(cost).compareTo(LIMIT) > 0) return deny(c, "累计预算不足");
    spent = spent.add(cost);
    audit.add(c.requestId()+" ALLOW "+c.tool()+" "+cost);
    return true;
  }
  static boolean deny(Call c, String reason) {
    audit.add(c.requestId()+" DENY "+reason); return false;
  }
  public static void main(String[] args) {
    System.out.println(approve(new Call("create_draft_purchase", "120.00", "r-1")));
    System.out.println(approve(new Call("wire_money", "1.00", "r-2")));
    System.out.println(approve(new Call("create_draft_purchase", "400.00", "r-3")));
    audit.forEach(System.out::println);
  }
}

预期输出依次为 true、false、false:第一笔只创建草稿,第二笔工具不被允许,第三笔超过累计额度。不要把这里的内存变量直接用于生产;多实例服务必须用数据库事务或带条件写入的额度账本。

常见错误:仅限制工具名却不校验参数;把"创建草稿"和"提交付款"放在同一工具;重试时重复扣减;审计日志包含密钥或原始敏感提示词。它适合低到中风险、规则清晰的流程,不适合让模型自行决定付款、删库或人事处分。工程化改进包括租户隔离、幂等键、每工具限额和人工双人复核。5分钟练习:为 create_draft_purchase 加"单笔超过 200 元必须 REVIEW"的返回状态。

预算是产品能力,不是财务报表

最实用的预算规则通常分三层:单次调用限制爆炸半径,单个任务限制循环,租户日限额控制总体风险。调用前冻结额度,执行成功后确认,失败或取消后释放,才能避免并发任务都读到"余额充足"。若工具会产生不可逆副作用,预算通过也不等于可以执行:界面还要显示工具名、参数摘要、预计金额和确认人。审计记录至少包含请求 ID、模型版本、策略版本、决策、执行结果与操作者;但不应完整保存敏感提示词或凭据。上线后按拒绝原因统计:工具名频繁被拒,说明能力设计要拆分;预算频繁被拒,说明需要排队或重新分配额度,而不是悄悄把阈值调高。

官方文档:Function calling。你的Agent应该按调用次数、金额还是风险等级先触发人工确认?

关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。


本文首发于 java4u.cn,转载请注明出处。

相关推荐
橘和柠1 小时前
vLLM高吞吐推理引擎:本地高并发推理服务
人工智能
小林ixn1 小时前
别再手写 Agent 基建了:用 deepagents 中间件,30 行代码搞定文件系统 / 记忆 / 上下文压缩
人工智能·langchain
云和数据.ChenGuang1 小时前
langchain4j InMemoryEmbeddingStore常用的方法
java·人工智能·windows·java-ee·fastapi·springai
小天源1 小时前
GEO 品牌监测系统实战:基于 Node.js + Playwright 实现多平台采集与报告导出
人工智能·node.js·geo·品牌检测·ai诊断
skywalk81631 小时前
光明语言入榜计划:GitHub Linguist 注册指南・光明语言模块参考
人工智能·编程·光明
天空鸟_时光不老1 小时前
07-检查点与状态持久化
java·人工智能·spring boot·spring·spring cloud·kafka·maven
Latchh1 小时前
PDF打开不要密码却显示已加密,前端怎么判断
前端·图像处理·人工智能·计算机视觉·pdf
thinking_talk1 小时前
企业AI记忆产品科学选型框架
人工智能·机器学习·ai记忆
卿卿的产品经理日记2 小时前
【AI产品经理实战】Day 33|计算机科学速成:从巴贝奇到“AI是围墙“
人工智能·aigc·产品经理