转载--Spring AI Alibaba 生产级落地指南:从消息契约、状态编排到多 Agent 体系化建设
原文:https://mp.weixin.qq.com/s/ldd6Hvb8k82-0tjgpaVw2A
面向 Java 技术栈的 AI 应用,真正困难的部分从来不是“把模型调通”,而是把一个会思考、会调用工具、会维护上下文、会跨服务协作的 Agent 系统,做成一个可治理、可扩展、可观测、可回放、可恢复的生产平台。
Spring AI Alibaba 的价值,也不在于“再封装一次大模型 API”,而在于它试图把 AI 应用从 Demo 代码提升为工程系统。
目录
-
1. 为什么很多 AI Demo 一上线就失控
-
2. 理解 Spring AI Alibaba:不是 SDK,而是一套生产框架
-
3. 先抓住主线:Message 才是 AI 应用的基础设施
-
4. 核心原理:ReAct、StateGraph 与可恢复执行
-
5. 生产架构设计:协议层、治理层、状态层三层拆解
-
6. 实战案例:构建一个生产级电商智能客服与履约协同系统
-
7. 代码骨架:从单 Agent 到可扩展工作流
-
8. 高并发与可扩展设计:真正决定系统上限的部分
-
9. 多 Agent 架构:什么时候该拆,怎么拆,拆完如何治理
-
10. 上下文工程:不是保存聊天记录,而是控制推理成本
-
11. 工具治理与安全护栏:避免 Agent 从“聪明”变成“危险”
-
12. 可观测、压测与故障演练:生产系统的生命线
-
13. 部署落地:Kubernetes、Redis、Nacos、消息队列如何协同
-
14. 常见误区与架构建议
-
15. 演进路线:从单体 AI 能力到企业级 Agent 平台
-
16. 总结
1. 为什么很多 AI Demo 一上线就失控
一个 AI Demo 从“能回答问题”走到“能承担业务”,中间隔着一整套工程鸿沟。很多团队在第一阶段进展很快:
-
• 接一个模型 SDK
-
• 拼一个 Prompt
-
• 注册几个工具
-
• 暴露一个聊天接口
本地效果通常不错,甚至看起来已经具备“智能客服”“智能助手”“流程自动化”的雏形。但只要开始接真实流量,问题会立刻暴露:
-
• 上下文越来越长,响应越来越慢,成本越来越高
-
• 工具调用不可控,模型偶发误用高风险操作
-
• 多轮对话中状态丢失,用户上一轮说过的话下一轮忘掉
-
• 服务重启后流程中断,退款审批、工单流转无法恢复
-
• 多实例部署后会话分散,某个请求打到新 Pod 就像“失忆”
-
• 流式输出链路不稳定,前端经常收到半截响应
-
• 高峰期模型限流、外部工具超时、重试风暴相互放大
-
• 日志只看到一堆 HTTP 请求,看不到一次 Agent 决策到底做了什么
本质上,这类系统失败的原因不是模型不够强,而是把一个具备状态、决策、工具、副作用、协作关系的复杂系统,当成了普通 HTTP 接口来设计。
所以我们要先统一一个认知:
生产级 AI 应用不是“模型调用系统”,而是“以模型为决策核心的状态化分布式应用”。
这个认知一旦立住,就能理解为什么 Spring AI Alibaba 值得认真看。它提供的不是几个便捷 API,而是一套让 Java 团队可以把 AI 应用纳入熟悉工程范式的基础设施。
2. 理解 Spring AI Alibaba:不是 SDK,而是一套生产框架
如果只从表面看,Spring AI Alibaba 似乎只是围绕 Spring AI 做了一层增强封装。但从生产落地角度看,它真正解决的是四类问题:
-
1. 统一模型与工具抽象
让 ChatModel、Tool、Prompt、Memory、Message 等对象成为标准组件,而不是散落在业务代码里的临时拼装。 -
2. 统一 Agent 运行时
不再把 Agent 理解成一个黑箱函数,而是理解为一个可编排、可中断、可恢复、可观测的状态机。 -
3. 统一工程集成方式
把 AI 能力接入 Spring Boot、配置中心、服务发现、缓存、消息队列、可观测栈、Kubernetes。 -
4. 统一生产治理能力
包括上下文控制、人工审批、工具权限、分布式会话、流式输出、指标埋点、失败恢复、成本治理。
从架构视角,可以把 Spring AI Alibaba 理解为下面这张图:
+-----------------------------------------------------------------------------------+
| Business Applications |
| 智能客服 / 企业知识助手 / 工单助手 / 数据分析助手 / 流程协同 |
+-------------------------------------------+---------------------------------------+
| Agent / Workflow Layer | Platform / Governance |
| ReactAgent / Sequential / Parallel | Observation / Eval / Admin / Studio |
| Routing / Supervisor / Loop / Graph | Prompt Ops / Policy / Human Review |
+-------------------------------------------+---------------------------------------+
| Spring AI Alibaba Runtime & Integration |
| Message / Tool / Hook / Saver / Memory / A2A / MCP / Streaming / StateGraph |
+-----------------------------------------------------------------------------------+
| Spring AI Core Abstractions |
| ChatModel / Embedding / VectorStore / Advisor / Tool |
+-----------------------------------------------------------------------------------+
| Model Providers & Enterprise Infrastructure |
| DashScope / OpenAI / DeepSeek / Ollama / Redis / MQ / Nacos / K8s / OTEL |
+-----------------------------------------------------------------------------------+
这套分层意味着一个重要事实:
Spring AI Alibaba 的最佳使用方式不是“在 Controller 里直接调 Agent”,而是把它当成 AI 运行时内核,再围绕业务域构建应用层架构。
3. 先抓住主线:Message 才是 AI 应用的基础设施
很多文章讲 Spring AI Alibaba,会从 Agent、Tool Calling、多 Agent 开始。但如果站在资深架构师视角,我更建议先抓住 Message。
因为对生产系统而言,Message 不是“聊天消息 DTO”,而是三件事的统一载体:
-
• 协议载体:承载 user、assistant、system、tool 等角色语义
-
• 状态载体:承载一轮或多轮推理过程中的上下文快照
-
• 治理载体:承载审计、脱敏、回放、归档、成本统计、风险判定所需元数据
如果 Message 设计得太薄,后面所有能力都会变成散乱补丁。
如果 Message 设计得足够强,它就能支撑整套 AI 工程体系。
3.1 Message 为什么不是普通聊天记录
在一个生产级 Agent 系统里,一条消息往往至少包含以下信息:
|
维度 |
示例 |
作用 |
|---|---|---|
|
角色 |
system/user/assistant/tool |
区分消息语义 |
|
文本内容 |
用户提问、模型回复、工具结果 |
构成推理上下文 |
|
结构化片段 |
tool call、thinking、JSON 输出 |
支撑流程编排 |
|
线程标识 |
sessionId/threadId |
关联一次对话或工作流 |
|
幂等标识 |
messageId/requestId |
防止重复处理 |
|
时间信息 |
创建时间、过期时间 |
生命周期管理 |
|
风险标签 |
PII、敏感指令、高风险工具 |
安全治理 |
|
追踪信息 |
traceId、spanId |
链路观测 |
|
成本信息 |
token、模型名、时延 |
成本与性能分析 |
|
可见性标记 |
用户可见/系统可见 |
控制前端展示与内部决策 |
也就是说,Message 更像“AI 时代的事件对象”,而不仅仅是“聊天气泡”。
3.2 把 Message 看成协议层
所谓协议层,重点不是类名,而是边界清晰:
-
• 用户输入如何进入系统
-
• System Prompt 如何注入
-
• Tool Result 如何回写模型上下文
-
• 多 Agent 之间如何交换结果
-
• 前端如何消费流式 Token
-
• 审计系统如何复盘一次决策链路
如果协议不统一,就会出现几个典型问题:
-
• 某些工具返回的是自然语言,某些工具返回 JSON,模型无法稳定消费
-
• 多 Agent 交接时字段命名随意,路由逻辑越来越脆弱
-
• 流式响应和非流式响应不是同一种消息模型,前后端协议分裂
-
• 审批节点、回放节点、重试节点各自维护一套“上下文格式”
所以在项目一开始,就应该为消息建立明确契约。
3.3 一个生产可用的消息对象骨架
下面给一个工程里常见的消息对象设计骨架。它不依赖特定版本 API,重点是表达设计原则:
public record AiMessageEnvelope(
String messageId,
String sessionId,
String traceId,
MessageRole role,
String model,
String content,
List<ContentBlock> blocks,
Map<String, Object> metadata,
Instant createdAt
) {
}
public enum MessageRole {
SYSTEM,
USER,
ASSISTANT,
TOOL
}
public sealed interface ContentBlock
permits TextBlock, ToolCallBlock, ToolResultBlock, ReasoningBlock, JsonBlock {
}
public record TextBlock(String text) implements ContentBlock {
}
public record ToolCallBlock(
String callId,
String toolName,
String argumentsJson
) implements ContentBlock {
}
public record ToolResultBlock(
String callId,
String toolName,
String resultJson,
boolean success
) implements ContentBlock {
}
public record ReasoningBlock(String summary) implements ContentBlock {
}
public record JsonBlock(String json) implements ContentBlock {
}
这个模型的关键点不在“字段够不够多”,而在以下几个能力:
-
• 内容与元数据分离
-
• 文本块与工具块分离
-
• 对前端展示内容与内部治理内容分别建模
-
• 为回放、审计、脱敏、幂等等非功能需求预留空间
3.4 Message 为什么决定系统可治理性
后续所有能力,本质都依赖 Message:
-
• 上下文压缩:对哪些消息做摘要、保留哪些消息,依赖 Message 分类
-
• Tool Calling:模型输出工具调用结构,依赖 Message block 解析
-
• Human-in-the-Loop:中断前的待审批动作,需要作为消息或状态持久化
-
• 多 Agent 编排:一个 Agent 的输出,要能成为另一个 Agent 的输入
-
• SSE 流式输出:增量 Token 需要映射为前端可消费的事件消息
-
• 审计与合规:敏感词、敏感字段、敏感工具,都要能挂接到消息维度
因此,理解 Spring AI Alibaba,真正应该从 Message 开始。
它是协议层、治理层、状态层的共同基底。
4. 核心原理:ReAct、StateGraph 与可恢复执行
4.1 ReAct 并不是“让模型自己循环”
ReAct 的表面形式是:
Thought -> Action -> Observation -> Thought -> ...
但在工程上,它不能只是 while(true) 调模型。
真正可上线的 ReAct 必须具备四个约束:
-
• 有明确的停止条件
-
• 有状态持久化能力
-
• 有工具调用边界控制
-
• 有异常恢复与人工接管机制
因此,ReAct 在生产里更适合被理解成一个有状态的条件图。
4.2 StateGraph 的价值:把 Agent 变成可编排状态机
无论是单 Agent、审批流、专家协作,还是多阶段推理,本质上都可以抽象成:
-
• 节点:一次模型调用、一次工具调用、一次规则判断、一次人工审批
-
• 边:节点之间的转移关系
-
• 状态:节点运行过程中的上下文数据
这就是 Graph 运行时的价值。它带来的不是“画图更好看”,而是以下工程收益:
-
• 可以中断:某个节点前暂停,等待人工审批
-
• 可以恢复:进程重启后,从中断点继续
-
• 可以分流:根据状态条件走不同分支
-
• 可以回放:重建某次流程的执行轨迹
-
• 可以并行:多个子任务同时执行并合并结果
4.3 为什么生产系统必须支持可恢复执行
以退款助手为例,一次请求并不是“用户问一句,模型答一句”这么简单,它可能经历:
-
1. 意图识别
-
2. 订单查询
-
3. 退款资格校验
-
4. 风险判断
-
5. 人工审批
-
6. 发起退款
-
7. 发送通知
其中任何一步失败,都不应该让整条流程完全丢失。
如果系统无法恢复,只能让用户重新发起一遍,会造成:
-
• 体验差
-
• 数据不一致
-
• 重复副作用
-
• 审计链断裂
所以真正的生产级 Agent,必须具备“长流程、可中断、可恢复、可幂等”能力。
4.4 一个典型 StateGraph 工作流骨架
@Configuration
public class RefundWorkflowConfiguration {
@Bean
public CompiledGraph refundWorkflow(
KeyStrategyFactory keyStrategyFactory,
RefundIntentNode refundIntentNode,
EligibilityNode eligibilityNode,
RiskReviewNode riskReviewNode,
HumanReviewNode humanReviewNode,
SubmitRefundNode submitRefundNode,
NotifyNode notifyNode
) {
StateGraph graph = new StateGraph(keyStrategyFactory)
.addNode("intent", node_async(refundIntentNode))
.addNode("eligibility", node_async(eligibilityNode))
.addNode("risk_review", node_async(riskReviewNode))
.addNode("human_review", node_async(humanReviewNode))
.addNode("submit_refund", node_async(submitRefundNode))
.addNode("notify", node_async(notifyNode))
.addEdge(START, "intent")
.addEdge("intent", "eligibility")
.addEdge("eligibility", "risk_review")
.addConditionalEdges(
"risk_review",
edge_async(state -> {
boolean needHumanReview = (boolean) state.value("needHumanReview").orElse(false);
return needHumanReview ? "manual" : "auto";
}),
Map.of(
"manual", "human_review",
"auto", "submit_refund"
)
)
.addEdge("human_review", "submit_refund")
.addEdge("submit_refund", "notify")
.addEdge("notify", END);
return graph.compile(CompileConfig.builder()
.interruptBefore("human_review")
.build());
}
}
注意,真正让这个图具备生产能力的,不是 addNode 这些 API,而是下面这些约束:
-
• 每个节点输入输出都可结构化
-
• 每个状态字段有合并策略
-
• 中断点可持久化
-
• 副作用节点有幂等保护
-
• 失败节点可重试或转人工
4.5 KeyStrategy 的工程意义
状态图一旦复杂,最容易出问题的不是路由,而是状态合并。
例如:
-
•
messages应该追加,而不是覆盖 -
•
riskScore应该覆盖,而不是累加 -
•
toolResults可能需要按 key 合并 -
•
auditTrail需要 append
一个常见设计如下:
@Bean
public KeyStrategyFactory keyStrategyFactory() {
return () -> {
Map<String, KeyStrategy> strategies = new HashMap<>();
strategies.put("messages", new AppendStrategy());
strategies.put("toolResults", new MergeStrategy());
strategies.put("riskScore", new ReplaceStrategy());
strategies.put("approved", new ReplaceStrategy());
strategies.put("auditTrail", new AppendStrategy());
strategies.put("costSnapshot", new ReplaceStrategy());
return strategies;
};
}
这实际上是在做一件非常重要的事:
把 AI 运行时里的“共享内存写入规则”显式化。
这能极大降低并发分支、长流程和多 Agent 协作下的数据混乱风险。
5. 生产架构设计:协议层、治理层、状态层三层拆解
围绕 Spring AI Alibaba 落地企业级系统时,我建议把架构拆成三层:
5.1 协议层:解决“怎么说”
协议层负责统一表达:
-
• 用户消息如何封装
-
• 模型消息如何落库
-
• 工具调用如何描述
-
• 工具返回如何结构化
-
• SSE 如何推送增量事件
-
• 多 Agent 如何交换上下文
协议层最重要的原则是:
-
• 不把自然语言字符串当作唯一边界
-
• 对 tool call、tool result、risk signal、summary、event 等建立结构化契约
-
• 让前端、后端、模型、工具、审计系统都面向同一套消息语义
5.2 治理层:解决“能不能放行”
治理层负责控制:
-
• 哪些工具能被调用
-
• 哪些参数需要脱敏
-
• 哪些操作必须人工审批
-
• 哪些请求需要降级
-
• 哪些会话应做摘要
-
• 哪些输出不能直接回用户
治理层本质上是在给模型自由度上“护栏”。
这层如果缺失,模型越强,风险反而越大。
治理层常见能力包括:
-
• 工具白名单与黑名单
-
• 按租户/角色/环境控制工具可见性
-
• Prompt 模板版本管理
-
• Token 预算与成本限额
-
• 输出 JSON Schema 校验
-
• 高风险动作审批
-
• 敏感信息脱敏与回显控制
5.3 状态层:解决“记住什么、何时恢复”
状态层是 AI 应用最容易被低估的部分。它不仅要记忆对话,还要维护:
-
• 当前流程进行到哪个节点
-
• 工具调用过哪些外部系统
-
• 哪些副作用已经提交
-
• 哪些消息已摘要
-
• 当前风险评分是多少
-
• 当前是否处于人工审批等待中
-
• 当前线程是否可以重入
一个成熟的状态层通常会区分三类状态:
|
状态类型 |
说明 |
存储建议 |
|---|---|---|
|
短期会话状态 |
最近消息、临时工具结果、流式输出缓存 |
Redis |
|
长流程状态 |
工作流节点、审批状态、恢复点 |
Redis + DB |
|
审计归档状态 |
完整消息链、工具入参与结果、风险动作 |
OLTP/日志系统/对象存储 |
5.4 三层之间的关系
用户请求
->
协议层:消息标准化、角色标注、事件封装
->
治理层:权限校验、工具筛选、预算控制、风险评估
->
状态层:加载线程上下文、恢复中断点、写回执行状态
->
Agent / Graph Runtime 执行
->
治理层:输出审查、脱敏、合规过滤
->
协议层:转为 SSE/HTTP/A2A 响应
这三层拆开后,系统会明显更稳:
-
• 协议问题不污染业务逻辑
-
• 治理逻辑不散落在每个 Tool 里
-
• 状态恢复不耦合 Controller
这就是从 Demo 进入工程系统的关键一步。
6. 实战案例:构建一个生产级电商智能客服与履约协同系统
为了把上面的原理落到地上,我们用一个真实感较强的案例贯穿全文。
6.1 业务目标
我们要做的不是一个“回答 FAQ 的聊天机器人”,而是一个具备以下能力的智能客服系统:
-
• 查询订单、物流、退款、发票、优惠券
-
• 基于知识库回答售前售后问题
-
• 能判断问题是否超出权限并转人工
-
• 对退款、改地址、补偿发券等动作走风险控制
-
• 与订单、支付、物流、会员、工单等服务协同
-
• 支持 Web/App/H5 多端流式会话
-
• 支持高峰活动期间扩容与降级
6.2 领域拆分
从领域上,我们不建议把所有能力都堆进一个大 Agent,而是至少拆成以下职责:
|
组件 |
职责 |
|---|---|
Conversation Gateway |
接收会话请求,维护线程、鉴权、限流、SSE |
Customer Service Agent |
处理对话、解释、澄清、工具选择 |
Knowledge Agent |
面向知识库检索与答案生成 |
Order Tool Service |
查询订单、履约、发票等只读能力 |
Refund Workflow |
有状态退款流程,含审批与幂等控制 |
Risk Engine |
风险评分、策略判定、黑白名单 |
Audit Service |
存储消息链、工具调用链、审批记录 |
Ops Platform |
观测、回放、评估、灰度、Prompt 管理 |
6.3 参考部署拓扑
Client(Web/App)
|
API Gateway / Ingress
|
Conversation Gateway
|
+-------------------------------+------------------------------+
| | |
| Customer Service Agent |
| | |
| +-----------------+-----------------+ |
| | | |
| Knowledge Agent Refund Workflow |
| | | |
| Vector Store / KB Risk Engine / Human Ops |
| |
+-------------------------------+------------------------------+
| | | |
Order Service Payment Service Logistics Service Ticket Service
|
Redis Cluster / MQ / Nacos / Observability / Audit Store
这个拓扑体现了两个原则:
-
• 对话与副作用分离
-
• 决策与执行分离
也就是说,Agent 可以负责理解与决策,但真正的业务副作用最好交给受控工作流和业务服务去完成。
7. 代码骨架:从单 Agent 到可扩展工作流
下面开始给出更偏生产骨架的示例。
示例重点不是追求“最少代码”,而是体现可扩展性。
7.1 Maven 依赖建议
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>${spring-ai-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-agent-framework</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-graph-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-observation-extension</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
</dependencies>
建议额外补齐:
-
• 向量检索相关依赖
-
• MQ 客户端
-
• 审计存储访问层
-
• 数据库访问组件
7.2 配置基线
server:
port: 8080
spring:
application:
name: customer-service-agent
ai:
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY}
chat:
options:
model: qwen-max
temperature: 0.2
top-p: 0.8
data:
redis:
timeout: 2s
lettuce:
pool:
max-active: 128
max-idle: 32
min-idle: 8
cluster:
nodes:
- redis-0:6379
- redis-1:6379
- redis-2:6379
resilience4j:
circuitbreaker:
instances:
llmProvider:
sliding-window-type: count_based
sliding-window-size: 20
failure-rate-threshold: 50
wait-duration-in-open-state: 30s
toolRefund:
sliding-window-size: 20
failure-rate-threshold: 40
timelimiter:
instances:
llmProvider:
timeout-duration: 25s
toolRefund:
timeout-duration: 5s
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
tracing:
sampling:
probability: 1.0
7.3 会话请求模型
public record ChatRequest(
@NotBlank String sessionId,
@NotBlank String userId,
@NotBlank String tenantId,
@NotBlank String message,
String channel,
Map<String, Object> ext
) {
}
public record ChatResponse(
String sessionId,
String traceId,
String answer,
boolean escalatedToHuman
) {
}
7.4 工具接口不要直接暴露业务服务
很多项目第一版会这样写:
@Tool
public RefundResult refund(String orderId, BigDecimal amount) {
return refundService.refund(orderId, amount);
}
这在生产里风险很高,因为工具边界过于粗暴。更好的方式是引入工具门面层:
@Component
public class RefundToolFacade {
private final RefundEligibilityService eligibilityService;
private final RefundCommandService refundCommandService;
private final RiskFacade riskFacade;
public RefundToolFacade(
RefundEligibilityService eligibilityService,
RefundCommandService refundCommandService,
RiskFacade riskFacade
) {
this.eligibilityService = eligibilityService;
this.refundCommandService = refundCommandService;
this.riskFacade = riskFacade;
}
@Tool(name = "check_refund_eligibility", description = """
校验订单是否满足退款条件。
当用户明确表达退款意图时调用。
输入订单号,返回是否满足退款、原因、可退金额、是否需要人工审批。
该工具不会执行实际退款。
""")
public RefundEligibilityResult checkEligibility(
@ToolParam(description = "订单号") String orderId,
ToolExecutionContext context
) {
UserPrincipal user = context.get(UserPrincipal.class);
RefundEligibilityResult result = eligibilityService.check(user.userId(), orderId);
RiskDecision riskDecision = riskFacade.evaluate(orderId, user.userId(), result.refundableAmount());
return result.withRisk(riskDecision.level(), riskDecision.needHumanReview());
}
@Tool(name = "create_refund_ticket", description = """
创建退款申请单,不直接执行打款。
仅在用户确认后调用。
返回退款申请单号与后续处理状态。
""")
public RefundTicketResult createRefundTicket(
@ToolParam(description = "订单号") String orderId,
@ToolParam(description = "退款原因") String reason,
ToolExecutionContext context
) {
UserPrincipal user = context.get(UserPrincipal.class);
return refundCommandService.createTicket(user.userId(), orderId, reason);
}
}
这个设计的意义是:
-
• 读操作与写操作分离
-
• 风险判断前置
-
• 真正副作用动作从“直接退款”降级为“创建工单/申请单”
-
• 模型可调用的工具能力更加安全
7.5 Agent 装配时要把治理能力前置
@Configuration
public class CustomerServiceAgentConfiguration {
@Bean
public ReactAgent customerServiceAgent(
ChatModel chatModel,
ToolCallbackProvider toolCallbackProvider,
RedisAgentStateStore redisAgentStateStore,
HumanReviewPolicy humanReviewPolicy,
ToolVisibilityPolicy toolVisibilityPolicy
) {
return ReactAgent.builder()
.name("customer-service-agent")
.model(chatModel)
.systemPrompt("""
你是电商平台的生产级客服助手。
你的目标是优先帮助用户解决问题,但不得绕过业务规则。
规则如下:
1. 查询类请求可直接调用只读工具。
2. 对退款、改地址、补偿发券、账户信息修改等高风险动作,必须先确认并进入审批流程。
3. 对不确定信息不得编造,优先调用工具或知识库。
4. 如果工具失败,应向用户解释系统繁忙,并给出明确下一步,而不是重复无效调用。
5. 不得向用户暴露内部风险分或内部审核策略细节。
""")
.tools(toolCallbackProvider.getToolCallbacks())
.toolSelectionStrategy(context ->
toolVisibilityPolicy.selectTools(
(String) context.get("tenantId"),
(String) context.get("intent"),
(String) context.get("riskLevel")
)
)
.hooks(
new SummarizationHook(SummarizationConfig.builder()
.maxMessages(24)
.compressionThreshold(6000)
.build()),
new HumanInTheLoopHook(HumanInTheLoopConfig.builder()
.sensitiveTools(
"create_refund_ticket",
"modify_address",
"grant_coupon"
)
.build()),
new TokenBudgetHook(15000),
new OutputSchemaGuardHook()
)
.saver(redisAgentStateStore)
.maxIterations(12)
.build();
}
}
这里真正体现“生产级”的点有四个:
-
• 不是把工具全部暴露给模型,而是可见性可控
-
• 不是等风险发生后拦截,而是在 Agent 层预设行为边界
-
• 不是只记录消息,而是显式配置状态存储
-
• 不是任由模型无限循环,而是限制迭代次数与预算
7.6 用应用服务而不是 Controller 直接驱动 Agent
@Service
public class ConversationApplicationService {
private final ReactAgent customerServiceAgent;
private final ConversationStateRepository conversationStateRepository;
private final AuditService auditService;
public ConversationApplicationService(
ReactAgent customerServiceAgent,
ConversationStateRepository conversationStateRepository,
AuditService auditService
) {
this.customerServiceAgent = customerServiceAgent;
this.conversationStateRepository = conversationStateRepository;
this.auditService = auditService;
}
public Flux<ChatEvent> stream(ChatRequest request) {
String traceId = UUID.randomUUID().toString();
RunnableConfig config = RunnableConfig.builder()
.threadId(request.sessionId())
.metadata(Map.of(
"tenantId", request.tenantId(),
"userId", request.userId(),
"traceId", traceId,
"channel", Objects.toString(request.channel(), "web")
))
.build();
conversationStateRepository.touch(request.sessionId(), request.userId(), traceId);
auditService.recordUserInput(request.sessionId(), request.userId(), request.message(), traceId);
return customerServiceAgent.stream(request.message(), config)
.map(output -> ChatEventMapper.toEvent(output, traceId))
.doOnNext(event -> auditService.recordEvent(request.sessionId(), traceId, event))
.doOnError(ex -> auditService.recordFailure(request.sessionId(), traceId, ex))
.doOnComplete(() -> conversationStateRepository.finishTurn(request.sessionId(), traceId));
}
}
这种写法的好处是:
-
• Controller 只负责协议转换
-
• Agent 生命周期、审计、状态持久化由应用服务统一控制
-
• 方便后续接 WebSocket、SSE、A2A、MQ 等多个入口
7.7 SSE 接口要支持事件分型
@RestController
@RequestMapping("/api/ai/conversations")
public class ConversationController {
private final ConversationApplicationService applicationService;
public ConversationController(ConversationApplicationService applicationService) {
this.applicationService = applicationService;
}
@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> stream(@Valid @RequestBody ChatRequest request) {
return applicationService.stream(request)
.map(event -> ServerSentEvent.<String>builder()
.event(event.type())
.id(event.eventId())
.data(event.payload())
.build())
.timeout(Duration.ofSeconds(90));
}
}
建议至少区分这些事件:
-
•
token:流式文本片段 -
•
tool_call:模型发起工具调用 -
•
tool_result:工具返回结果 -
•
approval_required:进入人工审批 -
•
complete:本轮完成 -
•
error:发生异常
这样前端、客服工作台、审计平台都能消费同一条事件流,而不是只拿到一串字符串。
8. 高并发与可扩展设计:真正决定系统上限的部分
AI 系统一旦进入生产,高并发与可扩展设计的重要性通常会迅速超过 Prompt 调优。
8.1 性能瓶颈一般不止在模型
一次完整对话的时延,通常来自以下几个部分:
|
环节 |
典型问题 |
|---|---|
|
鉴权与线程加载 |
Redis 热点、线程状态读取慢 |
|
Prompt 构造 |
上下文膨胀、摘要不及时 |
|
模型调用 |
Provider 限流、首 Token 延迟高 |
|
工具调用 |
下游服务超时、串行调用过多 |
|
结果编排 |
JSON 解析和状态合并开销 |
|
流式输出 |
网关缓存、Nginx 超时、客户端断连 |
|
审计写入 |
同步落库放大 RT |
因此,优化不能只盯模型。
8.2 先区分三类请求
高并发设计里,我建议先把流量按性质拆开:
-
1. 纯问答类
无副作用、只读工具为主,可以追求低延迟。 -
2. 检索增强类
需要知识库召回、重排、生成,重点优化召回链路与上下文压缩。 -
3. 事务协同类
涉及退款、改地址、工单流转等副作用,重点是可靠性与幂等,不要盲目追求极低延迟。
不同类型请求不能用同一套 SLA 和资源池去管理。
8.3 并发模型建议:入口非阻塞,工具隔离,副作用异步化
一个比较稳妥的方案是:
-
• 网关层使用 WebFlux/SSE,减少连接阻塞
-
• 模型调用使用隔离线程池或虚拟线程
-
• 外部工具调用按域隔离线程池
-
• 耗时副作用流程通过 MQ 异步化
-
• 人工审批流程天然异步,不与用户对话线程强绑定
示意如下:
HTTP/SSE Request
-> Reactive Gateway
-> Agent Runtime
-> LLM Pool
-> Query Tool Pool
-> Risk Tool Pool
-> Approval Queue
-> Async Workflow Queue
8.4 Redis 设计不要只存聊天记录
很多团队使用 Redis 时,只做一件事:存消息列表。
生产里远远不够。
更合理的 Redis Key 设计示例:
|
Key |
用途 |
TTL |
|---|---|---|
ai:session:{sessionId}:messages |
最近 N 轮消息 |
24h |
ai:session:{sessionId}:summary |
摘要结果 |
24h |
ai:workflow:{threadId}:state |
Graph 状态快照 |
7d |
ai:workflow:{threadId}:lock |
并发执行锁 |
5min |
ai:request:{requestId}:dedup |
请求去重 |
10min |
ai:tool:{toolCallId}:result |
工具调用缓存 |
1h |
ai:budget:{tenantId}:{day} |
Token/费用预算 |
1d |
这背后体现的是:
Redis 在 AI 系统里既是会话存储,也是流程状态缓存、幂等辅助、限流辅助、预算辅助。
8.5 幂等性是高并发下的第一原则
涉及工具副作用时,必须把幂等设计做在模型之外。
例如退款申请:
-
• 用户可能重复点击
-
• 网关可能超时重试
-
• Agent 可能重复推理
-
• 下游服务可能响应丢失
如果没有幂等保护,就会重复创建工单,甚至重复退款。
推荐方案:
public class IdempotentRefundCommandService {
private final RefundTicketRepository refundTicketRepository;
public RefundTicketResult createTicket(String userId, String orderId, String reason, String requestId) {
return refundTicketRepository.findByRequestId(requestId)
.orElseGet(() -> {
RefundTicket ticket = RefundTicket.create(userId, orderId, reason, requestId);
refundTicketRepository.save(ticket);
return RefundTicketResult.from(ticket);
});
}
}
关键点:
-
• 幂等键来自请求或工具调用 ID
-
• 幂等控制放在业务服务/数据库,不依赖模型“别重复调用”
-
• 审批前后都要考虑重复提交
8.6 缓存策略要做“语义层”和“工具层”分离
在 AI 应用里,缓存一般有三层:
-
1. 工具结果缓存
例如物流轨迹、商品详情、运费规则等短时变化不大的只读数据。 -
2. 检索结果缓存
对热门 FAQ 或常见意图的知识检索结果缓存。 -
3. 生成结果缓存
只适合强模板、强约束、低个性化场景,不适合复杂个性化回复。
不要一上来就做“模型回答全量缓存”,否则命中率低、风险高、解释性差。
8.7 限流不能只做在 API Gateway
AI 系统至少要有四层限流:
-
• 用户级限流:防止单用户滥用
-
• 租户级限流:保护整体资源池
-
• 模型级限流:适配 Provider QPS/TPS 配额
-
• 工具级限流:保护内部核心系统
尤其是工具级限流非常重要。
否则大模型可能在高峰期把订单、物流、支付接口放大成压力源。
8.8 成本治理必须内建
高并发下,AI 成本问题本质上不是“单次调用贵”,而是:
-
• 多轮对话导致 token 指数放大
-
• 冗余工具描述拖长 prompt
-
• 低价值请求用了高阶模型
-
• 工具失败导致无意义重试
-
• 多 Agent 场景中多模型并行调用
建议至少内建以下能力:
-
• 按意图路由模型
-
• 按渠道设置预算
-
• 摘要与裁剪策略
-
• 工具动态筛选
-
• Prompt 模板去冗余
-
• 长尾低价值请求降级
9. 多 Agent 架构:什么时候该拆,怎么拆,拆完如何治理
9.1 不是任务一复杂就该上多 Agent
多 Agent 很容易被过度设计。
在不少场景下,一个设计良好的单 Agent + 工具集合就足够。
只有满足以下情况时,才建议拆分:
-
• 领域边界明显不同,例如售后、物流、财务、法务
-
• 工具集差异明显,全部暴露会造成模型混淆
-
• 不同子任务需要不同模型、不同 SLA、不同治理策略
-
• 需要跨团队独立演进和发布
9.2 六类常见协作模式
|
模式 |
适用场景 |
优势 |
风险 |
|---|---|---|---|
|
单 Agent |
能力边界明确 |
简单直接 |
工具集合易膨胀 |
|
Sequential |
固定处理流水线 |
可控性高 |
灵活性低 |
|
Parallel |
并行取数/多路检索 |
延迟更优 |
结果合并复杂 |
|
Routing |
根据意图路由专家 |
成本可控 |
路由错判会误分流 |
|
Supervisor |
复杂任务拆解与协调 |
适合复杂推理 |
调度开销大 |
|
Graph |
高定制、多条件流程 |
可恢复、强治理 |
工程复杂度高 |
9.3 一个更实用的原则:先领域化,再 Agent 化
不要先问“我有几个 Agent”。
应该先问:
-
• 我有哪些领域边界
-
• 哪些能力是解释型,哪些是事务型
-
• 哪些副作用必须走强规则
-
• 哪些组件需要独立扩缩容
通常更稳妥的演进路径是:
-
1. 先按领域拆工具与服务
-
2. 再把高复杂度领域演化为独立 Agent
-
3. 最后把长流程统一收敛到 Graph/Workflow
9.4 多 Agent 拆分后的治理重点
多 Agent 一旦拆出来,最容易失控的不是模型质量,而是“系统间协议不一致”。
必须统一的内容包括:
-
• 消息契约
-
• traceId 与 threadId 传递
-
• 工具与子 Agent 权限边界
-
• 统一错误码与恢复动作
-
• 统一审计字段
-
• 统一超时与重试原则
如果这些不统一,多 Agent 只会把复杂度从单进程扩散到整个系统。
10. 上下文工程:不是保存聊天记录,而是控制推理成本
很多人把上下文工程理解成“把聊天记录塞给模型”。
这只是最原始、也是最昂贵的做法。
10.1 生产里的上下文应该分层
建议至少拆成四层:
-
1. 会话层
最近几轮用户与助手对话。 -
2. 任务层
当前工作流状态、待确认动作、工具中间结果。 -
3. 记忆层
用户画像、长期偏好、历史关键事实摘要。 -
4. 知识层
外部知识库召回结果、规则说明、业务文档。
这四层不能简单拼成一个大 prompt,而应按场景装配。
10.2 摘要不是压缩文本,而是压缩状态
一个好的摘要策略,不只是“把历史消息变短”,而是保留后续推理真正需要的信息:
-
• 用户目标
-
• 已确认事实
-
• 已完成动作
-
• 未完成动作
-
• 风险决策结果
-
• 当前约束条件
例如:
public record ConversationSummary(
String userGoal,
List<String> confirmedFacts,
List<String> pendingActions,
List<String> riskNotes,
Instant updatedAt
) {
}
这类结构化摘要,对后续推理远比自然语言长段总结更稳定。
10.3 上下文装配策略建议
一个常见的装配流程如下:
用户输入
->
意图识别
->
加载最近消息
->
加载结构化摘要
->
如果需要,加载用户长期记忆
->
如果需要,做知识检索
->
根据工具可见性筛选工具描述
->
构造最终 Prompt
这里最关键的能力不是“存”,而是“选”。
上下文工程本质上是一个装配与裁剪问题。
10.4 长对话下的实用建议
-
• 最近消息只保留必要窗口,不要无限追加
-
• 对工具返回做结构化摘要,而不是原样拼接
-
• 高频固定规则放 system prompt,不要轮轮重复拼接
-
• 对知识库结果先重排再注入
-
• 对跨天会话优先加载摘要,不直接加载全量历史
11. 工具治理与安全护栏:避免 Agent 从“聪明”变成“危险”
11.1 工具设计的第一原则:模型负责决策,不负责越权
大模型非常擅长“决定下一步可能是什么”,但它不应该直接拥有无限业务执行权限。
因此在企业系统中,我们一般会把工具分成三类:
|
类型 |
示例 |
原则 |
|---|---|---|
|
查询类工具 |
订单查询、物流查询、FAQ 检索 |
可相对开放 |
|
建议类工具 |
推荐优惠方案、生成工单草稿 |
可开放,但需校验输出 |
|
执行类工具 |
退款、改地址、发券、删账户 |
必须强约束 |
11.2 建议使用“意图识别 + 权限判断 + 工具可见性”三段式
public interface ToolVisibilityPolicy {
List<ToolCallback> selectTools(String tenantId, String intent, String riskLevel);
}
@Component
public class DefaultToolVisibilityPolicy implements ToolVisibilityPolicy {
private final ToolRegistry toolRegistry;
public DefaultToolVisibilityPolicy(ToolRegistry toolRegistry) {
this.toolRegistry = toolRegistry;
}
@Override
public List<ToolCallback> selectTools(String tenantId, String intent, String riskLevel) {
return toolRegistry.list().stream()
.filter(tool -> tool.supportsIntent(intent))
.filter(tool -> tool.supportsTenant(tenantId))
.filter(tool -> tool.allowForRiskLevel(riskLevel))
.map(RegisteredTool::callback)
.toList();
}
}
这样做的价值非常大:
-
• 降低 prompt 体积
-
• 降低工具误选率
-
• 避免高风险工具暴露给不该用的请求
11.3 Human-in-the-Loop 不该只是一句“请人工确认”
人工审批真正要解决的是:
-
• 暂停在哪个节点
-
• 给审核员看到哪些上下文
-
• 审核超时怎么办
-
• 审核拒绝后如何回退
-
• 审核通过后如何恢复执行
因此,一套完整的人审链路至少应包含:
-
• 审批任务 ID
-
• 待审批动作摘要
-
• 风险标签
-
• 审批 SLA
-
• 审批结果回写接口
-
• 流程恢复机制
11.4 输出也要治理
很多团队只拦工具,不拦输出。
这同样危险。
需要治理的输出包括:
-
• 泄露内部策略
-
• 泄露其他用户信息
-
• 承诺超出公司政策的赔付
-
• 输出未校验的结构化数据
-
• 伪造工具执行结果
因此建议在最终输出前增加:
-
• 敏感词与敏感字段检查
-
• JSON Schema 验证
-
• 关键业务承诺规则校验
-
• 用户可见信息脱敏
12. 可观测、压测与故障演练:生产系统的生命线
一个没有观测的 Agent 系统,本质上不可运维。
12.1 至少观测四条链路
-
1. 对话链路
用户输入、模型响应、流式事件、完成状态。 -
2. 工具链路
哪个工具被调用、入参是什么、耗时多久、是否失败。 -
3. 工作流链路
当前节点、状态变更、分支决策、中断恢复。 -
4. 成本链路
用了哪个模型、多少 token、多少钱、失败重试次数。
12.2 推荐的指标体系
|
指标 |
含义 |
|---|---|
ai_requests_total |
总请求数 |
ai_request_duration_seconds |
请求耗时分布 |
ai_stream_first_token_seconds |
首 Token 时延 |
ai_model_calls_total |
模型调用次数 |
ai_model_errors_total |
模型调用失败数 |
ai_tool_calls_total |
工具调用次数 |
ai_tool_timeout_total |
工具超时数 |
ai_human_review_total |
进入人工审批次数 |
ai_workflow_resume_total |
流程恢复次数 |
ai_token_input_total |
输入 token 总量 |
ai_token_output_total |
输出 token 总量 |
ai_cost_total |
估算费用 |
12.3 Trace 才是排障关键
一次用户请求最好贯穿以下组件共享同一个 traceId:
-
• 网关
-
• Agent Runtime
-
• Tool Service
-
• Graph Workflow
-
• 审批系统
-
• 审计系统
这样在排查“为什么这次退款失败”时,才能看到完整链路:
用户请求
-> Agent 判定退款意图
-> 调用资格校验工具
-> 风险评分过高
-> 进入人工审批
-> 审批超时
-> 返回用户稍后通知
没有链路追踪时,这些信息会散落在多个日志系统里,基本无法复盘。
12.4 压测不能只测 HTTP QPS
AI 系统压测至少要覆盖:
-
• 普通问答压测
-
• 知识检索压测
-
• 工具调用压测
-
• 流式连接数压测
-
• 审批中断恢复压测
-
• Provider 限流场景压测
-
• 下游服务超时场景压测
尤其要模拟这些异常:
-
• 模型 429/5xx
-
• Redis 短时抖动
-
• 工具服务 3s 到 10s 延迟飙升
-
• SSE 客户端主动断连
-
• Graph 恢复点读取失败
-
• 审批系统回调重复投递
12.5 故障演练要从第一天开始
建议建立最基础的故障演练清单:
-
• 模型超时后是否降级到低阶模型或人工兜底
-
• 工具调用失败后是否给出明确用户提示
-
• 重启后是否能恢复待审批流程
-
• Redis 故障时是否能切换只读能力
-
• 审批超时后是否能关闭流程并归档
AI 系统的可靠性不是写出来的,是演练出来的。
13. 部署落地:Kubernetes、Redis、Nacos、消息队列如何协同
13.1 K8s 部署基线
apiVersion: apps/v1
kind: Deployment
metadata:
name: customer-service-agent
spec:
replicas: 4
selector:
matchLabels:
app: customer-service-agent
template:
metadata:
labels:
app: customer-service-agent
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
spec:
containers:
- name: app
image: registry.example.com/ai/customer-service-agent:1.0.0
ports:
- containerPort: 8080
env:
- name: AI_DASHSCOPE_API_KEY
valueFrom:
secretKeyRef:
name: ai-secrets
key: dashscope-api-key
- name: SPRING_DATA_REDIS_CLUSTER_NODES
value: redis-0:6379,redis-1:6379,redis-2:6379
- name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR
value: nacos-headless:8848
resources:
requests:
cpu: "2"
memory: "2Gi"
limits:
cpu: "4"
memory: "4Gi"
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
几点建议:
-
• AI 服务不要把资源申请压得过低,否则高峰期 GC 和线程争用会非常明显
-
• SSE 场景要特别关注连接数上限和网关超时
-
• readiness 一定要覆盖关键依赖的可用性检查
13.2 Redis 在架构里的角色
Redis 通常承担:
-
• 会话上下文缓存
-
• 工作流状态恢复
-
• 去重锁与并发锁
-
• Token 预算与限流辅助
-
• 热点工具结果缓存
因此 Redis 对 AI 系统往往是核心依赖,而不是“可有可无的优化组件”。
13.3 Nacos 与 A2A 的价值
当多 Agent 或领域服务拆分后,Nacos 这类注册发现组件开始发挥价值:
-
• 发现不同 Agent 服务实例
-
• 动态路由到不同领域能力
-
• 支持按版本灰度
-
• 支持环境隔离
如果再结合 A2A 通讯能力,多 Agent 间调用可以更加标准化,而不是到处手写 HTTP Client。
13.4 MQ 不是为了炫架构,而是为了隔离副作用
以下场景建议天然异步化:
-
• 用户会话结束后的审计归档
-
• 长耗时知识处理
-
• 工单创建后的后续通知
-
• 风险复核回调
-
• 人工审批后的流程恢复事件
这样可以把对话链路 RT 和副作用链路解耦开。
13.5 Nginx 与 SSE 的配置注意点
很多流式问题不在应用,而在代理层:
location /api/ai/conversations/stream {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
chunked_transfer_encoding on;
}
关键点:
-
• 关闭 buffering
-
• 保持长连接
-
• 放宽读写超时
否则本地能流式,线上经常只剩“攒一坨再吐给前端”。
14. 常见误区与架构建议
14.1 误区一:把 Agent 当成 Service 方法
错误做法:
-
• Controller 直接调 Agent
-
• Agent 直接调数据库
-
• Tool 直接做副作用
后果是边界混乱,无法治理,无法恢复,无法审计。
建议:
-
• Agent 负责决策
-
• 应用服务负责编排
-
• 领域服务负责业务规则
-
• Workflow 负责长流程与恢复
14.2 误区二:把长对话历史全量喂给模型
后果:
-
• 成本失控
-
• 延迟升高
-
• 噪声信息干扰推理
建议:
-
• 结构化摘要
-
• 分层记忆
-
• 按意图装配上下文
14.3 误区三:看到多 Agent 就兴奋
后果:
-
• 系统拆得太早
-
• 观测、协议、审计跟不上
-
• 实际收益不如单 Agent + Graph
建议:
-
• 先单 Agent 做稳
-
• 再按领域与 SLA 拆分
14.4 误区四:让模型直接操作核心交易
后果:
-
• 风险不可控
-
• 副作用重复
-
• 审计链断裂
建议:
-
• 通过工具门面层隔离
-
• 高风险动作审批
-
• 副作用动作幂等
14.5 误区五:只有日志,没有回放
很多 AI 问题单看日志定位不了,因为模型推理、工具调用、状态流转是一个复合过程。
建议:
-
• 保留消息链
-
• 保留工具入参与结果摘要
-
• 保留工作流节点轨迹
-
• 建立最小化回放能力
15. 演进路线:从单体 AI 能力到企业级 Agent 平台
阶段一:能力验证期
目标:
-
• 快速验证用户价值
-
• 建立最小工具集合
-
• 跑通基础流式会话
架构特征:
-
• 单体 Spring Boot
-
• 单 Agent
-
• Redis 做基础会话缓存
阶段二:生产接入期
目标:
-
• 接业务真实流量
-
• 建立审计、限流、回放、降级
-
• 引入摘要与成本治理
架构特征:
-
• Agent + 应用服务分层
-
• Tool 门面层
-
• SSE + Redis 状态共享
-
• 基础观测与告警
阶段三:流程化协同期
目标:
-
• 把高风险、高价值动作流程化
-
• 建立审批与恢复能力
-
• 控制副作用与幂等
架构特征:
-
• 引入 StateGraph
-
• 引入人工审批与任务恢复
-
• 引入 MQ 异步事件
阶段四:多 Agent 平台期
目标:
-
• 按领域拆分能力
-
• 按团队独立演进
-
• 建立统一协议、观测、治理平台
架构特征:
-
• 多 Agent / A2A
-
• 注册发现
-
• Prompt Ops、Eval、灰度发布
-
• 统一策略中心与审计中心
16. 总结
Spring AI Alibaba 真正值得企业团队重视的地方,不是它把 Tool Calling、多 Agent、Graph、SSE 这些关键词堆在了一起,而是它给 Java 体系提供了一条更像“工程建设”而不是“脚本拼装”的 AI 落地路径。
如果要把全文压缩成一句话,我会这样总结:
Spring AI Alibaba 的核心价值,是把 AI 应用从“模型调用代码”提升为“有消息契约、有状态编排、有治理护栏、有恢复能力”的生产系统。
真正的生产级落地,建议你重点抓住以下几件事:
-
1. 先把 Message 当成基础设施来设计,而不是聊天记录
-
2. 用协议层、治理层、状态层拆开 AI 系统复杂度
-
3. 让 Agent 负责决策,让工作流负责副作用和恢复
-
4. 把高并发、幂等、预算、限流、观测当成第一天就要建设的能力
-
5. 多 Agent 不要为了概念而拆,而要为了领域边界、SLA 和治理边界而拆
最后再强调一次,AI 应用的难点并不是“模型会不会回答”,而是:
-
• 回答是否可信
-
• 工具是否安全
-
• 状态是否可恢复
-
• 成本是否可控
-
• 系统是否经得住高峰和故障
如果你的目标不是做一个 Demo,而是做一个能进入生产、能承担真实业务责任的 AI 系统,那么 Spring AI Alibaba 的正确打开方式一定不是“从 Prompt 开始”,而是“从架构开始”。
附:生产落地检查清单
在项目上线前,建议至少逐项确认以下内容:
架构与边界
-
• 是否区分了协议层、治理层、状态层
-
• 是否区分了对话决策与业务副作用
-
• 是否避免 Controller 直接驱动复杂 Agent 逻辑
消息与状态
-
• 是否有统一 Message 契约
-
• 是否支持会话状态共享
-
• 是否支持长流程中断与恢复
-
• 是否对关键动作做了幂等控制
工具与安全
-
• 是否有工具白名单/可见性控制
-
• 是否对高风险工具做审批或规则保护
-
• 是否对最终输出做脱敏与合规校验
性能与成本
-
• 是否做上下文裁剪与摘要
-
• 是否做用户级、租户级、模型级、工具级限流
-
• 是否有模型路由与降级策略
-
• 是否有 Token/费用预算控制
可观测与运维
-
• 是否有模型、工具、流程、成本四类指标
-
• 是否有全链路 traceId
-
• 是否可回放典型会话与工作流
-
• 是否做过限流、超时、断连、恢复等故障演练
这份清单做完,才算真正进入“生产级”。
更多推荐




所有评论(0)