From 07dc1e9addb375ab4acd5f18bc26e6abdb9ad124 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sun, 20 Sep 2026 18:52:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E6=8F=90=E4=BA=A4=20Responses=20API?= =?UTF-8?q?=20=E4=B8=8E=20Agents=20SDK=20=E8=BF=81=E7=A7=BB=E8=AF=84?= =?UTF-8?q?=E4=BC=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/README.md 已引用该评估文档但文件未入库,导致 check:doc-index 与 pre-push 对所有人生效失败 本次把文档正文补进仓库,恢复文档索引门禁 --- ...Responses API与Agents SDK迁移评估-2026-09-07.md | 269 ++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 docs/technical/【技术评估】Responses API与Agents SDK迁移评估-2026-09-07.md diff --git a/docs/technical/【技术评估】Responses API与Agents SDK迁移评估-2026-09-07.md b/docs/technical/【技术评估】Responses API与Agents SDK迁移评估-2026-09-07.md new file mode 100644 index 000000000..2fb7cf128 --- /dev/null +++ b/docs/technical/【技术评估】Responses API与Agents SDK迁移评估-2026-09-07.md @@ -0,0 +1,269 @@ +# Responses API 与 Agents SDK 迁移评估 + +更新时间:`2026-09-07` + +## 结论 + +本次评估不建议把 Genarrative 的核心 Agent Runtime 整体迁移到 OpenAI Agents SDK。建议保留 `platform-llm` 的 Responses / Chat / Anthropic 协议适配、Tauri/Rust Runtime、项目文件与进程工具、审批、权限与沙箱、持久会话、任务图、重试、恢复、计费和现有 Codex app-server 路径。 + +可以保留一个有明确边界的 Agents SDK 试验:只在可信的服务端或受控 Tauri bridge 中,为 Project Supervisor / 专业 Agent 的只读交互聊天提供可选的 `Agent + Runner` 编排、只读专家路由和统一 tracing。该试验必须通过现有 Runtime 工具网关和事件投影,不能让 SDK 直接读写项目、启动进程、提交媒体任务、扣费或持有正式状态。 + +理由是当前系统已经拥有比 SDK 默认能力更严格的业务控制面。技术方案已经明确规定 AGC Runtime 由 Genarrative 自己掌控,不把 OpenAI Agents SDK sidecar 作为核心,只借鉴 Agent、Tools、Handoffs、Guardrails、Tracing 抽象(见 `docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` 的“技术选择”)。OpenAI 官方 Agents 文档也把 SDK 定位为建立在 Responses API 之上的编排层:SDK 用 `Agent` 和 `Runner` 管理 turns、tools、guardrails、handoffs 和 sessions;如果应用自己拥有这套循环,直接使用 Responses API 是合理路径。[Agents SDK Agents 指南](https://openai.github.io/openai-agents-python/agents/) + +## 现状盘点 + +### Responses 协议层 + +`server-rs/crates/platform-llm/src/lib.rs` 定义了协议中立的 `LlmRunRequest` / `LlmRunResponse`。请求包含模型、system/user/assistant 消息、图像输入、`max_output_tokens`、web search、reasoning effort、text verbosity、function tools 和 `tool_choice`(约第 167–194 行)。默认 `LlmApiKind` 是 `openai_responses`,同时显式支持 `openai_chat` 和 `anthropic`。 + +Responses 请求在 `build_request_body` 中映射到 `/responses`,包括 `input`、`stream`、`max_output_tokens`、原生 `web_search`、function tools、`tool_choice`、`reasoning.effort` 和 `text.verbosity`(约第 2321–2404 行)。消息映射保持 Responses 的角色差异:system/user 文本使用 `input_text`,assistant 文本使用 `output_text`,图像使用 `input_image`(约第 2895–2973 行)。 + +非流式响应会从 `output_text` 和 `function_call` 中恢复正文、工具调用、usage、finish reason 和 response id。`LlmClient::run` 负责请求验证、HTTP 执行、响应读取和协议解析(约第 1550–1585 行)。 + +流式 `LlmClient::stream_run` 自己维护 SSE 解析、UTF-8 分块、Responses `response.output_text.delta`、`response.output_item.added`、`response.function_call_arguments.delta/done`、`response.completed` / `response.incomplete`、错误和尾部异常处理(约第 1596–1869 行)。工具调用按 Responses `output_index` 聚合,完整参数由终态事件校正;工具分片没有完成信号时会失败关闭;只把文本增量和 finish reason 交给上层,工具调用留在最终 `LlmRunResponse.tool_calls`。 + +`server-rs/crates/platform-llm/src/provider_adapter.rs` 把该 client 接入 `agent-runtime-core` 的 Provider registry。Responses 适配器宣告 Streaming、FunctionTools、RequiredToolChoice、ImageInput、WebSearch、ReasoningEffort 和 TextVerbosity 能力。`platform-llm/README.md` 明确规定该 crate 只负责文本协议适配,不承接上下文、后台执行、业务状态或工具副作用。 + +### AGC 的生成工作流 + +`apps/ai-game-creator-shell/src-tauri/src/agent/generation/loop_orchestration.rs` 仍保留一条文件驱动的确定性生成链: + +1. Planner 读取用户需求、短期/长期记忆和项目黑板,生成 `.agent/spec.md`。 +2. Orchestrator 根据 spec、findings 和 manifest 生成 agenda / task graph。 +3. 按依赖 wave 并行生成设计、美术、程序等角色 brief,并写入本轮 pass 产物。 +4. Generator 根据 spec、findings、brief、素材和 agenda 生成结构化游戏草稿。 +5. Evaluator 写入 `.agent/findings.md`,失败时进入下一 pass 的修复范围。 +6. 产物写入、静态检查和试玩验证由 Runtime 完成,而不是由模型回复宣称完成。 + +Planner / Generator 使用独立的 system/user prompt 和严格结构化输出。Generator 选择 `run` 或 `stream_run`,但 legacy 生成 loop 的 streaming callback 为空,流式主要用于传输和容错;Generator 对 `EmptyResponse` 有有界重试,随后解析和校验 JSON。 + +这条链路的任务图、文件写入、Evaluator 反馈和产物门禁具有明确业务语义,不适合交给一个 SDK run loop 隐式管理。 + +### 后台 Runtime tool-plan 工作流 + +`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_actions/provider_request_builders.rs` 和 `provider_tool_plan.rs` 为每个后台 turn 动态构造请求: + +- 读取当前 Agent、Session、Run、Goal Contract、Acceptance Graph、黑板、项目摘要、受控观察和运行中追加指令。 +- 按 Agent 身份、run profile、项目阶段、审批策略和验证门动态收窄工具目录。 +- 以严格 JSON Schema function tools 暴露 `file.*`、`project.*`、`command.*`、`preview.*`、`canvas.*`、`asset.*`、`memory.*`、`task.*`、`agent.*`、`goal_contract`、`acceptance_update`、`update_agent_plan` 和 `respond_to_user` 等能力。 +- 普通 Runtime tool-plan 要求模型直接调用白名单函数,并将计划更新、工具动作、观察和最终回复拆成可持久化的协议阶段。 +- 工具调用解析后进入 `agent/runtime_tools/*`,再经过权限、路径、项目写锁、确认、revision、验证和 receipt 门禁;模型不能直接执行副作用。 +- Provider 成功结果先写入 handoff / lifecycle / Agent DB,再由 Runtime 消费;重复、迟到、身份冲突或无法确定终态时进入 `needs-reconciliation`,不自动重放。 + +`agent_native_tools.rs` 生成严格工具 schema,工具策略与动态目录由 Runtime 控制。当前工具目录和工具执行已经是领域合同,不是简单的 JSON function-call wrapper。 + +### 交互聊天和流式行为 + +交互层在 `apps/ai-game-creator-shell/src-tauri/src/agent/interaction.rs` 中使用一个受限 interaction kernel:普通问答直接回复,只有确实需要宿主持久能力时才调用一个 function tool;高影响请求先澄清,不擅自启动 Runtime。它复用现有 Provider registry,流式异常可按稳定错误类型回退一次非流式请求。 + +Tauri command `chat_with_game_creator_role_agent_stream` 会先写入用户消息,再发出 `started` 事件,随后发出带 `delta_text`、`accumulated_text` 和 `finish_reason` 的 `delta` 事件,最终发出 `completed` 或 `failed`(`apps/ai-game-creator-shell/src-tauri/src/commands.rs` 约第 1199–1335 行)。React 侧按项目、Agent、Run 和加载代次过滤迟到事件,以 `requestAnimationFrame` 合并正文,失败时保留已接收的完整正文。 + +后台 final reply 还使用 `AgentRuntimeResponseStreamPublisher` 将流持久化到 `.agent/runtime/response-streams//.json`。记录绑定 Agent/Task/Session/Run、request slot、steer cursor、响应 revision、sequence、status、正文和 finish reason,并支持 `streaming → ready → committed/failed/discarded` 的恢复和去重。SDK 流必须先转译到这一合同,不能绕过它直接推送 UI。 + +### Codex app-server 路径 + +AGC 当前默认路线可以是 `codex_app_server`。`codex_app_server.rs` 通过 JSON-RPC `turn/start` / `turn/completed` 管理独立 thread/turn,消费 agent message、activity、item、MCP 工具和终态事件,并把增量正文映射回 `LlmStreamDelta`。`config.rs` 要求该模式使用 `apiKind=openai_responses`。 + +这条路径已经是另一种 agentic transport,且包含 workspace mode、进程生命周期、MCP 审计、硬超时和 passive-item 边界。它不能与 Agents SDK 直接互换;任何试验都必须保留该模式及其回滚能力。 + +### API Server、Router 和其他调用方 + +`server-rs/crates/api-server/src/llm/mod.rs` 提供账号鉴权的 `/api/llm/responses` 代理:客户端只传平台 access token,服务器解析账号 Router credential、模型目录和计费,删除客户端的 `apiKey`、`baseUrl`、provider、api kind、agent mode 等控制字段,再将 `stream`、`input`、`tools`、`metadata` 转发到 Responses endpoint。流式代理等待 `response.completed` / `response.incomplete` 后才结算额度。 + +`platform-editor-agent` 仍有自己的 `Agent`/memory/tool harness,但其编辑器对话目前固定使用 OpenAI Chat;图片、音频、UI 识别、画布生成等 helper 具有各自的严格结构化合同。它们不应因为 AGC 聊天试验而一起迁移。 + +## Prompt、工具和状态边界 + +### Prompt 分类 + +| 类别 | 当前入口 | 主要约束 | 迁移判断 | +|---|---|---|---| +| Planner / Generator | `generation/prompt_context.rs`、`loop_orchestration.rs` | 严格 JSON、文件产物、Evaluator pass、模型输出不能伪造写入/验证 | 保留 Responses / 当前编排 | +| Runtime tool-plan | `runtime_actions/provider_request_builders.rs`、`prompt.rs` | 动态工具目录、身份策略、Goal/Acceptance、动作数量、确认和完成门 | 保留 Rust Runtime;SDK 只可作为未来只读 adapter | +| Final reply | `provider_final_reply.rs`、`provider_request_builders.rs` | 只能依据 observation,不能声称未发生副作用;规划 Agent 有固定信封 | 保留现有路径,若试验仅转译文本事件 | +| Interaction chat | `interaction.rs`、`prompt.rs` | 普通问答与单宿主工具决策;可流式;适合路由/澄清 | 唯一优先试验边界 | +| Editor / media helpers | `platform-editor-agent`、`api-server/llm`、各媒体 prompt | Chat/Responses 混合、严格 JSON、计费和外部副作用 | 保留现有协议和专用 harness | + +### 工具、委派和 handoff 的语义差异 + +当前 `agent.delegate` / isolated join 是持久任务调度动作,包含 parent/child ID、delivery、认领、all-join、恢复和完成门;Provider handoff sidecar 是跨 Runner 边界保存一次成功 Provider 响应。这两者都不等于 Agents SDK 的 handoff。 + +Agents SDK 的 handoff 是模型可见的工具式路由:一次 handoff 后由专业 Agent 接管同一 run 的对话;SDK 文档还区分了“manager + agents as tools”和“handoffs”。[Agents 组合模式](https://openai.github.io/openai-agents-js/guides/agents/) + +因此: + +- Supervisor 的只读问答可以使用 manager + `agent.asTool()`,保留 Supervisor 作为唯一面向用户的回复所有者。 +- 需要真正转移对话控制的只读专家咨询才考虑 SDK handoff,并通过 `inputFilter` 限定传入历史。 +- 任何涉及文件、命令、进程、媒体、审批、项目 revision、manifest、验证或 Git 的意图,必须先转成 Runtime 可验证的动作/委派请求,由 Rust 决定是否允许;SDK handoff 不能创建正式 child Run,也不能绕过 `agent.delegate`。 + +### 状态管理 + +当前正式状态由 `.agent/conversations/**/*.jsonl`、`.agent/runtime/**/*.json`、Agent DB、任务队列、manifest/revision、handoff/retry/confirmation ledger 和 finalization journal 组成。`AgentRuntimeProviderRequestSnapshot` 绑定 project/agent/task/session/run/source、goal revision/fingerprint、steer cursor、request kind/slot、web search 和 planning session binding。 + +Agents SDK 可以使用 `Session`、`conversationId`、`previousResponseId` 或 `RunState`,但官方文档提醒不要把多种历史策略叠加使用。[Agents SDK Sessions](https://openai.github.io/openai-agents-js/guides/sessions/) + +本项目即使引入试验,也只能选择一个“临时模型上下文”策略;`.agent` 对话、Runtime sidecar 和 Agent DB 仍是唯一正式事实源。SDK session 不拥有 project revision、工具 action、审批、billing、retry、resume 或 finalization。重启恢复必须先恢复 Genarrative sidecar,再决定是否重建 SDK run。 + +## 是否需要更 agentic 的架构 + +核心 Runtime 已经具备更 agentic 的架构,而且它比通用 SDK loop 多了本项目所需的持久治理: + +- 工具:严格 schema、身份目录、按角色/阶段动态收窄、auto/confirm/deny、项目锁和 revision。 +- 交接:静态专业 Agent、动态 isolated child、delivery receipt、all-join、恢复和 parent run 收束。 +- Guardrails:路径/文件类型、sandbox、权限、确认、Goal Contract、Acceptance Graph、验证 gate、最终回复门禁和敏感信息脱敏。 +- Tracing / audit:run trace、event、Agent DB、tool receipt、Provider lifecycle、request fingerprint 和 response stream sidecar。 +- Streaming:Responses SSE / Codex item events → Runtime stream publisher → Tauri events → 前端按 identity/sequence/revision 去重。 +- 状态:session catalog、JSONL conversation、Runtime state、task queue、retry/handoff sidecar、context compaction 和 crash recovery。 + +因此,整体迁移只会把已有能力复制一遍,带来两套 turn loop、两套状态、两套重试和两套工具授权;收益不足以抵消安全和恢复风险。 + +Agents SDK 对局部交互仍有增量价值: + +| 能力 | 在本项目的真实收益 | 可接受边界 | +|---|---|---| +| Agent loop | 减少只读聊天中手写单轮/多轮和路由 glue code | 只用于交互聊天或只读专家问答 | +| Tools | 统一工具参数解析、工具结果与模型 turn | function tool 只调用 Rust RPC 的窄只读 facade | +| Handoffs / agents-as-tools | 更容易表达 Supervisor→专家的语言路由 | 不创建正式 Runtime child;推荐 manager + agents-as-tools | +| Guardrails | 可增加聊天输入/输出格式和工具输入校验 | 不能替换 Rust 权限、确认、sandbox、revision gate | +| Streaming | 提供 raw model、run item、agent updated 等统一事件 | 先转成现有 response-stream 记录,必须等待 `stream.completed` | +| Tracing | 补充 generation/tool/handoff/guardrail latency 和 token span | 关联现有 run IDs,关闭敏感数据或自定义脱敏 processor | + +官方 Streaming 文档明确说明 `toTextStream()` 只给正文,工具、handoff、approval 等需要消费完整事件流;流结束后还可能进行 session 持久化或 compaction,因此必须等待 `completed`。[Agents SDK Streaming](https://openai.github.io/openai-agents-js/guides/streaming/) + +官方 Tracing 文档说明默认会记录 run/task/agent/turn、generation、function tool、guardrail 和 handoff spans,并支持自定义 trace processor;这对排查延迟和工具路由有价值,但也意味着 prompt 和工具数据必须显式设置敏感数据策略。[Agents SDK Tracing](https://openai.github.io/openai-agents-js/guides/tracing/) + +## 推荐架构边界 + +```text +Tauri / React + │ 现有 invoke + Tauri events + ▼ +Genarrative Rust Runtime(正式事实源) + ├─ session / conversation / task / revision / approval / recovery + ├─ tool policy / sandbox / filesystem / process / media / billing + ├─ existing response-stream sidecar and Agent DB + └─ Provider seam + ├─ current LlmClient + platform-llm (Responses/Chat/Anthropic) + ├─ Codex app-server (existing route) + └─ optional Agents SDK adapter (experimental, read-only chat only) + │ + └─ trusted Node/TS process or Tauri bridge; never browser bundle +``` + +可选 adapter 的职责应是:接收 Rust 生成的已脱敏 prompt/context snapshot;创建有限的 `Agent`、工具和可选只读专家;调用 `run(..., {stream: true})`;把 SDK event 转成现有 `ProviderStreamEvent` / `LlmStreamDelta` / Runtime observation;将最终文本和工具意图返回 Rust。Adapter 不得读取项目绝对路径、凭据、签名 URL 或任意环境变量,也不得自行重试有副作用的工具。 + +建议在试验中优先使用 manager + agents-as-tools,而不是让 SDK handoff 成为对话所有权切换。这样 Supervisor 仍是唯一的用户回复所有者,SDK 专家只返回短的只读咨询结果。若确实需要 handoff,必须由 Rust 提前给出允许目标集合,并在 SDK handoff callback 中再次校验目标和输入;模型传入的 routing metadata 只能作为受限说明,不能改变权限或项目目标。 + +## 模型与 Provider 建议 + +OpenAI 官方模型页当前建议:复杂推理和编码优先 GPT-6 Astra,平衡能力与成本选择 GPT-5.6 Terra,高量低成本选择 GPT-5.6 Luna;最新模型可通过 Responses API 和 Client SDK 使用。[OpenAI Models](https://developers.openai.com/api/docs/models) + +这不构成一次模型迁移任务:AGC 当前已有官方 Router / catalog alias 和每 Agent 配置,官方 route 已使用 `gpt-6-astra` 语义,客户端不能绕过服务器模型目录直接选择任意模型。迁移试验应冻结当前已配置模型和 reasoning/verbosity,先测编排差异;若要对 GPT-5.6 Terra/Luna 或其他新模型做基准,应作为独立模型评估,不与 SDK 迁移同时变更。 + +Agents SDK 试验只适合经过验证的 OpenAI Responses 路径。`openai_chat`、`anthropic`、VectorEngine/Ark 等兼容网关继续走 `platform-llm`,不要假设它们支持 SDK 的 hosted tools、server-managed conversation、Responses WebSocket 或完整事件形状。若自定义 base URL 不能稳定返回 function tool 和 SSE 终态事件,直接回退现有 Provider adapter。 + +## 测试与文档建议 + +现有测试应作为不可削弱的迁移门禁: + +- `cargo test -p platform-llm --manifest-path server-rs/Cargo.toml`:Responses body、tool schema、图像输入、非流式 function call、SSE text/tool 聚合、completed/incomplete 恢复、参数截断、尾部错误、超时和重试。 +- `cargo test -p platform-agent-harness --manifest-path server-rs/Cargo.toml`:staged memory 提交/回滚、非法 JSON 修复、deadline、顺序工具和确认。 +- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider -- --test-threads=1`:Provider、stream fallback、工具计划、retry、handoff、redaction 和 context compaction。 +- `apps/ai-game-creator-shell/src-tauri/src/tests/response_stream.rs` 及 `runtime_actions/response_stream_tests.rs`:stream sidecar 的 identity、sequence、reconnect、commit、discard、steer 和恢复。 +- `apps/ai-game-creator-shell/tests/appSurface/response-stream.suite.ts`、conversation/session、supervisor runtime、handoff、retry、runner-kill suites:UI 状态和真实恢复合同。 +- 现有 deterministic E2E 和 opt-in live Provider smoke 继续保留;live 测试不能成为默认 CI 依赖。 + +如果实施 SDK 试验,再增加: + +1. **差分 fixture**:同一脱敏输入同时跑现有 Responses adapter 和 SDK adapter,比较最终文本、tool name/arguments、finish reason、usage、模型和错误分类;不执行真实副作用。 +2. **事件转译合同**:覆盖 raw model delta、message output、tool called/output、agent updated、handoff requested/occurred、approval interruption、completed 的顺序、重复和取消。 +3. **持久流恢复**:中途进程退出、tail error、重复事件、sequence 回退、steer cursor 变化和 finalization 竞态,都必须回到现有 sidecar 语义。 +4. **Session/RunState 隔离**:证明 SDK session/RunState 不能替换 `.agent/conversations`、`.agent/runtime` 和 Agent DB;恢复后不得重放已提交 file/media/process/billing action。 +5. **工具授权和幂等**:未经 Rust policy 允许的 tool/handoff 被拒;retry、handoff、approval resume 不产生重复副作用。 +6. **Tracing 脱敏**:trace processor 中不存在 API key、Cookie、签名 URL、绝对路径、原始工具参数、项目源码和用户私密正文;trace/group/workflow ID 可关联现有 project/session/run/agent ID。 +7. **兼容网关能力探测**:分别验证 HTTP Responses、function tools、SSE completed/incomplete、图像输入和错误事件;不因模型名推断 endpoint 能力。 +8. **回滚差分**:SDK 失败、超时、unsupported event、handoff 拒绝和 stream 取消都回到现有 `provider` 或 `codex_app_server`,且响应和 conversation 只落一次。 + +文档建议在真正开始试验时再更新: + +- 为 AGC 增加 setup README:只在可信 Node/TS 进程或 bridge 安装并 pin `@openai/agents` 与 `zod`;说明 custom base URL、HTTP Responses transport、AppData credential、tracing key 与禁用/脱敏策略。SDK 不得打进浏览器 bundle,不能使用 Vite 暴露的 API key。 +- 更新 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md` 的 LLM/Responses 段,补充 adapter feature flag、custom provider 能力限制、trace privacy、canary 与 rollback 命令。 +- 更新 `server-rs/crates/platform-llm/README.md`,声明 SDK 若加入只位于协议层之上的编排 adapter,Responses/Chat/Anthropic parser 和错误/stream 合同仍由 `platform-llm` 负责。 +- 新增迁移 runbook,写明 `.agent` 状态不迁移、不删除、不由 SDK 接管,测试矩阵和恢复证据要求。 + +## 分阶段迁移计划 + +### Phase 0:合同冻结(先做) + +- 固定当前 `LlmRunRequest`、有效工具 schema、prompt bundle、model/api kind、reasoning/verbosity、stream 开关、retry/backoff、request fingerprint 和错误分类的 golden fixture。 +- 固定现有 response-stream sidecar 的 schema、identity、sequence、status、revision、steer cursor 和 finalization 行为。 +- 固定 `platform-llm`、AGC provider tests、response-stream tests、supervisor/handoff/recovery E2E 为 baseline。 +- 明确试验只允许 `provider` 的 OpenAI Responses 交互聊天;`codex_app_server`、Chat、Anthropic、legacy Planner/Generator 和项目副作用不进入首轮。 + +退出条件:所有 baseline 通过,且没有任何 SDK 依赖或状态格式变更。 + +### Phase 1:受控 SDK adapter(开发环境) + +- 在受信任的 Node/TS 服务或 Tauri bridge 中增加可选 adapter;不要在 React/browser bundle 中调用 SDK。 +- Adapter 只收 Rust 传来的脱敏 context snapshot,使用 `Agent`、窄只读 function tools 和 manager-style `agents as tools`。 +- Rust 继续分配 project/session/run/request slot 和 action identity;SDK 的 run id、session 或 trace id 只作关联元数据。 +- 所有 tool function 必须调用 Rust RPC 的只读 facade;写文件、命令、进程、媒体、外部 editor、审批、billing 和 Git 均拒绝。 +- Adapter 将 SDK stream events 映射成既有 response-stream publisher 输入,等待 `stream.completed` 后才返回最终结果。 + +退出条件:没有 SDK 直连项目文件/凭据;只读聊天的 text/tool/stream parity fixture 通过;中止和重复事件不破坏 sidecar。 + +### Phase 2:影子差分与 tracing bridge + +- 对脱敏的历史聊天 fixture 同时运行 current Provider 和 SDK adapter,但 SDK 侧不执行工具副作用。 +- 记录 final text、tool intent、事件延迟、首 token 延迟、token usage、错误类型、重试次数和取消行为,不记录原始 secret/prompt/tool payload。 +- SDK tracing 使用稳定 workflow name,例如 `genarrative-agc-interaction`;group id 绑定 session,metadata 只放哈希后的 project/agent/run/request identity。默认关闭敏感数据,或用自定义 processor 做字段级脱敏,并在任务结束 flush。 +- 统计差异而不是立即替换当前路径:结构化工具意图必须相同,文本差异需人工抽样,SDK 不得增加重复请求或扣费。 + +退出条件:在代表性 fixture 上,SDK 没有重复副作用、身份错配、公共信息泄漏、流式重复和不可解释的额外成本;否则停止试验。 + +### Phase 3:小流量可选 canary + +- 用按 Agent / 项目 / build 的 feature flag 只开放给开发调试入口或内部用户。 +- 运行时检测 custom endpoint 是否支持 function tools、SSE terminal event 和目标 Responses 字段;不支持就选择旧 Provider。 +- SDK stream、handoff、approval 或 tracing 任一异常时,按“尚未产生副作用”条件回退;若已经产生 Rust action,必须先以 action ledger / reconciliation 处理,禁止盲目重试。 +- 保持同一个 UI event 和 conversation projection,不让用户看到两种状态模型。 + +退出条件:canary 的成功率、首 token 延迟、终态延迟、工具意图一致率、恢复成功率、重复副作用数、泄漏数和成本达到事先设定门槛,并连续多个版本稳定。 + +### Phase 4:仅在数据支持时扩大 + +最多把只读 Supervisor/role chat 扩到更多内部聊天场景。不要因此迁移: + +- Planner→Generator→Evaluator 文件工作流。 +- 自主构建和正式 Runtime tool-plan。 +- `agent.delegate`、isolated child、all-join、DAG 和 manifest scheduler。 +- 文件、命令、进程、媒体、External Editor、Git、preview 和审批工具。 +- `platform-llm` 的 Chat/Anthropic/兼容网关和 API-server Router/billing。 +- Codex app-server DirectProject 路径。 + +只有在未来需求明确要求 SDK 的原生能力,并能证明它不会与上述合同冲突时,才另立架构决策评估核心迁移;本报告不预设该迁移。 + +## 回滚说明 + +- 首要回滚是关闭 feature flag,将该 Agent route 指回现有 `provider` 或 `codex_app_server`;不改 `.agent` 对话、Runtime state、Agent DB、manifest、revision 或 receipt schema。 +- SDK adapter 只允许生成可丢弃的临时 run/trace 记录。关闭后这些记录不参与恢复和最终回复;已有 Rust response-stream / finalization 记录继续按原逻辑收口。 +- 如果 SDK 已返回 tool intent 但 Rust 尚未提交 action,直接丢弃该意图并重新走旧 route;如果 Rust 已提交 action,必须按现有 receipt、ledger 和 reconciliation 恢复,不能用 SDK 重试覆盖。 +- 不通过自动降级重复调用可能产生计费或媒体副作用的请求。重试仍由现有 Runtime retry identity、attempt、backoff 和 provider handoff 控制。 +- 不把 SDK Session、Conversation ID、Previous Response ID 或 trace export 当作恢复依据;它们失效时不影响本地正式状态。 + +## 验证清单 + +- [ ] `platform-llm` 的 Responses request/response/SSE/tool parser 全量通过。 +- [ ] Chat、Anthropic、Codex app-server 和 legacy Planner/Generator 路径行为未变化。 +- [ ] SDK adapter 只在可信服务端/bridge 运行,浏览器 bundle 和前端环境变量没有 SDK key。 +- [ ] current Responses 与 SDK adapter 的 prompt、tool schema、tool choice、model、reasoning、verbosity 和 output budget 差分通过。 +- [ ] SDK stream event → `LlmStreamDelta` / `ProviderStreamEvent` → response-stream sidecar 的映射通过。 +- [ ] `started → delta → completed/failed` Tauri event 合同、sequence/revision/steer/session/run identity 和 UI 去重通过。 +- [ ] `stream.completed`、session persistence、approval interruption 和 cancellation 都被正确等待/收口。 +- [ ] SDK tool/handoff 不能绕过 Rust policy、confirmation、sandbox、project lock、revision、billing 或 finalization gate。 +- [ ] handoff/agents-as-tools 只作用于只读咨询;正式 `agent.delegate` 和 isolated join 仍由 Rust scheduler 管理。 +- [ ] 进程退出、网络尾错、重复事件、Runner kill、retry、steer 和 resume 不产生重复副作用或重复 assistant message。 +- [ ] trace 关联到现有 project/session/run/agent identity,敏感 prompt、路径、源码、凭据和 tool args 均不出现在 trace/export/log。 +- [ ] custom Responses endpoint 的 function tools、SSE terminal event、图像输入和错误事件能力已显式探测。 +- [ ] canary 指标满足门槛;若不满足,feature flag 可立即切回旧 route。 +- [ ] 文档已更新 setup、tracing privacy、provider capability、测试矩阵和 rollback runbook。