# 委派工作的上下文隔离

## 问题

当 Agent 将工作委派给子 Agent 时，每一块共享状态都是潜在的碰撞点。继承了父级完整上下文的子 Agent 可能基于过时假设行动；共享父级工作目录的子 Agent 可能覆盖父级正在读取的文件；能递归生成自己子级的子 Agent 会造成指数级的上下文膨胀。没有显式的隔离边界，一个子 Agent 的错误爆炸半径会波及整个会话。

这些问题出现在任何支持委派的 Agent 运行时中 — coordinator 模式、fork 模式、或任何形式的并行子 Agent 工作。它们是多 Agent 架构的固有特性，不限于任何特定实现。

## 黄金法则

### 零继承是最安全的默认

在 coordinator 模式中委派工作时，只传递显式的 prompt。子 Agent 不继承对话历史、不继承积累的上下文、不继承会话状态。这是最窄的边界：子 Agent 只能基于被告知的内容行动，父级会话中的任何信息都不会意外泄露。代价是 prompt 必须自给自足 — 子 Agent 完成工作所需的一切都必须明确写出。

### 全继承 fork 必须是单层的

当子 Agent 需要父级的完整上下文（fork 模式）时，复制上下文但强制执行单层边界：被 fork 的 Agent 不能再次 fork。没有这个约束，递归 fork 会指数级放大上下文成本 — 每层复制上层的所有内容，总成本在 fork 树深度上是 O(2^n)。单层边界将成本保持为线性。

### 文件系统隔离防止路径碰撞

当子 Agent 修改文件时，它需要自己的仓库工作副本。共享工作目录会产生竞态条件：父级读取文件，子 Agent 修改它，父级下次读取就返回意外内容。文件系统隔离（通过 worktree、临时目录或写时复制克隆）给每个 Agent 自己的视图。必须注入路径转换，让 Agent 操作隔离副本而非共享原件。

### 选择能用的最窄边界

隔离边界决定了子 Agent 错误的爆炸半径。零继承 worker 只能损坏自己的输出。全继承 fork 可能产出与父级状态不一致的结果。共享文件系统的 Agent 可以损坏父级的工作目录。始终从最窄边界开始，只在子 Agent 确实需要更多上下文时才放宽。

## 适用场景

- Agent 将工作委派给子 Agent 或生成并发 worker。
- 子 Agent 修改父级正在使用的同一仓库中的文件。
- 委派的子 Agent 产出相互矛盾或与父级状态矛盾的结果。
- 需要防止子 Agent 失败损坏父级会话。
- 并行 Agent 需要在同一代码库上工作而不互相踩脚。

## 权衡

| 决策 | 收益 | 代价 |
|---|---|---|
| 零继承委派 | 干净的上下文边界，无意外泄露 | 子 Agent 必须仅从 prompt 中自给自足 |
| 全继承 fork（单层） | 子 Agent 拥有完整上下文应对复杂任务 | 上下文成本翻倍；必须强制执行禁止递归 fork 规则 |
| 通过 worktree 文件系统隔离 | Agent 之间无文件级竞态条件 | Worktree 创建和销毁开销；磁盘成本 |
| 路径转换注入 | Agent 透明地操作自己的副本 | 转换逻辑必须覆盖所有文件操作工具 |
| 不可变共享状态 | 跨 Agent 安全并发读取 | 状态更新需要新快照，不能就地修改 |
| 单层 fork 边界 | 线性成本，非指数级 | 需要进一步委派的 fork Agent 必须改用 coordinator 模式 |

## 实现模式

- 对于 coordinator 模式委派，将子 Agent prompt 构建为自包含文档。在 prompt 中包含所有必要的上下文、约束和输出格式要求 — 不要依赖继承的会话状态。
- 对于 fork 模式委派，在 fork 时复制父级上下文并强制执行单层边界。被 fork 的 Agent 应该无法调用 fork 机制本身。如果被 fork 的 Agent 需要进一步委派，它必须为自己的子 Agent 使用 coordinator 模式（零继承）。
- 当子 Agent 修改文件时，在 Agent 启动前创建隔离的文件系统上下文（worktree、临时目录或写时复制克隆）。注入路径转换，使每个文件操作工具都指向隔离副本。
- 子 Agent 完成后，通过受控的集成点将结果合并回父级工作目录 — 不要让子 Agent 直接写入共享文件系统。
- 将父级和子 Agent 之间共享的所有状态标记为不可变。如果子 Agent 需要传达状态变更，应该作为返回值返回，而不是就地修改共享对象。
- 注册清理处理器，在子 Agent 完成或失败时销毁隔离的文件系统。泄露的 worktree 或临时目录会累积浪费磁盘。
- 当多个子 Agent 并行工作在同一代码库上时，尽可能分配不重叠的文件集。文件系统隔离处理通用情况，但不重叠的分配可以在集成点防止合并冲突。

## 踩坑指南

**递归 fork 产生指数级成本。** 如果被 fork 的 Agent 可以再次 fork，上下文成本在每层翻倍。三层递归 fork 意味着原始上下文的八份副本。在委派机制层面强制单层边界，不要只靠约定。

**路径转换必须覆盖所有文件操作工具。** 如果隔离机制注入了 worktree 路径但某个文件操作工具绕过了转换，该工具就会写入共享的原始目录。每个接触文件系统的工具都必须经过转换层。

**零继承 prompt 必须真正自包含。** 一个常见的失败模式是构建了一个隐式依赖父级拥有但子 Agent 没有的上下文的子 Agent prompt。审查零继承 prompt 是否有隐藏依赖：假设特定工作目录的文件路径、对早期对话轮次的引用、或对可用工具的假设。

**隔离 Agent 的结果合并可能冲突。** 当两个并行 Agent 在各自的 worktree 中修改同一文件时，将两者合并回来会产生冲突。设计任务分配以最小化重叠，并为不可避免的重叠准备冲突解决策略。

**Worktree 清理必须在所有退出路径上发生。** 如果清理只在成功完成时运行，失败或被杀的子 Agent 会泄露其 worktree。在进程级关闭处理器上注册清理，而不仅仅在成功路径上。

**不可变共享状态不意味着没有通信。** 子 Agent 仍然可以向父级返回结果 — 约束是它们返回值而不是修改共享对象。父级通过受控的更新路径将返回的结果集成到自己的状态中。

## Claude Code 实证

Claude Code 的委派系统在多种 Agent 协调模式中实现了这些隔离原则：

**零继承作为协调工作的默认。** 当运行时在 coordinator 模式中派发子 Agent 时，子 Agent 只接收其显式的任务 prompt。不继承对话历史、不继承积累的记忆、不继承父级会话状态。这是一个刻意的设计选择：子 Agent 的爆炸半径仅限于其自身输出。代价 — 每个子 Agent prompt 都必须完全自包含 — 被认为是值得的，因为它消除了一整类状态泄露 bug。

**单层 fork 边界。** Fork 机制将父级的完整对话上下文复制给被 fork 的 Agent，但强制被 fork 的 Agent 不能自己调用 fork 机制。如果被 fork 的 Agent 需要进一步委派，它必须为自己的子任务使用 coordinator 模式（零继承）。这将总上下文成本保持在父级上下文的 2 倍，而非 2^n。设计明确拒绝递归 fork，因为指数级成本使其在任何实际工作负载中都不现实。

**基于 worktree 的文件系统隔离。** 当子 Agent 需要修改文件时，运行时创建一个 git worktree，给 Agent 自己的仓库工作副本。注入路径转换，使每个文件操作工具都指向 worktree 而非父级的工作目录。这消除了并发 Agent 之间的文件级竞态条件。Worktree 在所有退出路径上清理，包括失败和被杀，通过进程级清理处理器。

**跨并发 Agent 的不可变共享状态。** 父级和子 Agent 之间共享的应用状态被包装在深度不可变类型中。子 Agent 不能就地修改这个状态。当子 Agent 产出结果时，它们作为值返回，由父级通过受控的更新路径集成。这个设计防止了最隐蔽的并发 bug 类别：共享对象的静默就地修改导致不同 Agent 看到不一致的状态。

**爆炸半径作为首要设计标准。** 每种委派类型的隔离级别是通过问"这个子 Agent 最坏能破坏什么？"来选择的。零继承 worker 只能产出糟糕的输出。全继承 fork 可能产出与父级上下文不一致的输出。共享文件系统的 Agent 可以损坏父级的工作目录。运行时默认使用最窄边界，只在用例需要时才放宽。
