deepseek-harness/.agents/notes/implemented/feature/2026-08-18-product-subagent-failure-facts.zh.md
pku-xht 84cbec28e9 Merge remote-tracking branch 'origin/master' into codex/localized-chinese-doc-links
# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.zh.md
#	.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md
#	.agents/notes/implemented/bug-fix/2026-07-29-pnpm-setup-runner-isolation.i18n.yaml
#	.agents/notes/implemented/bug-fix/2026-07-29-pnpm-setup-runner-isolation.zh.md
#	.agents/notes/implemented/bug-fix/2026-08-18-request-image-payload-bound.i18n.yaml
#	.agents/notes/implemented/bug-fix/2026-08-18-request-image-payload-bound.zh.md
#	.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md
#	.agents/notes/implemented/feature/2026-07-16-persistent-pty-sessions.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-21-cross-session-references.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-21-cross-session-references.zh.md
#	.agents/notes/implemented/feature/2026-07-22-web-multimodal-image-input-and-durable-attachments.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-22-web-multimodal-image-input-and-durable-attachments.zh.md
#	.agents/notes/implemented/feature/2026-07-27-web-subagent-conversations.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-31-permission-default-for-new-sessions.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-03-web-search-source-scroll.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-03-web-search-source-scroll.zh.md
#	.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md
#	.agents/notes/implemented/feature/2026-08-05-agent-teams.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md
#	.agents/notes/implemented/feature/2026-08-11-workspace-sidebar-order-and-folding.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-15-product-subagent-noninteractive-permissions.i18n.yaml
#	.agents/notes/implemented/process/2026-07-21-serial-cross-platform-ci-reference.i18n.yaml
#	.agents/notes/implemented/process/2026-07-21-serial-cross-platform-ci-reference.zh.md
#	.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.i18n.yaml
#	.agents/notes/implemented/process/2026-07-22-evidence-based-larger-hosted-runners.zh.md
#	.agents/notes/implemented/process/2026-07-23-portable-required-pull-request-ci.i18n.yaml
#	.agents/notes/implemented/process/2026-07-23-portable-required-pull-request-ci.zh.md
#	.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.zh.md
#	.agents/notes/implemented/testing/2026-07-30-web-browser-snapshot-ci-gate.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-30-web-browser-snapshot-ci-gate.zh.md
#	.agents/notes/proposed/architecture/2026-07-27-session-projection-and-command-log.i18n.yaml
#	README.i18n.yaml
#	README.zh.md
#	docs/architecture.i18n.yaml
#	docs/architecture.zh.md
#	docs/development.i18n.yaml
#	docs/development.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.zh.md
#	docs/subsystems/README.i18n.yaml
#	docs/subsystems/README.zh.md
#	docs/subsystems/agent-team.i18n.yaml
#	docs/subsystems/agent-team.zh.md
#	docs/subsystems/client-modules.i18n.yaml
#	docs/subsystems/client-modules.zh.md
#	docs/subsystems/commands.i18n.yaml
#	docs/subsystems/commands.zh.md
#	docs/subsystems/persistence.i18n.yaml
#	docs/subsystems/persistence.zh.md
#	docs/subsystems/session-reference.i18n.yaml
#	docs/tool-catalog.i18n.yaml
#	docs/tool-catalog.zh.md
#	docs/user/guide/providers.i18n.yaml
#	docs/user/guide/providers.zh.md
#	packages/README.i18n.yaml
#	packages/README.zh.md
#	packages/bundle/web-app/README.i18n.yaml
#	packages/bundle/web-app/README.zh.md
#	packages/client/README.i18n.yaml
#	packages/client/README.zh.md
#	packages/client/connection/README.i18n.yaml
#	packages/client/connection/README.zh.md
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.zh.md
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.zh.md
#	packages/client/ui-sidebar/README.i18n.yaml
#	packages/client/ui-sidebar/README.zh.md
#	packages/client/ui-workspace/README.i18n.yaml
#	packages/client/ui-workspace/README.zh.md
#	packages/context/README.i18n.yaml
#	packages/context/README.zh.md
#	packages/core/agent-loop/README.i18n.yaml
#	packages/credentials/README.i18n.yaml
#	packages/credentials/README.zh.md
#	packages/experimental/agent-team/README.i18n.yaml
#	packages/experimental/agent-team/README.zh.md
#	packages/experimental/tool-agent-team/README.i18n.yaml
#	packages/experimental/tool-agent-team/README.zh.md
#	packages/host/frontend-static/README.i18n.yaml
#	packages/host/frontend-static/README.zh.md
#	packages/host/webserver/README.i18n.yaml
#	packages/host/webserver/README.zh.md
#	packages/interaction/commands/README.i18n.yaml
#	packages/interaction/commands/README.zh.md
#	packages/plan/plan-mode/README.i18n.yaml
#	packages/plan/plan-mode/README.zh.md
#	packages/sandbox/sandbox-local/README.i18n.yaml
#	packages/sandbox/sandbox-local/README.zh.md
#	packages/session/README.i18n.yaml
#	packages/session/README.zh.md
#	packages/session/session-persistence-sqlite/README.i18n.yaml
#	packages/session/session-persistence-sqlite/README.zh.md
#	packages/session/session-projection-cache/README.i18n.yaml
#	packages/session/session-projection-cache/README.zh.md
#	packages/shell/tool-pwsh/README.i18n.yaml
#	packages/shell/tool-pwsh/README.zh.md
#	packages/subagent/subagent-codex/README.i18n.yaml
#	packages/subagent/subagent-codex/README.zh.md
#	packages/subagent/subagent/README.i18n.yaml
#	packages/subagent/subagent/README.zh.md
#	packages/web/tool-web/README.i18n.yaml
#	packages/web/tool-web/README.zh.md
#	scripts/snapshots/translation-prompt-v4/request-response.expected.json
2026-08-20 19:15:33 +08:00

8.4 KiB
Raw Blame History

Agent Note: 产品 subagent 公开有界结构化失败事实

Status: implemented

English | 中文

Problem

Claude Code 与 Codex 产品提供方会收到结构化产品失败,但已发布运行以往会把其中大多数压成共享的 error 终止原因。产品日志保留了细节,前台父 agent 与一次性后台 Job却无法据此区分产品限制、执行失败或进程提前退出。

若把 SDK 错误文本、app-server payload 或 stderr 复制进结果,就会暴露任务文本、路径、环境值、凭证或产品内部信息。若增加共享错误字段,又会让提供方无关的 subagent seam拥有彼此独立变化的产品版本词汇。

Decision

每个产品提供方分别拥有从锁定版本官方错误联合、当前操作和受管进程结果到一行固定安全诊断的映射。SubagentResult 保持不变:消费方仍接收现有的有界 diagnostic 字符串,而且不解析其中由产品私有的字段。

安全诊断

结构化行采用以下固定顺序:

Product subagent failure (product: <product>; stage: <stage>; category: <category>; HTTP status: <status>; exit code: <code>; signal: <signal>)

提供方会省略不可用的可选字段。退出码与信号是相互独立的事实,只要已观测到就分别保留。来自非交互权限决策且参与失败的权限决定会跟在结构化行之后;最新的安全权限事实仍只属于当前操作。共享结果边界会把完整文本限制在 4096 个 UTF-8 字节以内。

成功结果与本地取消都不公开失败事实。原始产品错误、stderr、工具输入、路径、环境值、凭证和协议 payload 绝不会进入诊断。启动与清理拒绝会在 Error 消息中使用同一安全行。原始失败保留在内部 cause 链中;提供方 Host 日志与转发的 stderr 也只作为产品本地观测。

Claude Code 事实

Agent SDK 0.3.220 定义四种错误子类型:error_during_execution、error_max_turns、error_max_budget_usd 和 error_max_structured_output_retries。Claude Code 提供方会把每种准确子类型保留为类别,同时维持共享终止原因 error。标记为错误或内容空白的成功消息使用 invalid-success,缺失结果使用 missing-result,SDK 给出终态结果前发生的进程退出使用 process-exit,无法识别的值或异常使用 unknown,且不会复制原值。

阶段 归属操作 可观察失败
query-start SDK query 构造、原生平台载荷启动与未发布回滚 start() 以固定安全事实和回滚前已观测到的进程结果拒绝
query-run 已发布 SDK 消息迭代与严格终态结果校验 运行以 error 兑现,并携带准确已知子类型或固定结果类别
process SDK 提供终态结果之前受管 CLI 已退出 运行以 error 兑现,并携带 process-exit 以及可用的退出码和信号
teardown Query 关闭与受管进程树释放 dispose() 独立拒绝并携带固定安全事实,同时清理仍会完成最终退出等待

Codex 事实

Codex app-server 0.147.0 定义十一种字符串类别与五种对象 variant。提供方会保留 contextWindowExceeded、sessionBudgetExceeded、usageLimitExceeded、serverOverloaded、cyberPolicy、internalServerError、unauthorized、badRequest、threadRollbackFailed、sandboxError 和 other。它还会保留 httpConnectionFailed、responseStreamConnectionFailed、responseStreamDisconnected、responseTooManyFailedAttempts 与 activeTurnNotSteerable;四种连接/stream variant 会保留数值 httpStatusCode,而 active-turn variant 不公开 turnKind。未知字符串、同时含其他 variant 的对象、格式错误值与未分类异常统一使用 unknown。

阶段 归属操作 可观察失败
initialize App-server spawn 与 initialize/initialized 握手 start() 以固定安全事实和已经观测到的进程结果拒绝
thread-start 临时 thread/start 请求与响应校验 start() 以线程阶段和可用进程结果拒绝
turn-start 已发布 turn/start 请求、暂定 id 与早到 frame 没有结构化类别时,运行以 error 和安全 unknown 回退兑现
turn 终态通知、最终答案选择与 error-info 映射 完整类别与可选 HTTP status 进入非完成结果
process 受管 app-server 在另一终态路径结算前退出 运行以 error 兑现,并携带 process-exit 以及可用的退出码与信号
teardown Wire 关闭与进程树释放 dispose() 独立拒绝;启动回滚聚合会同时公开启动与 teardown 两行

contextWindowExceeded 仍是 max-tokens;其他所有已知或未知 Codex 类别仍是 error,cyberPolicy 不会变成 refusal。

所有权与生命周期

事实或资源 Owner 消费方行为
产品错误类别 锁定版本的官方 SDK 或 app-server 提供方只映射已声明的结构化联合,并对联合外值使用 unknown
当前失败阶段 产品提供方操作 只在失败点派生;绝不持久化,也不作为恢复状态
退出码与信号 dsh-subprocess 进程句柄 提供方展示已观测值,不推测缺失值
诊断字节与送达 dsh-subagent、前台工具与 Job 运行时 两种调度模式都把同一份有界文本与 assistant 输出分开呈现
原始产品失败 产品运行时、内部 cause 链与 Host 观测 只保留在内部,绝不成为模型可见的结果文本

Verification

Claude Code 包测试固定四种 SDK 子类型、无效成功、缺失结果、未知值与异常、四个阶段、相互独立的退出码与信号字段、权限事实顺序、脱敏、成功结果与取消时省略诊断、并发运行隔离和清理完成。Codex 包测试固定全部十六种 error-info variant、HTTP status 存在与缺失、六个阶段、unknown 回退、终止原因保持不变、权限顺序、脱敏、取消、并发与清理聚合。真实 SDK/CLI fixture 会产生真实的 Claude error_max_turns,真实 app-server fixture 会产生真实的 Codex internalServerError;两个 fixture 都覆盖进程/协议失败与整棵进程树完全停稳。无密钥 ACP snapshot 会在前台错误输出、后台完成通知和 job_output 中记录两个产品各自的准确诊断。

Alternatives considered

返回原始 SDK 错误、app-server payload 或 stderr。 这些值可能包含命令、路径、工作区内容、环境值、凭证或上游文本。固定白名单映射可以保留可操作事实,同时不扩大模型可见的信任边界。

增加共享产品错误 enum 或结构化结果字段。 Claude Code 与 Codex 各自独立版本化错误联合。共享 enum 会复制这些权威,并迫使无关提供方和消费方跟随产品版本。

解析通用 stderr 与异常消息。 自由文本既不稳定也不安全。只有锁定版本产品提供的结构化字段和受管进程结果可以成为诊断输入。

持久化阶段或增加恢复控制器。 阶段只在报告失败时从当前调用点派生。持久化、重试、resume 与修复需要独立的所有权和用户约定。

把产品限制映射为新的共享终止原因。 Claude Code 的轮次和预算限制并不表示 token 窗口耗尽,错误类别也不能证明拒绝语义。既有终止原因保持不变。

Consequences

父 agent 可以区分重要的 Claude Code 限制,以及 Codex 预算、用量、服务、策略、请求、连接、stream、回滚、sandbox 和 active-turn 失败,而不会收到原始产品文本。前台与后台调度会保留同一事实,因为二者都消费同一个 SubagentResult。

诊断只是展示文本,不是新的公开协议。调用方可以呈现它,但不得根据其标点或产品私有类别名称进行分支。锁定产品版本升级并改变官方错误联合时,必须同步更新提供方映射与证据。

本决策不增加产品会话持久化、重试策略、恢复状态、stderr 分类器、身份验证或配置分类体系、进度流或人工交互路径。