Skip to main content
Glama

TaskSwarm · 任务蜂群

ZCode 插件的多 Agent 编排引擎:把一个目标拆成任务树,按依赖波次并行派发子代理,用共享看板让互不可见的子代理"看见"彼此。

tests coverage deps node


30 秒看懂

单个 AI 子代理能力很强,但一次只能干一件线性的事。面对"重构登录模块 + 补齐测试 + 更新文档"这种可并行的任务,只能串着做。

TaskSwarm 让主代理把目标拆成任务树,把互不依赖的部分同时派给多个后台子代理,再用一块共享看板让它们交换进度——最后主代理收波、转发关键产出、汇总。

一个目标  →  任务树(带依赖)  →  按波次并行派发  →  共享看板互通  →  汇总

Related MCP server: Project Manager MCP

核心设计洞察:子代理之间没有通信能力

这是本插件要解决的根本约束,也是在 ZCode 上做多 Agent 编排与在 Claude Code 上最大的不同。

我在实现前先做了能力探测,实测结论:

能力

主代理

子代理

启动子代理(Agent

✅ 有

没有

给别的代理发消息(SendMessage

✅ 有

没有

调用 MCP 工具

✅ 有

也就是说:子代理是一群"哑"worker——干得了活,喊不了话,也生不出小代理。

这个约束直接决定了两条通信通道:

  1. 看板拉取(默认通道):子代理通过 MCP 主动读写共享看板。领任务用 task_claim、汇报进度用 task_update、了解全队状态用 board、读同伴的完整结论用 task_notes。因为是"拉取",子代理永远不需要别人主动通知它。

  2. 主代理推送(补强通道):主代理是唯一有 SendMessage 的角色,因此它承担"信息搬运工":派发新任务时把上游产出写进子代理 prompt;收到某子代理完成通知后,把关键结论转发给正在跑的、与之相关的其他子代理。这条通道我做了实测:给一个正在执行长任务的子代理推送带验证码的消息,它在中途收到了——推送通道可用,不是理论设计。

架构图

(可编辑源文件:docs/architecture.drawio

为什么不能直接用现成的

调研结论(2026-09):Claude Flow / Ruflo(61k★)、barkain/claude-code-workflow-orchestrationAgent Teams 都是 Claude Code 专用,依赖 ZCode 没有的 TaskCreate / TeamCreate / hooks 实验机制,无法移植。

而 ZCode 这边:原生子代理可以调用 MCP 工具(已探针验证),但没有 SendMessage —— 所以互通必须设计成"看板拉取 + 主代理推送"双通道,而不可能靠代理间直连。

本插件的架构是 「MCP 提供确定性能力 + SKILL.md 提供编排流程」

  • 确定性部分全部下沉到 MCP Server:任务树存储、依赖判定、防重复领取、并发写盘、看板渲染、笔记分页。这些是"有明确正确答案"的事,不该交给 LLM 每次自由发挥。

  • 编排循环留给主代理:何时拆解、拆多细、派给谁、何时收波、如何转发——这些需要判断力,ZCode 没有插件级调度 API 可挂,主代理本身就是调度器。

安装

需要 Node.js ≥ 18,零第三方依赖。

git clone https://github.com/Wersky/taskswarm.git

然后在 ZCode 里:设置 → 插件管理 → 发现 → 「+」添加本地目录市场,指向包含 marketplace.json 的目录,安装 taskswarm,重启会话。

插件清单使用 ${ZCODE_PLUGIN_ROOT} / ${ZCODE_PROJECT_DIR} 占位符,不硬编码任何本机绝对路径——换台机器克隆下来即可运行。

使用

/swarm 重构登录模块并补齐测试

或者直接说「任务蜂群:<任务>」「把任务拆解并行处理」。

主代理会展示拆解出的任务树,按依赖波次派发,过程中你可以随时看板:

[T1] (done)        抽出认证接口 @agent-1 💬 接口定稿在 src/auth/types.ts,前端可直接引用
[T2] (in_progress) 重写登录流程 @agent-2 💬 已接通新接口,正在补错误分支
[T3] (pending)     更新登录文档 ← 依赖: T1

什么时候不该

  • < 3 个子项:拆解开销大于并行收益,主代理直接做。

  • 强串行依赖:拆了也是一波一波等,没有并行度。

  • 需要频繁来回讨论:用圆桌讨论(roundtable 插件)更合适。

  • 单纯查资料 / 读代码:Explore 子代理更省。

一条硬规则:改同一批文件的子任务必须串行

并行最常见的翻车方式,是让两个子代理同时改同一个文件——后写的覆盖先写的,而且双方都以为自己成功了。拆解时凡是要动同一批文件的任务,必须用 dependsOn 串起来。

MCP 工具

工具

调用方

作用

plan_create

主代理

创建任务树(递归嵌套 ≤ 5 层、依赖、环检测、failurePolicy

plan_get

主代理

任务树全貌 + 就绪任务 + 最近事件

task_ready

主代理

查询依赖已满足、可派发的任务(含 blockedBy 阻断标注)

task_claim

子代理

原子领取(防重复派发)

task_update

子代理 / 主代理

状态流转 + 进展笔记;主代理恢复死任务用 force:true

task_notes

所有人

读回笔记全文(分页,limit ≤ 200

task_add

主代理 / 子代理

执行中途追加任务(拆解可持续发生)

board

所有人

共享进度看板(状态、负责人、最新笔记摘要)

plan_reset / state

主代理

重开 / 状态落盘与恢复

真实工具名前缀是 mcp__plugin_taskswarm_taskswarm__,例如 mcp__plugin_taskswarm_taskswarm__task_claim

所有调用都要显式传 workspace(工作区绝对路径)——省略时会落到 server 进程的 cwd,而不是你以为的地方。这条行为有测试锁定(lock-failure.test.mjs 的「省略 workspace 时回退到进程 cwd」)。

测试与可靠性

91 个测试,全部通过;行覆盖 86.8%,函数覆盖 96.4%。

npm test          # 91 tests, 0 fail
npm run coverage  # 行覆盖 86.8% (696/802) · 函数覆盖 96.4% (80/83)

要求 Node ≥ 18,无任何测试框架依赖(用内置 node:test + node:assert/strict)。

测试为什么全部走子进程

本插件的可靠性承诺——多进程并发写不损坏数据、同一任务不会被重复领取——只有在多个真实进程共享同一个状态文件时才成立。同进程内的 Promise 并发测不出任何东西(事件循环天然串行)。因此所有测试都通过 spawn 启动真实的 MCP server 进程,与生产运行方式完全一致。

这套测试抓出过的真实缺陷

开发和审计过程中,测试(以及另写的独立复现脚本)定位并锁定了以下问题,现在它们都有回归防线:

缺陷

症状

现状

并发写坏状态文件

两进程各写 120 条笔记 → JSON 损坏、期间 217 次工具报错、整份计划不可恢复

原子替换 + 跨进程锁;测试「两进程各追加 120 条笔记」锁定

并发双重领取

60 次并发抢同一任务,4 次双方都领取成功

加锁后降为 0 次;测试「60 次并发抢同一任务」锁定

笔记无上限

状态文件与返回体量失控(500 条长笔记 ≈ 100 KB+),每次操作全量重写

每任务 500 条 / 单条 4000 字符上限,超限保留最新并记账 notesDropped

长文本读不回

plan_get/board 只给 60/120 字符截断摘要,全文无处可读

新增 task_notes 分页读全文

三级嵌套静默丢失

subtasks 只展开两层,第三层无声消失

递归展开 ≤ 5 层,超限明确报错

__proto__ 作任务 id

任务在落盘后凭空消失(原型污染)

id 严格校验 + Object.create(null)

失败上游仍派发下游

代码注释声称"阻断"但实测放行

failurePolicy: block(默认)真正阻断,proceed 可用并标注 blockedBy

状态机无守卫

任何人可改任何任务、终态可被任意回退、done 可重新领取

转移表 + owner 校验;恢复场景走 force:true(留审计日志)

损坏静默丢数据

文件损坏时只报"没有进行中的蜂群任务"

自动备份 .corrupt-<时间戳>.json + 明确错误提示

文档工具名前缀错误

SKILL.md 写 mcp__taskswarm__*,实际前缀是 mcp__plugin_taskswarm_taskswarm__*

已改正,并在 README/SKILL 显著标注

其中最值得说的一点:board 按 owner 过滤的原版测试断言写成了 !A || B 的形式——后半句恒为真,过滤功能完全失效时测试也会通过。新套件改成了双向断言(甲的视图必须含甲、必须不含乙),并额外校验 activeWorkers 也被过滤(这个字段原来确实漏了过滤,是新测试抓出来的)。

可靠性机制

  • 原子替换写盘:写 <file>.tmp-<pid>fsyncrename。读者永远看不到半截文件(8 次写入中强杀测试零损坏)。

  • 跨进程文件锁openSync(lock, 'wx') 原子加锁,持锁者记录 {pid, at, host};崩溃残留的陈旧锁通过 PID 存活探测锁龄超时 自动抢占,并留下「锁抢占」日志。

  • 损坏自愈:解析失败时先备份原文件再报错,绝不静默当成"没有计划"。

  • 失败语义可控:默认上游失败即挡住下游(避免在残缺基础上继续盖楼);允许带缺陷推进时用 proceed,并在 task_ready 里用 blockedBy 标明是哪个上游出的问题。

  • force 是审计机制,不是权限机制:MCP 协议层无法验证"你是不是主代理",任何调用方都可传 force:true。它的价值在于留下可追溯的审计事件(记录操作者、原 owner、状态迁移),而不是阻止别人。这个边界有专门的测试锁定,防止后人误以为它有防护能力。

工程要点

  • 零依赖:MCP Server 只用 Node 内置模块(fs / path / readline / os),没有 package-lock 与供应链风险。整个 server 约 1000 行。

  • 可移植:插件清单用占位符;裸 node 启动(有测试从无关 cwd 启动验证)。

  • 覆盖率统计的坑node --experimental-test-coverage子进程里跑的代码一无所知——直接跑会得到"0 个文件、100%"的空报告。因此写了 scripts/coverage.mjs:用 NODE_V8_COVERAGE 收集每个子进程的 V8 覆盖率再合并,按「覆盖该行的最内层 range」判定。该脚本先在已知答案的受控样本上验证过才用于正式统计(含一个刻意不调用的函数与一个未走到的分支,确认能正确判为未覆盖)。

  • 测试用优雅退出helpers.mjskill() 先关 stdin 让 server 正常 exit(0),超时才强杀——否则 V8 来不及写出覆盖率数据。需要模拟崩溃的场景显式用 killHard()

Roadmap

  • 子代理心跳与超时自动回收(当前失联任务需主代理手动 force 恢复)

  • 任务产出物登记(结构化记录每个任务的产物路径,便于汇总与验收)

  • 跨工作区蜂群(当前状态文件按工作区隔离)

  • roundtable 插件的组合流程(讨论定方案 → 蜂群做执行)

已知限制

  • 并行度:单波建议 ≤ 4 个后台子代理,实测更多会因上下文切换与 token 开销反噬收益。

  • 推送有延迟:子代理间信息传递依赖主代理收波转发,不是实时的。

  • force 非安全边界:见上文"可靠性机制"末条。

  • 多蜂群共用工作区会共享状态文件:长期任务请用独立工作区。

License

MIT © 2026 Wersky


TaskSwarm is a multi-agent orchestration plugin for ZCode: decompose a goal into a task tree, dispatch subagents in dependency waves, and let mutually-invisible subagents coordinate through a shared MCP board.

Core insight. Subagents in ZCode have no SendMessage and no Agent tool (verified by probing) — they can work, but they cannot talk to each other. This single constraint shapes the whole design: coordination must happen through two channels, (1) board pull — subagents read/write a shared MCP board (task_claim / task_update / board / task_notes), and (2) orchestrator push — the main agent is the only role with SendMessage, so it forwards key results between running subagents (verified working: a code sent mid-task reached a running subagent).

Deterministic work lives in the MCP server (task tree, dependency resolution, atomic claiming, crash-safe persistence, board rendering); the orchestration loop lives in the main agent (what to decompose, whom to dispatch, when to collect). Zero third-party dependencies.

Reliability. 91 tests (all passing), 86.8% line / 96.4% function coverage. Every test drives a real spawned MCP server process, because the guarantees that matter — no data corruption under concurrent multi-process writes, no double-claiming of the same task — only exist across processes. Measured: two processes appending 120 notes each previously corrupted the state file (217 tool errors, unrecoverable plan loss) and 60 concurrent claim attempts double-claimed 4 times; both are now zero, locked by regression tests. Writes are atomic (temp → fsync → rename) behind a cross-process file lock with stale-lock recovery; corrupt files are backed up rather than silently discarded.

Portable by design — plugin manifest uses ${ZCODE_PLUGIN_ROOT} placeholders, no hardcoded absolute paths.

MIT © 2026 Wersky

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers