原文:https://mp.weixin.qq.com/s/ldd6Hvb8k82-0tjgpaVw2A

面向 Java 技术栈的 AI 应用,真正困难的部分从来不是“把模型调通”,而是把一个会思考、会调用工具、会维护上下文、会跨服务协作的 Agent 系统,做成一个可治理、可扩展、可观测、可回放、可恢复的生产平台。
Spring AI Alibaba 的价值,也不在于“再封装一次大模型 API”,而在于它试图把 AI 应用从 Demo 代码提升为工程系统。


目录

  1. 1. 为什么很多 AI Demo 一上线就失控

  2. 2. 理解 Spring AI Alibaba:不是 SDK,而是一套生产框架

  3. 3. 先抓住主线:Message 才是 AI 应用的基础设施

  4. 4. 核心原理:ReAct、StateGraph 与可恢复执行

  5. 5. 生产架构设计:协议层、治理层、状态层三层拆解

  6. 6. 实战案例:构建一个生产级电商智能客服与履约协同系统

  7. 7. 代码骨架:从单 Agent 到可扩展工作流

  8. 8. 高并发与可扩展设计:真正决定系统上限的部分

  9. 9. 多 Agent 架构:什么时候该拆,怎么拆,拆完如何治理

  10. 10. 上下文工程:不是保存聊天记录,而是控制推理成本

  11. 11. 工具治理与安全护栏:避免 Agent 从“聪明”变成“危险”

  12. 12. 可观测、压测与故障演练:生产系统的生命线

  13. 13. 部署落地:Kubernetes、Redis、Nacos、消息队列如何协同

  14. 14. 常见误区与架构建议

  15. 15. 演进路线:从单体 AI 能力到企业级 Agent 平台

  16. 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. 1. 统一模型与工具抽象
    让 ChatModel、Tool、Prompt、Memory、Message 等对象成为标准组件,而不是散落在业务代码里的临时拼装。

  2. 2. 统一 Agent 运行时
    不再把 Agent 理解成一个黑箱函数,而是理解为一个可编排、可中断、可恢复、可观测的状态机。

  3. 3. 统一工程集成方式
    把 AI 能力接入 Spring Boot、配置中心、服务发现、缓存、消息队列、可观测栈、Kubernetes。

  4. 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. 1. 意图识别

  2. 2. 订单查询

  3. 3. 退款资格校验

  4. 4. 风险判断

  5. 5. 人工审批

  6. 6. 发起退款

  7. 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. 1. 纯问答类
    无副作用、只读工具为主,可以追求低延迟。

  2. 2. 检索增强类
    需要知识库召回、重排、生成,重点优化召回链路与上下文压缩。

  3. 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. 1. 工具结果缓存
    例如物流轨迹、商品详情、运费规则等短时变化不大的只读数据。

  2. 2. 检索结果缓存
    对热门 FAQ 或常见意图的知识检索结果缓存。

  3. 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. 1. 先按领域拆工具与服务

  2. 2. 再把高复杂度领域演化为独立 Agent

  3. 3. 最后把长流程统一收敛到 Graph/Workflow

9.4 多 Agent 拆分后的治理重点

多 Agent 一旦拆出来,最容易失控的不是模型质量,而是“系统间协议不一致”。

必须统一的内容包括:

  • • 消息契约

  • • traceId 与 threadId 传递

  • • 工具与子 Agent 权限边界

  • • 统一错误码与恢复动作

  • • 统一审计字段

  • • 统一超时与重试原则

如果这些不统一,多 Agent 只会把复杂度从单进程扩散到整个系统。


10. 上下文工程:不是保存聊天记录,而是控制推理成本

很多人把上下文工程理解成“把聊天记录塞给模型”。
这只是最原始、也是最昂贵的做法。

10.1 生产里的上下文应该分层

建议至少拆成四层:

  1. 1. 会话层
    最近几轮用户与助手对话。

  2. 2. 任务层
    当前工作流状态、待确认动作、工具中间结果。

  3. 3. 记忆层
    用户画像、长期偏好、历史关键事实摘要。

  4. 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. 1. 对话链路
    用户输入、模型响应、流式事件、完成状态。

  2. 2. 工具链路
    哪个工具被调用、入参是什么、耗时多久、是否失败。

  3. 3. 工作流链路
    当前节点、状态变更、分支决策、中断恢复。

  4. 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. 1. 先把 Message 当成基础设施来设计,而不是聊天记录

  2. 2. 用协议层、治理层、状态层拆开 AI 系统复杂度

  3. 3. 让 Agent 负责决策,让工作流负责副作用和恢复

  4. 4. 把高并发、幂等、预算、限流、观测当成第一天就要建设的能力

  5. 5. 多 Agent 不要为了概念而拆,而要为了领域边界、SLA 和治理边界而拆

最后再强调一次,AI 应用的难点并不是“模型会不会回答”,而是:

  • • 回答是否可信

  • • 工具是否安全

  • • 状态是否可恢复

  • • 成本是否可控

  • • 系统是否经得住高峰和故障

如果你的目标不是做一个 Demo,而是做一个能进入生产、能承担真实业务责任的 AI 系统,那么 Spring AI Alibaba 的正确打开方式一定不是“从 Prompt 开始”,而是“从架构开始”。


附:生产落地检查清单

在项目上线前,建议至少逐项确认以下内容:

架构与边界

  • • 是否区分了协议层、治理层、状态层

  • • 是否区分了对话决策与业务副作用

  • • 是否避免 Controller 直接驱动复杂 Agent 逻辑

消息与状态

  • • 是否有统一 Message 契约

  • • 是否支持会话状态共享

  • • 是否支持长流程中断与恢复

  • • 是否对关键动作做了幂等控制

工具与安全

  • • 是否有工具白名单/可见性控制

  • • 是否对高风险工具做审批或规则保护

  • • 是否对最终输出做脱敏与合规校验

性能与成本

  • • 是否做上下文裁剪与摘要

  • • 是否做用户级、租户级、模型级、工具级限流

  • • 是否有模型路由与降级策略

  • • 是否有 Token/费用预算控制

可观测与运维

  • • 是否有模型、工具、流程、成本四类指标

  • • 是否有全链路 traceId

  • • 是否可回放典型会话与工作流

  • • 是否做过限流、超时、断连、恢复等故障演练

这份清单做完,才算真正进入“生产级”。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐