主 Agent 与子 Agent 的共享和隔离
多 Agent 最容易产生的误解,是把“同进程”“同工作区”和“同上下文”当成同一件事。Claude Code 实际采用最小共享:共享昂贵且稳定的基础设施,复制需要一致起点的快照,隔离会并发变化的可变状态。
先定义三种关系
- 共享:访问同一个物理资源或可变对象,一方变化可能立即被另一方看见。
- 复制:创建时取得快照,之后各自变化,不会自动同步。
- 独立:由该 Agent 新建并独立拥有。
“都能读同一个文件”属于共享物理资源;“都知道父级已读过该文件”可能只是复制缓存;“都调用同一模型”也不代表共享 API 对话。
完整共享/隔离矩阵
| 维度 | 主 Agent | 同步 Subagent | 后台 Subagent | Fork | 同进程 teammate | pane teammate | Worktree Agent |
|---|---|---|---|---|---|---|---|
| OS 进程 | 主进程 | 共享 | 共享 | 共享 | 共享 | 独立进程 | 与所叠加 Agent 相同 |
| 物理文件 | 主 checkout | 默认同文件 | 默认同文件 | 默认同文件 | 默认同文件 | 默认同路径/同文件 | 独立 checkout,Git 仓储仍有关联 |
| 有效 CWD | session CWD | 默认继承 | 默认继承 | 默认继承 | 默认继承 | 启动时指定,默认同路径 | Agent 异步链覆盖到 worktree |
| 环境变量 | 进程环境 | 共享 | 共享 | 共享 | 共享 | 只保证显式转发的配置集合 | 同进程时共享 |
| API 认证与客户端基础 | 主配置 | 共享基础 | 共享基础 | 共享基础 | 共享基础 | 自己初始化,来源可相同 | 与所叠加 Agent 相同 |
| API conversation | 主查询链 | 独立 | 独立 | 独立链,复制父前缀 | 独立长期历史 | 独立 session | 取决于所叠加 Agent |
| 模型选择 | 主线当前模型 | 按 Agent 策略解析 | 按 Agent 策略解析 | 精确继承父级 | teammate 自身策略 | spawn 解析;仅 inherit/跟随策略才取 leader 模型 | Worktree 本身不改变模型 |
| system Prompt | 主线选择结果 | Agent 专用 | Agent 专用 | 优先复制已渲染父级字节;缺失时重建 | 主 Prompt + teammate 协议 | 新进程主 Prompt + teammate 协议 | Worktree 本身不改变选择策略 |
| 主对话 messages | 原始所有者 | 不共享 | 不共享 | 创建时复制前缀 | 不共享 | 不共享 | 取决于普通或 Fork |
| 工具池 | 主线当前快照 | 重新装配与裁剪 | 再加后台裁剪 | 精确复制父级工具 | 组装后按 teammate 边界裁剪 | 新进程完整组装 | 取决于所叠加 Agent |
| 权限硬约束 | 当前规则 | 从 live 父上下文派生并可向用户确认 | 默认避免弹窗;bubble/显式开放可送父终端 | 常用 bubble;同步回退时服从父路径 | 独立 worker 模式,可向 leader 确认 | 独立初始化,只转发受支持模式 | Worktree 不绕过权限 |
| 一般 AppState 写入 | 主所有者 | 当前同步路径共享父 setter | 隔离为 no-op | 异步时隔离;同步回退时共享 | runner 写根镜像,内部查询受隔离 | 完全独立,leader 仅镜像 | 与执行载体相同 |
| 根 runtime task 注册 | 共享根表 | 可写 | 可写 | 可写 | 可写 | 各进程独立,leader 有控制镜像 | 与执行载体相同 |
| 读取文件状态 | 主状态 | 从空状态开始 | 从空状态开始 | 复制父级快照后独立 | 每轮重新建立,不跨轮保留自身缓存 | 独立进程状态 | 普通 Agent 从空开始;Fork 复制旧 checkout 快照并收到重读提醒 |
| 内容替换决策 | 主状态 | 复制后独立 | 复制后独立 | 精确复制后独立 | 自己跨轮保持 | 独立 | 与对应 Agent 相同 |
| Skill 调用状态 | 以主 agentId 归属 | 同模块但按 agentId 隔离 | 同左,结束清理 | 同左 | 同进程 Map,按身份隔离 | 独立进程 Map | registry 可共享,调用状态仍按 Agent 隔离 |
| 取消信号 | 主 turn 控制 | 随父 turn | 独立 task controller | 异步时独立;后台总开关关闭导致同步时随父 turn | 生命周期与当前 turn 两层 | 独立进程 controller | 与执行载体相同 |
| Team task list | 条件启用时读写 | 普通 Subagent 不以此为主 | 普通后台 runtime task 不等于它 | 同左 | 共享带锁 JSON | 共享同一带锁 JSON | 配置目录仍共享 |
| Team mailbox | leader 地址 | 默认不用 | 可寻址时走普通 pending queue;不是 mailbox | 同左 | 共享 mailbox 文件 | 共享 mailbox 文件 | Worktree 不隔离 mailbox |
| transcript | 主 transcript | 独立 sidechain | 独立 sidechain | 含父前缀副本的 sidechain | runner 历史 + sidechain/UI 镜像 | 独立主 session transcript | metadata 额外记录 worktree |
| MCP | 主连接集 | 可复用父连接并增量创建 | 同左 | 精确工具前缀 | 同进程连接基础可共享 | 自己管理连接生命周期 | 外部能力并未被 worktree 隔离 |
| 外部网络/服务 | 主凭证边界 | 默认共享可达性 | 默认共享可达性 | 默认共享可达性 | 默认共享可达性 | 取决于显式环境与凭证 | 不因 worktree 自动隔离 |
共享的核心:基础设施和物理世界
同进程 Agent 通常共享:
- 进程、环境与模块注册表;
- API 认证基础和父级已建立的部分 MCP 连接;
- 根任务观察能力与同一个物理文件系统;
- 团队配置目录、网络和外部服务可达性。
共享这些资源减少了重复启动和连接成本,但也意味着同 checkout 并发写入、外部副作用和模块级全局状态都必须被谨慎管理。
复制只发生在确实需要一致前缀的状态
普通 Subagent 的读取缓存从空开始;内容替换状态仍复制成独立容器,但由于它没有父级消息中的工具调用标识,这份快照通常无从匹配。Fork 同时复制读取缓存、内容替换决策和消息前缀,三者才真正共同参与父级前缀复用;复制后也不会在并发完成时互相改写。
同进程 teammate 跨轮保留自己的累积消息与内容替换状态,但不会保留每轮产生的读取缓存。Fork 则把复制策略推到极致:system 优先复用已渲染字节,tools、model、thinking 与 messages prefix 尽量一致;system 快照缺失时会回退重建,所以缓存同一性是最佳努力。分叉点以后仍是两条独立消息链。
隔离的核心:会并发变化的控制状态
以下状态必须按 Agent 或 query chain 隔离:
- agentId、查询跟踪和 telemetry 归因;
- 消息历史、压缩边界和请求 ID;
- Skill 调用、嵌套 Memory 与发现状态;
- 当前工具进度、权限拒绝计数和取消资源;
- 专属 MCP、Hook 和 transcript 生命周期。
同进程并不妨碍这种隔离。Agent 身份、teammate 身份和有效 CWD 跟随各自异步链传播,避免多个并发任务争抢一个“当前 Agent”全局变量。
Worktree 的隔离边界最容易被高估
Worktree 隔离的是工作副本和分支,不隔离:
- 进程与环境变量;
- API 认证、MCP 和网络;
- team task、mailbox 与配置;
- Git common objects、refs 和 hooks;
- 数据库、云服务或其他外部副作用。
所以 Worktree 适合减少源码写冲突,不是安全 Sandbox,更不是完整租户隔离。
三个关键推论
- 同一个 checkout 不代表上下文共享:普通 Subagent 可修改主文件,却仍看不到主对话。
- 复制主对话不代表状态共享:Fork 复制前缀,但创建后不自动同步消息、缓存和取消状态。
- 独立进程不代表文件隔离:pane teammate 有独立内存和 API session,默认仍能修改 leader 的同一目录。
这套设计的精妙之处,是让每种隔离都对应一个明确问题,而不为“多 Agent”一次性复制整台运行环境。代价是调用方必须明确自己需要的是对话隔离、生命周期隔离,还是文件隔离。
源码定位
- Subagent 状态所有权:
src/utils/forkedAgent.ts、src/tools/AgentTool/runAgent.ts - Agent 并发身份:
src/utils/agentContext.ts、src/utils/teammateContext.ts - 有效 CWD:
src/utils/cwd.ts - 后台任务:
src/tasks/LocalAgentTask/ - 同进程 teammate:
src/utils/swarm/inProcessRunner.ts - 独立进程 teammate:
src/tools/shared/spawnMultiAgent.ts - 任务与 mailbox:
src/utils/tasks.ts、src/utils/teammateMailbox.ts - sidechain 与团队 transcript:
src/utils/sessionStorage.ts - Worktree:
src/utils/worktree.ts