# Subagent 集成评估

> 本文整理自对本项目 subagent 集成机制的评估讨论（2026-02，fork 后维护记录）。
> 涉及代码：`src/index.ts`（`rpcCall`、`spawnSubagent`、`checkSubagentsVersion`、`agentTaskMap`、
> `subagents:completed/failed` 监听、`TaskExecute`/`TaskOutput`/`TaskStop`）。
> 结论为**评估结论，不构成已实施改造**。

## 1. 依赖关系：可选，非必须

- `package.json` 不依赖 `@tintinweb/pi-subagents`，运行时也无硬性 require。集成完全走
  **eventbus 动态探测**：init 时 ping `subagents:rpc:ping`（5s 超时），并监听 `subagents:ready`
  事件重 ping；探测失败 → `subagentsAvailable = false`。
- 7 个工具中只有 `TaskExecute` 依赖 subagent；未安装时它返回友好提示（不崩溃），其余
  6 个工具完全独立工作。
- 反向不依赖：`pi-subagents` 不依赖本项目。单向耦合。

## 2. 协同工作步骤（与 @tintinweb/pi-subagents）

1. **握手**：init / `subagents:ready` 时 ping → 版本 == `PROTOCOL_VERSION`（2）→
   `subagentsAvailable = true`。版本不匹配只警告，不降级。
2. **执行**（`TaskExecute`）：校验任务 pending、有 `metadata.agentType`、依赖全 completed →
   发 `subagents:rpc:spawn {subagent_type, prompt, options}`（**30s 超时**）→ 拿 agentId →
   记入 `agentTaskMap`（agentId→taskId）+ `metadata.agentId` + 任务置 in_progress。
3. **运行**：pi-subagents 启动隔离子会话（同进程，受 maxConcurrent=4 排队、agent 类型配置
   约束）。子会话**不加载本扩展**，不会递归触发。
4. **回调**：`subagents:completed {id, result}`（或 `failed {id, error, status}`）→ 经
   `agentTaskMap` 反查 taskId → 任务置 completed + `metadata.result`；失败回滚 pending +
   `metadata.lastError`（`status == "stopped"` 例外：视为完成）。
5. **级联**（auto-cascade 开启时）：任务完成后找 `pending && blockedBy 含本任务 && 所有依赖
   已完成` 的下游任务 → 自动 spawn，prompt 注入上游 `metadata.result`（超 4000 字符截断）。
6. **辅助路径**：`TaskOutput` 阻塞等 completed/failed 事件匹配 agentId（默认 30s）；
   `TaskStop` 先标任务 completed 再发 `subagents:rpc:stop`（10s 超时，吞错）。

一句话：**探测握手 → RPC spawn → 事件回调映射回任务 → 更新状态 → 可选级联**。
全程走 eventbus，无文件、无共享 API。

## 3. 与其他 subagent 扩展的兼容性（billion-context-pi 案例）

- 协议是 `@tintinweb/pi-subagents` **自定义的 eventbus RPC**（`subagents:rpc:ping/spawn/stop` +
  `subagents:completed/failed/ready` + 带 requestId 的 reply 通道），不是 pi 官方 API。
- **billion-context-pi（0.1.37）实测不实现该协议**（其 dist 中 `subagents:rpc:*` 出现次数为 0）。
  它提供的是自研 `acp_delegate` / `acp_delegate_wait` / `acp_delegate_cancel` 工具：spawn 独立
  `pi -p` CLI 子进程（`@earendil-works/pi-coding-agent/dist/cli.js`），结果写 `%TMPDIR%/acp-delegate`，
  async 模式完成时向主会话注入通知。pi 核心（0.84.1）本身没有内置 spawn API。
- 因此所谓"与 billion-context-pi 协同"**不是代码层集成**，而是：
  `TaskExecute`（`subagentsAvailable=false`）返回提示文本 → **模型**读到提示后自主调用
  `acp_delegate` 执行 → 任务状态从未离开 pending（TaskExecute 降级分支不置 in_progress）、
  无回调、cascade 不触发、TaskOutput 为空。跟踪断裂是**静默**的。

## 4. 隐藏坑清单

| # | 坑 | 后果 |
|---|----|----|
| 1 | 协议版本硬编码 v2，只警告不降级 | pi-subagents 升级协议后仅一条 warning，`subagentsAvailable=false`，TaskExecute 静默失效 |
| 2 | spawn 超时 30s vs pi-subagents 排队（maxConcurrent 默认 4） | 并发 >4 时 spawn 排队可能超 30s → 任务回滚 pending，但 agent 稍后**仍会启动** → 幽灵 agent，完成事件映射不到任务 |
| 3 | `agentTaskMap` 纯内存 Map | 扩展热重载 / 切换会话后，运行中 agent 的完成事件丢失映射 → 任务卡 in_progress |
| 4 | eventbus 无鉴权 | 任何扩展都能伪造 `subagents:completed/failed` 事件 |
| 5 | TaskStop 先标 completed 再发 stop RPC（10s 超时被吞） | stop 失败时 agent 继续跑但任务已显示完成 |
| 6 | 协议字段靠约定无 schema | `status=="stopped"` 语义、options 透传、reply 形状依赖 pi-subagents 实现细节 |
| 7 | UI/工具面重叠 | 两扩展 widget 同屏渲染；LLM 同时看到 `TaskExecute` 与 `Agent`/`acp_delegate` 多个启动途径，promptGuidelines 只是劝告 |

## 5. 改造方案讨论：模型编排 + 状态收尾工具

目标：与协议各不相同的其他 subagent 扩展完整协同（执行后能正确更新任务状态）。

**原理**：把"收尾"从扩展内聚（自己监听事件映射）改为**模型编排 + 工具收尾**——所有
subagent 扩展对模型而言都是"调用工具 → 拿结果"的统一形态，模型是唯一的通用适配器；
完成信号不需要扩展发事件，模型看到工具结果本身就是信号。

**推荐设计（未实施）**：

```
TaskExecute（subagentsAvailable=false 时）
  ├─ 任务置 in_progress，记录 activeExecution（taskId → {启动时间, 使用的工具}）
  └─ 返回指引: "用 acp_delegate / Agent / 任意 subagent 工具执行，
      完成后调用 TaskComplete(taskId, result) 收尾"

模型 → 调用任意扩展的 agent 工具 → 拿到结果
  → 调用 TaskComplete(taskId, result)
      pi-tasks: 校验 in_progress + activeExecution 存在 → 置 completed
                + 存 metadata.result + 触发 cascade（复用现有逻辑）
```

**可靠性代价（关键弱点）**：从"程序硬保证"降为"模型软保证"，完成概率为概率叠加
`P(调用执行工具) × P(拿到结果后记得收尾) × P(任务关联正确)`，且后台 agent 完成通知
到达时模型在别的 turn、注意力被占、上下文可能已压缩，收尾更易丢失。

**兜底手段**：

| 风险 | 缓解 |
|------|------|
| 模型忘记收尾 / 中途转向 | TaskComplete 只接受 in_progress 且有 activeExecution 的任务；超时自动回滚 pending + 提示"执行过但未确认" |
| 模型把结果填错任务（并行时） | TaskComplete 要求回传 agentId/工具名，与 activeExecution 比对，不匹配拒绝 |
| 后台 agent 通知错位 | 通知携带上下文；配合 activeExecution 记录，模型看通知后查 TaskList 对上号；对不上走超时兜底 |
| 模型幻觉结果 | 不可根治；"任务状态"是模型操作的副作用，多一层人为错误面——本方案的本质代价 |

**推荐落地方案**：双轨并存——`subagents:rpc:spawn` 可用时走现有自动事件回调（硬保证）；
不可用时降级为"指引 + TaskComplete"（软保证）。改动量：新增 TaskComplete 工具 +
TaskExecute 降级分支 + activeExecution 记录 + 超时兜底。

## 6. 结论

- 依赖**可选**：优雅降级，未安装时其余功能完好；属软耦合 + 版本敏感。
- 与其他 subagent 扩展**无协议层兼容**，唯一的"协同"是模型看提示后自己动手，跟踪断裂。
- 改造为"模型编排 + TaskComplete 收尾"**原理可行**，但可靠性从事件保证降为模型自觉，
  需状态机校验、超时回滚、防串任务等兜底；双轨设计可在协议内保持硬保证。
