名称: 团队 描述: 使用Claude Code原生团队工具的N个协调代理处理共享任务列表 别名: [群组]
团队技能
生成N个协调代理,使用Claude Code的原生团队工具处理共享任务列表。取代了旧版的/swarm技能(基于SQLite),提供内置的团队管理、代理间消息传递和任务依赖——无需外部依赖。
swarm是此规范技能入口的兼容别名。
使用
/oh-my-claudecode:team N:代理类型 "任务描述"
/oh-my-claudecode:team "任务描述"
/oh-my-claudecode:team ralph "任务描述"
参数
- N - 队友代理数量(1-20)。可选;默认基于任务分解自动调整。
- 代理类型 - 为
team-exec阶段生成的OMC代理(例如,执行器、构建修复器、设计师)。可选;默认基于阶段感知路由(见下文阶段代理路由)。 - 任务 - 高层任务,分解并分配给队友
- ralph - 可选修饰符。当存在时,将团队管道包装在Ralph的持久循环中(失败重试,完成前架构师验证)。见团队+Ralph组合部分。
示例
/team 5:执行器 "修复项目中的所有TypeScript错误"
/team 3:构建修复器 "修复src/中的构建错误"
/team 4:设计师 "为所有页面组件实现响应式布局"
/team "重构认证模块,进行安全审查"
/team ralph "构建完整的用户管理REST API"
架构
用户: "/team 3:执行器 修复所有TypeScript错误"
|
v
[团队编排器(主导)]
|
+-- TeamCreate("fix-ts-errors")
| -> 主导变为 team-lead@fix-ts-errors
|
+-- 分析并分解任务为子任务
| -> explore/architect 生成子任务列表
|
+-- TaskCreate x N(每个子任务一个)
| -> 任务 #1, #2, #3 带依赖
|
+-- TaskUpdate x N(预分配所有者)
| -> 任务 #1 所有者=worker-1,等
|
+-- Task(team_name="fix-ts-errors", name="worker-1") x 3
| -> 生成队友进入团队
|
+-- 监控循环
| <- 来自队友的 SendMessage(自动交付)
| -> TaskList 轮询进度
| -> SendMessage 以解锁/协调
|
+-- 完成
-> 向每个队友发送 SendMessage(shutdown_request)
<- SendMessage(shutdown_response, approve: true)
-> TeamDelete("fix-ts-errors")
-> 删除 .omc/state/team-state.json
存储布局(由Claude Code管理):
~/.claude/
teams/fix-ts-errors/
config.json # 团队元数据 + 成员数组
tasks/fix-ts-errors/
.lock # 并发访问的文件锁
1.json # 子任务 #1
2.json # 子任务 #2(可能为内部)
3.json # 子任务 #3
...
阶段管道(规范团队运行时)
团队执行遵循阶段管道:
team-plan -> team-prd -> team-exec -> team-verify -> team-fix (循环)
阶段代理路由
每个管道阶段使用专用代理——不仅仅是执行器。主导根据阶段和任务特性选择代理。
| 阶段 | 必需代理 | 可选代理 | 选择标准 |
|---|---|---|---|
| team-plan | explore (haiku), planner (opus) |
analyst (opus), architect (opus) |
需求不清晰时使用analyst。系统边界复杂时使用architect。 |
| team-prd | analyst (opus) |
product-manager (sonnet), critic (opus) |
用户面向功能时使用product-manager。挑战范围时使用critic。 |
| team-exec | executor (sonnet) |
deep-executor (opus), build-fixer (sonnet), designer (sonnet), writer (haiku), test-engineer (sonnet) |
匹配代理到子任务类型。复杂自主工作时使用deep-executor,UI时使用designer,编译问题时使用build-fixer,文档时使用writer,测试创建时使用test-engineer。 |
| team-verify | verifier (sonnet) |
test-engineer (sonnet), security-reviewer (sonnet), code-reviewer (opus), quality-reviewer (sonnet), performance-reviewer (sonnet) |
始终运行verifier。认证/加密更改时添加security-reviewer。>20个文件或架构更改时添加code-reviewer。延迟敏感代码时添加performance-reviewer。 |
| team-fix | executor (sonnet) |
build-fixer (sonnet), debugger (sonnet), deep-executor (opus) |
类型/构建错误时使用build-fixer。回归隔离时使用debugger。复杂多文件修复时使用deep-executor。 |
路由规则:
- 主导选择每阶段代理,而非用户。 用户的
N:代理类型参数仅覆盖team-exec阶段工作者类型。所有其他阶段使用阶段专用专家。 - MCP提供商补充Claude代理。 可用时,将分析/审查路由到Codex (
ask_codex),UI/大上下文工作路由到Gemini (ask_gemini)。MCP工人是一次性的,不参与团队通信。 - 成本模式影响模型层级。 降级时:
opus代理转为sonnet,sonnet转为haiku(质量允许)。team-verify始终使用至少sonnet。 - 风险级别升级审查。 安全敏感或>20文件更改必须在
team-verify中包含security-reviewer+code-reviewer(opus)。
阶段进入/退出标准
- team-plan
- 进入:团队调用被解析,编排开始。
- 代理:
explore扫描代码库,planner创建任务图,可选analyst/architect用于复杂任务。 - 退出:分解完成,可运行任务图准备就绪。
- team-prd
- 进入:范围不明确或验收标准缺失。
- 代理:
analyst提取需求,可选product-manager/critic。 - 退出:验收标准和边界明确。
- team-exec
- 进入:
TeamCreate、TaskCreate、分配和工作者生成完成。 - 代理:工作者生成为子任务专用类型(见路由表)。
- 退出:执行任务达到当前轮次的终端状态。
- 进入:
- team-verify
- 进入:执行轮次结束。
- 代理:
verifier+ 任务专用审查者(见路由表)。 - 退出(通过):验证门通过,无所需后续。
- 退出(失败):生成修复任务,控制移至
team-fix。
- team-fix
- 进入:验证发现缺陷/回归/不完整标准。
- 代理:
executor/build-fixer/debugger取决于缺陷类型。 - 退出:修复完成,流返回
team-exec然后team-verify。
验证/修复循环和停止条件
继续team-exec -> team-verify -> team-fix直到:
- 验证通过且无所需修复任务剩余,或
- 工作达到显式终端阻塞/失败结果并带证据。
team-fix受最大尝试限制。如果修复尝试超过配置限制,转至终端failed(无无限循环)。
阶段移交惯例
在阶段间转换时,重要上下文——决策、被拒替代方案、识别风险——仅存在于主导的对话历史中。如果主导上下文压缩或代理重启,此知识丢失。
每个完成阶段必须在转换前产生移交文档。
主导写入移交到.omc/handoffs/<阶段名称>.md。
移交格式
## 移交: <当前阶段> → <下一阶段>
- **决定**: [此阶段做出的关键决策]
- **拒绝**: [考虑过的替代方案及拒绝原因]
- **风险**: [为下一阶段识别的风险]
- **文件**: [创建或修改的关键文件]
- **剩余**: [下一阶段处理的剩余项]
移交规则
- 主导在生成下一阶段代理前读取前次移交。 移交内容包含在下一阶段代理生成提示中,确保代理以完整上下文启动。
- 移交累积。 验证阶段可读取所有先前移交(plan → prd → exec)以获得完整决策历史。
- 团队取消时,移交保留在
.omc/handoffs/中供会话恢复。TeamDelete不删除它们。 - 移交轻量。 最多10-20行。捕捉决策和原理,非完整规范(这些存在于可交付文件如DESIGN.md中)。
示例
## 移交: team-plan → team-exec
- **决定**: 微服务架构,3个服务(认证、API、工作者)。PostgreSQL持久化。JWT用于认证令牌。
- **拒绝**: 单体(扩展担忧)、MongoDB(团队专长为SQL)、会话cookie(API优先设计)。
- **风险**: 工作者服务需Redis作业队列——尚未配置。认证服务初始设计无速率限制。
- **文件**: DESIGN.md, TEST_STRATEGY.md
- **剩余**: 数据库迁移脚本、CI/CD管道配置、Redis配置。
恢复和取消语义
- 恢复: 使用阶段状态+实时任务状态从最后非终端阶段重启。读取
.omc/handoffs/恢复阶段转换上下文。 - 取消:
/oh-my-claudecode:cancel请求队友关机,等待响应(尽力),标记阶段cancelled并active=false,捕获取消元数据,然后删除团队资源并清除/保留团队状态。.omc/handoffs/中的移交文件保留用于潜在恢复。 - 终端状态为
complete、failed和cancelled。
工作流
阶段1:解析输入
- 提取N(代理数量),验证1-20
- 提取代理类型,验证映射到已知OMC子代理
- 提取任务描述
阶段2:分析与分解
使用explore或architect(通过MCP或代理)分析代码库并将任务分解为N个子任务:
- 每个子任务应为文件范围或模块范围以避免冲突
- 子任务必须独立或有清晰依赖顺序
- 每个子任务需要简洁
subject和详细description - 识别子任务间依赖(如"共享类型必须在消费者前修复")
阶段3:创建团队
调用TeamCreate,使用从任务派生的slug:
{
"team_name": "fix-ts-errors",
"description": "修复项目中的所有TypeScript错误"
}
响应:
{
"team_name": "fix-ts-errors",
"team_file_path": "~/.claude/teams/fix-ts-errors/config.json",
"lead_agent_id": "team-lead@fix-ts-errors"
}
当前会话变为团队主导(team-lead@fix-ts-errors)。
使用state_write MCP工具为适当会话范围持久化写入OMC状态:
state_write(mode="team", active=true, current_phase="team-plan", state={
"team_name": "fix-ts-errors",
"agent_count": 3,
"agent_types": "executor",
"task": "fix all TypeScript errors",
"fix_loop_count": 0,
"max_fix_loops": 3,
"linked_ralph": false,
"stage_history": "team-plan"
})
注意: MCP
state_write工具将所有值传输为字符串。消费者读取状态时必须将agent_count、fix_loop_count、max_fix_loops强制转为数字,linked_ralph转为布尔值。
状态模式字段:
| 字段 | 类型 | 描述 |
|---|---|---|
active |
布尔值 | 团队模式是否激活 |
current_phase |
字符串 | 当前管道阶段:team-plan、team-prd、team-exec、team-verify、team-fix |
team_name |
字符串 | 团队的slug名称 |
agent_count |
数字 | 工作者代理数量 |
agent_types |
字符串 | team-exec中使用的逗号分隔代理类型 |
task |
字符串 | 原始任务描述 |
fix_loop_count |
数字 | 当前修复迭代计数 |
max_fix_loops |
数字 | 失败前的最大修复迭代(默认:3) |
linked_ralph |
布尔值 | 团队是否链接到ralph持久循环 |
stage_history |
字符串 | 带时间戳的阶段转换逗号分隔列表 |
每次阶段转换时更新状态:
state_write(mode="team", current_phase="team-exec", state={
"stage_history": "team-plan:2026-02-07T12:00:00Z,team-prd:2026-02-07T12:01:00Z,team-exec:2026-02-07T12:02:00Z"
})
读取状态以检测恢复:
state_read(mode="team")
如果active=true且current_phase非终端,则从最后不完整阶段恢复而非创建新团队。
阶段4:创建任务
为每个子任务调用TaskCreate。使用TaskUpdate和addBlockedBy设置依赖。
// 子任务1的TaskCreate
{
"subject": "修复src/auth/中的类型错误",
"description": "修复src/auth/login.ts、src/auth/session.ts和src/auth/types.ts中的所有TypeScript错误。运行tsc --noEmit验证。",
"activeForm": "修复认证类型错误"
}
响应存储任务文件(如1.json):
{
"id": "1",
"subject": "修复src/auth/中的类型错误",
"description": "修复src/auth/login.ts...中的所有TypeScript错误",
"activeForm": "修复认证类型错误",
"owner": "",
"status": "pending",
"blocks": [],
"blockedBy": []
}
对于有依赖的任务,创建后使用TaskUpdate:
// 任务 #3 依赖于任务 #1(共享类型必须先修复)
{
"taskId": "3",
"addBlockedBy": ["1"]
}
主导预分配所有者以避免竞态条件(无原子声明):
// 分配任务 #1 给 worker-1
{
"taskId": "1",
"owner": "worker-1"
}
阶段5:生成队友
使用Task和team_name及name参数生成N个队友。每个队友获得团队工作序言(见下文)加其特定分配。
{
"subagent_type": "oh-my-claudecode:executor",
"team_name": "fix-ts-errors",
"name": "worker-1",
"prompt": "<工作序言 + 分配任务>"
}
响应:
{
"agent_id": "worker-1@fix-ts-errors",
"name": "worker-1",
"team_name": "fix-ts-errors"
}
副作用:
- 队友添加到
config.json成员数组 - 自动创建内部任务(带
metadata._internal: true)跟踪代理生命周期 - 内部任务出现在
TaskList输出中——计数真实任务时过滤它们
重要: 并行生成所有队友(它们是后台代理)。不要在生成下一个前等待一个完成。
阶段6:监控
主导编排器通过两个通道监控进度:
-
入站消息——队友完成任务或需要帮助时发送
SendMessage到team-lead。这些自动到达为新对话轮次(无需轮询)。 -
TaskList轮询——定期调用
TaskList检查整体进度:#1 [completed] 修复src/auth/中的类型错误 (worker-1) #3 [in_progress] 修复src/api/中的类型错误 (worker-2) #5 [pending] 修复src/utils/中的类型错误 (worker-3)格式:
#ID [status] subject (owner)
主导可采取的协调动作:
- 解锁队友: 发送
message带指导或缺失上下文 - 重新分配工作: 如果队友提前完成,使用
TaskUpdate将待处理任务分配给他们并通过SendMessage通知 - 处理失败: 如果队友报告失败,重新分配任务或生成替换
任务看守策略
监控卡住或失败队友:
- 最大进行中时间: 如果任务保持
in_progress超过5分钟无消息,发送状态检查 - 疑似死亡工作者: 无消息+卡住任务10+分钟→重新分配任务给另一工作者
- 重新分配阈值: 如果工作者失败2+任务,停止分配新任务给它
阶段6.5:阶段转换(状态持久化)
每次阶段转换时更新OMC状态:
// 规划后进入team-exec
state_write(mode="team", current_phase="team-exec", state={
"stage_history": "team-plan:T1,team-prd:T2,team-exec:T3"
})
// 执行后进入team-verify
state_write(mode="team", current_phase="team-verify")
// 验证失败后进入team-fix
state_write(mode="team", current_phase="team-fix", state={
"fix_loop_count": 1
})
这启用:
- 恢复: 如果主导崩溃,
state_read(mode="team")显示最后阶段和团队名称用于恢复 - 取消: 取消技能读取
current_phase知道需要什么清理 - Ralph集成: Ralph可读取团队状态知道管道是否完成或失败
阶段7:完成
当所有真实任务(非内部)完成或失败:
- 验证结果——通过
TaskList检查所有子任务标记为completed - 关机关队友——发送
shutdown_request给每个活跃队友:{ "type": "shutdown_request", "recipient": "worker-1", "content": "所有工作完成,关闭团队" } - 等待响应——每个队友响应
shutdown_response(approve: true)并终止 - 删除团队——调用
TeamDelete清理:
响应:{ "team_name": "fix-ts-errors" }{ "success": true, "message": "清理了团队\"fix-ts-errors\"的目录和工作树", "team_name": "fix-ts-errors" } - 清理OMC状态——删除
.omc/state/team-state.json - 报告摘要——向用户呈现结果
代理序言
生成队友时,在提示中包含此序言以建立工作协议。根据队友特定任务分配调整。
你是团队 "{team_name}" 中的团队工作者。你的名称是 "{worker_name}"。
你向团队主导("team-lead")报告。
== 工作协议 ==
1. 声明:调用TaskList查看你的分配任务(所有者 = "{worker_name}")。
选择第一个状态为 "pending" 且分配给你的任务。
调用TaskUpdate设置状态 "in_progress":
{"taskId": "ID", "status": "in_progress", "owner": "{worker_name}"}
2. 工作:使用你的工具(Read、Write、Edit、Bash)执行任务。
不要生成子代理。不要委托。直接工作。
3. 完成:完成后标记任务完成:
{"taskId": "ID", "status": "completed"}
4. 报告:通过SendMessage通知主导:
{"type": "message", "recipient": "team-lead", "content": "完成任务 #ID: <所做摘要>", "summary": "任务 #ID 完成"}
5. 下一个:检查TaskList是否有更多分配任务。如果你有更多待处理任务,转到步骤1。
如果没有更多任务分配给你,通知主导:
{"type": "message", "recipient": "team-lead", "content": "所有分配任务完成。待命。", "summary": "所有任务完成,待命"}
6. 关机:当你收到shutdown_request时,响应:
{"type": "shutdown_response", "request_id": "<来自请求>", "approve": true}
== 阻塞任务 ==
如果任务有blockedBy依赖,跳过它直到这些任务完成。
定期检查TaskList看阻塞是否已解决。
== 错误 ==
如果你无法完成任务,向主导报告失败:
{"type": "message", "recipient": "team-lead", "content": "失败任务 #ID: <原因>", "summary": "任务 #ID 失败"}
不要标记任务为完成。保持它为in_progress以便主导重新分配。
== 规则 ==
- 永不生成子代理或使用Task工具
- 始终使用绝对文件路径
- 始终通过SendMessage向"team-lead"报告进度
- 仅使用类型为"message"的SendMessage——永不"broadcast"
通信模式
队友到主导(任务完成报告)
{
"type": "message",
"recipient": "team-lead",
"content": "完成任务 #1: 修复了src/auth/login.ts中的3个类型错误和src/auth/session.ts中的2个。所有文件通过tsc --noEmit。",
"summary": "任务 #1 完成"
}
主导到队友(重新分配或指导)
{
"type": "message",
"recipient": "worker-2",
"content": "任务 #3 现在已解锁。同时接管任务 #5,它原本分配给worker-1。",
"summary": "新任务分配"
}
广播(谨慎使用——发送N个单独消息)
{
"type": "broadcast",
"content": "停止:src/types/index.ts中的共享类型已更改。继续前拉取最新。",
"summary": "共享类型更改"
}
关机协议(阻塞)
关键:步骤必须按确切顺序执行。在关机确认前永不调用TeamDelete。
步骤1:验证完成
调用TaskList——验证所有真实任务(非内部)完成或失败。
步骤2:请求每个队友关机
主导发送:
{
"type": "shutdown_request",
"recipient": "worker-1",
"content": "所有工作完成,关闭团队"
}
步骤3:等待响应(阻塞)
- 每个队友最多等待30s的
shutdown_response - 跟踪哪些队友确认 vs 超时
- 如果队友30s内未响应:记录警告,标记为无响应
队友接收并响应:
{
"type": "shutdown_response",
"request_id": "shutdown-1770428632375@worker-1",
"approve": true
}
批准后:
- 队友进程终止
- 队友自动从
config.json成员数组移除 - 该队友的内部任务完成
步骤4:TeamDelete——仅在所有队友确认或超时后
{ "team_name": "fix-ts-errors" }
步骤5:孤儿扫描
检查在TeamDelete后存活的代理进程:
node "${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-orphans.mjs" --team-name fix-ts-errors
这扫描匹配团队名称的进程,其配置不再存在,并终止它们(SIGTERM → 5s等待 → SIGKILL)。支持--dry-run用于检查。
关机序列是阻塞的: 在直到所有队友都满足以下条件前不要进行到TeamDelete:
- 确认关机(
shutdown_response带approve: true),或 - 超时(30s无响应)
重要: request_id在队友接收的关机请求消息中提供。队友必须提取它并传回。不要伪造request IDs。
MCP工人(混合角色)
团队技能支持混合执行,结合Claude代理队友和外部MCP工人(Codex和Gemini CLI)。两种类型都可进行代码更改——它们在能力和成本上不同。
执行模式
任务在分解时标记执行模式:
| 执行模式 | 提供商 | 能力 |
|---|---|---|
claude_worker |
Claude代理 | 完整Claude Code工具访问(Read/Write/Edit/Bash/Task)。最适合需要Claude推理+迭代工具使用的任务。 |
mcp_codex |
Codex CLI (ask_codex) |
完整文件系统访问在working_directory中。自主运行。最适合代码审查、安全分析、重构、架构。 |
mcp_gemini |
Gemini CLI (ask_gemini) |
完整文件系统访问 + 1M令牌上下文。自主运行。最适合UI/前端工作、大规模更改、文档。 |
MCP工人如何操作
Codex和Gemini CLI在完全自动模式下运行,带文件系统访问。它们是自主执行器,不仅仅是分析者:
- 主导写任务指令到
prompt_file - 主导调用
ask_codex或ask_gemini,working_directory设置为项目根 - CLI读取文件,进行更改,运行命令——都在工作目录内
- 结果/摘要写入
output_file - 主导读取输出,标记任务完成,并将结果馈送到依赖任务
与Claude队友的关键区别:
- MCP工人通过CLI操作,非Claude Code的工具系统
- 它们不能使用TaskList/TaskUpdate/SendMessage(无团队感知)
- 它们作为一次性自主作业运行,非持久队友
- 主导管理其生命周期(生成、监控、收集结果)
何时路由到何处
| 任务类型 | 最佳路由 | 原因 |
|---|---|---|
| 迭代多步骤工作 | Claude队友 | 需要工具介导迭代 + 团队通信 |
| 代码审查 / 安全审计 | Codex MCP | 专用,比Claude opus便宜 |
| 架构分析 / 规划 | Codex MCP | 外部视角,强分析推理 |
| 重构(范围明确) | Codex MCP | 自主执行,擅长结构化转换 |
| UI/前端实现 | Gemini MCP | 1M上下文窗口,设计专长,可编辑多文件 |
| 大规模文档 | Gemini MCP | 写作专长 + 大上下文一致性 |
| 视觉/图像分析 | Gemini MCP | 多模态能力 |
| 构建/测试迭代循环 | Claude队友 | 需要Bash工具 + 迭代修复周期 |
| 需要团队协调的任务 | Claude队友 | 需要SendMessage状态更新 |
示例:带MCP执行器的混合团队
/team 3:执行器 "使用安全审查重构认证模块"
任务分解:
#1 [mcp_codex] 当前认证代码安全审查 -> 输出到 .omc/research/auth-security.md
#2 [mcp_codex] 重构auth/login.ts和auth/session.ts(使用#1发现)
#3 [mcp_gemini] 重新设计认证UI组件(登录表单、会话指示器)
#4 [claude_worker] 更新认证测试 + 修复集成问题
#5 [mcp_codex] 所有更改的最终代码审查
主导运行#1(Codex分析),然后#2和#3并行(Codex重构后端,Gemini重新设计前端),然后#4(Claude队友处理测试迭代),然后#5(最终Codex审查)。
MCP预飞分析(可选)
对于大型模糊任务,在团队创建前运行分析:
- 调用
ToolSearch("mcp")发现延迟MCP工具(首次使用前必需) - 调用
ask_codex(规划者角色)带任务描述 + 代码库上下文 - 使用分析产生更好任务分解
- 创建团队和任务带丰富上下文
如果ToolSearch未找到MCP工具,跳过MCP预飞并使用Claude代理代替。
这在任务范围不明确且受益于外部推理时特别有用,然后再承诺特定分解。
监控增强:发件箱自动摄取
主导可以使用发件箱阅读器工具主动摄取MCP工人的发件箱消息,启用事件驱动监控,而非仅依赖SendMessage交付。
发件箱阅读器函数
readNewOutboxMessages(teamName, workerName) —— 使用字节偏移游标读取单个工人的新发件箱消息。每次调用推进游标,所以后续调用仅返回自上次读取以来写入的消息。镜像readNewInboxMessages()的收件箱游标模式。
readAllTeamOutboxMessages(teamName) —— 读取团队中所有工人的新发件箱消息。返回{ workerName, messages }条目数组,跳过无新消息的工人。适用于监控循环中的批量轮询。
resetOutboxCursor(teamName, workerName) —— 将工人的发件箱游标重置回字节0。适用于主导重启后重新读取历史消息或调试。
在监控阶段使用getTeamStatus()
getTeamStatus(teamName, workingDirectory, heartbeatMaxAgeMs?)函数提供统一快照,结合:
- 工人注册 —— 哪些MCP工人已注册(从影子注册表 / config.json)
- 心跳新鲜度 —— 基于心跳年龄每个工人是否存活
- 任务进度 —— 每个工人和全团队任务计数(pending、in_progress、completed)
- 当前任务 —— 每个工人正在执行哪个任务
- 最近发件箱消息 —— 自上次状态检查以来的新消息
在监控循环中的示例用法:
const status = getTeamStatus('fix-ts-errors', workingDirectory);
for (const worker of status.workers) {
if (!worker.isAlive) {
// 工人已死——重新分配其进行中任务
}
for (const msg of worker.recentMessages) {
if (msg.type === 'task_complete') {
// 标记任务完成,解锁依赖
} else if (msg.type === 'task_failed') {
// 处理失败,可能重试或重新分配
} else if (msg.type === 'error') {
// 记录错误,检查工人是否需要干预
}
}
}
if (status.taskSummary.pending === 0 && status.taskSummary.inProgress === 0) {
// 所有工作完成——进行到关机
}
基于发件箱消息的事件驱动动作
| 消息类型 | 动作 |
|---|---|
task_complete |
标记任务完成,检查阻塞任务是否现在解锁,通知依赖工人 |
task_failed |
递增失败侧车,决定重试 vs 重新分配 vs 跳过 |
idle |
工人无分配任务——分配待处理工作或开始关机 |
error |
记录错误,检查consecutiveErrors在心跳中用于隔离阈值 |
shutdown_ack |
工人确认关机——安全从团队移除 |
heartbeat |
更新活跃性跟踪(与心跳文件冗余但用于延迟监控) |
此方法通过提供基于拉的机制补充现有基于SendMessage的通信,用于不能使用Claude Code团队消息工具的MCP工人。
错误处理
队友任务失败
- 队友发送
SendMessage给主导报告失败 - 主导决定:重试(重新分配同一任务给相同或不同工人)或跳过
- 重新分配:
TaskUpdate设置新所有者,然后SendMessage给新所有者
队友卡住(无消息)
- 主导通过
TaskList检测——任务卡在in_progress太久 - 主导发送
SendMessage给队友询问状态 - 如果无响应,认为队友死亡
- 通过
TaskUpdate重新分配任务给另一工人
依赖阻塞
- 如果阻塞任务失败,主导必须决定是否:
- 重试阻塞者
- 移除依赖(
TaskUpdate带修改blockedBy) - 完全跳过阻塞任务
- 通过
SendMessage向受影响队友通信决策
队友崩溃
- 该队友的内部任务将显示意外状态
- 队友从
config.json成员消失 - 主导重新分配孤儿任务给剩余工人
- 如果需要,用
Task(team_name, name)生成替换队友
团队+Ralph组合
当用户调用/team ralph,说"team ralph",或结合两个关键词时,团队模式将自身包装在Ralph的持久循环中。这提供:
- 团队编排——多代理阶段管道,每阶段专用代理
- Ralph持久性——失败重试,完成前架构师验证,迭代跟踪
激活
团队+Ralph在以下情况激活:
- 用户调用
/team ralph "task"或/oh-my-claudecode:team ralph "task" - 关键词检测器在提示中找到
team和ralph - 钩子检测
MAGIC KEYWORD: RALPH伴随团队上下文
状态链接
两种模式写入自己的状态文件带交叉引用:
// 团队状态(通过state_write)
state_write(mode="team", active=true, current_phase="team-plan", state={
"team_name": "build-rest-api",
"linked_ralph": true,
"task": "构建完整的REST API"
})
// Ralph状态(通过state_write)
state_write(mode="ralph", active=true, iteration=1, max_iterations=10, current_phase="execution", state={
"linked_team": true,
"team_name": "build-rest-api"
})
执行流
- Ralph外循环开始(迭代1)
- 团队管道运行:
team-plan -> team-prd -> team-exec -> team-verify - 如果
team-verify通过:Ralph运行架构师验证(至少STANDARD层) - 如果架构师批准:两种模式完成,运行
/oh-my-claudecode:cancel - 如果
team-verify失败或架构师拒绝:团队进入team-fix,然后循环回team-exec -> team-verify - 如果修复循环超过
max_fix_loops:Ralph递增迭代并重试整个管道 - 如果Ralph超过
max_iterations:终端failed状态
取消
取消任一模式取消两者:
- 取消Ralph(链接): 首先取消Team(优雅关机),然后清除Ralph状态
- 取消Team(链接): 清除Team,标记Ralph迭代取消,停止循环
见下文取消部分细节。
幂等恢复
如果主导在运行中崩溃,团队技能应检测现有状态并恢复:
- 检查
~/.claude/teams/中匹配任务slug的团队 - 如果找到,读取
config.json发现活跃成员 - 恢复监控模式而非创建重复团队
- 调用
TaskList确定当前进度 - 从监控阶段继续
这防止重复团队并允许从主导失败中优雅恢复。
比较:团队 vs 旧版Swarm
| 方面 | 团队(原生) | Swarm(旧版SQLite) |
|---|---|---|
| 存储 | ~/.claude/teams/和~/.claude/tasks/中的JSON文件 |
.omc/state/swarm.db中的SQLite |
| 依赖 | 不需要better-sqlite3 |
需要better-sqlite3 npm包 |
| 任务声明 | TaskUpdate(owner + in_progress)——主导预分配 |
SQLite IMMEDIATE事务——原子 |
| 竞态条件 | 可能如果两个代理声明同一任务(通过预分配缓解) | 无(SQLite事务) |
| 通信 | SendMessage(DM、广播、关机) |
无(即发即弃代理) |
| 任务依赖 | 内置blocks / blockedBy数组 |
不支持 |
| 心跳 | Claude Code的自动空闲通知 | 手动心跳表 + 轮询 |
| 关机 | 优雅请求/响应协议 | 基于信号的终止 |
| 代理生命周期 | 通过内部任务 + config成员自动跟踪 | 通过心跳表手动跟踪 |
| 进度可见性 | TaskList显示带所有者的实时状态 |
任务表上的SQL查询 |
| 冲突预防 | 所有者字段(主导分配) | 带超时的基于租约声明 |
| 崩溃恢复 | 主导通过缺失消息检测,重新分配 | 5分钟租约超时后自动释放 |
| 状态清理 | TeamDelete移除所有 |
手动rm SQLite数据库 |
何时使用团队而非Swarm: 新工作始终首选/team。它使用Claude Code的内置基础设施,无需外部依赖,支持代理间通信,并有任务依赖管理。
取消
/oh-my-claudecode:cancel技能处理团队清理:
- 通过
state_read(mode="team")读取团队状态获取team_name和linked_ralph - 发送
shutdown_request给所有活跃队友(从config.json成员) - 等待每个
shutdown_response(每成员15s超时) - 调用
TeamDelete移除团队和任务目录 - 通过
state_clear(mode="team")清除状态 - 如果
linked_ralph为true,也清除ralph:state_clear(mode="ralph")
链接模式取消(团队+Ralph)
当团队链接到ralph时,取消遵循依赖顺序:
- 从Ralph上下文触发取消: 首先取消Team(所有队友优雅关机),然后清除Ralph状态。这确保工作者在持久循环退出前停止。
- 从Team上下文触发取消: 清除Team状态,然后标记Ralph为取消。Ralph的停止钩子将检测缺失团队并停止迭代。
- 强制取消(
--force): 通过state_clear无条件清除team和ralph状态。
如果队友无响应,TeamDelete可能失败。在这种情况下,取消技能应短暂等待并重试,或通知用户手动清理~/.claude/teams/{team_name}/和~/.claude/tasks/{team_name}/。
配置
通过.omc-config.json的可选设置:
{
"team": {
"maxAgents": 20,
"defaultAgentType": "executor",
"monitorIntervalMs": 30000,
"shutdownTimeoutMs": 15000
}
}
- maxAgents - 最大队友数(默认:20)
- defaultAgentType - 未指定时的代理类型(默认:
executor) - monitorIntervalMs - 轮询
TaskList的频率(默认:30s) - shutdownTimeoutMs - 等待关机响应的时间(默认:15s)
注意: 团队成员无硬编码模型默认。每个队友是单独Claude Code会话,继承用户配置的模型。由于队友可生成自己的子代理,会话模型充当编排层,而子代理可使用任何模型层级。
状态清理
成功完成时:
TeamDelete处理所有Claude Code状态:- 移除
~/.claude/teams/{team_name}/(配置) - 移除
~/.claude/tasks/{team_name}/(所有任务文件 + 锁)
- 移除
- 通过MCP工具的OMC状态清理:
如果链接到Ralph:state_clear(mode="team")state_clear(mode="ralph") - 或运行
/oh-my-claudecode:cancel自动处理所有清理。
重要: 仅在所有队友已关机后调用TeamDelete。TeamDelete将失败如果活跃成员(除主导外)仍存在于配置中。
Git工作树集成
MCP工人可在隔离的git工作树中操作,以防止并发工人间的文件冲突。
工作原理
-
工作树创建: 在生成工人前,调用
createWorkerWorktree(teamName, workerName, repoRoot)在.omc/worktrees/{team}/{worker}创建隔离工作树,分支omc-team/{teamName}/{workerName}。 -
工人隔离: 传递工作树路径作为工人
BridgeConfig中的workingDirectory。工人在其自己的工作树中独家操作。 -
合并协调: 工人在其任务完成后,使用
checkMergeConflicts()验证分支可干净合并,然后mergeWorkerBranch()用--no-ff合并以获得清晰历史。 -
团队清理: 团队关机时,调用
cleanupTeamWorktrees(teamName, repoRoot)移除所有工作树及其分支。
API参考
| 函数 | 描述 |
|---|---|
createWorkerWorktree(teamName, workerName, repoRoot, baseBranch?) |
创建隔离工作树 |
removeWorkerWorktree(teamName, workerName, repoRoot) |
移除工作树和分支 |
listTeamWorktrees(teamName, repoRoot) |
列出所有团队工作树 |
cleanupTeamWorktrees(teamName, repoRoot) |
移除所有团队工作树 |
checkMergeConflicts(workerBranch, baseBranch, repoRoot) |
非破坏性冲突检查 |
mergeWorkerBranch(workerBranch, baseBranch, repoRoot) |
合并工人分支(–no-ff) |
mergeAllWorkerBranches(teamName, repoRoot, baseBranch?) |
合并所有完成工人 |
重要说明
tmux-session.ts中的createSession()不处理工作树创建——工作树生命周期单独通过git-worktree.ts管理- 工作树不在单个工人关机时清理——仅在团队关机时,以允许事后检查
- 分支名称通过
sanitizeName()净化以防止注入 - 所有路径验证防止目录遍历
陷阱
-
内部任务污染TaskList——当队友生成时,系统自动创建内部任务带
metadata._internal: true。这些出现在TaskList输出中。计数真实任务进度时过滤它们。内部任务的subject是队友名称。 -
无原子声明——与SQLite swarm不同,
TaskUpdate无事务保证。两个队友可能竞态声明同一任务。缓解: 主导应在生成队友前通过TaskUpdate(taskId, owner)预分配所有者。队友应仅处理分配给它们的任务。 -
任务ID是字符串——ID是自动递增字符串(“1”、“2”、“3”),非整数。始终传递字符串值到
taskId字段。 -
TeamDelete需要空团队——所有队友必须在调用
TeamDelete前关机。主导(唯一剩余成员)排除于此检查。 -
消息自动交付——队友消息作为新对话轮次到达主导。入站消息无需轮询或收件箱检查。然而,如果主导在轮次中(处理),消息排队并在轮次结束时交付。
-
队友提示存储在配置中——完整提示文本存储在
config.json成员数组中。不要在队友提示中放置秘密或敏感数据。 -
关机时成员自动移除——队友批准关机并终止后,它自动从
config.json移除。不要重新读取配置期望找到已关机队友。 -
shutdown_response需要request_id——队友必须从传入的关机请求JSON中提取
request_id并传回。格式是shutdown-{timestamp}@{worker-name}。伪造此ID将导致关机静默失败。 -
团队名称必须是有效slug——使用小写字母、数字和连字符。从任务描述派生(如"fix TypeScript errors"变为"fix-ts-errors")。
-
广播昂贵——每个广播发送单独消息给每个队友。默认使用
message(DM)。仅用于真正团队范围关键警报时广播。 -
MCP工人是一次性的,非持久——Codex和Gemini CLI有完整文件系统访问并可进行代码更改。然而,它们作为自主一次性作业运行——它们不能使用TaskList/TaskUpdate/SendMessage。主导必须管理其生命周期:写prompt_file、调用MCP、读output_file、标记任务完成。它们不像Claude队友那样参与团队通信。