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

19 阅读10分钟

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

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


一、为什么需要 Multi-Agent?

单个 Agent 的局限:

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

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

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

二、四种经典编排模式

2.1 顺序链(Pipeline)

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

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

代码示例:

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,各自独立完成后汇总。

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

代码示例:

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 根据输入判断该交给谁处理,类似微服务网关。

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

代码示例:

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 或投票机制选最优。

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

三、编排模式对比

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

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

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

4.1 三种状态传递方式

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

4.2 共享上下文实现

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 三级容错策略

容错策略

├── Level 1: 重试
   ├── 对失败 Agent 自动重试(最多 N 次)
   ├── 适合:LLM 调用超时、网络抖动
   └── 不适合:逻辑错误、参数错误

├── Level 2: 降级
   ├──  Agent 失败  切换到备选 Agent
   ├── 复杂 Agent 失败  切换到简单版本
   └── 适合:非核心路径

└── Level 3: 隔离
    ├── 失败 Agent 的结果标记为 error
    ├── 其他 Agent 继续执行
    └── 适合:分发-聚合模式

5.2 容错代码示例

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 系统架构

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

6.2 核心实现

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:

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

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

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

七、编排框架对比

7.1 主流框架

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

7.2 Spring AI 实现 Multi-Agent

@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 间上下文泄露

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

坑 2:无限递归

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

坑 3:聚合结果矛盾

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

坑 4:成本爆炸

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

九、设计 Checklist

#检查项说明
1Agent 职责是否单一?一个 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 协作编排