---
title: 会话级子 Agent 委派
created: 2026-04-19
updated: 2026-04-23
type: entity
tags: [agent, runtime, websocket, backend]
sources: [packages/backend/src/modules/netaclaw/service/subagent.ts, packages/backend/src/modules/netaclaw/subagent/process_runner.ts, packages/backend/src/modules/netaclaw/subagent/process_protocol.ts, packages/backend/src/modules/netaclaw/subagent/worker.ts, packages/backend/src/modules/netaclaw/subagent/worker_tools.ts, packages/backend/src/modules/netaclaw/session-tree/types.ts, packages/frontend/src/modules/agent/store/chat.ts]
---

# 会话级子 Agent 委派

会话级子 Agent 委派是普通对话内部的临时任务分解能力。它不同于长期运行的 [[crew-orchestration]]：主 Agent 在一次对话中把局部目标交给一个或多个预设 Agent，子 Agent 执行后把摘要和结果回填到当前会话树。

当前实现已经从“服务内复用 runAgent 的元数据聚合”升级为“SubagentService + 独立 worker 进程 + JSONL 协议 + Session Tree 节点”的运行模型。

## 核心职责

- 接收主 Agent 的 `delegate_task` / `delegate_parallel` 工具调用。
- 为每个任务创建受限的 Agent 配置和工具集合。
- 根据 [[tool-runtime-policy]] 推导子进程工具策略。
- 通过 `process_runner.ts` 启动 worker，消费 JSONL 事件。
- 将子任务批次写入 `subagent_batch` 和 `subagent_result` 树节点。
- 向前端推送批次状态、工具路由、运行结果。

## 关键文件

| 文件 | 职责 |
| --- | --- |
| `service/subagent.ts` | 子 Agent 批次编排、任务状态聚合、结果归档 |
| `subagent/process_protocol.ts` | 父子进程之间的 envelope、policy、manifest、事件协议 |
| `subagent/process_runner.ts` | 启动/取消/超时控制 worker，处理 proxy tool call |
| `subagent/worker.ts` | 子进程入口，执行受限 Agent |
| `subagent/worker_tools.ts` | 子进程本地工具适配 |
| `tools/manifest.ts` | 为子 Agent 生成工具 manifest |
| `tools/runtime_policy.ts` | 推导 worker policy 和工具运行路由 |
| `session-tree/types.ts` | `subagent_batch` / `subagent_result` 节点类型 |

## 进程协议

父进程向 worker 发送 `SubagentTaskEnvelope`，其中包含：

- `protocolVersion`
- `runId`
- `sessionId`
- `parentEntryId`
- `task`
- `agentConfig`
- `toolNames`
- `toolManifest`
- `policy`
- `timeoutMs`

worker 以 JSONL 形式回传事件：

- `run_start`
- `token`
- `thinking`
- `log`
- `tool_call`
- `tool_result`
- `proxy_tool_call`
- `run_end`
- `run_error`

`runId` 是父进程校验事件归属的边界，避免不同子任务输出串流。

## 工具路由

子 Agent 不再简单复制主 Agent 工具集，而是按 manifest 和 policy 分三类：

| 路由 | 含义 |
| --- | --- |
| `worker-local` | 可在 worker 内直接执行，例如只读文件搜索类工具 |
| `main-process-proxy` | worker 发起 `proxy_tool_call`，父进程代执行，例如写文件、技能、记忆类工具 |
| `disabled` | 当前策略下不可用，例如缺少 workspace root、shell 被禁、只读策略阻止写入 |

这个设计把“工具是否被 Agent 选择”和“工具能否在子进程执行”拆开，避免子 Agent 越权。详见 [[tool-runtime-policy]]。

## Session Tree 表达

子 Agent 结果现在是会话树的一部分：

- `subagent_batch` 表示一个批次开始或运行中状态。
- `subagent_result` 表示批次结果和每个子任务的最终输出。
- 节点通过 `parentEntryId` 关联到触发它的主 Agent 消息或工具调用。
- 前端可在刷新后从 snapshot 恢复批次卡片，不依赖仅存在内存里的 streaming state。

这使子 Agent、压缩、分支摘要、普通消息都能进入统一的 [[session-tree-runtime]]。

## 与 Agent 配置的关系

Agent 编辑页需要配置的不只是“是否允许子 Agent”：

- `subagentConfig.enabled`
- `subagentConfig.maxConcurrent`
- `subagentConfig.allowedPresetAgentIds`
- `subagentConfig.allowedToolNames`
- 每个工具的有效运行画像和子 Agent 可用性诊断
- 本地存储、workspace、shell、readonly 等会影响工具路由的策略输入

这些配置最终应通过后端 projection 返回给前端，避免工具列表、工具管理页、Agent 配置页三处口径不一致。

## 与 Crew 的边界

| 维度 | 会话级子 Agent | Crew 编排 |
| --- | --- | --- |
| 生命周期 | 一次普通 chat 内部的临时批次 | 独立编排运行 |
| 状态载体 | Session Tree 节点 | Crew run/task 记录 |
| 展示位置 | Agent 对话页内联卡片 | Crew 页面、画布、监控视图 |
| 工具入口 | `delegate_task` / `delegate_parallel` | Crew orchestration 入口 |
| 权限模型 | 主 Agent 控制的受限 worker | Crew 配置控制 |

## 相关页面

- [[agent-runtime]]
- [[session-tree-runtime]]
- [[tool-runtime-policy]]
- [[tool-governance]]
- [[tool-system]]
- [[frontend-architecture]]
- [[websocket-gateway]]
- [[crew-orchestration]]

## 2026-04-22 Replay Contract

`subagent_result` is now the durable replay/evidence node for session-level subagents.

- `subagent_result.metadata.processEvents` stores projected worker JSONL events such as `run_start`, `tool_call`, `tool_result`, `proxy_tool_call`, `run_end`, and `run_error`.
- `subagent_result.metadata.evidenceSummaries` stores structured summaries derived from tool results, for example file counts or tool-result previews.
- `subagent_batch.metadata.events` and `subagent_batch.metadata.latestEvent` remain runtime/status projection data. They are useful while a batch is running, but they are not the primary refresh/replay source.
- `processEvents` and `evidenceSummaries` must not be injected into `runtimeContext.messages`; they are UI replay/evidence metadata, not LLM conversation context.
- Frontend projection lives in `packages/frontend/src/modules/agent/store/chat.ts` via `subagentEvidenceSummariesByEntryId` and `subagentProcessEventsByEntryId`.

## 2026-04-23 Projection And Evidence Model

本轮实现把“子 Agent 执行结果”拆成三层，避免运行态、持久态和展示态混在一起：

- `service/subagent.ts` 负责产出原始结果载荷：`finalOutput`、`rawFinalContent`、`toolResults`、`evidenceSummary`、`processEvents`、`toolRuntimeRoutes`。
- `service/subagent_evidence.ts` 负责把工具结果规范化，并按任务目标推导证据摘要；当前支持文件计数类摘要和工具预览类摘要。
- `service/chat_orchestrator.ts` 在批次完成后把结果聚合进 `subagent_result.metadata.finalResults/processEvents/evidenceSummaries`，使刷新后的 replay 不依赖内存态。
- `session-tree/subagent_projection.ts` 再把这些持久化数据投影成 `metadata.subagentProjection`，其中包含 `taskPanels`、每个 task 的 `toolExecutions`、剩余 `processEvents` 以及诊断信息。

这里要特别区分两个节点职责：

- `subagent_batch` 更偏运行中状态：批次任务列表、最近事件、运行态工具路由。
- `subagent_result` 更偏最终回放状态：最终结果、过程时间线、证据摘要、任务面板。

因此“刷新后还能看到什么”应首先看 `subagent_result`，而不是假设 `subagent_batch` 会长期保存完整过程。
