# Agent Note: 产品 subagent 公开最小可行动诊断

Status: implemented

[English](2026-08-21-product-subagent-minimal-diagnostics.md) | 中文

## Problem

Claude Code 与 Codex 提供方会从彼此独立版本化的产品运行时接收结构化失败。如果把这些上游错误联合的每个成员都镜像进模型可见诊断，那么即使多个类别会让父 agent 采取同一种下一步动作，每次运行时升级仍会扩大提供方约定。

原始 SDK 错误、app-server payload、stderr、命令、路径、任务内容、环境值与凭证都不能取代结构化映射，因为这些内容跨越产品进程边界时没有稳定的安全保证。父 agent 仍需要足够信息来区分产品限制、访问限制、服务或传输问题、无效结果与受管进程失败。

## Decision

每个产品提供方都会根据当前操作与安全的结构化产品事实派生少量行动类别。现有 `SubagentResult.diagnostic` 字符串仍是唯一公共表示：消费方只展示而不解析，共享 subagent 结果边界继续对完整文本执行 4096 字节 UTF-8 上限。

Claude Code 会把 Agent SDK 结果映射为五种类别：

| 类别 | 安全输入 |
| --- | --- |
| `limit` | 轮次、预算或结构化输出重试限制 |
| `product-error` | 一般 SDK 执行失败 |
| `invalid-result` | 标记为错误或内容空白的成功结果，或缺失终态结果 |
| `process` | 受管 CLI 在终态结果前退出 |
| `unknown` | 启动、清理、无法识别的 SDK 值，或没有更具体安全事实的失败 |

诊断还会保留派生的 `query-start`、`query-run`、`process` 或 `teardown` 阶段，以及分别观测到的退出码与信号。参与失败的权限决定会跟在失败行之后。成功完成与本地取消不公开失败诊断，原始 SDK 文本只留在内部 cause 链和 Host 观测中。

Codex 会把 app-server 失败映射为八种类别：

| 类别 | 安全输入 |
| --- | --- |
| `limit` | 上下文、会话预算或用量限制 |
| `access-policy` | 身份验证、网络安全策略、产品策略或 sandbox 失败 |
| `service` | 过载或内部服务失败 |
| `transport` | HTTP 与响应 stream 连接失败或尝试耗尽 |
| `product-error` | 无效请求、回滚、活动轮次或其他产品失败 |
| `invalid-result` | 已完成轮次没有非空白最终答案 |
| `process` | 受管 app-server 在其他终态结果前退出 |
| `unknown` | 启动、清理、格式错误的协议值，或没有更具体安全事实的失败 |

Codex 诊断会保留 `initialize`、`thread-start`、`turn-start`、`turn`、`process` 或 `teardown`，以及适用的数值 HTTP status 和分别观测到的退出码与信号。`contextWindowExceeded` 仍把共享终止原因映射为 `max-tokens`；其他所有类别仍使用 `error`。只有结构化协议事实会贡献权限说明。产品 stderr 只供 Host 观测，既不会被分类，也不会复制进结果。

### 所有权与生命周期

| 事实或操作 | 责任方 | 结果 |
| --- | --- | --- |
| 产品错误解释 | 官方产品运行时 | 提供方只消费其锁定集成公开的结构化事实 |
| 行动类别与阶段 | 单次产品提供方运行 | 在失败位置派生，并在结果结算后丢弃 |
| 退出码与信号 | `dsh-subprocess` 句柄 | 观测到时分别展示，不推断缺失值 |
| 权限决定 | 产品提供方权限回调或协议 | 只在参与失败运行时追加 |
| 诊断传递与字节上限 | `dsh-subagent` 及其前台或 Job 消费方 | 一个有界可选字符串继续与 assistant 输出分离 |

## Verification

Claude Code 包测试覆盖全部粗粒度类别、四个阶段、未知结构化值、权限顺序、原始文本排除、成功与取消时省略、并发运行隔离，以及彼此独立的退出码与信号字段。真实 Agent SDK 0.3.241 与 Claude Code 2.1.241 fixture 会产生实际 max-turns 限制、进程失败、权限拒绝、严格最终答案、取消与整棵进程树完全停稳。Codex 包测试覆盖全部粗粒度类别、六个阶段、适用 HTTP status、结构化权限顺序、stderr 排除、成功与取消时省略、并发及清理聚合。真实 0.149.1 app-server fixture 会产生服务、产品错误、进程、最终答案、模型隔离、取消与完全停稳证据。Loader 与无密钥产品组合继续公开静态工具，不增加诊断解析器或模型可见类别输入。

## Alternatives considered

**保留每个上游枚举成员。** 多个成员会触发同一种父级动作，而只负责展示的消费方无法从准确名称获得额外行为。继续保留会让常规产品升级重新定义更大的 Harness 可见承诺。

**返回原始产品文本或分类一般 stderr。** 自由文本可能包含敏感任务与环境数据，也没有稳定的版本化含义。只有结构化产品事实、提供方阶段、权限决定与受管进程结果可以成为输入。

**增加共享结构化错误类型。** 两个产品独立版本化失败，而当前消费方只呈现有界字符串。共享枚举会在没有消费需求的情况下，把产品发布变动移入提供方无关的 seam。

**根据类别重试或 fallback。** 提供方只拥有一次 one-shot 运行，没有重试权限、fallback 模型、持久产品会话或恢复状态。类别只用于通知父级，不会启动另一项产品动作。

## Consequences

产品运行时升级不再要求为每个 SDK 或 app-server 错误成员提供模型可见承诺。父级仍可区分限制、访问与策略限制、服务与传输失败、一般产品失败、无效结果、受管进程退出与未知失败，并保留适用的阶段、权限、HTTP 与进程事实。

诊断仍是安全展示文本，而不是恢复协议。本改动不增加原始错误转发、fallback 模型、自动重试、产品会话持久化、公共结构化结果字段或动态提供方与模型选择。
