这是一个 Pi 扩展包,用于把复杂任务拆成任务图,交给隔离的 Pi 子进程执行,并通过同模型审核器自动重试和升级 worker 等级。 - 0xBB2B/pi-subagent-cluster

这是一个 Pi 扩展包,用于把复杂任务拆成任务图,交给隔离的 Pi 子进程执行,并通过同模型审核器自动重试和升级 worker 等级。
为了让主 agent 更稳定地判断任务复杂度、拆解任务并提交可审核的任务图,建议将本仓库 AGENTS.md 中的内容添加到你自己的 AGENTS.md 中。这样 Pi 在处理项目任务时可以遵循统一的任务分流、验收标准和协作约束,通常能获得最佳效果。
当前 Pi CLI 的 npm 包源使用 npm: 前缀:
pi install npm:@0xbb2b/pi-subagent-cluster
安装后重启 Pi。扩展会自动注册 subagent_cluster 工具、/subagent-cluster dashboard 命令和 /subagent-settings 设置命令。
将 <仓库地址> 替换为实际 Git 仓库地址,将扩展克隆到本地:
git clone <仓库地址> "$HOME/Projects/pi-subagent-cluster"
Pi 的包根目录必须是包含 package.json 的目录。可以全局安装这个本地包:
pi install "$HOME/Projects/pi-subagent-cluster"
如果只希望某个项目使用本地版本,请在目标项目目录执行:
cd /path/to/your-project
pi install -l --approve "$HOME/Projects/pi-subagent-cluster"
-l 会把配置写入当前项目的 .pi/settings.json。本地路径安装不会复制文件,Pi 会直接读取 Git 克隆目录,因此修改代码后无需重新安装,也不需要先执行 npm publish。当前包只使用 Pi 已提供的核心依赖,无需在扩展目录单独执行 npm install。
进入本地克隆目录后,直接修改 extensions/ 下的 TypeScript 文件:
cd "$HOME/Projects/pi-subagent-cluster"
# 修改 extensions/index.ts、extensions/scheduler.ts 等文件
正在运行 Pi 时可以输入 /reload 重新加载扩展;如果当前 Pi 版本或运行模式不适合热重载,退出后重新启动 Pi 即可。也可以不写入任何安装配置,临时加载入口进行验证:
pi --no-extensions \
--extension "$HOME/Projects/pi-subagent-cluster/extensions/index.ts"
发布前可以在无需联网的情况下运行回归测试,并检查 npm 包实际会包含哪些文件:
cd "$HOME/Projects/pi-subagent-cluster"
npm test
npm pack --dry-run
查看或移除本地安装:
pi list
pi remove "$HOME/Projects/pi-subagent-cluster"
# 如果使用了项目级安装:
cd /path/to/your-project
pi list
pi remove -l "$HOME/Projects/pi-subagent-cluster"
项目配置放在 .pi/subagent-cluster.json,也可以放在 ~/.pi/agent/subagent-cluster.json 作为全局配置。配置会从当前工作目录向上查找,项目配置优先于全局配置。
当前只支持标准 JSON:配置文件中不能写 //、/* ... */ 注释,也不能使用尾逗号。下面的示例可以直接复制到 .pi/subagent-cluster.json;参数解释见后面的参数速查表。
{
"levels": {
"high": {
"model": "openai/gpt-5.6",
"thinkingLevel": "high",
"tools": ["read", "grep", "find", "ls", "bash", "edit", "write"],
"timeoutMs": 1800000
},
"medium": {
"model": "openai/gpt-5.6",
"thinkingLevel": "medium",
"tools": ["read", "grep", "find", "ls", "bash", "edit", "write"],
"timeoutMs": 1200000
},
"low": {
"model": "openai/gpt-5.6",
"thinkingLevel": "low",
"tools": ["read", "grep", "find", "ls", "bash", "edit", "write"],
"timeoutMs": 900000
}
},
"reviewer": {
"thinkingLevel": "medium",
"tools": ["read", "grep", "find", "ls"],
"timeoutMs": 180000
},
"maxConcurrency": 4,
"maxTasks": 16,
"maxRetriesPerLevel": 1,
"learning": {
"enabled": true,
"taskTypeUpgradeThreshold": 2,
"historyRetentionDays": 30
}
}
整体省略 learning 时会自动使用默认值;显式提供时必须是对象,且 enabled 必须是布尔值,taskTypeUpgradeThreshold 和 historyRetentionDays 必须是正整数,缺少字段或类型不正确时配置会被拒绝并提示错误。
| 参数 | 类型 | 作用 |
|---|---|---|
levels |
对象 | 配置三个 worker 等级;必须包含 low、medium、high。 |
levels.<level>.model |
字符串 | worker 使用的模型,推荐使用 provider/model 格式。 |
levels.<level>.thinkingLevel |
字符串 | worker 的推理强度;/subagent-settings 会根据当前模型能力过滤可选值。 |
levels.<level>.tools |
字符串数组 | worker 可调用的工具;写入类工具会允许 worker 修改项目。 |
levels.<level>.timeoutMs |
正整数 | 该等级 worker 的单次超时时间,单位毫秒。 |
reviewer.model |
字符串 | 审核器使用的固定模型;省略时跟随主 agent。 |
reviewer.thinkingLevel |
字符串 | 审核器推理强度;省略时跟随主 agent,固定模型时按模型能力选择。 |
reviewer.tools |
字符串数组 | 审核器工具,只能是 read、grep、find、ls。 |
reviewer.timeoutMs |
正整数 | 单次审核超时时间,单位毫秒。 |
maxConcurrency |
正整数 | 同时运行的最大 worker 数量。 |
maxTasks |
正整数 | 单次集群允许的最大任务数量,默认 16,便于细粒度任务图。 |
maxRetriesPerLevel |
非负整数 | 自动升级前的同等级重试次数。 |
learning.enabled |
布尔值 | 是否启用全局跨运行学习;默认 true。关闭后不读取也不写入学习证据。 |
learning.taskTypeUpgradeThreshold |
正整数 | 全局共享的同一 taskType 触发提升所需的不同运行有效升级证据数量;运行以 projectKey 和 runId 的组合去重,默认 2。 |
learning.historyRetentionDays |
正整数 | 学习证据的有效天数;默认 30。 |
reviewer.model 可配置固定审核模型;省略时审核器使用当前主 agent 的模型。reviewer 只控制审核器的模型、thinking level、只读工具和超时。
使用 /subagent-settings 打开 subagent-cluster 专属设置页。它不会覆盖 Pi 内置的 /settings:
/settings:Pi 自身设置。/subagent-settings:subagent-cluster 设置。设置页主菜单按分组显示:
HIGH
MEDIUM
LOW
REVIEWER
CLUSTER
进入 HIGH、MEDIUM 或 LOW 二级菜单后,可以配置模型、thinking level、worker tools 和 timeout。进入 REVIEWER 二级菜单后,可以配置固定模型、thinking level、只读 tools 和 timeout;当 Model 选择“跟随主 agent”时,Thinking level 也可以选择“跟随主 agent”。reviewer tools 可在 read、grep、find、ls 中多选。CLUSTER 二级菜单配置最大并发数、最大任务数、同等级重试次数、学习开关、同类型提升阈值和证据有效天数,也可以选择 Clear learning evidence 清除所有项目共享的全部全局学习证据。清除前会明确要求确认;未确认不会删除任何记录。
二级设置页使用 ←/→ 双向循环切换 thinking level、学习开关和数字参数;模型与工具仍使用 Enter 打开选择页,清除学习证据使用 Enter 执行。每次模型、thinking、tools、学习开关或数字参数切换后都会自动保存,不需要单独点击保存。
首次打开 /subagent-settings 且全局配置不存在时,会立即创建并保存完整默认配置;之后每次修改也会自动写入同一文件:
~/.pi/agent/subagent-cluster.json
项目配置仍然可以放在 .pi/subagent-cluster.json,并且优先于全局配置;/subagent-settings 修改的是全局配置,便于多个项目共享同一套模型和调度参数。如果当前项目存在 .pi/subagent-cluster.json,它会覆盖全局配置;要让当前项目使用全局设置,需要删除或移走项目级配置。
调用 subagent_cluster 时,主 agent 必须先完成细粒度拆分和任务图门禁,再提交结构化任务图。下面的契约定义每个 worker 任务的输入边界和可验证结果。
subagent_cluster 接收的是主 agent 已经完成拆分的任务图。worker 只执行分配到的单一任务,不负责重新拆分、扩大范围、补写依赖或自行升级模型。调用前必须通过任务图门禁;门禁拒绝的任务图不能启动任何 worker。
调用参数的顶层结构为 goal 和 tasks。tasks 中每个任务必须包含以下字段:
| 字段 | 要求 |
|---|---|
id |
稳定且唯一的任务 ID。 |
title |
清楚描述一个主要交付物。 |
kind |
一个任务性质,可使用 implementation、verification 或 integration。 |
taskType |
非空的稳定类型,使用 <技术栈>/<任务性质>/<作用范围> 格式,例如 typescript/backend-api/cross-module。系统会去除首尾空白并统一为小写,用于任务类型学习。 |
task |
单一、精确的执行要求;不能把多个主要交付物并列在同一任务中。 |
scope.paths |
非空的仓库相对路径数组,表示允许修改或新增的最小范围。 |
nonGoals |
本任务明确不做的相邻工作;没有排除项也必须写 []。 |
validation |
包含 commands 数组的验证对象;命令必须能直接检查本任务结果。 |
acceptanceCriteria |
审核器可以逐条判断的客观验收标准。 |
level |
初始 worker 等级:low、medium 或 high。 |
dependsOn |
所有前置任务 ID;没有前置任务必须写 []。 |
cwd |
可选的任务工作目录。 |
其中 scope.paths 是写入边界,不是参考信息。路径相同、父子路径、共同生成文件或共同配置文件,都属于 scope 冲突。没有依赖的任务可能并行执行,因此并行任务不得修改重叠路径;共享文件应改为串行依赖,或由后置 integration 任务统一负责。
提交前按以下规则拒绝不合格任务图:
scope.paths 覆盖整个仓库、整个 src/、整个 tests/ 等无法审核的范围。kind、scope.paths、nonGoals、validation、acceptanceCriteria 或 dependsOn,或者其中要求非空的结果、范围、验证无法具体判断。dependsOn 引用了不存在的任务,或把真实前置关系留给 worker 猜测。kind: "integration" 的验证任务。integration 任务必须依赖所有需要汇合的生产任务,使用不与前置任务重叠的路径,并验证组合后的结果。integration 任务不是额外的实现大杂烩,而是任务图中明确的最终验证交付物。它可以运行构建、测试或端到端检查,并只修改自己声明的集成测试、配置或报告路径。多任务图中,前置任务完成后才执行 integration 验证。
下面的示例把实现、测试和集成验证分成三个可审核任务;前两个任务路径不重叠,可以并行,最后的 integration 任务等待两者完成:
{
"goal": "补充设置保存校验并验证设置模块集成结果",
"tasks": [
{
"id": "settings-validation",
"title": "补充设置保存校验",
"kind": "implementation",
"taskType": "typescript/bugfix/local",
"task": "在设置校验模块中补充必填项和邮箱格式校验。",
"scope": {
"paths": ["src/settings/validation.ts"]
},
"nonGoals": [
"不修改页面布局",
"不修改服务端接口"
],
"validation": {
"commands": [
"node --experimental-strip-types --test tests/settings-validation.test.ts"
]
},
"acceptanceCriteria": [
"空值被拒绝",
"非法邮箱被拒绝",
"合法输入通过"
],
"level": "low",
"dependsOn": []
},
{
"id": "settings-validation-tests",
"title": "补充设置校验测试",
"kind": "verification",
"taskType": "typescript/test/unit",
"task": "为必填项、非法邮箱和合法邮箱场景补充单元测试。",
"scope": {
"paths": ["tests/settings-validation.test.ts"]
},
"nonGoals": [
"不修改生产实现",
"不新增端到端测试"
],
"validation": {
"commands": [
"node --experimental-strip-types --test tests/settings-validation.test.ts"
]
},
"acceptanceCriteria": [
"三个场景各有明确断言",
"测试文件可以独立运行并通过"
],
"level": "low",
"dependsOn": []
},
{
"id": "settings-integration",
"title": "验证设置模块集成结果",
"kind": "integration",
"taskType": "typescript/test/integration",
"task": "在前置任务完成后运行设置模块相关测试,确认校验实现和测试组合结果通过。",
"scope": {
"paths": ["tests/settings-integration.test.ts"]
},
"nonGoals": [
"不重新实现校验逻辑",
"不修改前置任务负责的文件"
],
"validation": {
"commands": [
"npm test"
]
},
"acceptanceCriteria": [
"设置模块相关测试全部通过",
"没有超出声明路径的修改"
],
"level": "medium",
"dependsOn": ["settings-validation", "settings-validation-tests"]
}
]
}
主 agent 应在调用前完成门禁检查;worker 收到的就是最终任务,不应再创建子任务或自行改变 scope.paths。kind、taskType、title、task、scope.paths、nonGoals、validation.commands 和 acceptanceCriteria 共同决定精确任务指纹;相同任务类型的学习证据按规范化后的 taskType 跨运行累计。
这个任务图体现两级学习范围:相同项目中相同任务指纹的有效升级证据可以在下一次直接提高最低起始等级;不同任务但相同 taskType 的证据会在所有项目间共享,只有达到 learning.taskTypeUpgradeThreshold 个不同运行后才会提高该类型的最低起始等级。运行以 projectKey 和 runId 的组合去重,因此同一项目的不同运行会累计,不同项目的同名运行也会分别累计。学习结果只会提高主 agent 请求的等级,不会降低请求等级。
执行集群后任务会在后台运行,不会占用输入栏。输入栏下方会显示一行集群状态栏:
↓:选择集群状态栏Enter:打开集群管理 dashboard,等价于 /subagent-cluster/subagent-cluster 打开 dashboard↑↓ 或 j/k:选择任务Enter:展开或收起选中任务的输出p:暂停或继续集群r:重试等待用户决策的任务e:手动提升等待用户决策的任务等级a:接受当前结果x:放弃当前任务d 或 Delete:确认后删除选中的非活动集群历史;活动集群不能删除Escape:退出 dashboard,返回输入栏,不会取消集群Ctrl+C:取消整个集群任务需要用户决策时,问题会回到主对话区,并暂停任务调度及正在运行的 worker/reviewer,避免等待期间消耗超时时间。请在主输入框回复选项编号或动作(例如 1、retry、升级);答复会直接恢复对应任务,不会再触发一轮无关的主 agent 对话。
底部快捷键会按状态动态显示:运行中显示暂停和取消;手动暂停时显示继续;等待用户决策时显示重试、升级、接受和放弃;集群列表选中非活动历史时显示删除;完成、失败或取消后只保留适用操作。删除历史前会显示包含运行 ID 的二次确认,确认后会删除该运行的状态快照和任务输出,且不可撤销。
暂停会终止 worker/reviewer 当前尚未完成的网络请求,并冻结累计运行 timeout;恢复后通过隔离的临时 Pi 会话和当前工作区状态继续,避免挂起请求在恢复瞬间超时。Dashboard 展示的集群和任务运行时长也会扣除暂停区间。取消会终止所有 worker 和审核器子进程。
TaskAttempt 分别保存 worker 和审核器的完整执行结果,包括模型、输出、stderr、停止原因、错误、工具调用、消息历史、usage 与 API 重试记录。审核器执行中产生的历史和 usage 会实时进入当前 attempt,Dashboard 可以在审核尚未结束时展示。input + output + cacheRead + cacheWrite。provider 上报的 reasoning 是 output 的子集,不会再次相加。界面显示总 Token、输入、输出、turns 和整体缓存命中率;缓存读写与成本仍保留在内部 usage 数据中,不在界面展开。executionDataVersion: 1,表示 worker 与审核器的统计和历史完整。version: 2 且没有该标记的快照会显示“统计不完整,缺少审核器数据”和“完整审核器历史未记录”;扫描历史时会直接删除 version: 1 运行目录。auto_retry_start 时,集群会立即终止该子进程的内建 2/4/8 秒退避,并使用同一个临时 session 按集群策略恢复,避免两层退避叠加。Pi 自动重试关闭时,最终 assistant 错误由 Pi AI 的瞬时错误分类器判定后进入相同流程。TaskAttempt,不消耗 maxRetriesPerLevel。退避等待不扣减 worker/reviewer timeout;暂停会冻结剩余等待,取消会立即结束。认证、配置、上下文、取消、进程错误和其他非瞬时错误不会进入 API 退避。管理页采用分层 workflow navigator:
taskType、主 agent 请求等级、实际初始等级,以及等级选择说明;发生等级提升时,该说明显示为等级调整原因。Enter:进入当前 subagent 详情页,查看状态、taskType、请求等级、实际初始等级、等级选择说明(发生等级提升时显示为等级调整原因)、模型、Prompt、Result 和最近活动。Enter:进入完整历史 pager,按 attempt 查看 worker 执行、审核器完整执行和结构化审核结论;每次执行显示模型、退出码、停止原因、输出、stderr、Pi/provider 实际返回的 user、assistant 文本、公开 thinking、工具调用、工具结果、usage、API 重试与错误。每次审核器执行和结论紧跟对应 worker,位于下一次 worker 之前。结构化结论完整显示 decision、reason、missingCriteria 和 nextInstruction,不承诺隐藏推理。↑↓、j/k、PgUp/PgDn、Home/End 翻阅全部上下文;n/p 可直接跳到下一个/上一个 worker 标题,到达首尾后停止并提示。Escape 按页面层级逐级返回;概览页按 Escape 退出 dashboard。goal 和 tasks,为每个任务声明 kind、scope.paths、nonGoals、validation、acceptanceCriteria 和 dependsOn,并保证一个任务只有一个主要交付物。taskType 证据,计算任务的实际初始等级;学习关闭时直接使用请求等级。pi --mode json 子进程和进程级临时会话执行;消息历史和 usage 随 JSON 事件实时写入当前 attempt。paused_for_user,问题回到主对话区等待用户决策;等待期间暂停任务调度及正在运行的子进程。timed_out,审核器返回无效 JSON 会将任务标记为审核失败,不会误进入 paused_for_user。~/.pi/agent/subagent-cluster/runs/--项目绝对路径编码--/<run-id>/,包括状态快照、完整 worker/reviewer 统计与历史、API 重试记录和各任务输出。~/.pi/agent/subagent-cluster/learning/evidence/;文件名使用 UUID,先写入同目录临时文件再 rename,多个 Pi 进程不会重写同一个全局 JSON。每条证据包含项目 key。~/.pi/agent/subagent-cluster/learning/evidence/,每个有效升级证据是一个独立 JSON 文件,不创建项目级 history.json。kind、taskType、title、精确 task、scope.paths、nonGoals、validation.commands 和验收标准组成;读取时还必须匹配当前项目 key,因此相同指纹不会跨项目套用。匹配证据存在时,下次直接把最低起始等级提高到证据中的等级。taskType 相同,就会在所有项目间累计。每个目标等级独立统计,必须有 learning.taskTypeUpgradeThreshold 个不同运行都证明同一较低等级不足,才会提高到该目标等级;medium 的证据不会与单条 high 证据混合后误升到 high。去重键包含项目 key 和 runId,所以同一项目的不同运行会累计,不同项目即使使用相同 runId 也会分别计数;同一项目同一运行的多个同类任务对同一目标等级只计一次。默认阈值为 2。typescript/backend-api/cross-module 任务在运行 run-7 产生一次 low→medium 有效升级,项目 B 的同类型任务在也叫 run-7 的运行产生另一次 low→medium 有效升级;两条证据的项目 key 不同,会共同达到默认阈值并提升项目 C 的同类型任务,但 A 的精确任务指纹证据不会提升 B 的同指纹任务。retry 或 escalate,随后由更高等级 worker 通过审核。跨越多个等级时会分别形成 low→medium 和 medium→high 证据,使每个目标等级独立学习。learning.historyRetentionDays 后失效。/subagent-settings,进入 CLUSTER 并选择 Clear learning evidence,在确认框中确认后清除证据目录中的全部全局学习证据,影响所有项目;未确认不会执行清除,不需要手工定位存储文件。worker 子进程不会加载当前扩展,避免扩展递归启动;它会在任务目录中使用项目上下文和配置的工具权限。审核器只使用只读工具。