omp packages

wj-pi-subagents0.7.0

Multi-level subagent orchestration plugin for Pi — no built-in templates, no preset workflows, everything is yours to shape

bxqyher Published 7 days ago MIT ~1.6K downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

🌳 wj-pi-subagents

English | 简体中文

Pi 的多级子代理编排插件

无内置模板 · 无预设工作流 · 一切由你塑造

License: MIT Node.js Pi

📖 简介

wj-pi-subagents 在当前 Pi 会话内创建相互独立的子代理,将分析、实现、测试或评审等任务分离开来,由父代理统筹结果。获得授权的子代理还可以继续创建下一级代理,形成多级代理树。

💡 本插件不内置任何子代理模板,也不预设任何工作流。 首次使用前,请先创建你自己的模板,自由定义每个代理的角色、可用工具、模型以及多级权限。 插件只负责组织代理树 —— 代理之间如何协作,完全由你决定。

✨ 亮点特性

特性 说明
🌳 多级代理树 根代理创建子代理;未达到深度限制且获得授权的子代理可依次创建下一级代理
🧩 完全可定制 无内置模板、无预设工作流 —— 通过 Markdown 模板自由定义提示词、工具、扩展、模型、思考等级与多级权限
📦 独立上下文 每个子代理都运行在各自的 Pi 会话中,不复制父级历史,适合隔离大型任务、减少上下文噪音
⚡ 并行协作 没有依赖或资源冲突的任务,可以委派给多个子代理并行执行
♻️ 上下文复用 同一个子代理可以连续承接任务,并保留自己的会话上下文
🎛️ 受控管理 父代理只能管理其直接子级,支持等待、状态查询、中断、复用与终止
👁️ 状态可见 TUI 展示直接子代理的状态;/agents 展示当前会话范围内的完整代理树
🔭 实时动态查看器 在树中的任意代理上按 Enter,即可实时观看它的工作过程
🗜️ 原生上下文压缩 依赖 Pi >= 1.2.0 的工具执行后压缩流程;每个根会话和子代理都通过自己独立的 Pi 会话管理上下文

📦 环境要求

项目 要求
Node.js >= 22.19.0
Pi >= 1.2.0

🚀 安装

用户级安装

为当前用户的所有 Pi 项目启用:

pi install npm:wj-pi-subagents

项目级安装

仅为当前项目启用:

cd <PROJECT_DIR>
pi install npm:wj-pi-subagents -l

项目级安装会写入 <PROJECT_DIR>/.pi/settings.json;只有在项目获得 Pi 授权后才会加载。

临时使用

仅为本次 Pi 进程加载:

cd <PROJECT_DIR>
pi -e npm:wj-pi-subagents

使用以下命令验证安装:

pi list

🏁 快速开始

1️⃣ 创建代理模板

用户级模板存放于:

<PI_AGENT_DIR>/agents/*.md

<PI_AGENT_DIR> 是 Pi 的用户级代理目录:跟随 PI_CODING_AGENT_DIR 环境变量;该变量未设置或为空串时回退 <USER_HOME>/.pi/agent。

项目级模板存放于:

<PROJECT_DIR>/.pi/agents/*.md

例如,创建 researcher.md:

---
description: Read-only analysis of code, docs, and tests
tools:
  - read
  - grep
  - find
  - ls
allowSubagents: false
contextFiles: true
systemPromptMode: append
---

Read the relevant implementation and tests first, then give conclusions with file locations. Do not modify files.

模板 ID 即去掉 .md 扩展名后的文件名。本例中的模板 ID 为 researcher。

2️⃣ 启动或重载 Pi

在目标项目中启动 Pi:

cd <PROJECT_DIR>
pi

新增或修改模板后,执行:

/reload

/reload 会刷新模板;已创建的子代理保持原有配置不变。

👀 查看代理状态

只要当前会话中存在子代理,输入框上方就会常驻一个 Agents 区域。每个尚未终止的直接子代理在此占一行:先是实时状态图标(工作时为动态旋转指示),其后依次为模板、名称、状态、活动阶段、上下文用量与耗时。当子代理全部消失时,该区域随之隐藏:

● Agents
├─ ⠋ researcher · explore-auth · working · processing · 12.3%/200k · 2m 14s
└─ ○ worker · fix-tests · idle · 0s

执行以下命令打开代理树面板:

/agents

根会话可以查看整棵代理树;子代理只能查看自己的子树。父代理只能操作其直接子级。

代理树面板内部:

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ AGENT TREE                                 REV 7 ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ › ▾ worker · fix-tests · working · processing    ┃
┃     · reviewer · review-pr · idle                ┃
┃   ▸ researcher · explore-auth · idle             ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ ↑↓ scroll · ←→ fold · Home/End jump · Esc close  ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
按键 操作
↑ / ↓ 移动选中项
← / → 折叠 / 展开分支
Home / End 跳转到首行 / 末行
Enter 打开所选代理的实时动态查看器
Esc 关闭面板

在 Pi 的全屏 TUI 模式(启动时加 --tui-mode fullscreen,或在 /settings 中切换 TUI 模式)下支持鼠标操作:滚轮滚动,点击选中一行,再次点击已选中的行则折叠或展开其子级。在普通模式下,鼠标由终端接管,请使用键盘。

🔭 实时动态查看器

想了解子代理在 working 状态背后究竟在做什么?在树中选中任意代理 —— 直接子级、孙级或任意更深层的后代均可 —— 按 Enter 打开其实时动态查看器:一个只读的全屏视图,展示该代理的工作过程,呈现方式与你的主会话十分相似。

打开查看器后,会先回放该代理最近的动态,然后在其工作期间持续追加新事件。你可以看到:

  • 助手回复以 Markdown 渲染,书写过程中实时流式输出
  • 思考折叠为一行 Thinking —— 仍在生成时标记为 streaming,可展开以实时跟随推理过程
  • 工具活动以按类型着色的单行摘要展示:读取或写入了哪些文件、搜索了什么、创建或联系了哪些代理 —— shell 命令完整显示
  • 父级消息与提交的回复/报告,可展开查看完整 Markdown 正文

整个视图如下所示:

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ AGENT ACTIVITY · worker · fix-tests · working                              ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ ▸ Parent message                                                           ┃
┃ ▸ Thinking                                                                 ┃
┃ The failing test expects unclosed brackets to be rejected — checking       ┃
┃ the parser implementation first.                                           ┃
┃ ↻ read · test/parser.test.ts                                               ┃
┃ ▸ ✓ bash · timeout 120s                                                    ┃
┃ ✓ edit · src/parser.ts                                                     ┃
┃ ▸ ✓ final_report                                                           ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ ↑↓ scroll · Tab/Shift+Tab select · Enter expand · Home/End jump · Esc back ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
按键 操作
↑ / ↓ 滚动
Home / End 跳转到顶部 / 底部
Tab / Shift+Tab 选中下一个 / 上一个可展开条目
Enter 或 Space 展开 / 折叠所选条目
→ / ← 仅展开 / 仅折叠
Esc 返回代理树面板

这里同样支持鼠标:滚轮滚动,点击可展开的行即可将其展开或折叠。

查看器会自动跟随最新动态。向上滚动会暂停跟随;滚回底部(或按 End)即可恢复。

几点值得了解:

  • 查看器是只读的:浏览不会向代理发送任何内容。
  • 动态仅用于展示:不会进入你的主会话,也不会消耗父代理的上下文或 token。
  • 每个代理会在内存中为当前会话保留最近 100 条动态;更早的条目将被丢弃,并显示 Older activity omitted 提示。
  • 动态仅存于内存:退出 Pi 或执行 /reload 都会将其清空。
  • 已终止的代理在当前会话内仍可回放,你可以在它们消失之后回顾其做过的事情。
  • 查看器仅在 TUI 模式下可用。

🧩 代理模板

模板存放位置

范围 路径 说明
用户级 <PI_AGENT_DIR>/agents/*.md 对所有项目可用
项目级 <PROJECT_DIR>/.pi/agents/*.md 仅在项目获得 Pi 授权后可用

<PI_AGENT_DIR> 是 Pi 的用户级代理目录:跟随 PI_CODING_AGENT_DIR 环境变量;该变量未设置或为空串时回退 <USER_HOME>/.pi/agent。

模板目录只读取直接的、小写的 .md 文件,不会递归扫描子目录。当项目模板与用户模板同名时,项目模板优先。模板 ID 区分大小写。

模板字段

字段 必填 默认值 说明
description 是 无 模板的用途
tools 否 Pi 默认工具 子代理可用的业务工具:纯工具名与 * 通配
excludeTools 否 无 从子代理移除的业务工具;条目支持 * 通配,不得命中协议工具,且优先于 tools
extensions 否 Pi 默认扩展发现机制 子代理可用的额外扩展来源:本地路径、npm:、git:、URL 或 builtin:<name>
allowSubagents 否 true 子代理是否可以创建下一级子代理
contextFiles 否 true 是否加载 AGENTS.md、CLAUDE.md 等上下文文件
systemPromptMode 否 append append 将模板正文追加到基础系统提示之后;replace 替换基础系统提示
model 否 继承父代理当前模型 格式:provider/model
thinking 否 继承父代理当前等级 off、minimal、low、medium、high、xhigh 或 max

模板使用严格的 YAML frontmatter,仅支持上表所列字段。正文即为子代理的角色提示词。

省略字段并不总是等价于传入空数组:

写法 行为
省略 tools 采用 Pi 正常的工具选择逻辑;不改动宿主默认工具集
tools: [] 常规选择中无业务工具,仅保留运行子代理所必需的工具(未列出的 MCP 工具仍会注册 —— 如需移除请使用 excludeTools)
省略 excludeTools 不排除任何工具
excludeTools: [] 与省略它等价
省略 extensions 采用 Pi 正常的扩展发现规则
extensions: [] 禁用正常扩展发现,仅加载本插件自身

extensions 支持本地路径、npm:、git:、URL 与 builtin:<name>。builtin:<name> 引用 pi 内置扩展(如 builtin:mcp)。声明 extensions 时本插件会传入 --no-extensions,因此未显式列出的内置扩展(如 builtin:llama.cpp、builtin:codemode、builtin:tool-search)也会被屏蔽,只有列出的项通过 -e 加载。内置扩展提供的工具同样需要列入 tools 才能被子代理调用 —— 例如在 extensions 中列出 builtin:codemode,并在 tools 中列出 codemode。

仅加载内置 MCP 扩展的示例:

---
description: 使用 MCP 工具完成资料核查
extensions:
  - builtin:mcp
---
先通过 MCP 工具收集事实,再给出结论。

完整示例:

---
description: Implement the specified module and self-check
tools:
  - read
  - edit
  - write
  - bash
allowSubagents: false
contextFiles: true
systemPromptMode: append
model: openai/gpt-5.4
thinking: high
---

Confirm the existing implementation and constraints first, then make the changes. Keep the change scope focused and run relevant checks before reporting the result.

工具声明与排除

tools 采用白名单写法:接受纯工具名与 * 通配。* 可以出现在条目的任意位置,一个条目中也可以出现多个。+name / -name 修饰符不受支持 —— 使用修饰符的模板在加载期即被判为无效,诊断会指向该模板与 tools 字段。修饰符的基准集来自宿主的默认工具配置,模板无法控制。

通配同样覆盖 MCP 工具:mcp__radius__* 选中 radius MCP 服务器的全部工具,mcp__* 选中全部 MCP 工具。

tools 白名单并不排他:未列出的工具(尤其是 MCP 工具)仍会注册,并可经 codemode 一类间接路径调用。要移除不应可达的工具,请使用 excludeTools。它接受 YAML 字符串数组,条目遵循与 tools 相同的名字形状规则 —— 非空、无内部逗号或空白、无重复项 —— 并且同样支持 * 通配。与 tools 一样,excludeTools 会在加载期拒绝 +name / -name 修饰符,诊断指向该模板与 excludeTools 字段。排除在工具注册阶段生效,因此被排除的工具即使经上述间接路径也不可达。当 tools 与 excludeTools 同时覆盖某个工具时,排除优先。

排除项不得命中子代理的协议工具 —— 八个管理工具加 normal_reply、final_report —— 协议工具必须全部保留。协议工具的字面名,以及任何可能匹配到协议工具名的 * 模式(如 *、*report*、normal_*),都会让模板在加载期被判为无效,诊断指向该模板与 excludeTools 字段。不会命中协议工具的模式(如 mcp_*、read)照常有效。同理,tools 会拒绝协议工具的字面名;tools 中的 * 通配仍可覆盖它们,因为白名单无法移除工具。

本插件不暴露 --no-mcp:排除 MCP 工具由模板的 excludeTools 承担。要排除全部 MCP 工具,请声明 excludeTools: ["mcp__*"]。

本插件不校验子代理的实际活动工具集是否等于声明。拼错的工具名只会静默地少一个工具,不会阻止启动。

⚙️ 运行时配置

运行时配置可放置于:

<PI_AGENT_DIR>/wj-pi-subagents.json
<PROJECT_DIR>/.pi/wj-pi-subagents.json

<PI_AGENT_DIR> 是 Pi 的用户级代理目录:跟随 PI_CODING_AGENT_DIR 环境变量;该变量未设置或为空串时回退 <USER_HOME>/.pi/agent。

已授权的项目配置优先于用户配置。未提供配置时,采用以下默认值:

{
  "maxDepth": 2,
  "maxChildrenPerAgent": 4,
  "maxAgentsPerTree": 16,
  "waitTimeoutMs": 60000
}
字段 默认值 取值范围 说明
maxDepth 2 1..8 子代理最大深度;根会话为第 0 级
maxChildrenPerAgent 4 1..16 每个代理可保有的直接子级数量
maxAgentsPerTree 16 1..64 整棵树中未终止的子代理数量
waitTimeoutMs 60000 10000..600000 默认等待时长(毫秒)

运行时配置在根会话启动时读取。修改后需退出并重启 Pi;/reload 不会重新读取这些配置。

桥接运行时

子代理桥接进程运行在 JavaScript 运行时之上。Pi 通常复用自身的可执行文件;当 Pi 本身是单文件编译产物(其可执行文件不是 node/nodejs/bun)时,插件会从 PATH 中依次解析 node、bun。

如需显式固定运行时,可在启动 Pi 前把 WJ_PI_SUBAGENTS_BRIDGE_RUNTIME 环境变量设置为运行时可执行文件的路径。若无法解析到可用运行时,spawn_agent 会立即以 spawn_failed 失败,而不是等待启动超时。

🗜️ 上下文压缩

Pi >= 1.2.0 在每次工具执行后,通过原生的 post-tool 流程决定并执行上下文压缩。根会话与每个子代理都是独立的 Pi 会话,各自根据实际上下文状态完成压缩并继续工作,无需任何额外的插件或协调协议。

本插件通过监听 Pi 原生压缩生命周期事件和 get_state.isCompacting 来校准代理状态与 TUI 动态提示。父代理发给子 Pi 的消息仍由 Pi 命令响应裁定;若 Pi 因正在压缩而拒绝消息,调用方会收到可重试的 compaction_active。Pi 没有 abort_compaction RPC,因此在压缩期间发起中断时,插件不会调用无法取消压缩的普通 abort,而是基于当前对原生压缩的观察返回 compaction_active。子级回复使用 Pi 的 fire-and-forget 扩展消息 API;调用成功仅表示父扩展运行时已接受该提交。

🔄 更新与卸载

更新插件:

pi update --extension npm:wj-pi-subagents

移除用户级安装:

pi remove npm:wj-pi-subagents

移除项目级安装:

cd <PROJECT_DIR>
pi remove npm:wj-pi-subagents -l

🛡️ 使用边界

  • 子代理以与当前 Pi 进程相同的操作系统用户权限运行。
  • 工作目录用于项目资源发现和相对路径解析;它并不是文件系统沙箱。
  • 模板中的 tools 只限制模型可调用的工具;并不限制进程自身的系统权限。
  • Pi 扩展可以执行原生代码;请只安装可信且经过审查的来源。
  • 处理不可信代码时,请在容器、虚拟机或其他隔离环境中运行 Pi。

🛠️ 开发与调试

获取源码并安装依赖:

git clone https://github.com/nlbwqmz/wj-pi-subagents.git
cd wj-pi-subagents
npm ci --legacy-peer-deps

常用检查命令:

npm run typecheck
npm test
npm run check

构建并保留一个从 npm tarball 安装的本地测试包:

npm run pack:smoke

每次运行都会重新构建 package-smoke/。验证完成后,可安装的包目录为 package-smoke/node_modules/wj-pi-subagents。例如,在仓库根目录下执行:

pi install "./package-smoke/node_modules/wj-pi-subagents"

本项目无需开发服务器。要在目标项目中临时加载源码:

cd <PROJECT_DIR>
pi --verbose -e "<REPOSITORY_PATH>"

修改源码或模板后执行 /reload。修改 wj-pi-subagents.json 后需重启 Pi。

📄 许可证

本项目基于 MIT 许可证 授权。