Yoda
参考Agent 设计指南工程流

Agent SDK

CC 有成熟的官方 Agent SDK(TS/Py,包 claude 二进制);Codex 已悄然补齐官方 SDK 双形态(TS 包 exec JSONL、Py 包 app-server JSON-RPC)。两家协议互不兼容,统一调用只能靠自建 IR + 薄 adapter。

Agent SDK

结论

两家都已提供「把 agent 当库嵌进程序」的官方路径,但形态和成熟度不同。Claude Agent SDK(TS/Python)是一等公民产品:query() 一个入口、stream-json 私有协议、内置 hooks/sessions/结构化输出,本质是 claude 二进制的进程级遥控器,每一层都写死 CC 私有格式。Codex 在仓库 sdk/ 目录下已有两个官方 SDK:TypeScript 的 @openai/codex-sdk(spawn codex exec --experimental-json,走 JSONL 事件流)和 Python 的 openai-codex(直接做 codex app-server 的 stdio JSON-RPC 客户端)——所以"Codex 没有 SDK、app-server 只是事实 SDK"的说法已过时,但「Codex SDK = CLI/app-server 的薄包装」这一架构判断依然成立。两套 SDK 的 wire 协议零兼容,用任何一家 SDK 统一调用另一家不可行;harness 的正确姿势是自定义中间表示(IR)+ 每家一个薄 adapter。

研究问题

  • Claude Agent SDK(TS/Py)的能力面(hooks/sessions/structured outputs/stream-json 协议)到底覆盖到哪?
  • Codex 有没有官方 SDK?它和 app-server、codex exec --json 是什么关系?
  • 「用一个 SDK 统一调用所有 agent」的可行性结论是否仍成立?
  • SDK vs CLI spawn:harness(Yoda 现走 CLI spawn)该走哪条接入路线?

各 Agent 设计与实现

Claude Code

入口与协议。SDK 提供 query() 异步迭代器作为唯一主入口(TS @anthropic-ai/claude-agent-sdk / Py claude_agent_sdk),返回 user/assistant/system/result 消息流 [一手文档](claude-code-docs/docs/agent-sdk__overview.md 开头示例;agent-sdk__typescript.md:53-58query() 签名)。曾经的 V2 session API(createSession/send/stream)已在 0.3.142 被移除,官方明确"回归 query() + options"路线 [一手文档](agent-sdk__typescript-v2-preview.md: "The V2 session API is no longer supported... removes unstable_v2_createSession...")。

底层是 claude 二进制的遥控器 [一手源码]。Python SDK 的默认 transport SubprocessCLITransport 逐级查找并启动 claude 可执行文件,找不到直接抛 CLINotFoundErrorclaude-agent-sdk-python/.../transport/subprocess_cli.py:50-112);注入 CLAUDE_CODE_ENTRYPOINT=sdk-py 并强制 MINIMUM_CLAUDE_CODE_VERSION = "2.0.0"subprocess_cli.py:433 / :31)。ClaudeAgentOptions 只有 cli_path没有 base_url/provider 字段(types.py:1702-1706)——换得了二进制路径,换不了 runtime。

wire 协议是 CC 私有 stream-json:消息判别符 type: user/assistant/system/result/stream_event/rate_limit_event_internal/message_parser.py:79-318),控制协议 subtype initialize/can_use_tool/hook_callback/mcp_message/rewind_files/set_permission_mode/interrupt 等(types.py:1942-2043)[一手源码]。

Sessionscontinue(接最近一次)、resume(按 session_id)、fork 都是 query() 的 option 字段;session_id 从 init 消息里取(agent-sdk__sessions.md:28-36, 174-188)[一手文档]。

Hooks-in-SDKoptions.hooks 注册进程内回调(PreToolUse/PostToolUse/idle/stop 等),配 matcher 过滤,返回 permissionDecision: "deny" 可拦截工具调用;settings 文件里的 shell hook 也会按 settingSources 一并加载(agent-sdk__hooks.md:19-43)[一手文档]。这是 CC SDK 相对 Codex SDK 最大的能力差:控制面回调跑在宿主进程里,不需要额外协议。

输入双模式:SDK 有两种输入形态——Streaming Input Mode(默认推荐,传 AsyncIterable<SDKUserMessage> 维持持久交互会话)与 Single Message Input(一次性 prompt,依赖 session 状态与 resume)[一手文档](agent-sdk__streaming-vs-single-mode.md:5-20)。多轮对话的正确姿势是前者,而不是反复 query() + resume

可观测与成本:SDK 自身不产遥测——「The SDK does not produce telemetry of its own. Instead, it passes configuration through to the CLI process, and the CLI exports directly to your collector」,CLI 内建 OpenTelemetry 埋点(模型请求/工具执行 span、token 与成本 metrics),OTLP 直推 Honeycomb/Datadog/Langfuse 等后端(agent-sdk__observability.md:16-22)[一手文档];逐次调用的 token/成本也可直接从响应流读(agent-sdk__cost-tracking.md:9)。

计费边界:2026-06-15 起订阅计划下 SDK 与 claude -p 用量计入独立的 Agent SDK 月度额度(headless.md:10)[一手文档]——harness 选型时要把这条算进成本模型。

Codex CLI

官方 SDK 已存在,且是双形态 [一手源码](codex @ b89ce9a,仓库根 sdk/ 目录):

  1. TypeScript @openai/codex-sdk:README 自述 "wraps the codex CLI... spawns the CLI and exchanges JSONL events over stdin/stdout"(sdk/typescript/README.md)。源码证实:sdk/typescript/src/exec.ts:87 拼出 ["exec", "--experimental-json"]exec.ts:181 spawn() 子进程。API 模型是 Codex → startThread() → thread.run()/runStreamed(),事件即 codex exec --jsonitem.completed/turn.completed JSONL(见 headless 章)。支持 outputSchema 结构化输出。包版本仍是 0.0.0-devsdk/typescript/package.json)。
  2. Python openai-codex(Beta):不是包 exec,而是「Synchronous typed JSON-RPC client for codex app-server over stdio」(sdk/python/src/openai_codex/client.py:193),启动参数 ["app-server", "--listen", "stdio://"]client.py:230)。能力面更宽:thread_start/run、流式事件、登录管理(login_chatgpt/login_api_keysdk/python/README.md)、沙箱与审批模式(_sandbox.py/_approval_mode.py)。类型从 app-server schema 生成(generated/v2_all.py)。

app-server 是协议地基:自述「powers rich interfaces such as the Codex VS Code extension」,JSON-RPC 2.0 语义但 wire 上省略 jsonrpc: "2.0" 头,transports 有 stdio(默认)/websocket(实验)/unix socket(app-server/README.md:1-40)[一手源码]。codex app-server generate-ts / generate-json-schema 可导出与该版本严格对应的 schema——这是 Codex 给第三方 harness 留的正门。连 codex exec 自己内部也在跑 in-process app-server 协议(exec/src/lib.rs:931-1014 处理 ClientRequest::TurnInterruptServerNotification::TurnCompleted)[一手源码]。

Thread 续传:TS SDK 在同一 Thread 实例上反复 run() 即续对话(sdk/typescript/README.md),底层对应 codex exec resume <session_id>|--lastexec/src/cli.rs:165-204:session id 可以是 UUID 或 thread name,--last 取最近会话)[一手源码];--ephemeral 则完全不落盘(cli.rs:30-32),适合不想留痕的嵌入场景。Python SDK 通过 app-server 的 thread 生命周期 API 管理(05_existing_thread06_thread_lifecycle_and_controls 两个官方示例,sdk/python/examples/)。

两家协议零兼容:CC 发 can_use_tool,Codex 发审批请求与 item/* 通知;语义同构(turn/工具调用/审批/usage),wire 层判别符、方法名全不同(详见先行报告 §3,output/articles/手工川-agent-sdk-统一调用可行性-2026-06-09-v0.1.md)[一手源码]。SDK 里唯一的"缝"——CC 的 Transport 抽象基类——注释写明用途是 "remote Claude Code connections",其上仍跑 CC 控制协议,拿它驱动 Codex 等于重写完整协议翻译层(先行报告 §4.1)[一手源码]。

差异矩阵

维度Claude CodeCodex CLI
官方 SDK@anthropic-ai/claude-agent-sdk(TS)/ claude_agent_sdk(Py),GA@openai/codex-sdk(TS,0.0.0-dev)/ openai-codex(Py,Beta),随主仓 sdk/ 发布
入口模型query() 异步迭代器(V2 session API 已移除)Thread.run()/runStreamed()(TS);typed JSON-RPC client(Py)
底层 transportspawn claude 二进制 + stream-json stdioTS: spawn codex exec --experimental-json;Py: codex app-server --listen stdio://
控制面(审批/hook)进程内回调:can_use_tooloptions.hooks(PreToolUse 等)app-server 审批请求/通知;TS exec 形态控制面弱(无 hook 回调,策略需预先固化)
Session 管理continue/resume/fork optionsthread 概念;codex exec resume、Py thread 对象
结构化输出--json-schemastructured_output 字段outputSchema / --output-schema FILE
可观测性CLI 内建 OTel(span/metrics/log events),SDK 透传配置OTel 在 codex-rs otel crate;SDK 层无独立遥测面 [推断]
输入模式Streaming Input(AsyncIterable,推荐)/ Single Message单 turn 输入(thread.run(prompt)),无流式输入通道
协议 schema 可导出否(私有契约,跟版本走)是:app-server generate-ts/json-schema [一手源码]
换 runtime 的可能无(cli_path 只能指向另一个 claude)无(绑死 codex 二进制 / Responses API wire)

最小复现

# CC SDK 同款行为的 CLI 等价(SDK 内部即拼这些 flag)
claude -p "列出本目录文件" --output-format stream-json --verbose | head -3
# {"type":"system","subtype":"init",...}
# {"type":"assistant",...}

# Codex TS SDK 同款行为的 CLI 等价
codex exec --json "列出本目录文件" | head -3
# {"type":"thread.started","thread_id":"..."}
# {"type":"turn.started"}
# {"type":"item.completed","item":{...}}

# Codex Py SDK 的协议地基:导出该版本的协议类型
codex app-server generate-ts --out ./schema
// 两家 SDK 的最小对照(均为官方 README 示例风格)
// CC:query() 异步迭代器
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
  prompt: "Find and fix the bug in auth.ts",
  options: { allowedTools: ["Read", "Edit", "Bash"] },
})) { console.log(message); }

// Codex:Thread 模型
import { Codex } from "@openai/codex-sdk";
const thread = new Codex().startThread();
const turn = await thread.run("Diagnose the test failure");
console.log(turn.finalResponse, turn.items);

Harness 接入建议(Yoda 实践)

  • Yoda 当前走 CLI spawn + PTY(26 个 provider 统一用 provider registry 描述 CLI flag/resume/keystroke 行为,yoda/agents/integrations/providers.md),这本质上就是「自建 IR + 薄 adapter」路线——与先行报告结论一致,不要回头赌单家 SDK 当统一层
  • 但对 CC/Codex 这两家头部 provider,建议把 PTY 文本解析升级为结构化双轨:CC 走 claude -p --output-format stream-json(或直接 Agent SDK),Codex 走 codex exec --json 或 app-server stdio。Yoda 已有 agent-event-classifier 抽象(src/main/core/conversations/impl/agent-event-classifiers/),把 classifier 输入从终端文本换成 JSONL 事件即可,上层 IR 不用动。
  • Codex 侧优先 app-server(Python SDK 同款协议)而非 exec JSONL:app-server 有审批回调、thread 生命周期和可导出 schema;exec JSONL 没有审批交互(策略只能预先用 --sandbox/-c 固化)。
  • CC 侧注意 2026-06-15 的 SDK 独立计费额度——Yoda 用户用订阅登录时,spawn claude -p 的量会从新额度扣,需要在 UI 上向用户解释用量归属。

失效条件

  • Claude Agent SDK 若重新引入 session 类 API(V2 曾出现又移除),query() 单入口结论需复核
  • @openai/codex-sdk 仍标 0.0.0-dev、Python SDK 标 Beta:API 面(thread/turn 命名、事件 shape)可能破坏性变更
  • --experimental-json 别名转正或 ThreadEvent 事件 tag 变化(exec/src/exec_events.rs)需回归
  • CC stream-json 控制协议 subtype 集合随版本增删(types.py 判别符),SDK 与 CLI 版本须同步升级

参考资料

  • 先行报告:output/articles/手工川-agent-sdk-统一调用可行性-2026-06-09-v0.1.md(接口层/协议层逐条源码论证)
  • CC 文档:claude-code-docs/docs/agent-sdk__overview.mdagent-sdk__sessions.mdagent-sdk__hooks.mdagent-sdk__typescript-v2-preview.mdheadless.md
  • Codex 源码:codex/sdk/typescript/README.mdcodex/sdk/typescript/src/exec.tscodex/sdk/python/src/openai_codex/client.pycodex/codex-rs/app-server/README.md(均 @ b89ce9a 2026-06-06)
  • 交叉章节:chapters/workflow/headless-ci.md(exec/print 模式细节)、chapters/standards/acp.md(编辑器侧中立协议)

On this page