Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions docs/blog/swarm_mode/article.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Claude Code 上了 Dynamic Workflows,我们叫它蜂群

<!-- 转为飞书文档并提交到微信公众号 -->

<!-- 封面: assets/swarm-cover.png -->

5 月 28 日 Claude Code 发了 Dynamic Workflows。我看完公告,第一反应不是「又出新功能了」,而是「这不就是我们叫蜂群的那套吗」。

简单说,它干的事是:把一个大任务拆开,多个子 agent 并行跑,跑完有人专门挑刺,最后汇总成一个结论。我们做 axon 时早就在这么干,只是名字不一样。

---

<!-- 配图1: assets/swarm-vs-single.png -->

举个例子。你要审计一个开源仓库,里面有 7 个业务模块,每个模块都有自己的 spec 和真实测试。让单个 agent 从头读到尾,读到第三个模块就开始忘第一个模块的结论。最后它跟你说「基本完成」,你不敢信。

更靠谱的做法是:7 路并行审计,每路只盯一个模块;第一轮结束后,再派 7 个专门找茬的 agent,问「真的完成了吗?有没有 stub?测试是不是假的?」主 agent 收齐 14 份结果,再写最终报告。

axon 是开源 AI 编程助手,GitHub 地址:https://github.com/kill136/axon
自己 clone 下来就能跑,不用等邀请码。

## 一个人扛不动大仓库

问题不在 token 数字。200K 窗口也会满,关键是前面读过的东西,后面用不上。

大任务串行做也等不起。7 个模块一个一个查,光读代码就要好几轮。更麻烦的是没人复核:它自己读完、自己说查完了,漏掉的问题你事后才发现。

<!-- 配图2: assets/swarm-same-idea.png -->

Claude Code 的 workflow 和 axon 的蜂群,干的是同一件事:拆任务、并行、复核。名字不同,拆法类似。

Claude 那边,你在 prompt 里提到 workflow,它会写一段编排脚本,子 agent 并行跑(官方说一次最多 16 路),有的 agent 专门反驳前面的结论。axon 这边分两层。

<!-- 配图3: assets/swarm-dual-layer.png -->

轻量用法:主对话里用 Task 工具直接扇出多个子 agent。每个子 agent 有独立上下文,干完只把摘要还给主对话。适合审计、调研、全库扫描这类「要结论、不改工程」的活。

工程用法:要从需求交付能跑的代码,走 Blueprint。先聊清楚要啥,生成蓝图当锚点;LeadAgent 接管后一直挂着,自己改关键文件,独立模块派 Worker 去干;Swarm Console 里能看到每个 agent 在干嘛。

Claude 在终端里确认一下就开跑。axon 多一个可视化控制台,代码在本地跑,编排逻辑开源能翻。

## 14 个 agent 怎么跑起来的

回到那个 7 模块审计。

<!-- 配图4: assets/swarm-audit-fanout.png -->

主 agent 先把仓库摸清,列出 7 个域和对应的 spec、测试文件。然后同时派出 7 个审计 agent——各读各的代码,对照 spec 逐条核对,产出带证据的结论。

第一轮结束后,主 agent 不急着写报告。再派 7 个复核 agent,工作就一件事:质疑前一轮的「已完成」。有没有降级实现?eval 是不是空壳?接口是不是只写了类型没写逻辑?

14 份结果回到主 agent,它做汇总,标出争议点,写最终报告。这一路走的是轻量蜂群,主对话里 Task 并行派发就够了,不用上 Blueprint。

如果只是查代码、出报告,到这儿就结了。如果要「从一句话需求到能跑的工程」,得上第二层。

SmartPlanner 跟你聊两三轮,把需求落成蓝图。LeadAgent 接手后探索代码库、拆任务、自己改核心文件,独立模块通过 DispatchWorker 派出去。Worker 改完要过 lint 和 typecheck,该跑 E2E 就开浏览器测。Swarm Console 里能点开每个 agent 的对话流——谁改了哪个文件、哪一步挂了,都能追。

axon 还有一条 Coding Pipeline:spec、蓝图、测试、交付前有硬门。蜂群负责拆和跑,硬门负责「真能交付」。这是后话,这篇不展开。

## 多出来的几件事

开源,编排逻辑在 `src/blueprint/` 里,能翻代码,不满意可以自己改。

本地跑,直接改磁盘上的工程,不用把整个仓库上传到云端沙盒。

Swarm Console 能回放每个 agent 的对话流。排查「谁改坏了」,比翻终端日志省事。

路线和 Claude Code 不同,各有取舍。Claude 背靠 Anthropic 的模型和额度;axon 适合想自己托管、想看清 agent 每一步的团队。

## 自己试

```bash
git clone https://github.com/kill136/axon
cd axon
npm install
npm run dev
```

浏览器打开 https://localhost:3456,扔同一个大任务进去——全库审计、安全扫描、多模块对照 spec,都行。有 Claude Code workflow 的话,同一个 prompt 两边各跑一遍,自己比。

<!-- 编辑备注(勿发布):配图源文件在 docs/blog/swarm_mode/assets/,透明底 PNG,可直接插入公众号编辑器。 -->
74 changes: 74 additions & 0 deletions docs/blog/swarm_mode/assets/preview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>蜂群软文配图预览</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, "PingFang SC", sans-serif;
background: #1a1a2e;
color: #e2e8f0;
padding: 40px;
}
h1 { font-size: 24px; margin-bottom: 8px; }
p { color: #94a3b8; margin-bottom: 32px; font-size: 14px; }
code { background: rgba(255,255,255,0.08); padding: 2px 6px; border-radius: 4px; }
.grid { display: flex; flex-direction: column; gap: 48px; }
.item h2 { font-size: 16px; margin-bottom: 12px; color: #818cf8; }
.checker { display: inline-block; padding: 20px; border-radius: 12px; }
.checker.light { background: #f8fafc; }
.checker.darkbg { background: #0f172a; }
.checker.real { background: repeating-conic-gradient(#2a2a3e 0% 25%, #1f1f30 0% 50%) 50% / 24px 24px; }
.checker img { display: block; max-width: 100%; height: auto; }
.row { display: flex; gap: 24px; flex-wrap: wrap; }
.col { display: flex; flex-direction: column; gap: 8px; }
.meta { font-size: 12px; color: #64748b; }
.tag { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 999px; }
.tag.t { background: rgba(34,211,238,0.15); color: #67e8f9; }
.tag.d { background: rgba(99,102,241,0.18); color: #a5b4fc; }
</style>
</head>
<body>
<h1>蜂群模式公众号配图预览</h1>
<p>
每张图两套:<span class="tag t">透明底</span> <code>name.png</code>(浅/深背景各预览)·
<span class="tag d">深色底</span> <code>name-dark.png</code>(真实导出)。
重新渲染:<code>node docs/blog/swarm_mode/scripts/render-wechat-assets.mjs</code>
</p>

<div class="grid" id="grid"></div>

<script>
const items = [
{ name: 'swarm-cover', title: '封面 (900×383)', w: 450 },
{ name: 'swarm-vs-single', title: '配图1 一个人 vs 分开干', w: 500 },
{ name: 'swarm-same-idea', title: '配图2 拆任务·并行·复核', w: 500 },
{ name: 'swarm-dual-layer', title: '配图3 Task / Blueprint 两层', w: 500 },
{ name: 'swarm-audit-fanout', title: '配图4 7×2 扇出', w: 500 },
];
const grid = document.getElementById('grid');
for (const it of items) {
grid.insertAdjacentHTML('beforeend', `
<div class="item">
<h2>${it.title}</h2>
<div class="row">
<div class="col">
<div class="checker light"><img src="${it.name}.png" width="${it.w}"></div>
<div class="meta"><span class="tag t">透明</span> 浅底</div>
</div>
<div class="col">
<div class="checker darkbg"><img src="${it.name}.png" width="${it.w}"></div>
<div class="meta"><span class="tag t">透明</span> 深底</div>
</div>
<div class="col">
<div class="checker real"><img src="${it.name}-dark.png" width="${it.w}"></div>
<div class="meta"><span class="tag d">深色底</span> 真实导出(棋盘格=图外无背景)</div>
</div>
</div>
</div>
`);
}
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions docs/blog/swarm_mode/assets/swarm-audit-fanout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 1080px; height: 608px;
background: transparent;
font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
display: flex; align-items: center; justify-content: center;
position: relative;
}
.badge {
position: absolute; top: 32px; right: 48px;
font-size: 22px; font-weight: 600; color: #818cf8;
padding: 8px 20px; border-radius: 8px;
border: 1px solid rgba(129,140,248,0.5);
background: rgba(99,102,241,0.1);
}
.wrap { width: 960px; }
.row { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 20px; }
.row-label {
font-size: 18px; color: #64748b; width: 60px; text-align: right;
}
.box {
width: 72px; height: 56px; border-radius: 8px;
display: flex; align-items: center; justify-content: center;
font-size: 14px; font-weight: 600; color: #e2e8f0;
}
.module {
background: rgba(100,116,139,0.3);
border: 1px solid #64748b;
}
.audit {
background: rgba(99,102,241,0.2);
border: 1px solid #6366f1;
}
.review {
background: rgba(34,211,238,0.15);
border: 1px solid #22d3ee;
}
.merge {
width: 120px; height: 64px; border-radius: 12px;
background: linear-gradient(135deg, #6366f1, #22d3ee);
border: none; font-size: 18px; font-weight: 700; color: #fff;
margin: 24px auto 0;
display: flex; align-items: center; justify-content: center;
}
.connector {
display: flex; justify-content: center; gap: 12px; margin: 8px 0;
}
.vline {
width: 2px; height: 24px; background: linear-gradient(180deg, #6366f1, #22d3ee);
opacity: 0.5;
}
.vlines { display: flex; justify-content: center; gap: 82px; }
.title {
text-align: center; font-size: 20px; color: #94a3b8; margin-bottom: 28px;
}
</style>
</head>
<body>
<div class="badge">14 agents</div>
<div class="wrap">
<div class="title">7 模块审计 → 7 路复核 → 汇总</div>
<div class="row">
<div class="row-label"></div>
<div class="box module">M1</div><div class="box module">M2</div><div class="box module">M3</div>
<div class="box module">M4</div><div class="box module">M5</div><div class="box module">M6</div>
<div class="box module">M7</div>
</div>
<div class="vlines">
<div class="vline"></div><div class="vline"></div><div class="vline"></div>
<div class="vline"></div><div class="vline"></div><div class="vline"></div><div class="vline"></div>
</div>
<div class="row">
<div class="row-label">审计</div>
<div class="box audit">A1</div><div class="box audit">A2</div><div class="box audit">A3</div>
<div class="box audit">A4</div><div class="box audit">A5</div><div class="box audit">A6</div>
<div class="box audit">A7</div>
</div>
<div class="vlines">
<div class="vline"></div><div class="vline"></div><div class="vline"></div>
<div class="vline"></div><div class="vline"></div><div class="vline"></div><div class="vline"></div>
</div>
<div class="row">
<div class="row-label">复核</div>
<div class="box review">R1</div><div class="box review">R2</div><div class="box review">R3</div>
<div class="box review">R4</div><div class="box review">R5</div><div class="box review">R6</div>
<div class="box review">R7</div>
</div>
<div class="merge">汇总报告</div>
</div>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/blog/swarm_mode/assets/swarm-cover-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions docs/blog/swarm_mode/assets/swarm-cover.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 900px; height: 383px;
background: transparent;
font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
display: flex; align-items: center; justify-content: center;
overflow: hidden;
}
.wrap { text-align: center; padding: 40px; }
.brand {
font-size: 20px; font-weight: 600; color: #818cf8;
letter-spacing: 0.2em; margin-bottom: 20px;
}
.title {
font-size: 42px; font-weight: 700; color: #f1f5f9;
line-height: 1.35; margin-bottom: 24px;
}
.title span { color: #22d3ee; }
.sub {
font-size: 22px; color: #94a3b8;
}
.dots {
display: flex; justify-content: center; gap: 12px; margin-top: 32px;
}
.dot {
width: 12px; height: 12px; border-radius: 50%;
background: linear-gradient(135deg, #6366f1, #22d3ee);
opacity: 0.7;
}
.dot:nth-child(2) { opacity: 0.85; }
.dot:nth-child(3) { opacity: 1; }
.dot:nth-child(4) { opacity: 0.85; }
.dot:nth-child(5) { opacity: 0.7; }
</style>
</head>
<body>
<div class="wrap">
<div class="brand">AXON</div>
<div class="title">Claude Code 上了 Dynamic Workflows<br>我们叫它<span>蜂群</span></div>
<div class="sub">拆任务 · 并行 · 复核</div>
<div class="dots">
<div class="dot"></div><div class="dot"></div><div class="dot"></div>
<div class="dot"></div><div class="dot"></div>
</div>
</div>
</body>
</html>
Binary file added docs/blog/swarm_mode/assets/swarm-cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions docs/blog/swarm_mode/assets/swarm-dual-layer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 1080px; height: 608px;
background: transparent;
font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif;
display: flex; align-items: center; justify-content: center;
}
.wrap { width: 900px; }
.fork-top {
text-align: center; margin-bottom: 24px;
font-size: 24px; color: #94a3b8;
}
.paths { display: flex; flex-direction: column; gap: 48px; }
.path {
display: flex; align-items: center; gap: 24px;
padding: 28px 40px;
border-radius: 16px;
border: 2px solid;
}
.path.light {
border-color: rgba(34,211,238,0.5);
background: rgba(34,211,238,0.06);
}
.path.heavy {
border-color: rgba(99,102,241,0.5);
background: rgba(99,102,241,0.06);
}
.scene {
font-size: 26px; font-weight: 600; color: #e2e8f0;
min-width: 280px;
}
.arrow { font-size: 32px; color: #64748b; }
.tool {
font-size: 28px; font-weight: 700;
padding: 12px 28px; border-radius: 10px;
font-family: "SF Mono", "Menlo", monospace;
}
.path.light .tool {
color: #22d3ee; background: rgba(34,211,238,0.15);
border: 1px solid rgba(34,211,238,0.4);
}
.path.heavy .tool {
color: #818cf8; background: rgba(99,102,241,0.15);
border: 1px solid rgba(129,140,248,0.4);
}
.desc {
font-size: 20px; color: #94a3b8; margin-left: auto;
}
</style>
</head>
<body>
<div class="wrap">
<div class="fork-top">两层蜂群,看你要干嘛</div>
<div class="paths">
<div class="path light">
<div class="scene">查代码 · 出报告</div>
<div class="arrow">→</div>
<div class="tool">Task</div>
<div class="desc">主对话扇出子 agent</div>
</div>
<div class="path heavy">
<div class="scene">做工程 · 要交付</div>
<div class="arrow">→</div>
<div class="tool">Blueprint</div>
<div class="desc">蓝图 + LeadAgent + Worker</div>
</div>
</div>
</div>
</body>
</html>
Binary file added docs/blog/swarm_mode/assets/swarm-dual-layer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading