Agent Harness 学习
← 返回对照矩阵

subagent isolation

多 Agent

子代理隔离

派生一个子代理时,它和父代理共享什么、隔离什么?

横向读这一行

覆盖度差异最大的一行。openJiuwen 有完整的子代理运行时(注册表、会话管理、转录、持久化),Codex 有角色与控制层,DeepSeek 走得最远——它能把 Claude Code 和 Codex 当作子代理进程挂进来,而 Pi 干脆不在内核里提供子代理,只给一个示例扩展。

对比
openJiuwen带代码

独立子代理运行时,带并发上限与 LRU 驱逐

harness/subagent_runtime/ 是一个完整的运行时模块:注册表、会话管理、实例、状态与状态事件、活动流、转录流、持久化、输出文件各成一个文件。配置层直接把子代理当作需要限量的资源管理——最多 10 个实例、同时运行不超过 5 个、单轮超时、开启 LRU 驱逐。活动流还带节流和文本截断,因为子代理输出会淹没父代理的上下文。

@dataclass(frozen=True)
class SubagentRuntimeConfig:
    """Tunable runtime limits for subagent instances."""

    max_subagents: int = 10
    max_concurrent_running: int = 5
    turn_timeout_s: float = TURN_TIMEOUT_S_DEFAULT
    enable_lru_eviction: bool = True
    enable_activity_stream: bool = True
    activity_queue_size: int = 256
    activity_text_max_len: int = 2000
    activity_throttle_ms: float = 500.0
    enable_transcript_stream: bool = True
openjiuwen/harness/subagent_runtime/config.py:15-27@ fd6c47854201
Codex带代码

独立线程 + 从父配置派生的角色覆盖

子代理是一个独立的 ThreadId,由 AgentControl 操作管理,并有 spawn 深度上限防止无限派生。隔离的粒度是「角色」:AgentRoleOverrides 在父配置的基础上覆盖 developer instructions、模型、推理强度、人格、特性开关与 skills 配置。注意源码措辞是 parent-derived configuration——子代理默认继承父的一切,只覆盖显式声明的部分。

/// The role name used when a caller omits `agent_type`.
pub const DEFAULT_ROLE_NAME: &str = "default";

#[derive(Default, Serialize)]
struct AgentRoleOverrides {
    developer_instructions: Option<String>,
    model: Option<String>,
    model_reasoning_effort: Option<ReasoningEffort>,
    model_reasoning_summary: Option<ReasoningSummary>,
    model_verbosity: Option<Verbosity>,
    personality: Option<Personality>,
    service_tier: Option<String>,
    features: BTreeMap<String, bool>,
    skills: Option<SkillsConfig>,
}

/// Applies typed role overrides to the existing parent-derived configuration.
codex-rs/core/src/agent/role.rs:32-50@ 4beea50e26dd

子代理是可插拔 provider —— 包括别家的 Harness

把「子代理怎么跑」也做成了插件族:fork(用父会话已完成的轮次播种的进程内子代理)、spawn(干净的进程内子代理)、acp、dsh-sdk,以及最值得注意的两个——subagent-claude-code 和 subagent-codex。前者调用官方 Claude Agent SDK,后者用 app-server --stdio 起一个临时 Codex 线程,两者都在委派会话的工作区里执行,并通过共享的结果契约返回。四家里唯一把竞品 Harness 当作可挂载能力的实现。

packages/subagent/
├── subagent/                    # 共享结果契约
├── subagent-fork-in-process/    # 用父会话已完成轮次播种的进程内子代理
├── subagent-spawn-in-process/   # 干净的进程内子代理
├── subagent-in-process-driver/
├── subagent-acp/                # ACP 协议子代理
├── subagent-dsh-sdk/
├── subagent-claude-code/        # ← 调用官方 Claude Agent SDK
├── subagent-codex/              # ← app-server --stdio 起临时 Codex 线程
├── tool-subagent/               # 暴露给模型的委派工具
├── tool-subagent-control/
└── tool-subagent-report/

# subagent-fork-in-process/README.md:
# "The fork provider creates an in-process child seeded with the parent's
#  completed conversation turns. It shares all run mechanics with spawn;
#  the session seed is the only behavioral difference."
packages/subagent@ b150a551b8d4
Pi带代码

内核不提供,示例扩展用独立进程实现

全仓检索 subagent 只命中 CHANGELOG、测试与 examples/extensions/subagent/ —— 内核没有子代理概念。示例扩展给出的方案反而是四家里隔离最彻底的:每个子代理是一个独立的 pi 进程,上下文窗口天然隔离,Ctrl+C 会传播下去杀掉子进程。这与它的沙箱选择完全同构:内核保持最小,隔离交给操作系统的进程边界。

# packages/coding-agent/examples/extensions/subagent/README.md

# Subagent Example

Delegate tasks to specialized subagents with isolated context windows.

## Features

- **Isolated context**: Each subagent runs in a separate `pi` process
- **Streaming output**: See tool calls and progress as they happen
- **Parallel streaming**: All parallel tasks stream updates simultaneously
- **Usage tracking**: Shows turns, tokens, cost, and context usage per agent
- **Abort support**: Ctrl+C propagates to kill subagent processes
packages/coding-agent/examples/extensions/subagent/README.md:1-12@ bfb004d4418f

design space / 设计空间分析

四家把「子代理是什么」映射到了四种不同的隔离对象——受限资源、覆盖角色、可插拔执行后端、操作系统进程边界——而 openJiuwen 和 codex 这两格目前带着未回填的上游变动信号,正文里的机制描述只锁定在各自审计 commit 上。

openJiuwen 把子代理当作需要限量调度的资源:harness/subagent_runtime/ 是一个完整运行时模块,注册表、会话管理、实例、状态与状态事件、活动流、转录流、持久化、输出文件各成一个文件;SubagentRuntimeConfig 直接设了硬限额——max_subagents 10、max_concurrent_running 5、turn_timeout_s、enable_lru_eviction;活动流还带节流(activity_throttle_ms)和文本截断(activity_text_max_len),因为子代理输出会淹没父代理的上下文。

codex 把隔离粒度落在「角色」上:子代理是一个独立 ThreadId,由 AgentControl 管理,并有 spawn 深度上限防止无限派生;AgentRoleOverrides 在父配置基础上覆盖 developer_instructions、model、model_reasoning_effort、model_reasoning_summary、model_verbosity、personality、service_tier、features、skills——源码措辞是 parent-derived configuration,子代理默认继承父的一切,只覆盖显式声明的部分。

deepseek harness 把「子代理怎么跑」本身做成了可插拔的 provider 族:packages/subagent/ 下有 subagent-fork-in-process(用父会话已完成轮次播种的进程内子代理,README 写明它与 spawn 共享全部运行机制,会话种子是唯一行为差异)、subagent-spawn-in-process(干净的进程内子代理)、subagent-acp、subagent-dsh-sdk,以及 subagent-claude-code(调用官方 Claude Agent SDK)和 subagent-codex(用 app-server --stdio 起一个临时 Codex 线程)——两者都在委派会话的工作区里执行,通过共享结果契约返回。格子指出这是四家里唯一把竞品 Harness 当作可挂载能力的实现。

pi 的内核没有子代理概念,全仓检索只命中 CHANGELOG、测试与示例扩展;examples/extensions/subagent/README 描述的方案是把每个子代理起成独立的 pi 进程,上下文窗口靠进程边界天然隔离,Ctrl+C 会传播下去杀掉子进程——格子把这称为四家里隔离最彻底的方案,与它在沙箱维度上「内核最小、隔离靠操作系统」的选择同构。

另有两条来自周报的记录值得放在一起看:2026-W34 记录 openJiuwen 新增了 subagent_spawn / wait / list / send_input / close / resume 六个工具,子代理从「派出去等结果」变成「派出去还能持续交互」;同一周报也记录 codex 有一条修复「在子代理 fork 时保留 developer instruction 标注」,直接触及上面 AgentRoleOverrides.developer_instructions 的继承语义。以上关于 openJiuwen 和 codex 的机制描述锁定在各自审计 commit 上,不是对上游当前状态的断言。

编辑判断

四种隔离对象——资源、角色、可插拔后端、进程边界——对应四种不同的「子代理该是什么」的默认假设:openJiuwen 把子代理当作要限量调度和防止拖垮父上下文的资源,codex 当作带覆盖规则的角色分身,deepseek harness 当作可以换成任意执行后端(甚至别家 harness)的插槽,pi 让操作系统的进程模型承担全部隔离工作、框架本身不建模。这段是本站的编辑推断,不是各项目的官方表述。

尚未收敛:openJiuwen 新增的子代理持续交互工具(spawn/wait/list/send_input/close/resume)和 codex 对 developer instruction 继承语义的修复,具体如何改变上面描述的资源限额模型与角色覆盖模型,本站还没有对照新 commit 重新走读源码,暂不下结论;四种隔离对象在跨会话状态泄漏、子代理崩溃恢复等场景下的实际差距,本站也没有一手测试数据。

back to course / 回到课程

矩阵展示的是「各家怎么做」。这个问题本身为什么存在、有哪些经典权衡,在课程里讲:

7

多 Agent 协作

受限子代理、消息总线与验证者:编排多个循环