目录

编排逻辑 — 系统提示词驱动的主从协作模式

编排逻辑 — 系统提示词驱动的主从协作模式

源码路径:/mnt/e/code/cc/claude-code-main/src/coordinator/coordinatorMode.ts 核心文件:coordinatorMode.ts, builtInAgents.ts, AgentTool.tsx 技术栈:系统提示词 + AsyncLocalStorage + Team/SendMessage 工具


1. 概述:为什么不用硬编码算法

传统的多智能体系统往往通过复杂的硬编码状态机来管理任务分配、结果聚合与流程控制。Claude Code 的做法截然不同:编排逻辑几乎完全卸载到系统提示词中coordinatorMode.ts 导出的核心函数只有:

  • getCoordinatorSystemPrompt() — 返回协调者系统提示词
  • getCoordinatorUserContext() — 注入工人工具上下文
  • isCoordinatorMode() — 模式开关
  • matchSessionMode() — 会话恢复时的模式对齐

这种设计的精妙之处在于:LLM 本身就擅长理解指令、执行流程和做决策。将"何时分发任务"“何时等待"“何时聚合"这些逻辑用自然语言描述,比用 if-else 状态机更灵活、更易于迭代。


2. 架构总览

┌────────────────────────────────────────────────────────────────────┐
│                        User Session                                 │
│                                                                    │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │              Coordinator (主控 Agent)                         │  │
│   │   系统提示词定义了:角色、工具集、工作流、Worker 通信协议      │  │
│   │                                                              │  │
│   │   工具集:                                                     │  │
│   │   • AgentTool ──────→ Spawn Worker                          │  │
│   │   • SendMessageTool ─→ Continue Worker                      │  │
│   │   • TaskStopTool ────→ Stop Worker                          │  │
│   │                                                              │  │
│   │   工作流:                                                      │  │
│   │   Research ──→ Synthesis ──→ Implement ──→ Verify           │  │
│   └──────────────────────────────────────────────────────────────┘  │
│                                    │                                 │
│         ┌──────────────────────────┼──────────────────────────┐     │
│         │                          │                          │     │
│         ▼                          ▼                          ▼     │
│   ┌──────────┐             ┌──────────┐             ┌──────────┐   │
│   │ Worker A │             │ Worker B │             │ Worker C │   │
│   │(Research)│             │(Research)│             │(Implement)│   │
│   └────┬─────┘             └────┬─────┘             └────┬─────┘   │
│        │                         │                          │        │
│        └─────────────────────────┴──────────────────────────┘        │
│                                  │                                    │
│                    <task-notification> XML 消息回调                   │
│                                  │                                    │
└──────────────────────────────────┼────────────────────────────────────┘
                                   │
                    coordinatorMode.ts 的系统提示词驱动

3. 入口控制:如何进入协调者模式

3.1 特性开关

// src/coordinator/coordinatorMode.ts
export function isCoordinatorMode(): boolean {
  if (feature('COORDINATOR_MODE')) {
    return isEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE)
  }
  return false
}

两个条件同时满足才进入协调者模式:

  1. GrowthBook 特性开关 COORDINATOR_MODE 开启
  2. 环境变量 CLAUDE_CODE_COORDINATOR_MODE=1 设置

这提供了三层控制:

  • 管理员可通过 GrowthBook 对特定用户/实验组开启
  • 用户可通过环境变量自行启用
  • 会话恢复时通过 matchSessionMode() 自动对齐

3.2 会话恢复时的模式对齐

export function matchSessionMode(
  sessionMode: 'coordinator' | 'normal' | undefined,
): string | undefined {
  const currentIsCoordinator = isCoordinatorMode()
  const sessionIsCoordinator = sessionMode === 'coordinator'

  if (currentIsCoordinator === sessionIsCoordinator) return undefined

  // 翻转环境变量,使 isCoordinatorMode() 实时返回正确值
  if (sessionIsCoordinator) {
    process.env.CLAUDE_CODE_COORDINATOR_MODE = '1'
  } else {
    delete process.env.CLAUDE_CODE_COORDINATOR_MODE
  }

  logEvent('tengu_coordinator_mode_switched', { to: sessionMode })
}

3.3 Worker 工具上下文注入

export function getCoordinatorUserContext(
  mcpClients: ReadonlyArray<{ name: string }>,
  scratchpadDir?: string,
): { [k: string]: string } {
  if (!isCoordinatorMode()) return {}

  const workerTools = isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)
    ? [BASH_TOOL_NAME, FILE_READ_TOOL_NAME, FILE_EDIT_TOOL_NAME].sort().join(', ')
    : Array.from(ASYNC_AGENT_ALLOWED_TOOLS)
        .filter(name => !INTERNAL_WORKER_TOOLS.has(name))
        .sort().join(', ')

  let content = `Workers spawned via the ${AGENT_TOOL_NAME} tool have access to these tools: ${workerTools}`

  if (mcpClients.length > 0) {
    const serverNames = mcpClients.map(c => c.name).join(', ')
    content += `\n\nWorkers also have access to MCP tools from connected MCP servers: ${serverNames}`
  }

  if (scratchpadDir && isScratchpadGateEnabled()) {
    content += `\n\nScratchpad directory: ${scratchpadDir}\nWorkers can read and write here without permission prompts. Use this for durable cross-worker knowledge — structure files however fits the work.`
  }

  return { workerToolsContext: content }
}

支持两种 Worker 工具集:

  • SIMPLE 模式:仅 Bash、Read、Edit(适合受限场景)
  • 完整模式:所有 ASYNC_AGENT_ALLOWED_TOOLS(除内部工具)

4. 核心系统提示词详解

4.1 角色定义

// src/coordinator/coordinatorMode.ts (行 116-126)
return `You are Claude Code, an AI assistant that orchestrates software engineering tasks across multiple workers.

## 1. Your Role

You are a **coordinator**. Your job is to:
- Help the user achieve their goal
- Direct workers to research, implement and verify code changes
- Synthesize results and communicate with the user
- Answer questions directly when possible — don't delegate work that you can handle without tools

Every message you send is to the user. Worker results and system notifications are internal signals, not conversation partners — never thank or acknowledge them. Summarize new information for the user as it arrives.
`

关键约束:

  • Worker 结果不是对话伙伴 — 不感谢、不确认,像处理系统通知一样处理
  • 自己能做的就不委托 — 避免过度工程化
  • 持续向用户汇报 — 保持透明,不让用户等待

4.2 工具集与调用约束

// 行 128-140
## 2. Your Tools

- **AgentTool** - Spawn a new worker
- **SendMessageTool** - Continue an existing worker (send a follow-up to its `to` agent ID)
- **TaskStopTool** - Stop a running worker
- **subscribe_pr_activity / unsubscribe_pr_activity** (if available) - Subscribe to GitHub PR events

When calling AgentTool:
- Do not use one worker to check on another. Workers will notify you when they are done.
- Do not use workers to trivially report file contents or run commands. Give them higher-level tasks.
- Do not set the model parameter. Workers need the default model for the substantive tasks you delegate.
- Continue workers whose work is complete via SendMessageTool to take advantage of their loaded context
- After launching agents, briefly tell the user what you launched and end your response. Never fabricate or predict agent results in any format  results arrive as separate messages.

调用约定是最重要的工程约束之一:

  • 不设 model 参数 — Worker 默认使用主模型,确保能力一致
  • 不预测结果 — Agent 结果通过 <task-notification> 异步到达
  • Launch 后立即告知用户 — 保持 UX 流畅

4.3 任务通知格式

Worker 完成时,主控收到的不是普通消息,而是一个特殊的 <task-notification> XML:

<task-notification>
<task-id>{agentId}</task-id>
<status>completed|failed|killed</status>
<summary>{human-readable status summary}</summary>
<result>{agent's final text response}</result>
<usage>
  <total_tokens>N</total_tokens>
  <tool_uses>N</tool_uses>
  <duration_ms>N</duration_ms>
</usage>
</task-notification>

主控 Agent 被训练识别这个格式:

  • <task-id> 作为 SendMessageToolto 参数继续该 Worker
  • <result> 包含 Worker 的最终文本响应
  • <usage> 记录资源消耗(用于监控和成本控制)

4.4 工作流四阶段

// 行 198-218
## 4. Task Workflow

Most tasks can be broken down into the following phases:

### Phases

| Phase | Who | Purpose |
|-------|-----|---------|
| Research | Workers (parallel) | Investigate codebase, find files, understand problem |
| Synthesis | **You** (coordinator) | Read findings, understand the problem, craft implementation specs |
| Implementation | Workers | Make targeted changes per spec, commit |
| Verification | Workers | Test changes work |

### Concurrency

**Parallelism is your superpower. Workers are async. Launch independent workers concurrently whenever possible  don't serialize work that can run simultaneously and look for opportunities to fan out.**

四阶段分工清晰:

  1. Research — 并行探索,充分利用异步能力
  2. Synthesis — 主控亲自做,必须理解 Worker 的发现才能写好实现 spec
  3. Implementation — 写文件、跑测试、commit
  4. Verification — 独立验证,不是重跑实现者的测试

4.5 验证的真正含义

// 行 220-227
### What Real Verification Looks Like

Verification means **proving the code works**, not confirming it exists. A verifier that rubber-stamps weak work undermines everything.

- Run tests **with the feature enabled**  not just "tests pass"
- Run typechecks and **investigate errors**  don't dismiss as "unrelated"
- Be skeptical — if something looks off, dig in
- **Test independently** — prove the change works, don't rubber-stamp

这段提示词直接针对"验证惰性"这个常见问题给出了具体指导。


5. Worker 提示词工程

这是协调者模式中最精华的部分——如何写出高质量的 Worker 指令。

5.1 必须合成(Synthesize)

// 行 253-270
### Always synthesize  your most important job

When workers report research findings, **you must understand them before directing follow-up work**.

反模式:

AgentTool({ prompt: "Based on your findings, fix the auth bug", ... })
AgentTool({ prompt: "The worker found an issue in the auth module. Please fix it.", ... })

好模式:

AgentTool({ prompt: "Fix the null pointer in src/auth/validate.ts:42. The user field on Session (src/auth/types.ts:15) is undefined when sessions expire but the token remains cached. Add a null check before user.id access — if null, return 401 with 'Session expired'. Commit and report the hash.", ... })

关键:不要把理解工作委托给 Worker。Coordinator 必须先理解发现,再写出包含具体文件路径、行号和变更细节的指令。

5.2 Continue vs. Spawn 的决策矩阵

// 行 280-293
| Situation | Mechanism | Why |
|-----------|-----------|-----|
| Research explored exactly the files that need editing | **Continue** (SendMessageTool) | Worker already has the files in context |
| Research was broad but implementation is narrow | **Spawn fresh** | Avoid dragging along exploration noise |
| Correcting a failure or extending recent work | **Continue** | Worker has the error context |
| Verifying code a different worker just wrote | **Spawn fresh** | Verifier should see the code with fresh eyes |
| First attempt used wrong approach entirely | **Spawn fresh** | Wrong-approach context pollutes retry |
| Completely unrelated task | **Spawn fresh** | No useful context to reuse |

这是一个非常务实的决策表——没有绝对的规则,只有基于上下文重叠度的判断。

5.3 Worker 提示词最佳实践

// 行 308-335
**Good examples:**

1. Implementation: "Fix the null pointer in src/auth/validate.ts:42. The user field can be undefined when the session expires. Add a null check and return early with an appropriate error. Commit and report the hash."

2. Precise git operation: "Create a new branch from main called 'fix/session-expiry'. Cherry-pick only commit abc123 onto it. Push and create a draft PR targeting main. Add anthropics/claude-code as reviewer. Report the PR URL."

3. Correction (continued worker, short): "The tests failed on the null check you added — validate.test.ts:58 expects 'Invalid session' but you changed it to 'Session expired'. Fix the assertion. Commit and report the hash."

**Bad examples:**

1. "Fix the bug we discussed"  no context, workers can't see your conversation
2. "Based on your findings, implement the fix"  lazy delegation
3. "Create a PR for the recent changes"  ambiguous scope
4. "Something went wrong with the tests, can you look?"  no error message

好提示词的共性:具体到文件路径和行号、定义完成标准、给出错误示例


6. Worker 管理生命周期

6.1 Spawn — 启动 Worker

// AgentTool.tsx 行 282-300
if (teamName && name) {
  // 团队成员 Spawn 路径
  const result = await spawnTeammate({ name, prompt, team_name, ... }, toolUseContext)
  return { data: { teammate_id: result.teammateId, ... } }
}

协调者模式下的 Worker 通过 AgentTool 启动,subagent_typeworker

6.2 SendMessage — 继续 Worker

// AgentTool.tsx 行 681-686
const effectiveType = subagent_type ?? (isForkSubagentEnabled() ? undefined : GENERAL_PURPOSE_AGENT.agentType)
const isForkPath = effectiveType === undefined

// Worker 通过 SendMessageTool 继续

Worker 完成 Research 后,Coordinator 用 SendMessageTool 向其发送实现指令,利用 Worker 已加载的上下文。

6.3 TaskStop — 停止 Worker

// coordinatorMode.ts 行 237-249
// Use TaskStopTool to stop a worker you sent in the wrong direction
${AGENT_TOOL_NAME}({ description: "Refactor auth to JWT", prompt: "..." })
// ... returns task_id: "agent-x7q" ...

// User clarifies: "keep sessions — just fix the null pointer"
${TASK_STOP_TOOL_NAME}({ task_id: "agent-x7q" })

// Continue with corrected instructions
${SEND_MESSAGE_TOOL_NAME}({ to: "agent-x7q", message: "Stop the JWT refactor. Instead..." })

停止 ≠ 丢弃——停止后的 Worker 仍可继续,只需换一套指令。

6.4 失败处理

// 行 229-233
### Handling Worker Failures

When a worker reports failure (tests failed, build errors, file not found):
- Continue the same worker with SendMessageTool  it has the full error context
- If a correction attempt fails, try a different approach or report to the user

失败处理的策略:

  1. 继续同一个 Worker — 它有完整的错误上下文
  2. 换思路或上报用户 — 两次失败后不再原地打转

7. 完整协作会话示例

// 行 337-368
User: "There's a null pointer in the auth module. Can you fix it?"

You:
  Let me investigate first.

  AgentTool({ description: "Investigate auth bug", subagent_type: "worker", prompt: "Investigate the auth module in src/auth/. Find where null pointer exceptions could occur around session handling and token validation... Do not modify files." })
  AgentTool({ description: "Research auth tests", subagent_type: "worker", prompt: "Find all test files related to src/auth/. Report the test structure, what's covered, and any gaps..." })

  Investigating from two angles  I'll report back with findings.

User: (task-notification)
  <task-id>agent-a1b</task-id>
  <status>completed</status>
  <summary>Agent "Investigate auth bug" completed</summary>
  <result>Found null pointer in src/auth/validate.ts:42. The user field on Session is undefined when the session expires but ...</result>

You:
  Found the bug  null pointer in validate.ts:42.

  SendMessageTool({ to: "agent-a1b", message: "Fix the null pointer in src/auth/validate.ts:42. Add a null check before accessing user.id — if null, return 401... Commit and report the hash." })

  Fix is in progress.

注意:所有 “You:” 都是协调者回复,所有 “User:” 都是 <task-notification>(系统消息,不是用户输入)。


8. 关键设计洞察

8.1 提示词即架构

整个协调者模式的"业务逻辑"都在 getCoordinatorSystemPrompt() 返回的字符串中:

  • 角色定义 → 分工边界
  • 工具约束 → 能力边界
  • 工作流阶段 → 流程控制
  • 决策矩阵 → 路由逻辑

如果要改协调策略?改提示词就行,无需改代码。

8.2 状态外部化

协调者不需要维护"当前有哪些 Worker 在运行"“谁完成了什么"这类状态——这些信息通过 <task-notification> 实时流入。协调者每次回复都是基于最新状态做决策。

8.3 上下文传递协议

Worker 无法看到主控与用户的对话。每个 Worker prompt 必须是自包含的,包含:

  • 具体文件路径和行号
  • 完整的上下文(不是"基于你的发现”)
  • 明确的完成标准

这是整个系统最容易被破坏的接口——Coordinator 必须 discipline 自己不偷懒。

8.4 SIMPLE 降级模式

通过 CLAUDE_CODE_SIMPLE=1 环境变量,Worker 工具集可降级为仅 Bash/Read/Edit,适用于:

  • MCP 服务器受限环境
  • 安全性要求更高的场景
  • 调试和问题定位

9. 与其他协作模式的关系

┌─────────────────────────────────────────────────────────┐
│                    AgentTool 路由                        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  team_name + name ──────→ spawnTeammate (团队成员模式)     │
│                                                         │
│  subagent_type = "worker" ──→ Coordinator Worker          │
│                                                         │
│  subagent_type = "Explore/Plan" ──→ 内置专业 Agent        │
│                                                         │
│  subagent_type = "fork" ──────→ Fork 分支子代理           │
│                                                         │
│  subagent_type = undefined ──→ general-purpose Agent      │
│                                                         │
└─────────────────────────────────────────────────────────┘

协调者模式只是 AgentTool 多种工作模式之一。它与其他模式的核心区别在于:

  • 团队成员模式:多个 Agent 平等协作,通过 SendMessage 通信
  • 协调者模式:主从架构,主控负责任务分配与结果聚合
  • Fork 模式:分支上下文并行探索,无中心协调

10. 核心文件索引

文件职责
src/coordinator/coordinatorMode.ts协调者系统提示词、模式开关、上下文注入
src/tools/AgentTool/builtInAgents.ts协调者模式下动态加载 Worker Agent 定义
src/tools/AgentTool/AgentTool.tsxAgentTool 入口,路由到 spawn/worker/fork 路径
src/tools/SendMessageTool/向 Worker 发送后续指令
src/tools/TaskStopTool/停止运行中的 Worker

文档版本:v1.0 | 更新:2026-04-06