docs(agent-notes): replace product provider proposal
This commit is contained in:
11 files changed
+193
-159
No files matched your search
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md
|
||||
2026-06-21-subagent-capability-seam.md: 043092884731c403a11b71ef8b5a410e9e5af7e0
|
||||
2026-06-21-subagent-capability-seam.zh.md: 6a4a5798199ca7d6d7c011668a319d65a0553208
|
||||
2026-06-21-subagent-capability-seam.md: fd22b883572e5304c1587c818026c36235ef504d
|
||||
2026-06-21-subagent-capability-seam.zh.md: fcfdf3e9c1eb35d7c372aa4311ebf8da192b56a7
|
||||
@@ -14,7 +14,8 @@ The distinctive requirement — the one that shapes the whole design — is that
|
||||
|
||||
- **in-process** — a child concrete `Agent` on the same `Context` (the cheapest, and nearly free given the existing agent factory);
|
||||
- **ACP** — act as an ACP *client* driving another agent process (which can be another instance of ourselves);
|
||||
- later: **A2A**, the **Codex app-server**, and the **Claude Code Agent SDK** — each the same out-of-process "start a child, prompt it, stream updates, cancel" shape as the ACP backend.
|
||||
- **Codex app-server** — a current one-shot sibling that applies the same named-provider seam to the official product process ([product-provider Agent Note](../../proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.md));
|
||||
- later: **A2A** and the **Claude Code Agent SDK** — the same out-of-process "start a child, prompt it, settle, cancel" shape; the Claude sibling remains in the product-provider proposal.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ harness 有一个长期搁置的 seam 用于 **subagent**:一个 agent(智
|
||||
|
||||
- **进程内**:在同一个 `Context` 上创建一个具体的子 `Agent`(最廉价,且鉴于现有 agent 工厂几乎零成本);
|
||||
- **ACP**:作为 ACP *客户端*驱动另一个 agent 进程(可以是自身的另一个实例);
|
||||
- 后续:**A2A**、**Codex app-server** 与 **Claude Code Agent SDK**——每种都与 ACP 后端相同的进程外形状:「启动子 agent、发送提示词、流式接收更新、取消」。
|
||||
- **Codex app-server**:当前的一次性兄弟提供方,将同一个命名提供方 seam 应用于官方产品进程([产品提供方 Agent Note](../../proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.md));
|
||||
- 后续:**A2A** 与 **Claude Code Agent SDK**——两者采用同样的进程外形态:「启动子 agent、发送提示词、结算、取消」;Claude 兄弟提供方仍在产品提供方提案中。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-06-22-acp-subagent-backend.md
|
||||
2026-06-22-acp-subagent-backend.md: 5f12aa1c08d4f4cfaa35f2f7f4b09ad341c3eae8
|
||||
2026-06-22-acp-subagent-backend.zh.md: 61359246b0c552f6126cd82ae843d489de809a38
|
||||
2026-06-22-acp-subagent-backend.md: ea0ec821b1f7a55d173f58c5bc4ba8829ef65c54
|
||||
2026-06-22-acp-subagent-backend.zh.md: 32e83a7a4e89eb7adb17220dc66952bca0a165aa
|
||||
@@ -59,4 +59,4 @@ Every run pays a fresh subprocess (spawn + `initialize` + `newSession`). The par
|
||||
|
||||
## Future providers
|
||||
|
||||
The same out-of-process spawn/prompt/stream/cancel shape generalizes to other transports named in the seam Agent Note — A2A, the Codex app-server, and the Claude Code Agent SDK — each a sibling provider registered by name. The ACP backend is the proof that the seam supports the boundary; those are mechanically similar.
|
||||
The [Codex app-server provider](../../proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.md) now applies the same out-of-process spawn/prompt/settle/cancel boundary as a sibling registered by name. A2A and the Claude Code Agent SDK remain future sibling transports; the ACP backend proves that the common seam supports the boundary without owning their private protocols.
|
||||
@@ -59,4 +59,4 @@ ACP `StopReason` → harness `SubagentStopReason`:`end_turn`→`completed`、`
|
||||
|
||||
## 后续提供方
|
||||
|
||||
同样的进程外启动/提示词/流式输出/取消形态可泛化到 seam Agent Note 中列出的其他传输方式——A2A、Codex app-server 和 Claude Code Agent SDK——每个都是按名称注册的兄弟提供方。ACP 后端证明了 seam 支持跨进程边界;其余在机制上类似。
|
||||
[Codex app-server 提供方](../../proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.md)已将同样的进程外启动/提示词/结算/取消边界应用于按名称注册的兄弟提供方。A2A 与 Claude Code Agent SDK 仍是未来的兄弟传输方式;ACP 后端证明了通用 seam 能够支持该边界,而无需负责它们的私有协议。
|
||||
@@ -1,74 +0,0 @@
|
||||
# Agent Note: Claude Code and Codex subagent providers
|
||||
|
||||
Status: proposed
|
||||
|
||||
English | [中文](2026-07-07-claude-code-and-codex-subagent-backends.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
The named [`ctx.subagents`](../../implemented/feature/2026-06-21-subagent-capability-seam.md) registry lets a parent agent delegate work without knowing how the child runs, but the harness needs first-party routes to the real Codex and Claude Code products. A useful first version must hand either product one self-contained task, use the parent Session's workspace, return a final answer or explicit failure, and leave no managed product process behind.
|
||||
|
||||
Product integration must not create a second owner for task text, cwd, cancellation, result settlement, or process trees. It must also prove the real product path in required keyless tests: a fake wrapper or direct model HTTP request cannot establish that the Loader, provider registration, official product protocol, authentication, final answer, and teardown compose correctly.
|
||||
|
||||
## Proposal
|
||||
|
||||
Two sibling one-shot providers register fixed deployment names and are exposed through two fixed `dsh-tool-subagent` instances:
|
||||
|
||||
- `@deepseek-ai/dsh-subagent-codex` registers `codex`, driven through `codex app-server --stdio`, and is implemented.
|
||||
- `@deepseek-ai/dsh-subagent-claude-code` will register `claude-code`, driven through the official Claude Agent SDK and its bundled CLI, and remains pending.
|
||||
|
||||
The model-facing tools are `subagent_codex` and `subagent_claude_code`. Each tool binds one provider at deployment time, accepts a standalone task, and omits the background parameter in the initial compositions. Product selection is not another model argument.
|
||||
|
||||
Both providers report `inheritsParentContext: false`, advertise no optional start capabilities, and use the parent Session cwd without copying the parent conversation. Every call creates a fresh product process and one non-resumable product conversation. The shared subagent service continues to own request resolution, lifecycle events, result settlement, and foreground disposal; the shared subprocess service owns environment scrubbing, process-tree termination, and whole-tree exit observation.
|
||||
|
||||
## Codex provider
|
||||
|
||||
The Codex provider has fixed name `codex` and fixed command `codex app-server --stdio`. Its public configuration contains only explicit `env` entries and a positive finite `disposeGraceMs`; it does not expose command, cwd, model, base URL, API key, sandbox, approval, product home, or session settings. Production resolves Codex from `PATH` and uses the host's native Codex configuration and authentication. Credential-shaped ambient variables are scrubbed by `dsh-subprocess`, while explicit `env` values merge afterward.
|
||||
|
||||
Before publication, the provider validates a non-empty text-only task, starts the managed app-server, performs `initialize` → `initialized`, and creates an `ephemeral: true` thread in the parent workspace. The returned run owns exactly one `turn/start`; product thread and turn ids stay private and are not persisted in the parent Session.
|
||||
|
||||
`turn/completed` is the authoritative remote terminal fact. The latest nonblank `agentMessage` with `phase: "final_answer"` wins, with the latest nullable-phase message as the compatibility fallback; commentary never replaces an answer. A completed turn without an answer, a failed or interrupted remote turn, malformed payload, protocol closure, early process exit, or unknown server request becomes a shared `error`. Local cancellation wins the race and remains `aborted`.
|
||||
|
||||
The unattended wire declines command and file approvals, grants no requested permissions for the turn, and declines MCP elicitation. It fails closed for every other server request instead of waiting for UI that this provider does not supply.
|
||||
|
||||
Publication transfers the wire and process handle to one holder. Idempotent disposal best-effort interrupts a known turn, closes the wire, ends stdin, invokes the shared termination escalation, and waits for whole-tree exit. An unpublished startup failure performs the same cleanup before `start()` rejects.
|
||||
|
||||
## Claude Code provider
|
||||
|
||||
The Claude Code sibling follows the same fixed-name, self-contained, one-shot, parent-cwd, shared-result, and managed-tree boundaries. Its product-specific implementation will use the official Agent SDK's `query()` and spawn hook, keep SDK protocol ownership separate from `dsh-subprocess` process-tree ownership, omit human-interaction callbacks, and derive only a strict final SDK result after the message iterator ends normally.
|
||||
|
||||
The Claude package will expose the same two configuration concerns, `env` and `disposeGraceMs`. Product installation, native settings, and login remain deployment responsibilities rather than plugin-managed state. This note stays proposed until that sibling and the combined two-product evidence are implemented.
|
||||
|
||||
## Evidence contract
|
||||
|
||||
Each product owns package-level branch-complete tests, a required real-product spec, and a real Loader snapshot. The real-product tier must use the exact official distribution under test, a non-empty fake product key, an isolated temporary workspace and product configuration, and a loopback fixed-answer model; it fails rather than skips when the binary, authentication request, task, answer, cancellation, or process-exit proof is missing.
|
||||
|
||||
The Codex evidence pins `@openai/codex@0.146.0` / `codex-cli 0.146.0`. Its real-product spec observes the exact Bearer key, original task, byte-exact final answer, unattended command rejection with no file side effect, local cancellation, and every managed handle reaching whole-tree quiescence. Its Loader snapshot fixes the no-background tool schema, exact tool call and result, full persisted parent Session, product request, and pre-teardown quiescence. The npm package is a development dependency for reproducible evidence; production still uses `codex` from `PATH`.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**Direct model HTTP or `codex exec`.** These paths bypass the products' official extensible process protocols and cannot prove product configuration, tools, approvals, lifecycle, or teardown. The providers use app-server and the official Agent SDK instead.
|
||||
|
||||
**A shared product-process helper package.** The existing subagent and subprocess seams already own every shared task, result, environment, and process-tree concern. A new helper would duplicate ownership before two production consumers demonstrated a missing common contract, so product-specific adapters call the existing seams directly.
|
||||
|
||||
**A model-visible product selector.** Product availability and authentication are deployment facts. Two fixed tools keep each schema and provider binding explicit and avoid adding dynamic selection state to the common service.
|
||||
|
||||
**Product doubles as required evidence.** Doubles are useful for exhaustive private protocol branches but do not prove package exports, official binaries, authentication, or real process behavior. Required evidence drives the official product against loopback model fixtures.
|
||||
|
||||
**Plugin-managed login, product home, models, or permissions.** Those settings would create another authority beside each product's native configuration and enlarge a one-shot provider into account management. The providers expose only explicit environment overlay and teardown grace; unattended interaction fails closed.
|
||||
|
||||
**Continuation, progress, and shared parent context.** The first user result needs one self-contained task and one final answer. Product sessions, resume, follow-up, intermediate messages, parent transcript transfer, structured output, and background collection need separate user contracts and are not prebuilt.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
The proposal is complete when both fixed tools reach their corresponding real products through the Loader, return exact final answers or explicit failure/cancellation, persist the complete model-visible parent transcript, and prove managed process-tree quiescence in required keyless CI. Both packages have complete configuration, lifecycle, failure, model-experience, and limitation documentation; the generated package, configuration, capability, dependency, and third-party records agree with the shipped manifests.
|
||||
|
||||
The implemented Codex half already satisfies this contract for its fixed tool and 0.146.0 product baseline. The note remains proposed because the Claude Code sibling and combined final evidence are not yet implemented.
|
||||
|
||||
## Risks
|
||||
|
||||
- The Codex app-server protocol is product-versioned and may change; production performs no runtime version probe, so every supported baseline change must refresh schema investigation and real-product compatibility evidence.
|
||||
- Product-native configuration makes behavior depend on the deployment's installed product and account state. Required tests isolate those inputs, while production deliberately leaves them under the product's own authority.
|
||||
- Every delegation pays for a fresh process and independent model context, and only final text reaches the parent.
|
||||
- Product tool or file side effects are not rolled back when a run fails or is cancelled.
|
||||
- Unattended approval denial keeps the initial provider safe from interactive hangs but cannot satisfy tasks that require new permission.
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
# Agent Note: Claude Code 与 Codex subagent 提供方
|
||||
|
||||
Status: proposed
|
||||
|
||||
[English](2026-07-07-claude-code-and-codex-subagent-backends.md) | 中文
|
||||
|
||||
## 问题
|
||||
|
||||
命名的 [`ctx.subagents`](../../implemented/feature/2026-06-21-subagent-capability-seam.md) 注册表让父 agent(智能体)无需了解子 agent 的运行方式即可委派工作,但 harness 需要接入真实 Codex 与 Claude Code 产品的第一方路径。一个实用的首版必须能把一个自包含任务交给任一产品,使用父会话的工作区,返回最终答案或明确失败,并且不留下任何受管产品进程。
|
||||
|
||||
产品集成不得让任务文本、工作目录、取消、结果结算或进程树出现第二个所有者。它还必须在强制无密钥测试中证明真实产品链路:假包装层或直接向模型发起的 HTTP 请求无法证明 Loader、提供方注册、官方产品协议、认证、最终答案和清理能够正确组合运行。
|
||||
|
||||
## 提案
|
||||
|
||||
两个同级的单次执行提供方注册固定部署名称,并通过两个固定的 `dsh-tool-subagent` 实例对外提供:
|
||||
|
||||
- `@deepseek-ai/dsh-subagent-codex` 注册 `codex`,由 `codex app-server --stdio` 驱动,现已实现。
|
||||
- `@deepseek-ai/dsh-subagent-claude-code` 将注册 `claude-code`,由官方 Claude Agent SDK 及其捆绑的 CLI(命令行界面)驱动,目前仍待实现。
|
||||
|
||||
面向模型的工具为 `subagent_codex` 和 `subagent_claude_code`。每个工具在部署时绑定一个提供方,接受一个独立任务,并在初始组合中省略后台参数。产品选择不作为额外的模型参数。
|
||||
|
||||
两个提供方均报告 `inheritsParentContext: false`,不声明任何可选启动能力,并使用父会话的工作目录而不复制父会话对话。每次调用都会创建一个全新的产品进程和一次不可恢复的产品对话。共享 subagent 服务继续负责请求解析、生命周期事件、结果结算和前台 dispose(资源释放);共享子进程服务负责环境清洗、进程树终止和整棵进程树的退出观测。
|
||||
|
||||
## Codex 提供方
|
||||
|
||||
Codex 提供方的固定名称为 `codex`,固定命令为 `codex app-server --stdio`。其公开配置只包含显式 `env` 条目和取正有限值的 `disposeGraceMs`;不公开命令、工作目录、模型、基础 URL、API 密钥、沙箱、审批、产品主目录或会话设置。生产环境从 `PATH` 解析 Codex,并使用宿主机原生的 Codex 配置和认证。`dsh-subprocess` 会清洗环境中形似凭证的变量,之后再合并显式 `env` 值。
|
||||
|
||||
在发布运行实例前,提供方会验证任务非空且仅含文本,启动受管 app-server,依次执行 `initialize` → `initialized`,并在父工作区中创建一个 `ephemeral: true` 线程。返回的运行实例只负责一次 `turn/start`;产品线程 ID 和轮次 ID 始终为私有信息,不会持久化到父会话中。
|
||||
|
||||
`turn/completed` 是判定远端终止状态的权威依据。最新一条内容非空且带有 `phase: "final_answer"` 的 `agentMessage` 优先;阶段字段可为空值的最新消息作为兼容回退。过程说明绝不取代答案。已完成但无答案的轮次、失败或中断的远端轮次、格式错误的载荷、协议关闭、进程提前退出或未知服务端请求,都会结算为共享的 `error`。本地取消会在竞态中胜出,结果仍为 `aborted`。
|
||||
|
||||
无人值守通信层会拒绝命令审批和文件审批,对于该轮次请求的权限一概不予授予,并拒绝 MCP elicitation。对于其他所有服务端请求,它都会以失败响应,而不会等待本提供方并未提供的 UI。
|
||||
|
||||
发布时,协议连接和进程句柄会移交给唯一持有者。幂等 dispose 会尽力中断已知轮次、关闭协议连接、结束 stdin、调用共享的逐级终止流程,并等待整棵进程树退出。若启动在发布前失败,`start()` 会先执行同样的清理,再以拒绝结束。
|
||||
|
||||
## Claude Code 提供方
|
||||
|
||||
Claude Code 同级提供方沿用相同边界:名称固定、任务自包含、仅执行一次、使用父级工作目录、结果由共享服务结算,且进程树受管。其产品专用实现将使用官方 Agent SDK 的 `query()` 与 spawn 钩子,将 SDK 协议所有权同 `dsh-subprocess` 的进程树所有权分开,不设置人机交互回调,并且仅在消息迭代器正常结束后提取严格的最终 SDK 结果。
|
||||
|
||||
Claude 包将公开相同的两个配置项:`env` 和 `disposeGraceMs`。产品安装、原生设置和登录仍由部署方负责,插件不管理这些内容。在该同级提供方及两种产品的组合证据实现之前,本文仍处于 proposed 状态。
|
||||
|
||||
## 证据契约
|
||||
|
||||
每个产品都有包(package)级分支完备测试、一项必需的真实产品规格测试,以及一份真实 Loader 快照。真实产品层必须使用受测的确切官方发行包、非空的假产品密钥、隔离的临时工作区与产品配置,以及固定答案的环回模型;如果缺少二进制文件、认证请求、任务、答案、取消或进程退出证明中的任一项,该层必须失败而非跳过。
|
||||
|
||||
Codex 证据固定使用 `@openai/codex@0.146.0` / `codex-cli 0.146.0`。其真实产品规格测试会观测确切的 Bearer 密钥、原始任务、字节完全一致的最终答案、无人值守下命令被拒绝且不产生文件副作用、本地取消,以及每个受管句柄对应的整棵进程树均达到完全停稳。其 Loader 快照固定记录不含后台参数的工具 schema、确切的工具调用与工具结果、完整持久化的父会话、产品请求,以及清理前的完全停稳状态。该 npm 包是用于提供可复现证据的开发依赖;生产环境仍使用 `PATH` 中的 `codex`。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
**直接向模型发起 HTTP 请求或 `codex exec`。** 这些路径会绕过产品官方的可扩展进程协议,无法证明产品配置、工具、审批、生命周期或清理。提供方改用 app-server 和官方 Agent SDK。
|
||||
|
||||
**共享产品进程辅助包。** 现有 subagent seam 和子进程 seam 已经负责所有共享任务、结果、环境和进程树关注点。在两个生产消费方证明通用契约确有缺口之前,新辅助包会造成所有权重复,因此产品专用适配器直接调用现有 seam。
|
||||
|
||||
**面向模型的产品选择器。** 产品可用性与认证属于部署事实。两个固定工具让各自的 schema 和提供方绑定保持显式,并避免向通用服务加入动态选择状态。
|
||||
|
||||
**将产品替身作为必需证据。** 替身适合完整覆盖私有协议分支,但无法证明包导出、官方二进制文件、认证或真实进程行为。必需证据使用环回模型 fixture(测试前置数据)驱动官方产品。
|
||||
|
||||
**由插件管理登录、产品主目录、模型或权限。** 这些设置会在每个产品的原生配置之外另立一个管理权威,并把单次执行提供方变成账户管理功能。提供方只公开显式环境叠加和清理宽限期;无人值守交互一律以失败响应。
|
||||
|
||||
**续接、进度与共享父级上下文。** 首版面向用户的功能只需接收一个自包含任务,并返回一个最终答案。产品会话、恢复、后续请求、中间消息、父级 transcript(文本记录)传递、结构化输出和后台收集各自需要独立的用户契约,本提案不会预先构建这些内容。
|
||||
|
||||
## 验收标准
|
||||
|
||||
当两个固定工具都能通过 Loader 接入各自的真实产品,返回精确的最终答案或明确的失败或取消结果,持久化完整的模型可见父级 transcript,并在强制无密钥 CI 中证明受管进程树完全停稳时,本提案即告完成。两个包都具备覆盖配置、生命周期、失败、模型体验与限制的完整文档;生成的包记录、配置记录、能力记录、依赖记录和第三方记录均与已发布的 manifest(元数据清单)一致。
|
||||
|
||||
已实现的 Codex 部分已经针对其固定工具和 0.146.0 产品基线满足此契约。本文仍处于 proposed 状态,因为 Claude Code 同级提供方和两种产品的最终组合证据尚未实现。
|
||||
|
||||
## 风险
|
||||
|
||||
- Codex app-server 协议随产品版本演进,可能发生变化;生产环境不执行运行时版本探测,因此每次变更受支持的基线时,都必须重新开展 schema 调查并更新真实产品兼容性证据。
|
||||
- 产品原生配置使行为取决于部署环境中安装的产品及其账户状态。强制测试会隔离这些输入,而生产环境则刻意让这些输入继续由产品自身掌控。
|
||||
- 每次委派都要承担启动全新进程和使用独立模型上下文的成本,而且只有最终文本会传回父 agent。
|
||||
- 运行失败或被取消时,产品工具或文件副作用不会回滚。
|
||||
- 无人值守模式下拒绝审批可防止初始提供方因交互而挂起,但无法满足需要新权限的任务。
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/proposed/feature/2026-07-07-claude-code-and-codex-subagent-backends.md
|
||||
2026-07-07-claude-code-and-codex-subagent-backends.md: 86a2e3489a84408e24c6c8091bc52b747b9069b9
|
||||
2026-07-07-claude-code-and-codex-subagent-backends.zh.md: ef2098b3afe3e5602ed93de1984c91a5c4c1e79e
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.md
|
||||
2026-08-04-claude-code-and-codex-subagent-backends.md: f8f9e10231874b6f97eba98594c952a86efd6901
|
||||
2026-08-04-claude-code-and-codex-subagent-backends.zh.md: 60437a1bc6d8d3c3c9677b4a466ce6a7122fa4fc
|
||||
@@ -0,0 +1,90 @@
|
||||
# Agent Note: Claude Code and Codex subagent backends
|
||||
|
||||
Status: proposed
|
||||
|
||||
English | [中文](2026-08-04-claude-code-and-codex-subagent-backends.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
The named [`ctx.subagents`](../../implemented/feature/2026-06-21-subagent-capability-seam.md) registry lets a parent agent delegate work without knowing how the child runs, but the harness needs first-party routes to the real Codex and Claude Code products. A useful first version must hand either product one self-contained task, let it work in the parent Session's workspace, return a final answer or an explicit failure or cancellation, and leave no managed product process behind.
|
||||
|
||||
The product integrations must not become second owners for task text, cwd, cancellation, result settlement, or process trees. They must also prove the real assembled path in required keyless tests. A direct model HTTP request, product double, or hand-mounted plugin cannot show that the Loader, fixed tool, provider registration, official product protocol, native authentication shape, final answer, and teardown work together.
|
||||
|
||||
## Proposal
|
||||
|
||||
The harness provides two sibling one-shot providers behind two fixed model-facing tools. `subagent_codex` selects the `codex` provider, and `subagent_claude_code` selects the `claude-code` provider. Each tool accepts only a standalone text task and binds its provider at deployment time; product selection and background execution are not model arguments.
|
||||
|
||||
The Codex provider is implemented against Codex 0.146.0. The Claude Code provider remains part of this proposal and will use Claude Agent SDK 0.3.220 with its bundled Claude Code 2.1.220 CLI. This Note remains proposed until both siblings and their combined evidence are present.
|
||||
|
||||
Both providers report `inheritsParentContext: false`, advertise no optional start capabilities, and pass the parent Session cwd without copying the parent conversation. Every call creates a fresh product process and a non-resumable product conversation. The shared subagent service continues to own request resolution, lifecycle events, result settlement, and foreground collection; the shared subprocess service owns credential scrubbing, process-tree termination, and whole-tree exit observation.
|
||||
|
||||
```text
|
||||
fixed tool → shared subagent service → product provider → official product process
|
||||
← final answer / explicit error / cancellation ← terminal product fact
|
||||
→ foreground disposal → shared process-tree termination → whole-tree exit
|
||||
```
|
||||
|
||||
### Ownership and lifecycle
|
||||
|
||||
| Phase | Shared owner | Product-specific responsibility | Observable result |
|
||||
| --- | --- | --- | --- |
|
||||
| Resolve | `dsh-tool-subagent` and `ctx.subagents` | Validate the product's text-only input and derive native startup parameters | Unsupported context or malformed input fails before a run is published |
|
||||
| Start | `dsh-subprocess` owns every acquired process tree | Reach the smallest native point at which the product conversation and process can both be controlled | `start()` publishes one existing `SubagentRun`, or cleans up and rejects |
|
||||
| Run | The product owns its native protocol facts; the holder owns their mapping | Submit exactly one task and derive one shared `completed`, `error`, or `aborted` result | The parent receives only a final answer or an explicit failure |
|
||||
| Dispose | The foreground consumer requests release; `dsh-subprocess` proves exit | Close the native protocol and express any best-effort native cancellation | Disposal is idempotent and returns only after the whole process tree exits |
|
||||
|
||||
## Codex provider
|
||||
|
||||
`@deepseek-ai/dsh-subagent-codex` registers the fixed `codex` provider and always starts `codex app-server --stdio` from `PATH`. Its public configuration contains only an explicit `env` overlay and a positive finite `disposeGraceMs`. Installation, login, `CODEX_HOME`, model selection, base URL, sandbox, approval policy, and product-session settings remain native Codex or deployment responsibilities.
|
||||
|
||||
Before publication, the provider validates a non-empty text-only task, starts the managed app-server in the parent workspace, completes `initialize` → `initialized`, and creates an `ephemeral: true` thread. The published run owns exactly one `turn/start`; its thread and turn ids remain private and are never persisted in the parent Session.
|
||||
|
||||
`turn/completed` is the authoritative remote terminal fact. The latest nonblank `agentMessage` with `phase: "final_answer"` wins. When the product emits no explicit final phase, the latest message with `phase: null` is the compatibility fallback; commentary never replaces either answer. A completed turn without an answer, a failed or interrupted remote turn, malformed wire data, protocol closure, early process exit, or unknown server request becomes `error`. Local cancellation wins its race and remains `aborted`.
|
||||
|
||||
The unattended wire declines command and file approvals, grants no requested permissions for the turn, and declines MCP elicitation. Any other server request fails the run instead of waiting for a user interface the provider does not supply.
|
||||
|
||||
An unpublished startup failure closes the wire, terminates the acquired process tree, waits for exit, and then rejects `start()`. Published disposal best-effort interrupts a known turn, closes the wire, ends stdin, invokes the shared termination escalation, and waits for whole-tree exit. Result failure and teardown failure stay independently observable.
|
||||
|
||||
## Claude Code provider
|
||||
|
||||
The Claude Code sibling follows the same fixed-name, standalone-task, parent-cwd, shared-result, and managed-tree boundaries. It will call the official Agent SDK's `query()` and use its `spawnClaudeCodeProcess` hook to pass the SDK-provided command, arguments, cwd, environment, and forwarded signal into `dsh-subprocess` without rewriting them.
|
||||
|
||||
The SDK will continue to own the Claude protocol and graceful `Query.close()` intent, while `dsh-subprocess` owns the actual CLI process tree and exit proof. Publication waits until both the SDK query and real CLI handle are controllable. A strict successful `SDKResultMessage` becomes `completed` only after asynchronous iteration ends normally; local cancellation becomes `aborted`, and every other result, iterator failure, protocol failure, or process failure becomes `error`.
|
||||
|
||||
The package will expose the same two configuration concerns, `env` and `disposeGraceMs`. It will keep native settings and login under Claude Code's authority, disable unattended `AskUserQuestion`, omit interactive callbacks, and create no plugin-owned product session or account state.
|
||||
|
||||
## Evidence contract
|
||||
|
||||
Each product owns branch-complete package tests, a required real-product spec, and a real Loader snapshot. The real-product tier uses the exact official distribution under test, a non-empty fake product key, an isolated temporary workspace and product home, and a loopback fixed-answer model. Missing product requests, wrong authentication, altered task text, a non-exact answer, a skipped real product, or a surviving managed handle fails the required test.
|
||||
|
||||
The Codex evidence pins `@openai/codex@0.146.0` and `codex-cli 0.146.0`. Its real-product spec observes the exact Bearer key, original task, byte-exact final answer, unattended command rejection with no file side effect, local cancellation, and whole-tree exit. Its Loader snapshot fixes the no-background tool schema, exact tool call and result, complete persisted parent Session, product request, and pre-teardown quiescence. The npm package is a development dependency for reproducible evidence; production still supplies `codex` on `PATH`.
|
||||
|
||||
The combined contract is complete only when the Claude sibling has equivalent real SDK and bundled-CLI evidence and one assembled Loader run proves both fixed tools coexist without changing the common subagent contract.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**Direct model HTTP, `codex exec`, or a hand-written Claude CLI protocol.** These paths bypass the products' official extensible process protocols and cannot prove native configuration, tools, approvals, result semantics, or teardown. The providers use app-server and the official Agent SDK instead.
|
||||
|
||||
**A shared product-process helper package.** The existing subagent and subprocess seams already own every shared task, result, environment, and process-tree concern. A new helper would duplicate ownership before the two products demonstrate a missing common contract, so each private adapter calls the existing seams directly.
|
||||
|
||||
**A model-visible product selector.** Product availability and authentication are deployment facts. Two fixed tools keep each schema and provider binding explicit and avoid adding dynamic selection state to the common service.
|
||||
|
||||
**Product doubles as required evidence.** Doubles are useful for exhaustive private protocol branches but do not prove package exports, official binaries, authentication, or real process behavior. Required evidence drives each official product against a loopback model fixture.
|
||||
|
||||
**Plugin-managed login, product home, models, or permissions.** Those settings would create another authority beside each product's native configuration and enlarge a one-shot provider into account management. The providers expose only an explicit environment overlay and teardown grace; unattended interaction fails closed.
|
||||
|
||||
**Continuation, progress, background collection, and shared parent context.** The first user result needs one self-contained task and one final answer. Product sessions, resume, follow-up, intermediate messages, parent transcript transfer, structured output, and background collection need separate user contracts and are not prebuilt.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
Both fixed tools reach their corresponding real products through the Loader, return exact final answers or explicit failure or cancellation, persist the complete model-visible parent transcript, and prove managed process-tree quiescence in required keyless CI. Both packages document their configuration, lifecycle, failure behavior, model experience, and limitations; generated package, configuration, capability, dependency, and third-party records agree with the shipped manifests.
|
||||
|
||||
The implemented Codex half satisfies this contract for its fixed tool and 0.146.0 baseline. The proposal becomes implemented only after the Claude Code sibling and the combined two-product evidence satisfy the same ownership and lifecycle boundaries.
|
||||
|
||||
## Risks
|
||||
|
||||
- The product protocols are versioned and may change. Production performs no runtime version probe, so every supported baseline change requires refreshed compatibility evidence.
|
||||
- Product-native configuration makes behavior depend on the deployment's installed product and account state. Required tests isolate those inputs, while production deliberately leaves them under the product's authority.
|
||||
- Every delegation pays for a fresh process and independent model context, and only final text reaches the parent.
|
||||
- Product tool or file side effects are not rolled back when a run fails or is cancelled.
|
||||
- Unattended interaction denial prevents hidden approval hangs but cannot satisfy tasks that require new permission or human input.
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
# Agent Note: Claude Code 与 Codex subagent 后端
|
||||
|
||||
Status: proposed
|
||||
|
||||
[English](2026-08-04-claude-code-and-codex-subagent-backends.md) | 中文
|
||||
|
||||
## 问题
|
||||
|
||||
命名的 [`ctx.subagents`](../../implemented/feature/2026-06-21-subagent-capability-seam.md) 注册表让父 agent(智能体)无需了解子级的运行方式即可委派工作,但 harness 需要通往真实 Codex 与 Claude Code 产品的第一方路径。可用的首版必须能向任一产品交付一项自包含任务,让它在父会话的工作区中执行,返回最终回答或明确的失败或取消结果,并且不留下任何受管的产品进程。
|
||||
|
||||
产品集成不得成为任务文本、cwd、取消、结果结算或进程树的第二责任方。它们还必须在强制性的无密钥测试中证明真实组装路径。直接发起模型 HTTP 请求、使用产品替身或手工挂载插件,都无法证明 Loader、固定工具、提供方注册、官方产品协议、原生身份验证形态、最终回答和资源清理能够协同工作。
|
||||
|
||||
## 提案
|
||||
|
||||
harness 在两个固定的面向模型工具背后提供两个一次性兄弟提供方。`subagent_codex` 选择 `codex` 提供方,`subagent_claude_code` 选择 `claude-code` 提供方。每个工具只接受独立文本任务,并在部署时绑定其提供方;产品选择与后台执行都不作为模型参数。
|
||||
|
||||
Codex 提供方基于 Codex 0.146.0 实现。Claude Code 提供方仍属于本提案的一部分,将使用 Claude Agent SDK 0.3.220 及其捆绑的 Claude Code 2.1.220 CLI(命令行界面)。在两个兄弟提供方及其组合证据全部具备之前,本 Agent Note 将保持提案状态。
|
||||
|
||||
这两个提供方都报告 `inheritsParentContext: false`,不声明任何可选的启动时功能,并传递父会话 cwd,但不会复制父级对话。每次调用都会创建一个全新的产品进程和一次不可续接的产品对话。共享 subagent 服务继续负责请求解析、生命周期事件、结果结算和前台收集;共享子进程服务负责凭证清洗、进程树终止以及整棵进程树的退出观测。
|
||||
|
||||
```text
|
||||
fixed tool → shared subagent service → product provider → official product process
|
||||
← final answer / explicit error / cancellation ← terminal product fact
|
||||
→ foreground disposal → shared process-tree termination → whole-tree exit
|
||||
```
|
||||
|
||||
### 归属与生命周期
|
||||
|
||||
| 阶段 | 共享责任方 | 产品特定职责 | 可观察结果 |
|
||||
| --- | --- | --- | --- |
|
||||
| 解析 | `dsh-tool-subagent` 与 `ctx.subagents` | 验证产品的纯文本输入并推导原生启动参数 | 不受支持的上下文或格式错误的输入会在发布运行前报错 |
|
||||
| 启动 | `dsh-subprocess` 负责每棵已获取的进程树 | 到达能够同时控制产品对话与进程的最小原生控制点 | `start()` 发布一个已存在的 `SubagentRun`,否则清理后拒绝调用 |
|
||||
| 运行 | 产品负责其原生协议事实;持有方负责映射这些事实 | 只提交一项任务,并推导一个共享的 `completed`、`error` 或 `aborted` 结果 | 父级只会收到最终回答或明确失败 |
|
||||
| dispose(资源释放) | 前台消费方请求释放;`dsh-subprocess` 证明进程已退出 | 关闭原生协议,并发出尽力而为的原生取消请求 | 释放操作具有幂等性,且仅在整棵进程树退出后才返回 |
|
||||
|
||||
## Codex 提供方
|
||||
|
||||
`@deepseek-ai/dsh-subagent-codex` 注册固定的 `codex` 提供方,并始终启动 `codex app-server --stdio`,该命令从 `PATH` 解析。其公开配置仅包含显式的 `env` 覆盖项和须为正有限值的 `disposeGraceMs`。安装、登录、`CODEX_HOME`、模型选择、基础 URL、沙箱、审批策略和产品会话设置仍由 Codex 原生机制或部署环境负责。
|
||||
|
||||
发布前,提供方会验证非空的纯文本任务,在父级工作区中启动受管的 app-server,完成 `initialize` → `initialized` 握手,并创建一个 `ephemeral: true` 线程。已发布的运行只拥有一次 `turn/start`;其线程 ID 与轮次 ID 保持私有,绝不会持久化到父会话。
|
||||
|
||||
`turn/completed` 是权威的远端终止事实。以最后一条非空白的 `agentMessage` 为准,但它必须带有 `phase: "final_answer"`。若产品没有发出明确的最终阶段,则以最后一条 `phase: null` 的消息作为兼容性回退;过程说明绝不会取代上述任一答案。轮次完成却没有答案、远端轮次失败或中断、协议数据格式错误、协议关闭、进程提前退出或未知的服务器请求,都会产生 `error`。本地取消在竞态中胜出并保持为 `aborted`。
|
||||
|
||||
无人值守的协议连接会拒绝命令与文件审批,不授予该轮次请求的任何权限,并拒绝 MCP elicitation。其他任何服务器请求都会导致此次运行失败,而不会等待本提供方没有提供的用户界面。
|
||||
|
||||
若启动在发布前失败,提供方会关闭协议连接、终止已获取的进程树并等待其退出,然后拒绝 `start()`。对已发布的运行执行释放时,提供方会尽力中断已知轮次、关闭协议连接、结束标准输入、调用共享的进程树逐级终止机制,并等待整棵进程树退出。结果失败与清理失败仍可彼此独立地观察。
|
||||
|
||||
## Claude Code 提供方
|
||||
|
||||
Claude Code 兄弟提供方遵循同样的固定名称、独立任务、父级 cwd、共享结果和受管进程树边界。它将调用官方 Agent SDK 的 `query()`,并使用其 `spawnClaudeCodeProcess` 钩子,将 SDK 提供的命令、参数、cwd、环境和转发的信号原样传入 `dsh-subprocess`。
|
||||
|
||||
SDK 将继续负责 Claude 协议,并通过 `Query.close()` 表达优雅关闭意图;`dsh-subprocess` 则负责实际的 CLI 进程树与退出证明。只有在 SDK query 和真实 CLI 句柄均可控后才会发布运行。只有严格表示成功的 `SDKResultMessage` 才会在异步迭代正常结束后成为 `completed`;本地取消成为 `aborted`,其他任何结果、迭代器失败、协议失败或进程失败都成为 `error`。
|
||||
|
||||
该包会公开相同的两个配置项:`env` 与 `disposeGraceMs`。它会继续让 Claude Code 负责原生设置与登录,禁用无人值守的 `AskUserQuestion`,不提供交互式回调,也不会创建由插件负责的产品会话或账户状态。
|
||||
|
||||
## 证据契约
|
||||
|
||||
每个产品都负责覆盖所有分支的包(package)测试、一项必跑的真实产品测试和一个真实 Loader 快照。真实产品测试层级使用被测的确切官方发行版、非空的伪产品密钥、隔离的临时工作区与产品主目录,以及能返回固定答案的回环模型。产品请求缺失、身份验证错误、任务文本被改动、答案不完全一致、真实产品被跳过或受管句柄仍存活,都会使这项必跑测试失败。
|
||||
|
||||
Codex 证据锁定 `@openai/codex@0.146.0` 与 `codex-cli 0.146.0`。其真实产品测试会观测确切的 Bearer 密钥、原始任务、逐字节完全一致的最终回答、不会产生文件副作用的无人值守命令拒绝、本地取消以及整棵进程树退出。其 Loader 快照锁定不支持后台执行的工具 schema、确切的工具调用与结果、完整的已持久化父会话、产品请求,以及清理前的完全停稳状态。该 NPM 包是用于复现证据的开发依赖;生产环境仍提供 `codex`,并通过 `PATH` 解析。
|
||||
|
||||
只有在 Claude 兄弟提供方具备同等的真实 SDK 与捆绑 CLI 证据,并且一次组装后的 Loader 运行证明两个固定工具可以共存且无需更改通用 subagent 契约时,组合契约才算完整。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
**直接模型 HTTP、`codex exec` 或手写的 Claude CLI 协议。** 这些路径会绕过产品的官方可扩展进程协议,无法证明原生配置、工具、审批、结果语义或资源清理。提供方改为使用 app-server 与官方 Agent SDK。
|
||||
|
||||
**共享产品进程辅助包。** 现有 subagent 与子进程 seam 已负责围绕任务、结果、环境和进程树的全部共享职责。在两个产品尚未证明通用契约存在缺口时,新辅助包只会造成责任重复,因此各自的私有适配器会直接调用现有 seam。
|
||||
|
||||
**面向模型的产品选择器。** 产品可用性和身份验证属于部署事实。两个固定工具使各自的 schema 与提供方绑定保持明确,也避免在通用服务中添加动态选择状态。
|
||||
|
||||
**以产品替身作为强制证据。** 替身有助于穷尽覆盖私有协议分支,但无法证明包导出、官方二进制程序、身份验证或真实进程行为。强制证据会驱动每个官方产品连接回环模型 fixture(测试前置数据)。
|
||||
|
||||
**由插件管理登录、产品主目录、模型或权限。** 这些设置会在每个产品的原生配置之外建立另一套权威来源,并将一次性提供方扩张为账户管理功能。提供方只公开显式环境覆盖项和清理宽限期;无人值守交互会以默认拒绝方式失败。
|
||||
|
||||
**续接、进度、后台收集和共享父级上下文。** 首个用户结果只需要一项自包含任务和一个最终回答。产品会话、恢复、后续交互、中间消息、父级 transcript(文本记录)传递、结构化输出和后台收集都需要独立的用户契约,本提案不会预先构建这些功能。
|
||||
|
||||
## 验收标准
|
||||
|
||||
两个固定工具都通过 Loader 到达相应的真实产品,返回完全一致的最终回答或明确的失败或取消结果,持久化完整的模型可见父级 transcript,并在强制性的无密钥 CI 中证明受管进程树完全停稳。两个包都会记录其配置、生命周期、失败行为、模型体验和限制;生成的包、配置、功能、依赖与第三方记录均与已交付的 manifest(元数据清单)一致。
|
||||
|
||||
已经实现的 Codex 部分为其固定工具和 0.146.0 基线满足了本契约。只有在 Claude Code 兄弟提供方及两种产品的组合证据满足相同的归属与生命周期边界后,本提案才会进入 implemented 状态。
|
||||
|
||||
## 风险
|
||||
|
||||
- 产品协议受版本约束,且可能发生变化。生产环境不会执行运行时版本探测,因此每次更改受支持的基线都必须刷新兼容性证据。
|
||||
- 产品原生配置使行为取决于部署环境中安装的产品与账户状态。强制测试会隔离这些输入,而生产环境会有意让产品继续负责它们。
|
||||
- 每次委派都要承担新建进程和独立模型上下文的开销,且只有最终文本会到达父级。
|
||||
- 运行失败或被取消时,产品工具或文件产生的副作用不会回滚。
|
||||
- 拒绝无人值守交互可以防止审批流程暗中挂起,但无法完成需要新权限或人工输入的任务。
|
||||
Reference in New Issue
Block a user