多智能体实战:基于 Spring AI Alibaba 构建生产级高并发故事创作智能体系统1. 引言在很多团队的实际落地过程中,“多智能体”很容易停留在 Demo 层面:能跑通几个 Agent 互相调用能生成一段看起来不错的内容能在单机环境完成一次链路演示但一旦进入真实业务环境,问题会马上出现:请求量上来后,模型调用延迟和成本不可控多个智能体之间上下文不一致,生成结果互相冲突缺少编排、限流、重试、降级、缓存、可观测,系统无法稳定运行代码层面只展示了简单样例,距离生产级实现差距很大本文不再停留在“如何写一个多 Agent Demo”,而是从架构师和资深工程师视角,系统讲清楚如何基于Spring AI Alibaba构建一个真正可落地的故事创作多智能体系统。文章重点包括:多智能体协作的原理与架构设计面向高并发场景的工程化方案生产级代码实现与核心设计模式缓存、异步化、限流、降级、可观测与部署方案一个贴近业务的完整案例:在线故事创作平台如果你希望的不只是“能生成故事”,而是“能支撑业务上线”,这篇文章会更接近你真正需要的答案。2. 业务背景与问题定义2.1 目标业务场景我们假设要建设一个在线 AI 创作平台,面向 C 端作者、内容社区、教育平台或互动小说应用,提供如下能力:用户输入主题、风格、受众、篇幅、角色偏好系统自动完成故事策划、角色设定、场景设计、章节生成、风格统一支持大批量并发生成支持流式返回和异步任务模式支持作品二次编辑、续写、重写典型请求示例:{ "theme": "废土世界中的亲情与救赎", "genre": "科幻冒险", "targetAudience": "18+", "chapters": 6, "style": "偏电影化叙事", "keywords": ["AI失控", "避难所", "兄妹", "牺牲"], "language": "zh-CN" }2.2 为什么适合用多智能体故事创作天然不是一个单点能力问题,而是一个复杂任务分解问题。一个高质量故事至少包含:世界观和主线冲突设计角色目标、动机与成长弧场景和章节推进文风统一和润色结果校验与质量评估如果把所有任务交给一个“大一统 Prompt”,常见问题是:输出长度不稳定结构松散风格漂移人物设定前后矛盾场景信息遗漏因此更合理的方式是:将复杂创作任务拆解为多个专业化智能体,由编排层协调执行,再由汇总智能体整合输出。2.3 真实工程挑战当系统进入生产环境,真正难的不是“写 Prompt”,而是解决以下问题:如何定义智能体职责边界,避免重复劳动和上下文污染如何保证多个智能体之间的数据契约一致如何让模型调用具备超时、重试、熔断、限流能力如何应对高并发下的线程池、连接池、消息积压与缓存击穿如何支持同步、流式、异步三种调用模式如何沉淀监控指标,定位慢调用、坏输出和成本异常3. 多智能体系统的核心设计原理3.1 从“Prompt 拼接”到“任务编排”多智能体系统的本质不是多个 LLM 实例,而是面向复杂任务的分工协作系统。它通常由四层组成:接入层:接收用户请求,做鉴权、限流、参数校验编排层:负责任务拆解、执行顺序、并行控制、超时控制智能体层:执行具体任务,如情节设计、人物塑造、风格统一基础设施层:模型网关、缓存、数据库、MQ、监控、日志、追踪3.2 多智能体协作模式常见协作模式有三种:模式一:串行链式协作适合强依赖型流程,例如:先生成故事大纲再基于大纲生成人物再基于人物和大纲生成章节优点:结果可控上下文依赖明确缺点:总耗时较长某一步失败会阻塞整体模式二:并行协作适合弱依赖或可提前拆分的任务,例如:角色设定场景设定风格约束优点:总时延低适合高并发优化缺点:汇总阶段复杂容易出现结果不一致模式三:评审闭环协作适合质量要求高的场景:生成智能体产出初稿评审智能体检查逻辑、风格、重复率、敏感内容修订智能体进行再加工优点:内容质量更稳定缺点:Token 成本更高处理链路更长实际生产中,往往是“串行 + 并行 + 评审闭环”的组合。3.3 本文采用的协作拓扑这里有三个关键设计思想:共享上下文对象:避免每个 Agent 自己拼 Prompt,导致上下文失真编排层控制执行:Agent 只关注能力,不关心调度细节评审闭环:将质量控制前置,而不是把低质量输出直接交给用户4. 生产级总体架构设计4.1 系统总体架构4.2 分层职责1)API Gateway职责:Token 校验与租户隔离接口限流和黑白名单请求透传 traceId路由同步接口与异步接口2)应用服务层职责:参数校验幂等控制返回任务单或流式响应选择合适执行模式3)编排层 Orchestrator职责:任务拆解并行编排超时控制审核闭环失败补偿4)Agent 能力层职责:只负责领域任务不耦合数据库、MQ、控制器输入输出通过 DTO/Domain Object 约束5)基础设施层职责:模型调用适配缓存消息驱动异步执行数据持久化监控和审计4.3 为什么不建议直接在 Controller 里串 Agent很多初学者实现是这样的:Controller 接收请求直接 new/注入多个 Agent顺序调用模型拼一个结果返回这种做法在 Demo 阶段没问题,但在生产环境存在明显风险:缺少职责分离,无法扩展无法复用编排逻辑无法做统一超时、熔断、重试测试困难后续难以接入异步任务、审核流、回调机制正确方式应该是:Controller 只做接入Application Service 只做用例编排入口Orchestrator 负责业务级工作流Agent 负责纯能力实现5. 技术选型与理由组件技术选型作用选型理由Web 框架Spring Boot 3.x服务承载生态成熟,便于整合监控、配置、数据层AI 框架Spring AI Alibaba模型接入统一抽象 ChatModel、Prompt、Advisor、Tool 等能力服务治理Spring Cloud Alibaba配置/注册发现与 Nacos、Sentinel 等整合较强缓存Redis结果缓存/幂等/热点保护高性能,适合分布式场景数据库MySQL 8.x请求、作品、审计持久化事务与结构化查询能力稳定MQKafka 或 RocketMQ异步生成、削峰填谷解耦同步链路与离线生成限流熔断Sentinel / Resilience4j流量治理保护模型网关和下游服务可观测Micrometer + Prometheus + Grafana + Zipkin/Tempo监控与追踪便于定位慢调用和异常链路容器化Docker + Kubernetes部署与扩缩容生产环境标准配置6. 领域建模:先把数据结构设计对多智能体系统最容易失控的点之一,就是各 Agent 输入输出随意定义。生产环境里,必须先做统一领域对象建模。6.1 核心请求对象package com.example.story.domain; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import java.util.List; public record StoryRequest( @NotBlank String requestId, @NotBlank String theme, @NotBlank String genre, @NotBlank String style, @NotBlank String targetAudience, @Min(1) @Max(20) int chapters, @NotEmpty ListString keywords, String language ) { }6.2 共享上下文对象package com.example.story.domain; import java.time.Instant; import java.util.ArrayList; import java.util.List; public class StoryContext { private final String requestId; private final StoryRequest request; private StoryOutline outline; private ListStoryCharacter characters = new ArrayList(); private ListStoryScene scenes = new ArrayList(); private ListStoryChapter chapters = new ArrayList(); private StoryReview review; private Instant startedAt = Instant.now(); public StoryContext(String requestId, StoryRequest request) { this.requestId = requestId; this.request = request; } public String requestId() { return requestId; } public StoryRequest request() { return request; } public StoryOutline outline() { return outline; } public void setOutline(StoryOutline outline