AI Agent 开发实战(十一):Multi-Agent 协作编排

AI Agent 开发实战(十一):Multi-Agent 协作编排

单个 Agent 再强,也只能干一件事。真正复杂的问题,需要多个 Agent 协作完成。今天聊 Multi-Agent 的编排模式:谁当领导、谁干活、谁拍板、出了错怎么兜底。读完这篇,你能在自己的项目里设计出靠谱的多 Agent 协作方案。


一、为什么需要 Multi-Agent?

单个 Agent 的局限:

markdown 复制代码
单 Agent 瓶颈
│
├── 1. 上下文窗口有限
│   └── 塞太多指令 → 遵循率下降
│
├── 2. 工具集臃肿
│   └── 100 个工具选哪个?选择成本高
│
├── 3. 角色混乱
│   └── 让一个 Agent 同时写代码 + 做测试 + 写文档 → 质量全拉
│
└── 4. 容错差
    └── 一个环节出错,整个链路崩

Multi-Agent 的核心思想:拆职责、专精化、可组合

复制代码
Multi-Agent 优势
│
├── 职责单一 → 每个 Agent 只做一件事,Prompt 更精准
├── 工具隔离 → 每个 Agent 只访问自己需要的工具
├── 并行执行 → 无依赖的步骤可以同时跑
├── 容错兜底 → 单个 Agent 失败不影响整体
└── 可测试性 → 每个 Agent 可以独立测试和优化

二、四种经典编排模式

2.1 顺序链(Pipeline)

最简单的模式:Agent A 的输出作为 Agent B 的输入,逐级传递。

css 复制代码
顺序链
│
├── 输入 → [翻译Agent] → [润色Agent] → [排版Agent] → 输出
│
├── 特点
│   ├── 简单可靠
│   ├── 每步只依赖上一步
│   └── 延迟 = 各步之和
│
└── 适用场景
    ├── 内容生产流水线
    └── 数据处理管道

代码示例:

java 复制代码
public class PipelineOrchestrator {

    private final List<Agent> agents;

    public String execute(String input) {
        String current = input;
        for (Agent agent : agents) {
            current = agent.run(current);
            if (current == null) {
                throw new AgentException(
                    "Agent [" + agent.getName() + "] returned null");
            }
        }
        return current;
    }
}

2.2 分发-聚合(Fan-out / Fan-in)

一个协调者把任务分给多个专业 Agent,各自独立完成后汇总。

css 复制代码
分发-聚合
│
├── 协调者
│   ├── → [代码审查Agent]
│   ├── → [安全扫描Agent]
│   ├── → [性能分析Agent]
│   └── → [风格检查Agent]
│
├── 各 Agent 并行执行
│
├── 协调者聚合结果
│   ├── 合并各 Agent 报告
│   ├── 去重和冲突处理
│   └── 生成最终报告
│
└── 适用场景
    ├── 代码审查
    ├── 多维度分析
    └── 并行信息收集

代码示例:

java 复制代码
public class FanOutOrchestrator {

    private final List<Agent> workers;
    private final Agent aggregator;

    public String execute(String input) {
        // 1. 并行分发给所有 Worker
        List<CompletableFuture<String>> futures = workers.stream()
            .map(worker -> CompletableFuture.supplyAsync(
                () -> worker.run(input)))
            .toList();

        // 2. 等待所有 Worker 完成
        List<String> results = futures.stream()
            .map(CompletableFuture::join)
            .toList();

        // 3. 聚合结果
        String combinedInput = String.join("\n---\n", results);
        return aggregator.run(combinedInput);
    }
}

2.3 路由模式(Router)

一个路由 Agent 根据输入判断该交给谁处理,类似微服务网关。

css 复制代码
路由模式
│
├── 输入 → [路由Agent]
│           │
│           ├── 技术问题 → [技术支持Agent]
│           ├── 订单相关 → [订单处理Agent]
│           ├── 投诉建议 → [客服Agent]
│           └── 无法判断 → [通用Agent]
│
├── 特点
│   ├── 动态选择,按需分发
│   ├── 路由 Agent 的判断力是关键
│   └── 可以多级路由
│
└── 适用场景
    ├── 客服系统
    ├── 智能工单分配
    └── 多技能助手

代码示例:

java 复制代码
public class RouterOrchestrator {

    private final Agent router;
    private final Map<String, Agent> routeTable;

    public String execute(String input) {
        // 1. 路由 Agent 决定走哪条路
        String route = router.run(input);

        // 2. 查表获取目标 Agent
        Agent target = routeTable.get(route);
        if (target == null) {
            target = routeTable.get("default");
        }

        // 3. 执行目标 Agent
        return target.run(input);
    }
}

2.4 辩论-裁决(Debate / Jury)

多个 Agent 对同一问题给出不同方案,由一个裁决 Agent 或投票机制选最优。

css 复制代码
辩论-裁决
│
├── 输入 → [方案A Agent] → 方案 A
│      → [方案B Agent] → 方案 B
│      → [方案C Agent] → 方案 C
│
├── [裁决Agent] 评估各方案
│   ├── 打分
│   ├── 指出各方案优劣
│   └── 选出最佳或合并
│
├── 特点
│   ├── 提高决策质量
│   ├── 适合开放性、创造性问题
│   └── 成本高(多次 LLM 调用)
│
└── 适用场景
    ├── 方案评审
    ├── 代码架构设计
    └── 创意生成

三、编排模式对比

维度 顺序链 分发-聚合 路由 辩论-裁决
复杂度
延迟 高(串行) 低(并行) 高(多轮)
成本 1x Nx 1-2x Nx+1
容错 差(链式) 好(隔离)
适用 流水线 多维度 分类 决策
关键风险 单点故障 聚合冲突 路由误判 成本失控

四、状态管理:Agent 间怎么传数据?

Multi-Agent 最大的坑不是编排,而是状态传递

4.1 三种状态传递方式

css 复制代码
状态传递方式
│
├── 1. 直接传参(最简单)
│   ├── Agent A 的输出 → Agent B 的输入
│   ├── 适合简单字符串传递
│   └── 问题:结构复杂时容易丢信息
│
├── 2. 共享上下文(最常用)
│   ├── 所有 Agent 读写同一个 Context 对象
│   ├── 类似黑板模式(Blackboard Pattern)
│   └── 问题:并发写入、覆盖冲突
│
└── 3. 消息总线(最解耦)
    ├── Agent 通过消息队列通信
    ├── 发布-订阅模式
    └── 问题:实现复杂、调试难

4.2 共享上下文实现

java 复制代码
public class AgentContext {

    private final Map<String, Object> data = new ConcurrentHashMap<>();
    private final List<String> executionLog = new CopyOnWriteArrayList<>();

    // 存数据
    public void put(String key, Object value) {
        data.put(key, value);
        executionLog.add(
            Thread.currentThread().getName() + " set " + key);
    }

    // 取数据
    @SuppressWarnings("unchecked")
    public <T> T get(String key, Class<T> type) {
        return (T) data.get(key);
    }

    // 获取执行日志(调试用)
    public List<String> getExecutionLog() {
        return Collections.unmodifiableList(executionLog);
    }
}

4.3 上下文设计原则

原则 说明 反例
命名空间隔离 各 Agent 用前缀区分 key 两个 Agent 都写 result
只追加不覆盖 用 list 而非单值 后写的覆盖先写的
不可变传递 传深拷贝而非引用 Agent A 修改了 Agent B 正在读的对象
记录来源 每个 key 标记写入者 不知道数据谁写的

五、错误处理:一个 Agent 挂了怎么办?

5.1 三级容错策略

yaml 复制代码
容错策略
│
├── Level 1: 重试
│   ├── 对失败 Agent 自动重试(最多 N 次)
│   ├── 适合:LLM 调用超时、网络抖动
│   └── 不适合:逻辑错误、参数错误
│
├── Level 2: 降级
│   ├── 主 Agent 失败 → 切换到备选 Agent
│   ├── 复杂 Agent 失败 → 切换到简单版本
│   └── 适合:非核心路径
│
└── Level 3: 隔离
    ├── 失败 Agent 的结果标记为 error
    ├── 其他 Agent 继续执行
    └── 适合:分发-聚合模式

5.2 容错代码示例

java 复制代码
public class ResilientOrchestrator {

    private static final int MAX_RETRY = 2;

    public String executeWithRetry(Agent agent, String input) {
        Exception lastError = null;

        for (int i = 0; i <= MAX_RETRY; i++) {
            try {
                return agent.run(input);
            } catch (AgentException e) {
                lastError = e;
                log.warn("Agent [{}] attempt {} failed: {}",
                    agent.getName(), i + 1, e.getMessage());
            }
        }

        // 重试耗尽,走降级
        Agent fallback = agent.getFallback();
        if (fallback != null) {
            log.warn("Falling back to [{}] for input",
                fallback.getName());
            return fallback.run(input);
        }

        throw new AgentException("All retries exhausted", lastError);
    }
}

六、实战:代码审查 Multi-Agent 系统

把四种模式组合起来,设计一个完整的代码审查系统。

6.1 系统架构

css 复制代码
代码审查 Multi-Agent 架构
│
├── [路由Agent] 判断变更类型
│   ├── 前端变更 → [前端审查组]
│   │   ├── [样式检查Agent]
│   │   ├── [组件规范Agent]
│   │   └── [可访问性Agent]
│   │
│   ├── 后端变更 → [后端审查组]
│   │   ├── [代码规范Agent]
│   │   ├── [安全扫描Agent]
│   │   └── [性能分析Agent]
│   │
│   └── 全栈变更 → 两组都执行
│
├── [聚合Agent] 汇总各组结果
│   ├── 去重
│   ├── 按严重度排序
│   └── 生成审查报告
│
└── [辩论Agent](可选)
    └── 对冲突意见进行裁决

6.2 核心实现

java 复制代码
public class CodeReviewOrchestrator {

    private final Agent router;
    private final Map<String, List<Agent>> reviewGroups;
    private final Agent aggregator;

    public ReviewResult review(String codeDiff) {
        // 1. 路由:判断走哪个审查组
        String group = router.run(codeDiff);

        // 2. 分发:并行执行对应审查组
        List<Agent> agents = reviewGroups.getOrDefault(group,
            reviewGroups.get("backend")); // 默认后端审查

        List<CompletableFuture<ReviewResult>> futures =
            agents.stream()
                .map(agent -> CompletableFuture.supplyAsync(
                    () -> {
                        try {
                            return agent.run(codeDiff);
                        } catch (AgentException e) {
                            return ReviewResult.error(
                                agent.getName(), e);
                        }
                    }))
                .toList();

        // 3. 聚合:汇总所有结果
        List<ReviewResult> results = futures.stream()
            .map(CompletableFuture::join)
            .toList();

        // 4. 合并
        String combined = results.stream()
            .map(ReviewResult::getReport)
            .collect(Collectors.joining("\n\n"));

        return aggregator.run(combined);
    }
}

6.3 Agent Prompt 设计示例

安全扫描 Agent 的 System Prompt:

markdown 复制代码
你是一个代码安全审查专家。你的职责:
1. 检查 SQL 注入风险
2. 检查 XSS 漏洞
3. 检查硬编码密钥/密码
4. 检查不安全的反序列化
5. 检查权限绕过风险

输出格式:
- 严重级别:CRITICAL / HIGH / MEDIUM / LOW
- 问题描述
- 所在位置(行号)
- 修复建议

只报告安全问题,不关心代码风格。

七、编排框架对比

7.1 主流框架

框架 语言 编排方式 特点
LangGraph Python 图(有向无环图) 灵活、可循环、有状态
CrewAI Python 角色协作 上手快、角色定义直观
AutoGen Python 对话驱动 Agent 间自然语言交流
Spring AI Java 编程式 企业级、与 Spring 生态融合
Semantic Kernel C# 编程式 微软生态、插件化

7.2 Spring AI 实现 Multi-Agent

java 复制代码
@Configuration
public class MultiAgentConfig {

    @Bean
    public Agent codeReviewAgent(
            ChatClient chatClient,
            List<ToolCallback> tools) {
        return Agent.builder()
            .name("code-reviewer")
            .chatClient(chatClient)
            .systemPrompt("""
                你是代码审查专家,专注于安全和规范。
                严格按照审查清单逐项检查。
                """)
            .tools(tools)
            .build();
    }

    @Bean
    public Agent securityAgent(ChatClient chatClient) {
        return Agent.builder()
            .name("security-scanner")
            .chatClient(chatClient)
            .systemPrompt("""
                你是安全扫描专家,只关注安全漏洞。
                """)
            .build();
    }

    @Bean
    public Agent aggregatorAgent(ChatClient chatClient) {
        return Agent.builder()
            .name("aggregator")
            .chatClient(chatClient)
            .systemPrompt("""
                你是审查报告聚合器。
                合并多份审查报告,去重,按严重度排序。
                """)
            .build();
    }
}

八、踩坑实录

坑 1:Agent 间上下文泄露

css 复制代码
问题:Agent A 的中间状态泄露到 Agent B 的 Prompt
原因:共享上下文对象,未做命名空间隔离
修复:
├── 每个 Agent 读写自己的 namespace
├── 敏感中间态不写入共享上下文
└── 聚合前做数据脱敏

坑 2:无限递归

arduino 复制代码
问题:路由 Agent 把请求路由给自己 → 无限循环
原因:路由表配置错误
修复:
├── 设置最大路由深度(如 3 层)
├── 路由历史写入 Context,检测循环
└── 无法路由时强制走 default

坑 3:聚合结果矛盾

arduino 复制代码
问题:安全 Agent 说"拒绝",性能 Agent 说"通过"
原因:各 Agent 优化目标不同
修复:
├── 明确优先级:安全 > 正确 > 性能 > 风格
├── 聚合 Agent 按优先级裁决
└── 冲突时标记为"需人工确认"

坑 4:成本爆炸

复制代码
问题:4 个 Agent 并行审查 × 3 轮辩论 = 12 次 LLM 调用
原因:没有成本预算机制
修复:
├── 设置 Token 上限
├── 非核心路径用小模型
├── 缓存相同输入的结果
└── 辩论最多 2 轮,避免无限讨论

九、设计 Checklist

# 检查项 说明
1 Agent 职责是否单一? 一个 Agent 只做一件事
2 工具集是否最小化? 只给必要的工具
3 状态传递是否安全? 命名空间隔离、不可变
4 容错策略是否到位? 重试 + 降级 + 隔离
5 路由是否可观测? 记录路由决策和原因
6 成本是否可控? Token 上限 + 缓存
7 是否有兜底? 失败时的 default 行为
8 调试是否方便? 执行日志 + 状态快照

十、面试速答模板

Q:Multi-Agent 和单 Agent 有什么区别?

核心区别是职责拆分和协作。单 Agent 所有能力塞一个 Prompt,工具多选择难、上下文容易乱。Multi-Agent 每个只做一件事,Prompt 更精准、工具更聚焦、容错更好,但引入了编排和状态传递的复杂度。

Q:Multi-Agent 编排有哪些模式?

四种经典模式:顺序链(Pipeline,串行传递)、分发-聚合(Fan-out/Fan-in,并行执行后汇总)、路由(Router,按类型分发)、辩论-裁决(Debate,多方案选最优)。实际项目通常是组合使用。

Q:Agent 间状态怎么传?

三种方式:直接传参(最简单,适合字符串)、共享上下文(最常用,类似黑板模式)、消息总线(最解耦,发布订阅)。关键原则:命名空间隔离、只追加不覆盖、不可变传递、记录来源。


下一篇我们聊 Agent 可观测性与调试:Multi-Agent 系统出了问题怎么查?执行日志怎么设计?如何给 Agent 加"黑匣子"?让每个决策都有据可查。


本文是 AI Agent 开发实战系列第 11 篇,系列目录:

  1. AI Agent 核心概念与架构
  2. 三大基石之 LLM 调用与 Prompt 工程
  3. 三大基石之记忆系统
  4. 三大基石之工具调用
  5. Java 生态 Agent 框架横评
  6. 用 Spring AI 搭建第一个 Agent
  7. Harness Engineering 与约束管理
  8. 输出 Schema 约束与结构化输出
  9. Grill Me 反问式规划
  10. Agent 设计模式(ReAct / Plan-Execute / Reflection)
  11. 本文:Multi-Agent 协作编排
相关推荐
众人皆醒我独醉2 小时前
Ray Serve:把 LLM 推理当"分布式 Actor"调度——不是 Kubernetes,是 Python 原生
面试·llm·ai编程
(轻舟已过万重山)2 小时前
第27章 框架实操:用 LangChain/LlamaIndex 搭建完整 RAG 系统
人工智能·ai·langchain
组合缺一2 小时前
SolonCode v2026.8.4 发布:界面字体可调、22 种语言、记忆搜索增强
llm·agent·ai编程·solon·claudecode·opencode
echoVic3 小时前
Orca:一个 DeepSeek 原生的终端 Coding Agent
开源·ai编程·deepseek
程序员天天困3 小时前
我用Doubao-Seed-Evolving做GitHub+Gitee编码档案
ai编程·豆包marscode
echoVic3 小时前
把 Orca 的 DeepSeek 缓存命中率打到 99%,我做了九轮优化
性能优化·ai编程·deepseek
颜进强3 小时前
Calude Code - 25 CodeGraph:让 AI 真正读懂你的代码库
前端·后端·ai编程
名不经传的养虾人4 小时前
从0到1:企业级AI项目迭代日记 Vol.81|工具调用前,先过一道审批门
数据库·人工智能·ai编程·ai工作流·企业ai
掘金一周4 小时前
有jy知道uniapp开发时候用微信开发工具真机模拟,图片不显示是为什么的么? | 沸点周刊 8.6
ai编程·沸点