
Spring AI 2.0 企业级 AI Agent 智能航空项目这个标题拆开看其实是一道非常完整的应用题怎么在 Spring 技术栈里把一个普通的 Java 后端项目升级成能调用多模型、能操作业务工具、能接入 MCP、能记住业务上下文、还能执行 Skills 的 Agent 系统。航空只是场景外壳项目真正解决的是大多数企业级系统都会遇到的共同问题——数据和知识散落在各个系统里模型本身又不了解企业真实业务单靠聊天式对话根本走不进生产环境。这个项目最适合两种人一种是已经写过 Spring Boot、但还不清楚 Agent 落地该怎么组织代码的后端另一种是看过很多 AI 概念、想找一条完整链路把概念串起来实践的开发者。它不涉及模型训练也不需要你从零搭建大模型平台重点是把模型调用、工具编排、外部协议接入、记忆检索、技能封装这些能力一次性打通。最值得关注的地方不是某一个 API 长什么样而是整体链路怎么拆分、每一层承担什么职责、出了问题往哪里查。1. 先别被标题吓住它解决的其实是企业系统的“连通”问题智能航空项目听起来窄实际上是把航空企业里已经存在的系统和服务当成 Agent 的操作对象。航空公司的日常生产环境里航班动态、维修手册、签派指令、气象报文、旅客服务记录通常分布在不同的业务系统里平时靠人工来回切换。Agent 的真正价值就是把“查哪个系统、按什么流程处理、输出什么格式”这件事自动化。1.1 航空场景只是一个壳底层是通用企业 Agent 底座从一个后端开发者的角度看航空场景里的几个典型任务其实特别适合 Agent 来做机务人员问“某个飞机最近有没有滑油系统维修记录”签派人员想快速知道当前天气是否影响某个航班值班经理要生成一份航班延误的旅客告知模板知识库检索“起落架更换后的试车要求”。这些需求背后都有共性数据在真实系统里、答案需要结合上下文、输出要符合业务规范。只要你把“航空”换成“电商”“金融”“制造”需求依然成立。所以这个项目最值得学的是那套能力底座不是民航业务本身。1.2 六个关键词对应六层能力标题里那一串词不是并列的功能点而是分层的能力。我用下面这张表概括关键词在项目中的角色解决的问题多模型模型接入层避免业务代码被某一家模型厂商绑死Tools工具调用层让 Agent 能查询、修改、触发真实业务系统MCP协议接入层统一第三方系统和外部服务接入标准多层记忆状态管理层让 Agent 记住会话内容、业务规则和历史操作Skills能力封装层把一套固定处理流程固化成可复用技能Agent编排决策层串联所有能力形成一个完整任务闭环这层划分很重要。很多人学 AI Agent 容易陷入一个误区今天看 Tools明天看 MCP后天又追新的框架结果每个点都知道一点但组合不起来。这个项目给了一个更稳妥的练习路径先有一层稳定接口再逐层加能力最后用 Agent 把它们编排起来。这不是炫技是最省事的企业级落地思路。2. 跑通最小链路环境、依赖和航空数据准备一次配齐任何项目第一个坎都是环境。Spring AI 这类框架版本变化快不同版本之间的 API 和配置有差异所以环境准备一定要按“先确认版本再写代码”的顺序来。2.1 基础环境怎么定这个项目是标准 Java 工程基础环境通常包含JDK 17 或 21建议直接上 21很多新依赖对高版本 JDK 支持更好Maven 或 Gradle看团队习惯Maven 用得更多一些Spring Boot 3.x因为 Spring AI 2.0 是在 Spring Boot 3 基础上构建的Spring AI 相关 starter注意版本必须和 Spring Boot 版本配套。这里特别提醒一句不要无脑拉最新版本。Spring AI 版本迭代很快有的版本只支持特定 Spring Boot 小版本拉错了启动就报错。稳妥做法是先看官方文档里的版本对照表或者直接用项目里锁好的版本组合。2.2 模型从哪里来企业项目接模型通常有两条路一条是云上模型 API比如 OpenAI 兼容接口、国内主流模型服务商的接口优点是开箱即用、能力全面缺点是要考虑数据能否出网、费用怎么控制。另一条是本地模型比如通过 Ollama 这类工具在本地拉起开源模型优点是数据不出内网适合敏感数据场景缺点是模型能力相比大厂 API 有差距部署和运维也需要成本。我的建议是先把一条路跑通再考虑第二路。开发阶段用云 API 最省事验证完链路之后再根据数据安全要求决定是否切本地模型。如果一开始就同时接多家模型、又跑本地又跑云环境问题会盖过业务问题。2.3 航空业务数据怎么准备这个项目不是拿空数据做演示航空场景里比较常见的数据源包括维修手册、操作手册、训练材料等文档航班计划表、历史运行记录维修工单、故障记录气象报文、机场通告。这些数据不能直接喂给模型。通用做法是先做解析和清洗把 PDF、Word 转成纯文本去掉页眉页脚、目录、重复声明再按段落大小分块最后做向量化存入向量库。分块大小会影响检索质量分得太细语义可能被切断分得太粗检索回来又浪费上下文空间。通常以几百字为一个块比较常见但最终要按你实际文档的结构去调。还有一点很关键涉及真实旅客信息、机组信息、真实运行数据时开发环境一定要用脱敏样例。这不是流程繁琐是企业级项目上线的底线。注意数据准备阶段就把目录、文件命名、版本管理做好后面排查“回答为什么不对”时会省很多时间。3. 多模型不是炫技是要让业务代码和模型厂商解耦Spring AI 里最基础的一块就是模型调用抽象。理解它后面的 Tools、MCP、Skills 才有稳定的地基。3.1 为什么要先做模型抽象假设你直接使用某一家模型厂商的 SDK业务代码里到处是它的请求对象和响应对象。换模型时所有调用点都要改。在企业里这个问题会被放大采购合同变化、模型效果不达标、数据合规要求调整都可能让你换模型。Spring AI 的模型抽象本质是把“发请求、拿文本、拿结构化信息”这部分收敛成统一的接口。业务代码只依赖这个接口模型厂商通过配置切换。这样换模型时大部分业务代码可以不动。3.2 配置和多模型切换的参考写法以“OpenAI 兼容接口”为例常见的配置风格是这样的spring: ai: openai: base-url: ${LLM_BASE_URL} api-key: ${LLM_API_KEY} chat: options: model: ${LLM_MODEL_NAME:qwen-max} temperature: 0.7代码里注入的对象通常是ChatClient或对应的ChatModel类似这样Service public class AgentChatService { private final ChatClient chatClient; public AgentChatService(ChatClient.Builder builder) { this.chatClient builder.build(); } public String chat(String userMessage) { return chatClient.prompt(userMessage) .call() .content(); } }注意不同 Spring AI 版本的包名和配置前缀可能有调整。上面的写法只作为理解方向的参考落地时要以你实际使用的版本文档为准。3.3 多模型怎么切、参数怎么调多模型的场景不是“所有请求都用最强的模型”而是按任务类型分流简单问答、意图识别用小模型速度快、成本低复杂规划、长文本总结用大模型效果好代码生成、结构化输出可能需要单独评估哪个模型更稳定。关键参数主要是温度和超时。温度控制随机性需要确定性输出的工具调用场景建议调到 0 附近需要创意文案的场景可以稍高一点。超时一定要设不然模型服务卡住时整个接口跟着卡。判断一个模型适不适合你的场景不要只看宣传效果要看几个实打实的指标单轮请求延迟、每千 token 成本、相同提示词下的输出稳定性、中文指令跟随能力。建议用固定的一批测试问题跑几轮记录结果再决定业务上怎么分配模型。4. Tools 是 Agent 的第一双手用 Tool 把业务系统变成可调用函数模型再强它也不知道你的航班动态系统里存了什么数据。Tools 解决的就是这个问题把真实的业务方法暴露给模型让模型根据用户问题决定是否调用、传什么参数。4.1 Tools 解决什么问题没有 Tools 的时候你问 Agent“B-1234 航班现在什么状态”模型只能根据训练数据猜一个答案。有 Tools 之后模型会先调用一个查询航班状态的函数拿到真实结果再基于这个结果组织回答。这背后的机制是函数调用也叫函数调用/工具调用。Spring AI 把工具方法标记出来后会在每次请求时把工具的描述、参数结构发给模型模型内部决定“是否需要调用”需要的话以结构化 JSON 返回调用意图框架负责执行方法并把结果带回给模型。4.2 一个航班查询工具的示例在 Spring AI 里声明工具通常靠一个注解Component public class AviationTools { private final FlightInfoService flightInfoService; public AviationTools(FlightInfoService flightInfoService) { this.flightInfoService flightInfoService; } Tool(description 根据航班号查询指定日期的航班动态返回航班状态、计划起降时间、实际起降时间、登机口信息) public String queryFlightStatus(String flightNo, String date) { return flightInfoService.queryStatus(flightNo, date); } }Tool注解会把方法暴露给模型。方法名和描述要写得尽量清楚因为模型靠描述决定“要不要用这个工具”。name 参数建议用英文或拼音避免中文名在序列化时出问题description 要写清“这个工具能干什么、返回什么信息”。4.3 工具返回结构怎么设计工具返回给模型的内容推荐用 JSON 字符串因为模型解析 JSON 比解析自由文本稳定得多。比如{ flightNo: B-1234, status: DELAYED, scheduledDeparture: 2025-06-01 10:00:00, actualDeparture: 2025-06-01 11:30:00, gate: A12, reason: 机场流量控制 }失败时不要直接抛异常。工具执行失败是常见情况应该在返回内容里带错误信息让模型知道这次结果不可靠。比如{ error: FLIGHT_NOT_FOUND, message: 未查询到该航班信息请确认航班号和日期 }这里有个容易踩的坑不要给模型暴露过于复杂的方法签名。参数个数越少、类型越简单模型越容易正确调用。如果某个工具需要七八个参数模型很可能会传错。更好的做法是把多个入参封装成一个对象或者拆成几个更细的工具。工具是给模型用的“函数”不是给开发者的内部 API。写工具时站在模型的角度想它拿到什么信息才能做出判断。5. MCP 解决的是“外部系统接入标准”问题MCPModel Context Protocol是最近 AI Agent 开发里绕不开的名词也是 Spring AI 2.0 项目里的重点。它的定位和 Tools 有点接近但解决的问题不同。5.1 MCP 到底是什么MCP 的全称是 Model Context Protocol中文可以理解为“模型上下文协议”。它定义了一组标准让模型应用能够发现、配置、调用外部能力。MCP Server 负责暴露能力MCP Client 负责连接和调用。你可以把 MCP 理解成 AI 世界里的 USB 接口不管外面插的是鼠标、键盘还是硬盘只要都遵循 USB 标准就能即插即用。在 Spring AI 这个项目里MCP 的主要作用是让 Agent 能通过标准协议接入第三方系统或内部服务而不需要为每个系统写一套自定义对接代码。5.2 航空场景里哪些事适合用 MCP适合用 MCP 的场景通常有几个特征有明确的接口协议、会被多个 Agent 或应用复用、希望保持统一接入方式。在智能航空项目里可以重点考虑这些接入点气象服务把气象报文、机场天气、预警信息包成一个 MCP Server机场运行数据航班桥位、跑道状态、机场通告文档知识库将内部文档系统、Wiki、手册仓库做成 MCP Server第三方服务比如地图、天气、航班动态等外部数据源。这么做的好处是标准化。以后新接一个系统只要它实现了 MCP 协议Spring AI 就能直接发现并调用不需要反复改代码。5.3 Tools、MCP、Skills 三者到底怎么区分这三个概念很容易混尤其是热词“agent skill 和 mcp 有什么区别”被反复提。结合项目来看更清晰的区分是这样的概念核心定位举个例子Tools单点函数调用面向“一个动作”查询航班状态、查询库存、写一条记录MCP协议级接入方式面向“外部系统标准”通过 MCP Client 连接气象服务、文档系统Skills流程级技能封装面向“一类任务”航班延误处置流程、维修工单生成流程Tools 是最细的粒度MCP 是接入手段Skills 是更上层的流程封装。实际项目里它们会组合使用一个 Skill 内部可能调用多个 Tool而某个 Tool 的实现可能来自 MCP Server。5.4 MCP Client 接入的参考配置在 Spring AI 里接入 MCP Client通常需要配置连接信息。大致风格如下spring: ai: mcp: client: connections: - name: weather-mcp url: http://weather-mcp.internal:8080/配置了连接之后MCP Server 暴露的工具会自动被注册为 Agent 可用的工具。学习阶段可以先用一些开放的 MCP Server 做连通测试比如把天气、文档检索或浏览器自动化能力的 MCP Server 跑起来确认协议调用链路是通的再替换成航空内部服务。注意各版本对 MCP 配置项的支持不完全一样。遇到配置不生效时先去看官方示例和版本说明确认当前版本支持的字段和方式。6. 多层记忆会话记忆、知识记忆、业务记忆三层分开存才不乱很多 Agent 项目跑起来的第一个问题是“失忆”模型每次请求都是独立的用户前一轮说过的信息下一轮就忘了。多层记忆就是专门解决这个问题的。6.1 短期记忆会话上下文短期记忆指一次会话内的上下文。用户可以连续追问Agent 需要记住前几轮的内容。最常见的实现方式是把对话历史放在内存或 Redis 里每次请求时拼进提示词同时控制总长度。这里要注意 token 长度限制。对话轮次多了历史记录会越来越长不仅增加成本还可能撑爆模型上下文窗口。常见做法是滑动窗口只保留最近几轮或者做摘要让模型把前面内容压缩成一段摘要再和最近几轮一起传给模型。Redis 方案示例思路以 sessionId 为 key保存近 N 轮 message 列表设置过期时间请求时读取历史并拼装提示词。6.2 长期记忆知识库检索长期记忆解决的是“模型训练数据里没有企业知识”的问题。比如维修手册、操作规范、历史事故分析这些内容不可能靠模型预训练掌握。做法是把文档分块、向量化、存入向量库每次用户提问时做相似度检索把最相关的片段召回并塞进提示词。这就是常说的 RAG。这个项目里航空维修手册和运行规范是最典型的长期记忆来源。使用时的重点不是向量库本身而是分块策略和检索质量。分块太小语义不完整分块太大噪声多召回数量也不是越多越好top-k 选 3 到 5 个通常比较合适。6.3 业务记忆结构化业务数据业务记忆和知识记忆不同。知识记忆是文档类知识业务记忆是用户在系统里留下的结构化数据。比如机务人员的岗位、负责的机型、处理过的历史工单、常用偏好。这些数据原本就在数据库里Agent 不应该把它们塞进向量库而是按查询条件去数据库里取。三层记忆必须分开管理记忆类型存储方式生命周期典型数据短期记忆Redis / 内存一次会话内对话历史、用户输入长期记忆向量库长期手册、规范、历史文档业务记忆MySQL / PostgreSQL与业务数据一致工单、偏好、权限、组织信息6.4 记忆的边界和踩坑记忆不是越多越好。我见过不少项目什么对话都往长期记忆里塞结果检索噪声越来越大回答质量反而下降。正确的思路是只有可复用、跨会话仍然有价值的信息才需要长期记忆会话历史要有过期时间不能无限累积业务记忆必须配合权限控制Agent 不能访问超出权限范围的数据知识记忆要记录来源模型回答时应该能指出“这是来自哪份手册的哪一节”。还有一个容易忽略的问题不要混淆“知识库内容”和“模型自身知识”。如果知识库里没有相关内容Agent 应该明确说“现有手册中没有查到”而不是依靠模型记忆编造答案。这对航空这类对准确性要求高的场景尤其重要。7. Skills 是比 Tools 更上层的“作业流程”封装Skills 在 AI Agent 里越来越热门热词里“ai skills 怎么写”“agent skills”“skills推荐”被频繁提到。理解 Skills 的关键是把它和 Tools 区分开。7.1 Skills 和 Tools/MCP 的区别Tools 回答“帮我做一件事”Skills 回答“按什么流程完成一整类事”。比如查询航班状态是 Tool生成航班延误处置建议是 Skill因为它在内部需要先查航班状态、再查天气、再查备降机场最后按模板生成建议。Skills 的价值是沉淀人的经验。业务专家知道“航班延误后应该先看什么、再决定什么”这些经验如果只靠每次写提示词很容易写漏。封装成 Skill 之后Agent 遇到同类场景就能自动按标准流程执行。7.2 一个航班延误处置 Skill 怎么定义一种常见的做法是用配置或代码定义一个 Skill 的描述、输入输出和步骤再写一个执行器去组装调用。参考风格如下skill: id: delay-handling name: 航班延误处置建议 description: 当航班延误且需要生成旅客处置建议时使用 inputs: flightNo: 航班号 delayMinutes: 预计延误分钟数 steps: - tool: queryFlightStatus - tool: queryWeather - tool: queryAlternateAirport - action: generateDelayNotice output: template: | 航班{flightNo}因为{reason}预计延误{delayMinutes}分钟。 当前航班状态{status} 如需改签可通过{channel}办理。执行器内部则负责把每个步骤串起来调用查询工具、拿到结果、填入模板、返回给模型。这样即使后续业务规则变了只需要改配置模板不需要重写整个业务流程。7.3 Skills 写法建议写 Skills 时我会优先盯这几个点触发条件要清晰。描述里写清楚“什么时候用这个技能”否则模型会乱套步骤要可回退。某一步失败时要定义降级方案而不是直接中断输出模板要稳定。固定模板方便后续做内容校验也方便追责命名和目录要规范。项目里 Skills 多了以后没有明确命名规范会非常乱。Skill 不是写得越长越好。一个 Skill 只负责一类任务拆得太粗会变成万能处理器拆得太细又会产生大量碎片代码。8. 把它们组装成一个 Agent一个机务值班场景的完整调用链前面几部分都是单点能力。真正让项目“活”起来的是把多模型、Tools、MCP、多层记忆、Skills 组装成一个能跑完整任务的 Agent 工作流。8.1 Agent 的调用链路一次完整的 Agent 请求内部通常经过这样一条链路接收用户请求提取会话上下文短期记忆识别意图规划任务检索长期记忆和业务记忆根据规划调用 Tools / MCP 获取真实数据需要的话执行对应的 Skill模型基于所有信息生成最终回答对输出做格式校验和内容校验记录日志、更新会话历史和必要的历史归档。这条链路里任何一环都可能失败。所以不要一开始就把 Agent 想成一个黑盒要把它想象成一个由多个微服务拼起来的调用过程每一环都要能单独验证。8.2 一个完整案例假设机务值班员提问“B-1234 右侧发动机滑油消耗偏高我应该先查什么”这个请求在 Agent 系统里会经历这样几步短期记忆里找到这是一次新会话没有历史上下文需要从维修手册角度回答意图识别判断这是一个“维修知识咨询风险排查建议”任务长期记忆从维修手册知识库中召回“滑油消耗偏高”相关章节业务记忆查询该飞机的机龄、最近维修工单、历史滑油消耗记录Tools 调用维修工单查询服务获取最近一次滑油加注记录如果环境里已有 MCP 接入的发动机健康监控服务再通过 MCP 获取实时监控数据执行一个“滑油异常排查”Skill按其步骤生成排查顺序建议模型最终生成回答并附上手册章节来源和处理建议日志里记录本次请求调用了哪些工具、花了多少 token、耗时多久。整个过程看起来复杂但其实每个环节都有独立逻辑。开发时只要保证每个环节可以单独测试联调时问题就能准确定位。8.3 工作流设计要避开的坑防止死循环。模型可能在工具调用里反复尝试同样操作必须设置最大迭代次数或最大工具调用次数防止 token 爆炸。每轮只保留必要信息不要把所有历史、所有知识、所有工具结果全部堆进提示词防止输出不可验证。对航空这类场景回答必须给出依据不能只给结论防止并发击穿。多个用户同时发起 Agent 请求时模型 API、数据库、工具服务的连接压力会迅速放大。这些都不是“能跑通 Demo”时需要想的但一旦要发布到内网使用就会变成最让运维头疼的问题。9. 企业级落地真正的门槛不在模型在稳定性和可观测性一个能聊天的 Agent Demo 和能上线的 Agent 系统差距非常大。这里说的差距主要是三块稳定性、可观测性、数据安全。9.1 稳定性四件套任何一个 Agent 系统都要有超时、重试、限流、降级四个基础能力。超时模型调用、工具调用、MCP 调用都要设置超时时间不能无限等重试只对幂等的操作重试。查询航班状态可以重试写入类操作要谨慎限流给模型 API、工具服务都加上限流防止异常流量打垮下游降级模型服务不可用时返回兜底提示或者引导用户走人工渠道。9.2 日志和链路追踪一次 Agent 请求可能经过模型、工具、MCP、记忆、Skills任何一环出问题都不好查。所以必须给每次请求打上 traceId完整记录用户输入命中哪些记忆、召回哪些知识片段调用了哪些工具每个工具耗时多少、返回结果是什么使用了哪个模型、消耗了多少 token、生成了什么输出最终输出经过哪些校验。日志不是用来事后追责的它是排查问题的第一入口。没有日志的 Agent 系统出问题基本只能靠猜。9.3 数据安全合规航空业务涉及运行数据、旅客信息、企业内部规范数据合规是硬要求。开发环境要用脱敏数据生产环境要控制 Agent 的访问权限日志里不能打印真实旅客姓名、证件号、联系方式。即使项目只是学习用途也建议从一开始就养成“最少权限、最小采集、脱敏开发”的习惯。9.4 批量任务要单独设计Agent 有时候不只是在线问答还可能要做批量任务比如批量生成工单摘要、批量检查维修记录完整性。这种场景不要一次性把几百条请求并发丢给模型。正确做法是分批处理控制并发数用任务队列管理失败的任务自动重试每条任务的结果落库方便检查和补跑输出保留对应输入和依据方便追溯。10. 高频报错和通用排查顺序最后把我在类似项目里经常遇到的报错和排查经验整理一下。这些问题看起来五花八门实际上很多都是同一类原因。10.1 高频问题速查表现象可能原因排查方向模型返回 401/403API Key 错误、无权限先检查配置里的 key再直接调用模型接口验证请求一直超时网络不通、模型服务不可用检查 base-url、网络连通性、最大超时时间工具没有被调用Tool 描述不清晰、参数类型不匹配看模型返回的调用意图检查工具定义工具调用报错方法签名过于复杂、参数为空简化参数给参数加必填校验MCP 连接失败地址错误、协议版本不匹配先独立启动 MCP Server再通过客户端测试回答“不知道”知识库没有内容、分块太差检查知识库入库流程、切分大小、top-k 值输出乱码或格式乱模型选错、提示词没规定格式补充输出格式约束换更稳定的模型并发时大量超时连接池太小、模型 API 限流看连接池配置和 API 服务商限流策略10.2 通用排查顺序遇到问题不要上来就改代码按顺序排查先看现象是直接报错、卡住、还是输出不符合预期再看输入问题描述、文件格式、路径、编码是否正常再看配置模型名、key、base-url、MCP 地址、端口有没有写错再看依赖Spring Boot 和 Spring AI 版本是否匹配starter 是否齐全再看资源内存、CPU、Redis 连接、数据库连接、连接池是否打满再看参数超时时间、温度、并发数、分块大小、top-k 是否合理最后看功能边界这个问题是不是当前模型或工具本身处理不了。大部分问题都不是模型不聪明而是前置条件和输入材料没处理干净。把这一层排查顺序固化下来能省掉很多加班时间。这个项目真正落地时最该盯住的不是功能列表而是输入格式、日志、失败重试和权限控制。我见过不少团队把 Tools、MCP、Skills 全接上了结果一问实时数据、一跑批量任务就乱。原因不是模型不够强而是链路里没有明确的边界和观测手段。以前我们调一个接口先看日志再定位问题现在调 Agent 也一样只是环节更多了模型、工具、协议、记忆、技能每一环都要能独立验证。建议先把最小链路跑稳再逐步加复杂能力。这样即使某个环节出问题也能最快定位不至于整个系统变成黑盒。