首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >别让 Agent 直接点下「发送」:Spring AI 2.1 工具确认实战

别让 Agent 直接点下「发送」:Spring AI 2.1 工具确认实战

原创
作者头像
HELLO程序员
发布于 2026-11-15 14:27:59
发布于 2026-11-15 14:27:59
150
举报

别让 Agent 直接点下“发送”:Spring AI 2.1 工具确认实战

给 Agent 接一个发邮件工具很容易,真正难的是在它把邮件发出去之前,让人看一眼收件人、主题和正文。AI 决定“要做什么”,不等于它已经获得“可以执行”的授权。Spring AI 2.1 新增的工具确认机制,正好把这两件事拆开。

只给高风险工具加确认

假设助手有两个工具:一个查询联系人邮箱,一个发送邮件。前者只读,后者不可撤销。正确做法不是让每一步都弹确认,而是只拦截有副作用的操作:

代码语言:javascript
复制
@Tool(name = "send-email",
      description = "Sends an email",
      requiresConfirmation = true)
public String sendEmail(@ToolParam(description = "Email to send") Email email) {
    mailClient.send(email);
    return "sent";
}

@Tool(name = "find-email", description = "Finds an email address by name")
public String findEmail(String name) {
    return contacts.findEmail(name);
}

加上 requiresConfirmation = true 后,Spring AI 不会直接执行 send-email,而是在 ChatResponse 中返回一个待确认的工具调用。查询邮箱仍然自动执行,不会把用户淹没在确认弹窗里。

不能只取 content()

常见聊天循环通常这样写:

代码语言:javascript
复制
String answer = chatClient.prompt(input).call().content();

这只拿到了文本,把待确认工具调用丢掉了。接入确认机制后必须拿完整响应:

代码语言:javascript
复制
ChatResponse response = chatClient.prompt(input)
    .advisors(SessionAdvisors.session(sessionId))
    .call()
    .chatResponse();

然后检查其中是否有等待人工决策的调用。核心循环可以概括为:

代码语言:javascript
复制
while (!ToolCallDecisions.awaitingDecision(response).isEmpty()) {
    ToolCallDecisions decisions = askUser(response);
    var result = toolCallingManager.executeToolCalls(
        new Prompt(List.of(), options), response, decisions);

    response = chatClient.prompt()
        .messages(result.conversationHistory().getLast())
        .advisors(SessionAdvisors.session(sessionId))
        .call()
        .chatResponse();
}

循环不能省略:用户批准发邮件后,模型可能基于工具结果又决定调用另一个高风险工具,仍然要再次确认。

确认界面要展示“将执行什么”

控制台、Web 弹窗或企业微信交互消息都可以承载确认,但至少要展示工具名和完整参数:

代码语言:javascript
复制
Tool: send-email
Arguments:
{
  "recipient": "bob@example.com",
  "subject": "Project update",
  "body": "..."
}
Allow? (y/N):

默认必须是拒绝,只有显式输入 y 或点击“允许”才执行。一次响应可能包含多个工具调用,甚至同一个工具被调用多次,所以每个决策都要绑定 Spring AI 返回的 tool-call key,不能简单按工具名批量放行。

拒绝不是终止对话

用户拒绝工具调用后,应用不应该直接报错退出。ToolCallingManager 会把“已拒绝”写回对话历史,模型可以继续说“好的,这封邮件不会发送”,或者建议修改正文。这样授权边界清晰,同时交互体验不会被打断。

恢复会话时要继续携带同一个 sessionId,让 Session 记忆覆盖确认前后的完整过程。否则 Agent 可能忘记刚刚被拒绝的动作,在下一轮又提出相同调用。

哪些工具应该需要确认

一个简单的判断标准是:操作是否可撤销、是否影响外部世界、是否可能造成资金或声誉损失。

  • 查询订单、读取文档、检索知识库:通常自动执行
  • 发邮件、修改数据库、创建工单:需要用户确认
  • 支付、删除数据、封禁账号:除确认外,还应有权限校验、审计日志和二次审批

工具确认不是为了让用户多点一次按钮,而是把“模型生成意图”和“系统执行权限”分离。Agent 可以起草邮件、准备 SQL、生成退款请求,但真正越过副作用边界的那一刻,应该由人决定。这个功能很小,却是 Agent 从演示走向生产环境的分水岭。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 别让 Agent 直接点下“发送”:Spring AI 2.1 工具确认实战
    • 只给高风险工具加确认
    • 不能只取 content()
    • 确认界面要展示“将执行什么”
    • 拒绝不是终止对话
    • 哪些工具应该需要确认
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档