1. 从单个 Agent 到 Agent 编排
单 Agent 调用 MCP 工具是「一个大脑 + 一双手」。现实任务往往更复杂:跨领域、多步骤、需要分工。此时需要多个 Agent 协作,而 MCP 提供的统一工具接口,正是让「多个 Agent 协作」成为可能的基础设施。
一句话:MCP 统一了「手」,编排决定了「谁动手、动哪只、动完传给谁」——工具标准化之后,真正的挑战在编排。
1.1 为什么需要编排
- 任务拆解:一个复杂任务拆成多个子任务
- 专业分工:代码/文档/数据分析分别由专门 Agent 处理
- 并发加速:相互独立的子任务并行
- 上下文隔离:每个 Agent 维护自己的上下文
- 失败隔离:一个子任务失败不拖垮整体
2. 三种协作模式
2.1 编排者-工作子(Orchestrator-Workers)
编排者(主 Agent)拆解任务 → 分派给工作子 → 汇总结果
例:编排者把「分析这个仓库」拆成
worker A: 读 README + 架构
worker B: 跑测试
worker C: 查依赖漏洞
汇总 → 生成报告
2.2 流水线(Pipeline)
任务按顺序经过多个 Agent,前一个的输出是后一个的输入
例:提取数据 → 清洗 → 分析 → 可视化 → 报告
每步一个 Agent,串行推进
2.3 群聊(Conversation / Blackboard)
多个 Agent 围绕共享问题自由交流,互相补充
例:产品经理 Agent + 技术 Agent + 风险 Agent 讨论方案
共享黑板(共享上下文)更新
| 模式 | 适合 | 结构 |
|---|---|---|
| 编排者-工作子 | 可拆解的大任务 | 星型 |
| 流水线 | 顺序依赖的流程 | 线性 |
| 群聊 | 多角度讨论 | 网状 |
一句话:三种模式对应三种任务结构——可拆解用星型、顺序依赖用线性、多方权衡用网状,选错模式是编排低效的第一来源。
3. 基于 MCP 的编排实现
3.1 编排者连接多个 MCP 服务器
// 编排者连接多个 MCP 服务器
const clients = [
await connectTo("search-mcp"),
await connectTo("code-mcp"),
await connectTo("db-mcp"),
];
// 汇总工具列表,交给 LLM 选择
const allTools = (await Promise.all(clients.map(c => c.listTools())))
.flatMap(r => r.tools);
3.2 工具路由
LLM 决定调用哪个工具 → 路由到对应服务器
路由策略:
- 按名称/前缀路由(search: → search-mcp)
- 统一调用 → 分发(一个 callTool 入口,按工具名分发)
- 能力路由(embedding 走向量服务器)
3.3 工具路由实现
async function routeCall(name: string, args: any) {
for (const c of clients) {
const has = (await c.listTools()).tools.some(t => t.name === name);
if (has) return c.callTool({ name, arguments: args });
}
throw new Error(`tool ${name} not found on any server`);
}
一句话:编排器是「多服务器 + 统一工具表 + 按名路由」——LLM 只看得到一个合并的工具列表,路由逻辑藏在编排层。
4. 并行、串行与循环
4.1 并行执行
独立子任务 → 并行(Promise.all)
例:同时查询三个数据源
收益:吞吐提升,但注意共享资源争用
const results = await Promise.all(
subtasks.map(async (task) => worker.execute(task))
);
4.2 串行依赖
后一步依赖前一步 → 串行
例:先建索引,再查询
收益:正确性优先
4.3 循环与重试
任务失败 → 评估 → 调整 → 重试(有限次数)
编排者判断:是工具参数问题?还是子任务本身不可行?
循环上限 + 退避 → 防死循环
async function runWithRetry(task, { max = 3, backoff = 500 }) {
for (let i = 0; i < max; i++) {
try { return await task(); }
catch (e) {
if (i === max - 1) throw e;
await sleep(backoff * 2 ** i);
}
}
}
一句话:执行拓扑按「依赖关系」决定——独立并行、依赖串行、失败重试,但每次重试都要有「重试有希望」的判断,否则只是放大错误。
5. 跨步骤状态传递
5.1 状态在哪里
编排过程的中间状态:
- 子任务输出(结构化的结果)
- 共享上下文(全局事实)
- 工具返回的引用(文件路径、ID)
传递方式:
参数传递(显式):把上游输出作为下游入参
共享存储(隐式):写入共享工作区/缓存
5.2 上下文管理
- 每个子 Agent 只给「它需要的上下文」(裁剪)
- 全局事实(用户目标、约束)进编排者上下文
- 大结果存引用,不复制全文(token 控制)
5.3 结果引用模式
// 大结果用「引用」而非复制
const result = await callTool("search", { query });
const ref = cache.set(result); // 存缓存,返回引用
// 后续 Agent 按 ref 取(需时再展开)
一句话:状态传递的黄金法则是「显式传小、引用传大、全局留编排」——控制 token 是编排能跑多远的决定因素。
6. 编排反模式
| 反模式 | 症状 | 纠正 |
|---|---|---|
| 过度拆解 | 大量小 Agent 反而慢 | 合并到必要粒度 |
| 无上下文的 Agent | 每个 Agent 重新问 | 传递关键上下文 |
| 全部并行 | 资源争用/不一致 | 依赖就串行 |
| 无限重试 | 死循环烧钱 | 上限 + 判定 |
| 全量上下文共享 | token 爆炸 | 按需裁剪 + 引用 |
| 单点编排 | 编排者瓶颈/单点故障 | 降级 + 故障恢复 |
7. 失败恢复与可靠性
7.1 失败分类
- 工具失败(可重试):网络、超时
- 子任务失败(可回退):换方案
- 不可恢复失败:向上抛,人工介入
7.2 降级策略
- 编排者不可用 → 单 Agent 直连模式(降级执行)
- 某服务器不可用 → 路由到备用/跳过该工具
- 上下文超限 → 摘要历史、截断最早内容
7.3 观测性
- 记录每个子任务:输入、输出、耗时、token
- 编排决策日志(为什么拆、为什么重试)
- 失败轨迹可回放
一句话:编排的可靠性靠「分类失败 + 降级路径 + 全程观测」——知道能降级到哪、为什么失败,编排才不会在复杂任务中「整链崩塌」。
8. 实践:一个多 MCP Agent 编排示例
// 任务:生成一份「代码仓库健康报告」
async function healthReport(repoPath) {
const { code, db, search } = await connectAll(); // 连接 3 个 MCP
// 1. 并行:收集原始数据
const [readme, deps, tests] = await Promise.all([
code.readResource({ uri: `repo://${repoPath}/README` }),
callSafe(search, "listDeps", { path: repoPath }),
callSafe(db, "query", { sql: "select * from test_runs" }),
]);
// 2. 串行:分析(依赖前一步结果)
const risk = await callTool(search, "analyze", { readme, deps });
// 3. 重试:可能失败的漏洞扫描
const vulns = await runWithRetry(
() => callTool(search, "scanVulns", { path: repoPath }),
{ max: 2 }
);
// 4. 汇总
return { summary: risk, vulns, testCount: tests.length };
}
9. 总结
MCP 与 LLM Agent 编排的要点可以概括为「统一工具、按需路由、谨慎协作」:
| 层面 | 要点 |
|---|---|
| 协作模式 | 编排者-工作子 / 流水线 / 群聊按任务选型 |
| 工具路由 | 合并工具表 + 按名路由 |
| 执行拓扑 | 独立并行、依赖串行、失败有上限重试 |
| 状态传递 | 小结果显式、大结果引用、上下文裁剪 |
| 反模式 | 避免过度拆解、无限重试、全量共享 |
| 可靠性 | 失败分类 + 降级 + 观测 |
MCP 给了 Agent 统一的工具接口,而编排决定了如何把这个接口用出「组织力」——选对协作模式、管好工具路由、控住状态与 token、设计降级路径,多 Agent 编排才能真正应对复杂任务,而不是制造混乱。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。