借助Spring AI,快速为AI Agent搭建API网关:TaoToken统一Key接入与settings.json配置实战

📅 发布时间:2026/9/29 6:52:18
借助Spring AI,快速为AI Agent搭建API网关:TaoToken统一Key接入与settings.json配置实战
1. 为什么要在 Spring AI 里给 AI Agent 加一层 API 网关如果你正在用 Spring AI 写 AI Agent大概率会遇到一个很现实的问题Agent 要调用外部 REST API但每个服务的鉴权方式、Base URL、超时策略都不一样。更麻烦的是模型厂商的 Key 也散落在各个配置文件里本地调试和生产部署两套环境改起来容易漏。我试过最直接的做法是把所有 API Key 硬编码在application.yaml结果换一台机器就要重新配一遍团队协作时还得靠聊天工具传 Key既不安全也不优雅。后来我把模型调用和工具调用统一收敛到一层网关上用 TaoToken 做统一 Key 入口Spring AI 侧只认一个base-url和一个api-key整个链路清爽了很多。这篇要解决的问题很具体用 Spring AI 构建 AI Agent 时如何通过 TaoToken 统一 Key 和 API 通道把 REST API 与 OpenAPI 服务接入进来并在本地快速跑通调用链路。适合已经写过 Spring Boot、想给 Agent 加工具调用能力、但不想在 Key 管理上反复折腾的开发者。核心检索词先摆出来Spring AI、AI Agent、API 网关、REST API、OpenAPI。这四个词基本覆盖了整条链路——Spring AI 负责 Agent 编排AI Agent 负责决策API 网关负责统一入口REST API 和 OpenAPI 负责具体工具能力。TaoToken 在这里扮演的角色是「统一 Key 与通道层」。你不需要在每个服务里单独配模型厂商的 Key而是让 Spring AI 的OpenAiApi指向 TaoToken 的兼容端点工具调用和模型对话走同一个出口。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。下面从配置骨架开始一步步把网关路由、鉴权验证、常见报错都过一遍。2. TaoToken 前置准备Key、端点与 settings.json 骨架在写 Java 代码之前先把「统一 Key」这件事落地。TaoToken 的控制台里可以创建 API Key这个 Key 会同时用于模型对话和工具调用链路。你需要先拿到两样东西API Key和Base URL。API Key 在控制台的 API Keys 页面创建建议按项目命名比如spring-ai-agent-dev方便后续区分环境。创建后立即复制保存页面刷新后不会再完整显示。Base URL 统一用https://taotoken.net/api不要加任何查询参数。Spring AI 的 OpenAI 兼容客户端会自动在这个地址后面拼接/v1/chat/completions等路径。关于settings.json这里要说明一下Spring AI 本身用的是application.yaml或application.properties但很多团队会用一个settings.json来集中管理网关路由和工具注册信息再由 Spring Boot 启动时加载。下面给出一份可复制的骨架字段含义我逐行标注。{ gateway: { baseUrl: https://taotoken.net/api, apiKeyEnv: TAOTOKEN_API_KEY, timeoutMs: 60000, maxRetries: 2 }, agent: { model: gpt-4o-mini, temperature: 0.2, systemPrompt: You are a tool-using agent. Call registered tools when needed. }, services: [ { name: booking, openapi: http://localhost:8080/v3/api-docs.yaml, baseUrl: http://localhost:8080, auth: { type: bearer, tokenEnv: BOOKING_TOKEN } }, { name: product, openapi: http://localhost:8082/v3/api-docs.yaml, baseUrl: http://localhost:8082, auth: { type: none } } ] }几个关键点apiKeyEnv指向环境变量名而不是明文 Key这样配置文件可以进 GitKey 留在本地环境变量里。services数组里每个条目对应一个 REST API 服务openapi字段指向该服务的 OpenAPI 描述文件网关启动时会拉取并解析成工具定义。auth字段描述该服务自身的鉴权方式和 TaoToken 的 Key 是两回事——TaoToken 管的是模型通道服务鉴权管的是业务 API。注意settings.json里的baseUrl只写https://taotoken.net/api不要写成带/v1的完整路径否则 Spring AI 拼接后会出现/v1/v1/chat/completions这种重复路径。环境变量设置方式Linux/macOS 下export TAOTOKEN_API_KEYsk-你的实际Key export BOOKING_TOKENbooking-service-tokenWindows PowerShell$env:TAOTOKEN_API_KEYsk-你的实际Key $env:BOOKING_TOKENbooking-service-token这一步做完统一 Key 的入口就有了。接下来把它接进 Spring AI 的配置。3. 可复制配置Spring AI 接入 TaoToken 与网关路由Spring AI 的 OpenAI Starter 默认读spring.ai.openai.api-key和spring.ai.openai.base-url。我们要做的就是把这两个值指向 TaoToken同时把settings.json里的服务列表加载成工具。先看application.yaml的核心片段spring: ai: openai: api-key: ${TAOTOKEN_API_KEY} base-url: https://taotoken.net/api chat: options: model: gpt-4o-mini temperature: 0.2 embedding: enabled: false gateway: settings-location: classpath:settings.json这里api-key用占位符引用环境变量base-url固定为 TaoToken 的 API 地址。embedding.enabled设为 false 是因为本篇只跑对话和工具调用不需要向量能力关掉可以减少启动时的外部请求。然后是加载settings.json并注册工具的配置类。核心思路是读取 JSON遍历services对每个服务拉取 OpenAPI 描述转换成 Spring AI 的ToolCallback。Configuration public class GatewayConfig { Value(${gateway.settings-location}) private Resource settingsResource; Bean public ListToolCallback openApiToolCallbacks(ObjectMapper mapper) throws IOException { Settings settings mapper.readValue(settingsResource.getInputStream(), Settings.class); ListToolCallback callbacks new ArrayList(); for (ServiceDef svc : settings.getServices()) { OpenApiParser parser new OpenApiParser(svc.getOpenapi(), svc.getBaseUrl()); callbacks.addAll(parser.toToolCallbacks()); } return callbacks; } Bean public ChatClient chatClient(OpenAiChatModel model, ListToolCallback tools) { return ChatClient.builder(model) .defaultTools(tools.toArray(new ToolCallback[0])) .build(); } }OpenApiParser的职责是把 OpenAPI 里的每个operationId映射成一个工具名把parameters映射成工具的入参 schema。这部分逻辑和 Spring AI 官方文档里ToolCallback的实现方式一致只是数据来源从注解变成了 OpenAPI 文件。网关路由的关键在于模型请求走 TaoToken工具请求走各自服务的baseUrl。两者在 Spring AI 里是分开的——OpenAiChatModel只负责和模型通信ToolCallback负责执行具体 HTTP 调用。所以你不会把业务 API 的流量也发到 TaoTokenTaoToken 只承载模型通道。如果你用的是 Coding Plan 做长期编码或 Agent 开发可以在控制台里单独创建一个 Key 用于开发环境和线上 Key 隔离。Coding Plan 的入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 适合需要长时间跑 Agent 任务的场景。配置写完后启动应用mvn spring-boot:run启动日志里应该能看到工具注册数量比如Registered 6 tool callbacks from 2 services。如果数量是 0说明 OpenAPI 拉取失败先检查openapi地址是否可访问。4. 验证请求从 curl 到 Agent 调用链路跑通配置对不对跑一个请求就知道。先验证模型通道是否通用 curl 直接打 TaoToken 的兼容端点curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: gpt-4o-mini, messages: [{role: user, content: ping}] }返回里如果有choices数组和正常的content说明 Key 和端点都没问题。这一步排除了网络和鉴权问题再去看 Spring AI 侧。接着验证 Agent 的工具调用。假设你的网关暴露了一个/invoke接口请求体里带用户消息curl -X POST http://localhost:7001/invoke \ -H Content-Type: application/json \ -d {message: 帮我查一下马德里有哪些酒店}预期结果是 Agent 先返回一个工具调用意图然后网关执行getHotelsByDestination最后把结果拼成自然语言返回。日志里会看到类似这样的顺序[Agent] model response: tool_call getHotelsByDestination({destination:Madrid}) [Tool] GET http://localhost:8080/hotels?destinationMadrid - 200 [Agent] final answer: 马德里目前有以下酒店...如果工具调用没触发先确认systemPrompt里有没有明确告诉模型「需要时调用工具」。有些模型对工具调用的触发比较保守把temperature降到 0.2 以下会稳定一些。再验证一个带参数的场景比如查价格curl -X POST http://localhost:7001/invoke \ -H Content-Type: application/json \ -d {message: 卡斯蒂利亚酒店 2025年8月5日入住5晚多少钱}这个请求会触发getHotelPrice工具参数里包含酒店名、日期和晚数。如果 OpenAPI 里的参数描述写得清楚模型提取参数的准确率会明显提高。实测下来description字段里带上示例值比如e.g. Madrid, Paris对参数提取帮助很大。到这里模型通道、工具注册、Agent 调用三条链路都验证过了。接下来把常见的坑列一下。5. 本篇常见错排查401、工具不触发、OpenAPI 解析失败错误一401 Unauthorized模型请求被拒。最常见的原因是环境变量没生效。Spring Boot 启动时如果读不到TAOTOKEN_API_KEYapi-key会变成空字符串请求自然被拒。排查方式是在启动日志里搜索api-key确认它显示的是占位符还是实际值。另一个原因是 Key 复制时带了空格建议用echo $TAOTOKEN_API_KEY | wc -c检查长度。错误二工具完全不触发Agent 只返回文本。先看工具注册数量是否为 0。如果注册成功但模型不调用检查systemPrompt是否过于模糊。把提示改成「当用户询问酒店、价格、预订相关问题时必须调用对应工具」会有效果。还有一种情况是模型本身不支持 function calling换一个支持工具调用的模型即可。错误三OpenAPI 解析失败启动报Failed to parse spec。多数是 OpenAPI 文件里的servers字段和baseUrl冲突。网关解析时以settings.json里的baseUrl为准如果 OpenAPI 里写的是相对路径解析器可能拼不出完整 URL。解决办法是在settings.json里显式写全baseUrl并确保 OpenAPI 里的paths是相对路径。错误四工具调用返回 404。说明baseUrl和 OpenAPI 里的路径拼接有问题。比如baseUrl是http://localhost:8080OpenAPI 里路径是/v1/hotels最终请求应该是http://localhost:8080/v1/hotels。如果baseUrl末尾多了斜杠会变成//v1/hotels部分服务端会返回 404。统一去掉末尾斜杠。错误五超时。Agent 调用工具时如果服务响应慢默认超时可能不够。在settings.json里把timeoutMs调到 60000并在OpenApiParser里给 HTTP 客户端设置相同的超时。注意 TaoToken 侧的模型请求也有超时长文本生成时建议留足余量。注意排查时不要把所有请求都打到 TaoToken 上。模型请求走 TaoToken业务 API 请求走各自服务两者日志分开看定位会快很多。如果排障过程中需要确认 Key 状态或重新生成去控制台的 API Keys 页面操作https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入细节和参数说明在文档里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。6. 统一 Key 之后Agent 网关的下一步与 CTA把 TaoToken 作为统一 Key 入口接进 Spring AI 之后最直接的变化是配置文件变干净了。模型通道只有一个base-url和一个环境变量业务服务的鉴权各自独立互不干扰。Agent 侧的工具注册完全由 OpenAPI 驱动新增一个 REST 服务只需要在settings.json里加一个条目不用改 Java 代码。如果你接下来要验证模型对话效果可以直接在模型对话页面测试不同模型对工具调用的支持情况https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果是要长期跑编码类 AgentCoding Plan 的通道更适合持续调用https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。控制台里可以管理所有 Key 和用量https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个实用技巧在settings.json里给每个服务加一个enabled字段本地调试时只开需要的服务启动会快很多工具列表也不会太长导致模型选择困难。这个字段在GatewayConfig里过滤一下就行改动量很小但日常开发体验提升明显。