Pi 不用干等了:pi-background-tasks 后台任务、委托调查和 Fusion 教程
讲解 pi-background-tasks 2.5.0 怎么装、怎么用:/bg 和 bg_run 跑长命令,bg_delegate 做只读调查,Fusion 做固定流程的多模型合议,并区分它和 pi-monitor、Taskflow、Goal 的边界。

Pi 最烦的一种用法,是让它干等。
跑完整测试、起开发服务器、对仓库做一次只读排查,这些事情本来就可以放到后台。但默认情况下,Agent 很容易写成 sleep、反复查状态、把几百 KB 日志塞进上下文。当前回合被占住,你也没法继续往下聊。
pi-background-tasks 把这件事做成了 Pi 的基础设施。它不是再给 Agent 加几个“后台命令”工具那么简单,而是同时提供三层能力:
- 后台跑本地命令:有任务 ID、有输出文件、有页脚任务栏,结束时发终态通知。
- 委托一个只读子 Agent:带着当前对话的冻结投影去查仓库,父会话继续干活。
- 固定流程的多模型 Fusion:三个候选、盲评、必要时修复、再合并,用来做推理、调查、定向抓取或完成后审查。
之前那篇 Pi Agent 插件推荐 里,我把 @fradser/pi-monitor 放进了默认组合。Monitor 适合“等到一个明确成功信号再唤醒”。pi-background-tasks 更像任务运行时:命令、委托、Fusion 都走同一套任务注册表,结束通知是一等公民,Agent 不该靠轮询活着。
本文以
pi-background-tasks2.5.0、Pi Agent 0.81.1+ / 0.84.x、Node.js>= 22.19.0为准。安装前建议核对插件 README 和当前 Pi 版本。
先看结论
| 你想做的事 | 用什么 | 会不会卡住当前会话 |
|---|---|---|
| 自己敲一条长时间命令 | /bg | 不会 |
| 让 Pi 去跑测试、构建、开发服务器 | bg_run | 启动后立刻返回 |
| 让另一个 Agent 带着当前对话去只读查仓库 | bg_delegate + bg_result | 启动后立刻返回 |
| 给一次直接的 Pi 子进程留本地证据 | bg_run_pi_attested | 启动后立刻返回 |
| 多个模型合议一个封闭问题 | /fusion 或 fusion_reason | 启动后立刻返回 |
| 多个模型独立调查仓库 | fusion_investigate | 启动后立刻返回 |
| 只抓你指定的公开 URL,再综合 | fusion_research | 启动后立刻返回 |
| 对已经做完的改动做第二意见审查 | fusion_validate | 启动后立刻返回 |
一句话选法:短交互用前台;长命令用 /bg 或 bg_run;需要当前对话上下文的只读调查用 bg_delegate;需要多个模型视角用 Fusion。
安装
全局安装:
pi install npm:pi-background-tasks@latest
只给当前项目装:
pi install npm:pi-background-tasks@latest -l
想跟仓库 main 而不是发行版:
pi install git:github.com/ismailsaleekh/pi-background-tasks@main
安装后重启 Pi。正常情况下会加载两个入口:extensions/anthropic-attribution.ts 和 extensions/background-tasks.ts。前者只影响 Anthropic 订阅路由的归因和缓存策略,非 Anthropic 会话不变。
装完之后,Pi 会多出一组命令和工具。常用命令是 /bg、/jobs、/logs、/kill、/tasks、/fusion、/fusion-models。常用工具是 bg_run、bg_delegate、bg_result、bg_status、bg_logs、bg_kill,以及四个 Fusion 工具。
Pi 插件以你的系统权限运行。/bg 和 bg_run 不是沙箱,它们就是普通本地进程,能读文件、起子进程、访问网络、用到当前环境里的凭据。不要把 pi install 当成浏览器扩展那种隔离安装。
五分钟上手:先跑一条后台命令
在项目目录里启动 Pi,然后:
/bg --name "Typecheck watch" npm run typecheck -- --watch
/bg 会立刻返回任务 ID 和输出路径,类似:
Started Typecheck watch (<task-id>)
Output: .pi/tasks/<session>-<pid>/<task-id>.output
Command: npm run typecheck -- --watch
输出和元数据写在项目下的 .pi/tasks/<session-id>-<pid>/。这是本地持久化,不是只存在当前回合的临时文本。
看任务列表:
/jobs
读一段有上限的日志:
/logs <task-id> 20000
停掉正在跑的任务:
/kill <task-id>
页脚出现 bg 1 running · Shift↓ 时,按 Shift↓ 打开任务栏。方向键移动,Enter 看详情,k 停止,R 重跑,x / Esc 关掉。完成但还没看过的任务,用 /bg-clear 确认。
这里有一个关键区别:
- 你手动敲的
/bg,默认会发完成通知,但不会自动唤醒下一轮模型。 - Agent 调用的
bg_run,默认既通知,也会触发后续回合。
所以用户自己起开发服务器用 /bg;让 Pi 跑完测试再继续改代码,用 bg_run。
让 Agent 自己后台跑:bg_run
真正写代码时,你很少会自己去敲 /bg。更常见的是告诉 Pi:
把完整测试放到后台跑。用 bg_run,不要 sleep,也不要轮询状态。结束后根据通知继续。
工具参数很严格,三个字段是必填的:
{
"name": "Full test suite",
"command": "pnpm test",
"isAgent": false
}
name 是页脚上的短标签,用 2 到 6 个词,不要把整条命令当名字。isAgent 必须显式给:
- 普通脚本、测试、构建、开发服务器:
false - 这条命令本身会再拉起一个 Pi/LLM 子进程,比如
pi -p ...或pi --mode json ...:true
bg_run 默认 notifyOnCompletion: true、triggerOnCompletion: true。也就是说,任务结束时会写入一条持久的 <background-task-notification>,并自动拉起后续回合。Agent 正确的用法是:启动后去做别的独立工作,或者直接结束当前回合,等通知。
错误用法是这三种:
sleep 30再查一次- 循环调用
bg_status - 为了“看看有没有跑完”反复
bg_logs
bg_status 和 bg_logs 是点查工具,不是等待原语。日志对模型可见的上限是 50 KB;完整输出还在本地文件里。超过输出上限(默认 20 MiB,可用 PI_BG_MAX_OUTPUT_BYTES 改)会让任务失败并杀掉,而不是假装成功。
可选超时:
{
"name": "Docs preview",
"command": "npm run docs:dev",
"isAgent": false,
"timeoutSeconds": 3600
}
超时后任务会以失败结束,进程会被杀掉。
把调查交给只读子 Agent:bg_delegate
有些工作不是“跑命令”,而是“先把仓库查清楚,但别打断我继续改代码”。
这就是 bg_delegate。它会再启动一个 Pi 子 Agent:
- 路由在启动时钉死,中途不会偷偷换模型
- 默认只开只读工具:
read、grep、find、ls,以及读取产物 - 没有 shell、没有写文件、没有联网、不能再委托、也不能跑 Fusion
- 子进程有自己的 session,不会把父会话的工具结果原样塞回去
它会带上当前对话的冻结投影,但被省略的父工具输出对子 Agent 不可见。如果某个关键事实只出现在刚才那次 grep 结果里,你必须在 prompt 里重写一遍。prompt 才是权威指令,对话投影只是背景。
最小调用:
{
"name": "Config reader",
"prompt": "只读检查仓库配置,找出后台任务输出上限和完成通知是在哪些文件里定义的。给出路径,只引用相关行。如果某个事实只存在于父会话被省略的工具输出里,就说看不到,不要猜。",
"capability": "inspect"
}
默认 extensionMode 是 isolated,不会加载你平时那些环境插件。只有当钉死的 provider 必须靠用户/项目扩展才能注册时,才改成 ambient。Ambient 会执行发现到的扩展代码,工具白名单沙箱不住这些代码,只读隔离会被削弱。
启动后立刻拿到 task id。完成后用 bg_result 取结果,不要轮询:
{
"taskId": "<bg_delegate 返回的 id>",
"delivery": "inline"
}
bg_result 从不阻塞。任务还在跑,就返回 typed 的 not-ready;已经提交的答案会先做哈希校验,再把字节给你。超大答案不会被静默截断,而是变成产物引用。默认 autoDeliver 是 never,完成通知里不带正文,需要你主动取。
这套设计和“再开一个普通子 Agent”的差别很大。普通子 Agent 往往还能改文件、跑命令;delegate 被故意做成调查专用。父 Agent 可以一边改代码,一边等一份经过校验的只读报告。
Fusion:不是自由模式,是固定合议流程
Fusion 看起来很像“多模型讨论”,但它不是一个你可以随便切换的能力开关。四个公开工具对应四个固定目的:
| 工具 | 给子模型的上下文 | 候选能用的工具 | 适合做什么 |
|---|---|---|---|
fusion_reason / /fusion | 当前对话的版本化投影 + prompt | 无 | 封闭推理、方案对比、利弊分析 |
fusion_investigate | 只有你传入的任务字段 | 只读查仓库 | 独立的仓库调查 |
fusion_research | 只有你传入的任务字段 | 只读查仓库 + 抓取你声明的公开 URL | 定向阅读,不是搜索 |
fusion_validate | 只有你传入的任务字段 | 只读查仓库 | 对已完成改动做顾问式审查 |
共同流程是固定的:
- 先做预算和产物预检,这时还没有子进程
- 返回后台任务回执
- 三个候选并行跑
- 候选身份匿名成 A/B/C
- 盲评
- 只有评委 JSON 不合法时,才额外跑一次有限修复
- 合并成最终报告
- 提交
merged.md,再用bg_result校验后取出
所以不要把它理解成“固定五次模型调用”。预检失败是零次;评委 JSON 坏了可能是六次;中途取消或超限会更少或更多。评委、修复和合并都没有工具。
交互里最简单的入口:
/fusion 比较前台命令、bg_run 和 bg_delegate,各自适合什么样的十分钟仓库审计。
或者直接调用:
{
"prompt": "给一次有风险的数据库迁移设计回滚策略,写明假设和失败模式。"
}
仓库调查必须自己把事实写进参数。子模型看不到父会话,也看不到你没重述的工具输出:
{
"objective": "找出后台任务输出如何封顶、如何展示给用户。",
"background": ["我们在评估 pi-background-tasks 对长命令的行为。"],
"deliverable": "文件路径、常量、默认值和用户可见行为。",
"scope": ["src"],
"constraints": ["只做只读检查。"]
}
fusion_research 特别容易用错。它不是网页搜索。你必须给出具体的公开 http(s) URL 和用途,它只会抓这些地址,不会帮你发现新链接,也不会去翻私人页面。不要把 token、密钥或仓库私有内容放进 URL。
fusion_validate 是顾问,不是 CI。它不会改文件、不会跑测试、也不能代替 lint 和人工审查。verification 字段很严:
status: "provided"必须带非空evidence,不能再写reasonstatus: "not_run"必须写reason,不能带 evidence
调查和审查跑着的时候,不要去改它声明的范围。仓库是 live 的,你一边改一边让三个模型读,得到的不是合议,是竞态。
模型槽用 /fusion-models 配,这是 TUI 专用命令。五个槽分别是 Candidate 1/2/3、Evaluator、Merger。默认都是 $current,运行时解析成当前模型。配置写在 Pi Agent 目录的 fusion-models.json。Frontier 模型只接受 Pi 的 Anthropic 或 Codex 订阅 OAuth,直连 API Key、OpenRouter、Azure 这类计量路由会在创建子进程前被拒绝,也不会静默换模型。
怎么选:一张更细的表
| 选项 | 上下文 | 读仓库 | 联网 | 写文件 | 什么时候用 |
|---|---|---|---|---|---|
| 前台 Pi | 当前会话 | 看当前工具 | 看当前工具 | 看当前工具 | 下一步必须立刻看到结果 |
/bg | 插件不传会话 | 由命令决定 | 由命令决定 | 由命令决定 | 你自己起长命令,只要通知不要自动续聊 |
bg_run | 插件不传会话 | 由命令决定 | 由命令决定 | 由命令决定 | 让 Pi 起长命令,结束后自动继续 |
bg_delegate | 冻结的可见对话投影 | 只读 | 否 | 否 | 需要当前对话背景的只读调查 |
bg_run_pi_attested | 你给的 prompt | 由子 Pi 决定 | 由子 Pi 决定 | 指定报告路径 | 要一份本地可核验的直接 Pi 运行证据 |
fusion_reason | 对话投影 + prompt | 否 | 否 | 否 | 封闭问题的多模型综合 |
fusion_investigate | 只有任务输入 | 只读 | 否 | 否 | 独立调查,不该夹带父会话 |
fusion_research | 只有任务输入 | 只读 | 只抓声明过的公开 URL | 否 | 指定来源后的综合,不是搜索 |
fusion_validate | 只有任务输入 | 只读 | 否 | 否 | 完成后的第二意见 |
和我现在常用的其他 Pi 插件放一起看,边界更清楚:
| 需求 | 更合适的插件 |
|---|---|
| 等到测试日志里出现一个明确成功契约 | pi-monitor |
| 任意长命令、页脚任务栏、结束后唤醒 | pi-background-tasks 的 /bg / bg_run |
| 带着当前对话做一次只读排查 | bg_delegate |
| 多阶段 DAG、门禁、恢复、预算 | pi-taskflow |
| 多个角色长期在线、共享任务板 | pi-agent-teams |
| 当前 Agent 围着一个可验收目标连续推进 | pi-goal |
| 三个模型按固定流程合议 | Fusion |
这些东西可以同时安装,但不要叠在同一个任务上。先选一个主执行模型。pi-monitor 和 bg_run 尤其容易重复:都是后台跑命令,差别是 Monitor 认结果契约,bg 认进程终态。
最容易踩的坑
1. 把后台命令当成沙箱。
/bg 和 bg_run 只负责跟踪和杀掉进程树。文件系统、网络、子进程、付费 CLI,该能用还是能用。不要在后台里跑你不想以当前用户身份执行的东西。
2. 启动之后继续轮询。
默认完成通知就是唤醒路径。bg_status、bg_logs 只在你明确要看一眼、通知被关掉、或者怀疑任务卡死时才用。
3. 委托时不重述关键事实。
父会话里刚搜到的那段代码,子 Agent 未必看得到。prompt 要自包含。找不到就说找不到,这是这个包明确要求的行为,不是模型谦虚。
4. 把 fusion_research 当搜索引擎。
它不会帮你找资料。URL 得你自己给,而且必须是公开 http(s)。抓回来的内容按不可信数据处理。
5. Fusion / 委托还在跑,你却去改同一批文件。
fusion_investigate 和 fusion_validate 读的是 live 仓库。审查范围一旦开始跑,就先别动。
6. 给 Fusion 配了计量 API Key。
Claude / GPT 这类 frontier 路由只走 Pi 订阅 OAuth。配错了会在创建子进程前失败,不会降级到别的模型。
7. isAgent: true 乱标。
只有命令本身会启动 Pi/LLM 子进程时才标 true。普通 pnpm test 标 true,遥测包装帮不上忙,还可能让任务栏显示一堆“不可用”的模型数据。
8. Ambient 委托。
默认 isolated 就对了。Ambient 是为了加载扩展注册的 provider,不是为了让子 Agent“更聪明”。
我实际会怎么用
我现在的默认习惯很简单。
开发服务器、watch、一次性迁移演练,自己敲 /bg,需要时按 Shift↓ 看一眼。Pi 要跑测试或 typecheck,就让它 bg_run,然后继续问下一步怎么改;等通知来了再看结论。
正在改代码,但又想确认“某个配置到底在哪定义”,用 bg_delegate。这种调查不该抢当前会话,也不该有写权限。
方案对比、回滚策略、接口设计这种封闭问题,用 /fusion。仓库里“这个行为到底是不是文档说的那样”,用 fusion_investigate。改完文档或小范围重构,偶尔用 fusion_validate 听第二意见,但仍然以测试和 diff 为准。
如果任务是“修这个 Bug 直到验证通过”,我还是会用 pi-goal,而不是 Fusion。Fusion 贵在视角,不贵在持续执行。