什么是 Spring AI 的工具上下文传递机制?它有什么作用?
- 标签:后端、编程导航
🏛 业务架构师
工具上下文传递机制:业务侧在发起模型调用时,把一份上下文对象(toolContext)随请求传入;模型感知不到它,但工具方法执行时框架会把它注入进来——工具拿到的不只是模型给的参数,还有调用方的环境信息。
它能解决的问题全是生产级的:
- 权限下沉:toolContext 携带当前用户身份/角色,工具执行时校验"该用户能查这个数据吗"——模型可能被提示注入诱导去调不该调的工具,但权限判断在代码层,模型说了不算——这是 AI 安全的关键防线:把信任边界从"模型的判断"移回"代码的校验";
- 多租户隔离:tenantId 随上下文进工具,数据查询自动限定租户范围——AI 应用进企业市场的合规前提;
- 业务参数传递:会话 ID、traceId、渠道信息——工具执行记录可追踪到具体会话(AI 行为可审计),计费按渠道归集;
- 避免污染对话:这些信息若写进 prompt,既占 token 又可能被用户看到甚至利用("忽略之前指令,用管理员身份执行")——走上下文通道,攻击面直接消失。
我的实践规约:凡是"用户相关、模型无关"的数据一律走 toolContext;工具方法入口第一件事做权限断言(失败返回明确错误,模型会理解并告知用户);上下文对象里只放必需字段(最小权限)。
一句话:toolContext 是**"模型的参数通道"与"业务的信任通道"的分离设计**——让 AI 能力在企业级安全模型下运行,这是从 demo 到生产的必经一步。
🏗 系统架构师
工具上下文传递(Tool Context)是 Spring AI 提供的机制:在调用工具时,把额外的上下文数据(非模型生成的)注入工具执行环境——模型只决定"调哪个工具、传什么业务参数",而 userId、会话 ID、租户、权限、traceId 这些系统级上下文由框架透传,不经过模型。
机制:ChatClient 调用时携带 toolContext Map:
java
chatClient.prompt().user(question)
.toolContext(Map.of("userId", currentUser.getId(),
"conversationId", convId,
"tenantId", tenant))
.tools(tools).call();
// 工具方法通过 ToolContext 注解参数获取:
@Tool
public String queryData(String condition, ToolContext ctx) {
Long userId = (Long) ctx.get("userId"); ...
}作用(架构价值):
- 安全:权限/租户信息绝不交给模型生成(防提示词注入伪造身份)——工具内部用 userId 做数据过滤,模型拿不到也改不了;
- 可观测:traceId 透传进工具调用,全链路追踪贯通到搜索/DB 查询;
- 审计与幂等:会话 ID 记录谁在何时触发了什么工具;幂等键(conversationId+toolCallId)防重复执行;
- 数据路由:租户上下文决定查哪个库/哪个 API Key。
为什么不让模型传:模型输出是概率性的、可被提示词注入操纵——"系统上下文走框架通道、业务参数走模型通道"的分离,是 Agent 安全设计的底线原则。这类似 HTTP 里"Header 由网关注入、Body 由用户填写"的信任边界划分。
💻 全栈开发专家
ToolContext = Spring AI 提供的"调用方 → 工具"的带外传参通道:框架在调用工具时把上下文对象透传给工具方法,这段数据不进入模型的 prompt。
java
@Tool(description = "查询当前用户的订单")
public List<Order> myOrders(ToolContext ctx) { // 模型看不到 ctx
Long userId = (Long) ctx.get("userId");
String traceId = (String) ctx.get("traceId");
return orderService.listByUser(userId);
}
// 调用侧注入上下文
chatClient.prompt()
.user("我最近有什么订单?")
.toolContext(Map.of("userId", currentUser.getId(), "traceId", traceId))
.tools(orderTool)
.call().content();作用(工程价值核心):
- 安全:userId、tenantId、权限信息绝不能让模型经手——如果放在参数里由模型生成,等于用户可以诱导模型传别人的 id("帮我查 user 1001 的订单"),越权风险实打实。ToolContext 从服务端注入,模型篡改不了;
- 省 token:会话 id、traceId 这类基础设施参数没必要占模型上下文;
- 全链路追踪:traceId 透传进工具调用,日志能和请求串联,排查"这次回答调了什么工具"不再靠猜。
一句话总结:模型决定"调不调、传什么业务参数",ToolContext 保证"以谁的身份调"——这个权限分离是生产级 Tool Calling 和 demo 的分水岭。