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-58 的 query() 签名)。曾经的 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 可执行文件,找不到直接抛 CLINotFoundError(claude-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)[一手源码]。
Sessions:continue(接最近一次)、resume(按 session_id)、fork 都是 query() 的 option 字段;session_id 从 init 消息里取(agent-sdk__sessions.md:28-36, 174-188)[一手文档]。
Hooks-in-SDK:options.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/ 目录):
- TypeScript
@openai/codex-sdk:README 自述 "wraps thecodexCLI... 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:181spawn()子进程。API 模型是Codex → startThread() → thread.run()/runStreamed(),事件即codex exec --json的item.completed/turn.completedJSONL(见 headless 章)。支持outputSchema结构化输出。包版本仍是0.0.0-dev(sdk/typescript/package.json)。 - Python
openai-codex(Beta):不是包 exec,而是「Synchronous typed JSON-RPC client forcodex app-serverover stdio」(sdk/python/src/openai_codex/client.py:193),启动参数["app-server", "--listen", "stdio://"](client.py:230)。能力面更宽:thread_start/run、流式事件、登录管理(login_chatgpt/login_api_key,sdk/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::TurnInterrupt、ServerNotification::TurnCompleted)[一手源码]。
Thread 续传:TS SDK 在同一 Thread 实例上反复 run() 即续对话(sdk/typescript/README.md),底层对应 codex exec resume <session_id>|--last(exec/src/cli.rs:165-204:session id 可以是 UUID 或 thread name,--last 取最近会话)[一手源码];--ephemeral 则完全不落盘(cli.rs:30-32),适合不想留痕的嵌入场景。Python SDK 通过 app-server 的 thread 生命周期 API 管理(05_existing_thread、06_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 Code | Codex 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) |
| 底层 transport | spawn claude 二进制 + stream-json stdio | TS: spawn codex exec --experimental-json;Py: codex app-server --listen stdio:// |
| 控制面(审批/hook) | 进程内回调:can_use_tool、options.hooks(PreToolUse 等) | app-server 审批请求/通知;TS exec 形态控制面弱(无 hook 回调,策略需预先固化) |
| Session 管理 | continue/resume/fork options | thread 概念;codex exec resume、Py thread 对象 |
| 结构化输出 | --json-schema → structured_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.md、agent-sdk__sessions.md、agent-sdk__hooks.md、agent-sdk__typescript-v2-preview.md、headless.md - Codex 源码:
codex/sdk/typescript/README.md、codex/sdk/typescript/src/exec.ts、codex/sdk/python/src/openai_codex/client.py、codex/codex-rs/app-server/README.md(均 @ b89ce9a 2026-06-06) - 交叉章节:
chapters/workflow/headless-ci.md(exec/print 模式细节)、chapters/standards/acp.md(编辑器侧中立协议)
IDE / ACP 集成
CC 用「lockfile 发现 + IDE 充当 MCP server」把 CLI 接进编辑器,扩展自带 GUI 面板;Codex 用 app-server JSON-RPC 给官方 VS Code 扩展供电。两家在本快照中都未实现 ACP。
Git Worktree 并行
CC 把 worktree 做成了一等能力:--worktree flag、EnterWorktree/ExitWorktree 工具、subagent isolation、.worktreeinclude、fail-closed 自动清理、非 git VCS hook 替换。Codex CLI 完全没有 worktree 管理——并行隔离押在云端容器(cloud-tasks)上。