Skip to content

第7章 多智能体协作

7.1 问题场景

业务复杂度上升后,单智能体同时承担规划、检索、执行、复核和结果收敛,往往会出现性能退化、错误归因困难和结果不稳定的问题。 多智能体协作的价值,不在于“多几个智能体(Agent)看起来更高级”,而在于把复杂任务拆解给不同角色,并在清晰协议和仲裁机制下提升质量与稳定性。

很多团队在这里容易犯两个极端错误:

  • 任务其实不复杂,却为了追热点硬上多智能体,最后成本和复杂度都飙升。
  • 任务已经明显需要角色分工,却仍然让单智能体硬扛,导致输出越来越不稳。

因此这一章的重点不是“怎么搭一个多智能体框架”,而是先判断什么时候真的需要多智能体,以及多智能体最小闭环应该如何设计。

前端迁移提示

前端工程师在多智能体协作里其实非常有优势,因为你已经熟悉:

  • 复杂模块拆分与边界设计。
  • 多状态源之间的协调与合并。
  • 协议设计和组件契约。
  • 冲突状态的展示和人工确认入口。

这些能力可以直接迁移为:

  • 角色边界设计。
  • 消息协议设计。
  • 仲裁与收敛机制。
  • 协作过程的前端可视化。

最小项目目标

本章建议先完成一个“3 角色最小协作闭环”项目,例如:

  • 规划者:拆任务。
  • 执行者:完成具体子任务。
  • 审查者:检查结果并给出修订意见。

参考入口:

7.2 核心原理

多智能体协作的关键,不是“角色越多越好”,而是把“角色分工、共享上下文、协作协议、冲突仲裁和结果收敛”控制在一个可解释、可治理的系统里。 如果缺少这层约束,多 Agent 很快就会变成一个难以调试的黑盒系统。

一、角色分工:不同 Agent 必须有清晰职责边界

最小协作系统里,建议先从最少角色集合开始。 例如:

  • 规划者:拆解目标、安排步骤。
  • 执行者:根据任务完成检索、生成或工具调用。
  • 审查者:判断结果质量,提出修正意见或仲裁。

如果角色定义不清,最常见的问题就是:

  • 大量重复劳动。
  • 相互覆盖和冲突。
  • 输出风格和决策标准不一致。

二、协作协议:没有统一消息结构,信息就会丢

多 Agent 不是“多个模型轮流说话”而已。 你至少要定义:

  • 每个角色接收什么输入。
  • 输出什么结构。
  • 如何引用前序结果。
  • 如何表达不确定性和失败。

参考入口:

  • docs/examples/assets/samples/chapter-07-collaboration-protocol.json

三、共享上下文:不是所有信息都要广播给所有角色

多 Agent 协作的一个大坑,是把所有上下文都平铺给所有角色。 更好的方式是:

  • 只给角色完成当前任务所需的信息。
  • 对共享信息做结构化摘要。
  • 对高风险信息做权限控制。

四、仲裁机制:冲突不可避免,关键是如何收敛

当多个角色结论不一致时,系统必须知道:

  • 谁拥有最终决定权。
  • 是否需要规则仲裁。
  • 是否需要人工介入。
  • 是否需要把冲突信息展示给用户。

如果没有仲裁,最终输出会不可预测。

五、成本与延迟:多角色带来的收益必须值得复杂度

多 Agent 常见误区是“效果可能更好,所以值得”。 真实工程里,你还必须评估:

  • 延迟是否显著增长。
  • 成本是否可接受。
  • 调试复杂度是否显著上升。
  • 相比单 Agent 是否真的带来收益。

7.3 实操步骤

推荐做法不是先搭复杂多角色系统,而是先做一个“最小角色集 + 最小协议 + 最小仲裁”闭环。 先证明多 Agent 真有必要,再扩展复杂度。

步骤 1:先判断是否真的需要多 Agent

先问三个问题:

  • 单 Agent 的主要瓶颈是什么。
  • 角色分工是否真的能提升质量或稳定性。
  • 这种提升是否值得额外成本和延迟。

步骤 2:定义最小角色集合

建议第一版先用 3 个角色以内。 例如:

  • 规划者。
  • 执行者。
  • 审查者。

步骤 3:定义共享消息协议

建议至少明确:

  • 消息发送者。
  • 接收者。
  • 当前任务。
  • 输入摘要。
  • 输出结构。
  • 是否需要仲裁。

步骤 4:实现最小协作回路

例如:

  1. 规划者拆解任务。
  2. 执行者按步骤处理。
  3. 审查者检查结果。
  4. 如有冲突,进入仲裁或人工确认。

步骤 5:增加冲突仲裁规则

至少定义:

  • 哪类冲突由规则自动处理。
  • 哪类冲突必须人工介入。
  • 最终输出如何收敛。

步骤 6:同步准备前端展示和证据材料

建议至少保留:

  • 协作协议样本:docs/examples/assets/samples/chapter-07-collaboration-protocol.json
  • 截图清单:docs/examples/assets/screenshots/README.md
  • 章节片段索引
  • 工作流骨架

步骤 7:做单 Agent 与多 Agent 对照实验

至少比较:

  • 完成率。
  • 一致性。
  • 延迟。
  • 成本。

如果没有对照实验,很难证明多 Agent 真的值得引入。

代码实战:可运行的多智能体系统

前面 7 个步骤讲的是思路和流程,这一节把它们落到可直接运行的 TypeScript 代码上。 建议先跑通"三角色协作"再看仲裁和可视化,一步一步来。

1. 三角色协作系统(TypeScript)

核心思路:规划者拆任务 → 执行者逐项完成 → 审查者打分,不通过则打回重做,最多重试两轮。 整个过程用消息日志串联,后续可接入前端可视化。

typescript
// multi-agent.ts — 规划者-执行者-审查者 三角色协作
import OpenAI from 'openai'

const client = new OpenAI()

// ── 角色与消息类型定义 ──

interface AgentRole {
  name: string
  systemPrompt: string
}

interface AgentMessage {
  from: string
  to: string
  type: 'task' | 'result' | 'review' | 'revision' | 'final'
  content: string
  metadata?: Record<string, unknown>
}

// ── 三个角色的 system prompt ──

const PLANNER: AgentRole = {
  name: '规划者',
  systemPrompt: `你是项目规划者。你的职责是:
1. 理解用户的复杂需求
2. 将需求拆解为 3-5 个具体的子任务
3. 为每个子任务指定清晰的输入、输出和验收标准
输出 JSON 格式:{ "tasks": [{ "id": number, "title": string, "description": string, "acceptanceCriteria": string }] }`
}

const EXECUTOR: AgentRole = {
  name: '执行者',
  systemPrompt: `你是任务执行者。你的职责是:
1. 按照规划者给出的子任务逐项执行
2. 每个任务产出具体结果
3. 如果遇到问题,明确标记为 blocked
输出 JSON 格式:{ "taskId": number, "status": "done" | "blocked", "result": string, "blockedReason"?: string }`
}

const REVIEWER: AgentRole = {
  name: '审查者',
  systemPrompt: `你是质量审查者。你的职责是:
1. 检查执行者的每个结果是否满足验收标准
2. 给出 pass/fail/revision_needed 判断
3. 如果需要修改,给出具体修改建议
输出 JSON 格式:{ "taskId": number, "verdict": "pass" | "fail" | "revision_needed", "feedback": string, "suggestions"?: string[] }`
}

// ── 调用单个 Agent ──

async function callAgent(role: AgentRole, userMessage: string): Promise<string> {
  const response = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      { role: 'system', content: role.systemPrompt },
      { role: 'user', content: userMessage },
    ],
    response_format: { type: 'json_object' },
    temperature: 0.3,
  })
  return response.choices[0].message.content!
}

// ── 消息日志 ──

const messageLog: AgentMessage[] = []

function logMessage(msg: AgentMessage) {
  messageLog.push(msg)
  console.log(`📨 [${msg.from} → ${msg.to}] ${msg.type}: ${msg.content.slice(0, 100)}...`)
}

// ── 协作主循环 ──

async function runMultiAgentTask(userRequest: string) {
  console.log(`\n🚀 启动多智能体协作\n`)
  console.log(`📋 用户需求: ${userRequest}\n`)
  const maxRevisions = 2

  // 步骤 1: 规划者拆解任务
  console.log('━'.repeat(50))
  console.log('📐 [规划者] 拆解任务...\n')
  const planResult = await callAgent(PLANNER, `用户需求:${userRequest}`)
  logMessage({ from: '规划者', to: '执行者', type: 'task', content: planResult })
  const plan = JSON.parse(planResult)
  console.log(`   拆解为 ${plan.tasks.length} 个子任务\n`)

  // 步骤 2-3: 执行 + 审查循环
  const finalResults: Record<number, unknown> = {}

  for (const task of plan.tasks) {
    console.log('━'.repeat(50))
    console.log(`⚡ [执行者] 处理任务 #${task.id}: ${task.title}`)

    let revisionCount = 0
    let currentTask = JSON.stringify(task)

    while (revisionCount <= maxRevisions) {
      const execResult = await callAgent(EXECUTOR, `执行以下任务:\n${currentTask}`)
      logMessage({ from: '执行者', to: '审查者', type: 'result', content: execResult })

      console.log(`🔍 [审查者] 审查任务 #${task.id} 结果...`)
      const reviewResult = await callAgent(
        REVIEWER,
        `审查以下结果:\n任务:${currentTask}\n执行结果:${execResult}\n验收标准:${task.acceptanceCriteria}`
      )
      logMessage({ from: '审查者', to: '执行者', type: 'review', content: reviewResult })

      const review = JSON.parse(reviewResult)

      if (review.verdict === 'pass') {
        console.log(`   ✅ 任务 #${task.id} 通过审查\n`)
        finalResults[task.id] = JSON.parse(execResult)
        break
      } else if (review.verdict === 'revision_needed' && revisionCount < maxRevisions) {
        revisionCount++
        console.log(`   🔄 需要修改 (第 ${revisionCount} 次): ${review.feedback}`)
        currentTask = JSON.stringify({
          ...task,
          revisionFeedback: review.feedback,
          suggestions: review.suggestions,
        })
      } else {
        console.log(`   ❌ 任务 #${task.id} 未通过(已达最大修改次数)`)
        finalResults[task.id] = { status: 'failed', lastReview: review }
        break
      }
    }
  }

  // 步骤 4: 汇总
  console.log('\n' + '━'.repeat(50))
  console.log('📊 协作完成,结果汇总:')
  console.log(JSON.stringify(finalResults, null, 2))
  console.log(`\n📬 共产生 ${messageLog.length} 条协作消息`)

  return { plan, results: finalResults, messageLog }
}

// ── 运行示例 ──
runMultiAgentTask(
  '为一个企业知识库 RAG 系统编写技术方案,需要包含架构设计、技术选型、数据处理流程和评测计划'
)

运行方式:

bash
# 安装依赖
npm install openai tsx

# 设置环境变量后运行
export OPENAI_API_KEY="sk-..."
npx tsx multi-agent.ts

2. 仲裁机制实现

当审查者判定 revision_needed 但执行者已达到最大重试次数,或者多个审查者意见冲突时,需要一个仲裁层做最终裁决。 下面的 Arbiter 可以直接嵌入上面的协作主循环。

typescript
// arbiter.ts — 仲裁器:冲突收敛的最后一道防线
import OpenAI from 'openai'

const client = new OpenAI()

interface Conflict {
  taskId: number
  executorResult: string
  reviewerFeedback: string
  revisionHistory: string[]
}

type ArbiterVerdict = {
  taskId: number
  decision: 'accept' | 'reject' | 'escalate'
  finalResult?: string
  reason: string
}

const ARBITER_PROMPT = `你是仲裁者,负责在执行者和审查者意见无法收敛时做最终裁决。
你必须基于以下信息做判断:
1. 原始任务描述
2. 执行者的最终结果
3. 审查者的反馈
4. 历次修订记录

裁决规则:
- 如果执行者结果基本满足验收标准(>= 80%),判 accept 并给出最终修正版
- 如果结果明显不合格且无法修补,判 reject
- 如果你无法判断(例如涉及业务规则不确定),判 escalate(交给人工)

输出 JSON:{ "taskId": number, "decision": "accept" | "reject" | "escalate", "finalResult"?: string, "reason": string }`

async function arbitrate(conflict: Conflict): Promise<ArbiterVerdict> {
  const response = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      { role: 'system', content: ARBITER_PROMPT },
      {
        role: 'user',
        content: JSON.stringify({
          taskId: conflict.taskId,
          executorResult: conflict.executorResult,
          reviewerFeedback: conflict.reviewerFeedback,
          revisionHistory: conflict.revisionHistory,
        }),
      },
    ],
    response_format: { type: 'json_object' },
    temperature: 0.2,
  })

  return JSON.parse(response.choices[0].message.content!) as ArbiterVerdict
}

// 在协作主循环的 else 分支里替换原来的 "未通过" 逻辑:
async function handleFailedTask(
  task: { id: number },
  execResult: string,
  review: { feedback: string },
  revisionHistory: string[]
) {
  console.log(`⚖️ [仲裁者] 介入任务 #${task.id}...`)

  const verdict = await arbitrate({
    taskId: task.id,
    executorResult: execResult,
    reviewerFeedback: review.feedback,
    revisionHistory,
  })

  switch (verdict.decision) {
    case 'accept':
      console.log(`   ✅ 仲裁通过(附修正): ${verdict.reason}`)
      return { status: 'accepted_by_arbiter', result: verdict.finalResult }
    case 'reject':
      console.log(`   ❌ 仲裁驳回: ${verdict.reason}`)
      return { status: 'rejected', reason: verdict.reason }
    case 'escalate':
      console.log(`   🙋 需要人工介入: ${verdict.reason}`)
      return { status: 'escalated', reason: verdict.reason }
  }
}

export { arbitrate, handleFailedTask }

将仲裁器集成到协作主循环只需一行改动——把 finalResults[task.id] = { status: 'failed', lastReview: review } 替换为:

typescript
finalResults[task.id] = await handleFailedTask(task, execResult, review, revisionHistory)

仲裁策略小结:

场景仲裁裁决后续动作
结果接近合格(>= 80%)accept + 附修正使用修正后结果
结果明显不合格reject标记失败,记入日志
无法自动判断escalate推送给人工审核

3. 前端协作可视化(React)

下面这个组件可以接收协作主循环产生的 messageLog,实时展示三角色的消息流和审查状态。 适合嵌入管理后台或内部调试工具。

tsx
// MultiAgentVisualizer.tsx — 多 Agent 协作过程可视化
import React, { useState, useEffect, useRef } from 'react'

interface AgentMessage {
  from: string
  to: string
  type: 'task' | 'result' | 'review' | 'revision' | 'final'
  content: string
  metadata?: Record<string, unknown>
}

interface RoleConfig {
  name: string
  color: string
  icon: string
  description: string
}

const ROLES: Record<string, RoleConfig> = {
  规划者: { name: '规划者', color: '#3B82F6', icon: '📐', description: '拆解任务、制定计划' },
  执行者: { name: '执行者', color: '#10B981', icon: '⚡', description: '逐项执行子任务' },
  审查者: { name: '审查者', color: '#F59E0B', icon: '🔍', description: '审查结果、给出反馈' },
  仲裁者: { name: '仲裁者', color: '#EF4444', icon: '⚖️', description: '冲突收敛、最终裁决' },
}

function RoleCard({ config, active }: { config: RoleConfig; active: boolean }) {
  return (
    <div
      style={{
        border: `2px solid ${active ? config.color : '#e5e7eb'}`,
        borderRadius: 12,
        padding: 16,
        textAlign: 'center',
        background: active ? `${config.color}10` : '#fff',
        transition: 'all 0.3s ease',
        minWidth: 140,
      }}
    >
      <div style={{ fontSize: 32 }}>{config.icon}</div>
      <div style={{ fontWeight: 600, marginTop: 8 }}>{config.name}</div>
      <div style={{ fontSize: 12, color: '#6b7280', marginTop: 4 }}>{config.description}</div>
      {active && (
        <div
          style={{
            marginTop: 8,
            fontSize: 12,
            color: config.color,
            fontWeight: 500,
          }}
        >
          处理中...
        </div>
      )}
    </div>
  )
}

function MessageBubble({ msg, index }: { msg: AgentMessage; index: number }) {
  const fromRole = ROLES[msg.from] || ROLES['规划者']
  const verdictMatch = msg.content.match(/"verdict"\s*:\s*"(\w+)"/)
  const verdict = verdictMatch?.[1]

  return (
    <div
      style={{
        display: 'flex',
        gap: 12,
        padding: 12,
        borderRadius: 8,
        background: index % 2 === 0 ? '#f9fafb' : '#fff',
        border: '1px solid #e5e7eb',
      }}
    >
      <div style={{ fontSize: 20 }}>{fromRole.icon}</div>
      <div style={{ flex: 1 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
          <span style={{ fontWeight: 600, color: fromRole.color }}>{msg.from}</span>
          <span style={{ color: '#9ca3af' }}>→</span>
          <span style={{ fontWeight: 500 }}>{msg.to}</span>
          <span
            style={{
              fontSize: 11,
              padding: '2px 8px',
              borderRadius: 4,
              background: '#f3f4f6',
              color: '#6b7280',
            }}
          >
            {msg.type}
          </span>
          {verdict && (
            <span
              style={{
                fontSize: 11,
                padding: '2px 8px',
                borderRadius: 4,
                fontWeight: 600,
                background: verdict === 'pass' ? '#d1fae5' : verdict === 'fail' ? '#fee2e2' : '#fef3c7',
                color: verdict === 'pass' ? '#065f46' : verdict === 'fail' ? '#991b1b' : '#92400e',
              }}
            >
              {verdict === 'pass' ? '✅ 通过' : verdict === 'fail' ? '❌ 未通过' : '🔄 需修改'}
            </span>
          )}
        </div>
        <div
          style={{
            fontSize: 13,
            color: '#374151',
            lineHeight: 1.5,
            maxHeight: 80,
            overflow: 'hidden',
          }}
        >
          {msg.content.slice(0, 200)}
          {msg.content.length > 200 && '...'}
        </div>
      </div>
    </div>
  )
}

export default function MultiAgentVisualizer({ messages }: { messages: AgentMessage[] }) {
  const [visibleCount, setVisibleCount] = useState(0)
  const listRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (visibleCount < messages.length) {
      const timer = setTimeout(() => setVisibleCount((c) => c + 1), 600)
      return () => clearTimeout(timer)
    }
  }, [visibleCount, messages.length])

  useEffect(() => {
    listRef.current?.scrollTo({ top: listRef.current.scrollHeight, behavior: 'smooth' })
  }, [visibleCount])

  const activeRole = visibleCount < messages.length ? messages[visibleCount]?.from : null

  return (
    <div style={{ maxWidth: 720, margin: '0 auto', fontFamily: 'system-ui, sans-serif' }}>
      <div style={{ display: 'flex', gap: 16, justifyContent: 'center', marginBottom: 24 }}>
        {Object.values(ROLES).map((role) => (
          <RoleCard key={role.name} config={role} active={activeRole === role.name} />
        ))}
      </div>

      <div
        ref={listRef}
        style={{
          display: 'flex',
          flexDirection: 'column',
          gap: 8,
          maxHeight: 480,
          overflowY: 'auto',
          padding: 8,
        }}
      >
        {messages.slice(0, visibleCount).map((msg, i) => (
          <MessageBubble key={i} msg={msg} index={i} />
        ))}
      </div>

      <div
        style={{
          marginTop: 16,
          textAlign: 'center',
          fontSize: 13,
          color: '#6b7280',
        }}
      >
        {visibleCount < messages.length
          ? `已显示 ${visibleCount} / ${messages.length} 条消息...`
          : `协作完成,共 ${messages.length} 条消息`}
      </div>
    </div>
  )
}

使用方式:

tsx
import MultiAgentVisualizer from './MultiAgentVisualizer'

// messages 来自协作主循环返回的 messageLog
<MultiAgentVisualizer messages={messageLog} />

4. 前端知识桥梁

如果你有前端背景,下面这张映射表可以帮你快速理解多智能体概念——它们本质上和你熟悉的前端模式非常接近。

多智能体概念前端对应概念类比说明
角色定义(AgentRole)组件 Props 接口每个角色有明确的输入输出契约,就像组件通过 Props 约定行为
消息协议(AgentMessage)Event Bus / Redux Action角色之间通过结构化消息通信,不直接互相调用
协作循环(主循环)组件通信 / Context多角色按顺序协作,就像父组件协调子组件的数据流
仲裁收敛(Arbiter)状态合并 / Conflict Resolution多方结论冲突时需要一个裁决层,类似 Redux reducer 合并
审查重试(Review Loop)表单校验 → 修改 → 再提交不通过就打回修改,和前端表单校验逻辑完全一样

5. 单 Agent vs 多 Agent 对比

同一个任务,单 Agent 一把梭和三角色协作的差异:

typescript
// comparison.ts — 单 Agent vs 多 Agent 对比

import OpenAI from 'openai'

const client = new OpenAI()

const TASK = '为企业知识库 RAG 系统设计数据处理流程,包含数据清洗、向量化和索引策略'

// ── 方式 A:单 Agent 一把梭 ──

async function singleAgent(task: string) {
  console.log('--- 单 Agent 模式 ---')
  const start = Date.now()

  const response = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      {
        role: 'system',
        content: '你是全栈 AI 工程师,直接输出完整方案。',
      },
      { role: 'user', content: task },
    ],
  })

  const elapsed = Date.now() - start
  const result = response.choices[0].message.content!
  console.log(`耗时: ${elapsed}ms | 长度: ${result.length} 字`)
  console.log(`Token: ${response.usage?.total_tokens}`)
  return { result, elapsed, tokens: response.usage?.total_tokens }
}

// ── 方式 B:三角色协作(简化版) ──

async function multiAgent(task: string) {
  console.log('--- 多 Agent 模式(规划→执行→审查) ---')
  const start = Date.now()
  let totalTokens = 0

  // 规划
  const planResp = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      { role: 'system', content: '你是规划者,把需求拆成 3 个子任务。输出 JSON。' },
      { role: 'user', content: task },
    ],
    response_format: { type: 'json_object' },
  })
  totalTokens += planResp.usage?.total_tokens ?? 0
  const plan = JSON.parse(planResp.choices[0].message.content!)

  // 执行(逐项)
  const results: string[] = []
  for (const sub of plan.tasks) {
    const execResp = await client.chat.completions.create({
      model: 'gpt-4o-mini',
      messages: [
        { role: 'system', content: '你是执行者,完成指定子任务并输出结果。' },
        { role: 'user', content: JSON.stringify(sub) },
      ],
    })
    totalTokens += execResp.usage?.total_tokens ?? 0
    results.push(execResp.choices[0].message.content!)
  }

  // 审查
  const reviewResp = await client.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      { role: 'system', content: '你是审查者,检查所有子任务结果的质量和完整性。输出总评。' },
      { role: 'user', content: `任务:${task}\n结果:${JSON.stringify(results)}` },
    ],
  })
  totalTokens += reviewResp.usage?.total_tokens ?? 0

  const elapsed = Date.now() - start
  const review = reviewResp.choices[0].message.content!
  console.log(`耗时: ${elapsed}ms | Token: ${totalTokens}`)
  console.log(`子任务数: ${plan.tasks.length} | 审查结论长度: ${review.length} 字`)
  return { plan, results, review, elapsed, totalTokens }
}

// ── 运行对比 ──

async function compare() {
  const a = await singleAgent(TASK)
  console.log()
  const b = await multiAgent(TASK)

  console.log('\n--- 对比 ---')
  console.log(`单 Agent: ${a.elapsed}ms, ${a.tokens} tokens`)
  console.log(`多 Agent: ${b.elapsed}ms, ${b.totalTokens} tokens`)
  console.log(`多 Agent 多了审查环节,通常输出更结构化、质量更可控,但耗时和 token 成本更高。`)
}

compare()

关键差异:

维度单 Agent多 Agent(三角色)
调用次数1 次5+ 次(规划 1 + 执行 N + 审查 1)
输出结构化程度取决于 prompt天然结构化(每步有约束)
质量可控性依赖单次生成质量审查环节兜底
成本高(约 3-5 倍 token)
适合场景简单任务、低风险复杂任务、需要质量保障

7.4 常见坑

坑 1:角色边界模糊

会导致重复劳动和职责冲突。

坑 2:协作链路过长

角色越多、轮次越多,延迟和故障点会快速增加。

坑 3:没有统一协议

信息丢失、上下文不一致和结果不可追踪都会随之出现。

坑 4:没有仲裁机制

多个角色意见不一致时,系统无法稳定收敛。

坑 5:只看效果,不看成本和延迟

多 Agent 不是越复杂越好,收益必须值得复杂度。

坑 6:前端不展示协作过程

这样用户很难理解系统为什么得出这个结果,也很难信任高风险决策。

7.5 验证方式

多智能体协作做完后,不应只看“角色有没有跑起来”,而要看它是否真的比单智能体更值得用。

一、质量收益是否明确

  • 正确率或完成率是否相较单 Agent 有提升。
  • 审查一致性是否更稳。

二、协作过程是否可追踪

  • 每个角色输出是否可回放。
  • 消息协议是否能追踪来源和流向。

三、冲突收敛是否稳定

  • 角色冲突时是否总能进入预期仲裁路径。
  • 最终输出是否可预测。

四、成本和延迟是否可接受

  • 是否在业务可接受区间内。
  • 是否相较收益值得保留。

五、证据材料

  • 协作协议样本:docs/examples/assets/samples/chapter-07-collaboration-protocol.json
  • 截图清单:docs/examples/assets/screenshots/README.md
  • 图解配图:docs/examples/assets/diagrams/chapter-06-workflow-state.svg
  • 章节片段索引

7.6 面试表达

我把复杂任务拆成多角色协作,并通过共享协议和仲裁机制保证输出最终收敛。 最终在保证成本和延迟可控的前提下,提高了复杂任务完成质量,也让系统决策过程更可追踪。

实战案例:招标文档多角色审查

  • 背景:单智能体难以同时覆盖条款抽取、风险识别和结论复核。
  • 动作:拆分规划者、执行者、审查者三角色,并建立统一消息协议和仲裁规则。
  • 结果:复杂文档任务完成率提升,审查结果一致性增强,冲突样本也更容易复盘。

推荐答题框架

如果面试官问“什么时候应该用多智能体”,可以按下面顺序回答:

  1. 先讲单智能体的瓶颈是什么。
  2. 再讲角色分工和协议设计。
  3. 再讲仲裁和收敛机制。
  4. 最后讲收益是否值得成本和延迟。

7.7 练习任务

  1. 定义 3 个最小协作角色,并写清楚边界职责。
  2. 设计一份统一消息协议模板,并给出一个最小样例。
  3. 设计一组冲突仲裁规则,并测试两组冲突样本。
  4. 选一个复杂任务,对比单智能体与多智能体的结果差异。
  5. 基于 docs/examples/assets/samples/chapter-07-collaboration-protocol.json,整理出你的第一版协作协议。
  6. 运行 multi-agent.ts 三角色协作代码,观察消息日志,记录每个角色的输出质量和审查通过率。
  7. 将仲裁器 arbiter.ts 集成到协作主循环中,构造一个审查不通过的场景,验证仲裁路径是否正确触发。
  8. 运行 comparison.ts 对比脚本,记录单 Agent 和多 Agent 在耗时、token 数和输出结构化程度上的差异。

7.8 验收清单

  • 任务完成率 >= 85%
  • 关键指标达标率 >= 90%
  • 异常场景通过率 >= 90%
  • 至少完成 1 份最小协作协议和 1 组冲突仲裁规则。
  • 至少保留 1 份协作样本、1 组截图占位清单和 1 份章节代码片段索引。
  • 至少能用 2 分钟讲清楚“为什么多 Agent 不是角色越多越好,而是要通过协议和仲裁获得可证明的收益”。