☰
Spring AI 学习篇(十五)| 实战:用 TaoToken 统一 Key 接入智能办公 Agent 的 MCP 工具链
2026/9/26 12:47:40 网站建设 项目流程

1. 智能办公 Agent 的真实痛点:工具越多,Key 越乱

做 Spring AI 智能办公 Agent 的同学大概率都经历过这个阶段:一开始只挂一个日历工具,application.yml里塞一个 API Key 就完事;后来加了邮件工具、文档检索工具、RAG 知识库工具,每个 MCP Server 背后可能对接不同厂商的模型服务,于是配置文件里出现了openai.api-key、claude.api-key、embedding.api-key、rerank.api-key一大堆字段。改一个 Key 要翻三个文件,测试环境和生产环境还不一样,稍不留神就把测试 Key 提交到了 Git。

更麻烦的是 ReAct 循环。Agent 在一次任务里可能先调日历工具查空闲时间,再调邮件工具发通知,最后调 RAG 工具检索会议背景资料。如果每个工具背后的模型调用走的是不同的 Key 和不同的 Base URL,那么一旦某个 Key 额度耗尽或者配置写错,整个 ReAct 链条就会在中间某一步断掉,报错信息还往往只告诉你“401 Unauthorized”,根本定位不到是哪个工具出的问题。

这篇要解决的就是这件事:用 TaoToken 统一 Key 接入智能办公 Agent 的 MCP 工具链,让日历、邮件、文档检索这些工具背后的模型调用都走同一个入口,application.yml里只维护一份配置,ReAct 循环一次跑通多工具。适合已经写过基础 Spring AI Agent、正在往多工具方向扩展的开发者。

2. TaoToken 前置准备:一个 Key 管住整条工具链

TaoToken 在这里扮演的角色是统一的模型服务入口。你可以把它理解成一个“模型调用的总闸”:不管你的 MCP 工具背后要调对话模型、Embedding 模型还是 Rerank 模型,都通过同一个 API Key 和同一个 Base URL 发出请求。这样 Spring AI 的OpenAiChatModel、OpenAiEmbeddingModel只需要配置一份凭证,工具层就不用各自维护 Key 了。

先拿到 Key。访问控制台创建 API Key:

https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite

创建时建议按用途命名,比如spring-ai-office-agent-dev,方便后续区分环境。Key 只在创建时完整显示一次,复制后先存到本地环境变量里,不要直接写进代码。

export TAOTOKEN_API_KEY="sk-你的实际Key"

Base URL 统一用:

https://taotoken.net/api

注意这个地址后面不加 UTM 参数,直接作为 Spring AI 的base-url使用。如果你需要确认当前可用的模型名称,可以打开模型对话页面手动发一条消息验证:

https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite

在对话页里选一个对话模型发一句“你好”,能正常返回就说明 Key 和网络都没问题。这一步看起来简单,但能帮你排除掉后面 80% 的“配置写了但调不通”的问题。

3. application.yml 统一 Key 与 MCP 客户端配置骨架

下面这份配置是整篇文章的核心。思路是把 TaoToken 的 Key 和 Base URL 抽成公共变量,对话模型、Embedding 模型、MCP 客户端都引用同一份,避免重复。

spring: ai: openai: # 统一入口:所有模型调用都走 TaoToken base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.3 embedding: options: model: text-embedding-3-small mcp: client: enabled: true name: office-agent-mcp-client version: 1.0.0 # 请求超时,办公工具里文档检索可能较慢 request-timeout: 30s # 按类型初始化,避免启动时阻塞 type: SYNC # 多个 MCP Server 统一在这里声明 sse: connections: calendar: url: http://localhost:8081 email: url: http://localhost:8082 document: url: http://localhost:8083 knowledge: url: http://localhost:8084 # Agent 自身的 ReAct 参数 office: agent: max-iterations: 15 confirm-dangerous-actions: true

几个关键点解释一下。base-url和api-key写在spring.ai.openai下,Spring AI 的自动配置会把它注入到OpenAiChatModel和OpenAiEmbeddingModel里,MCP 工具内部如果用到ChatClient,拿到的也是这份配置。mcp.client.sse.connections下面每个子项就是一个 MCP Server,名字对应工具来源,URL 指向你本地或远程启动的 MCP Server 进程。

如果你用的是 stdio 类型的 MCP Server,把sse换成stdio并配置command和args即可,Key 依然走上面那份统一配置,不需要在 stdio 的启动参数里再传一遍。

对应的 Java 配置类可以这样写,把 MCP 客户端注入到 Agent 的ToolCallbackProvider:

@Configuration public class OfficeAgentConfig { @Bean public ChatClient chatClient(OpenAiChatModel chatModel) { return ChatClient.builder(chatModel) .defaultSystem(""" 你是智能办公助手,可以调用日历、邮件、文档检索工具。 调用工具前先说明你的计划,危险操作(发邮件、删文件)必须先确认。 """) .build(); } @Bean public ToolCallbackProvider officeTools( SyncMcpToolCallbackProvider mcpToolCallbackProvider) { // 自动聚合所有已连接的 MCP Server 暴露的工具 return mcpToolCallbackProvider; } }

SyncMcpToolCallbackProvider会把application.yml里声明的四个 MCP Server 的工具全部注册进来,Agent 在 ReAct 循环里就能看到calendar_query、email_send、document_search、knowledge_query这些工具名。

4. ReAct 循环调用工具的验证步骤

配置写完,接下来验证 Agent 能不能在一次对话里串起多个工具。先写一个最小的 Controller:

@RestController @RequestMapping("/agent") public class OfficeAgentController { private final ChatClient chatClient; public OfficeAgentController(ChatClient chatClient) { this.chatClient = chatClient; } @GetMapping("/chat") public String chat(@RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); } }

启动应用,观察日志里 MCP 客户端的连接情况。正常情况下会看到类似MCP client connected to calendar、MCP client connected to email的输出,说明四个工具源都挂上了。

然后发一个需要多工具协作的请求:

curl "http://localhost:8080/agent/chat?message=帮我查一下明天下午3点有没有空,如果没有会议就发邮件通知team@example.com,主题是项目同步会"

预期 Agent 的 ReAct 过程是这样的:

第一步,Thought 判断需要先查日历,Action 调用calendar_query,参数是明天下午 3 点,Observation 返回“该时段空闲”。

第二步,Thought 判断需要发邮件,Action 调用email_send,参数包含收件人、主题、正文,Observation 返回“邮件已发送”。

第三步,Thought 判断任务完成,输出最终回答。

如果你在日志里看到Tool execution: calendar_query和Tool execution: email_send两条记录,并且最终返回了自然语言总结,说明统一 Key 配置生效了,ReAct 循环成功串起了两个工具。

再测一个带 RAG 的场景:

curl "http://localhost:8080/agent/chat?message=检索知识库里关于报销流程的文档,总结成三点发给我"

这个请求会触发knowledge_query工具,而知识库工具内部通常要调 Embedding 模型做向量检索。因为 Embedding 也走 TaoToken 的统一配置,所以不需要额外配 Key,直接就能跑。

5. 本篇常见错排查

5.1 启动时报 401 或 invalid api key

先确认环境变量有没有真正传进 JVM。用System.getenv("TAOTOKEN_API_KEY")打印一下,如果是 null,说明 IDE 的 Run Configuration 里没配环境变量。IDEA 里在 Run/Debug Configurations 的 Environment variables 一栏加上即可。另外检查api-key有没有多写空格,YAML 里${TAOTOKEN_API_KEY}前后不要加引号以外的字符。

5.2 MCP 工具注册了但 Agent 不调用

常见原因是系统提示词里没有明确告诉 Agent 有哪些工具可用。Spring AI 会把工具描述传给模型,但如果系统提示词过于简单,模型可能倾向于直接回答而不调工具。在defaultSystem里把工具用途写清楚,比如“查日程用 calendar_query,发邮件用 email_send”,命中率会明显提升。

5.3 ReAct 循环超过 max-iterations 还没结束

办公场景里文档检索和 RAG 查询比较慢,如果request-timeout设得太短,工具调用会超时,Agent 收到超时 Observation 后可能反复重试,把迭代次数耗尽。把request-timeout调到 30s 以上,同时在系统提示词里加一句“工具调用失败时不要重复调用超过两次,直接告知用户”。

5.4 多个 MCP Server 工具名冲突

如果两个 Server 都暴露了叫search的工具,Spring AI 注册时会冲突。解决办法是在 MCP Server 端给工具名加前缀,比如calendar_search、document_search,或者在客户端配置里用tool-name-prefix区分。命名规范建议从一开始就定好,后面加工具才不会乱。

5.5 Embedding 维度不匹配导致 RAG 检索报错

知识库工具如果之前用的是别的 Embedding 模型,换到 TaoToken 的text-embedding-3-small后维度可能对不上,向量库会报维度错误。这种情况需要重新灌一遍知识库数据,或者确认向量库的维度配置和当前 Embedding 模型一致。

6. 下一步:把统一 Key 用到长期编码和 Agent 任务里

一次配置跑通多工具之后,你会发现这套模式可以复用到更多场景。如果你打算把智能办公 Agent 做成长期运行的服务,或者接入 Coding Agent 做自动化开发任务,可以了解一下 Coding Plan,它适合需要持续调用模型、对额度有稳定预期的场景:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite

接入文档里有 Spring AI 和其他框架的完整配置示例,遇到 MCP 客户端参数不确定的地方可以直接对照:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite

如果你还没创建 Key,回到 API Keys 页面建一个专门给办公 Agent 用的:

https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite

我自己的习惯是给每个 Agent 项目单独建一个 Key,命名带上项目名和环境,这样月底看用量的时候一眼就能分清是哪个服务在消耗额度。统一 Key 最大的好处不是省事,而是排障时只需要检查一个地方——Key 没问题,那问题一定在工具实现或提示词上,定位范围直接缩小一半。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询