Codex App Server 精读
调研时间:2026-06-22 源码 commit: 98845e4本地 CLI: codex-cli 0.125.0
一句话定位
App Server 是 Codex 的协议层——一个双向 JSON-RPC 2.0 服务,让 CLI、IDE 扩展、Desktop App、Web 等所有 Surface 通过统一的 Thread/Turn/Item 原语与 Codex Core 交互,同时管理多连接、审批流和事件流。
日常类比
App Server 就像一家 24 小时营业的「智能客服调度中心」:
- Thread = 一个客户的工单(从开启到归档的完整服务记录)
- Turn = 工单中的一次交互(客户发消息 → 客服处理 → 回复)
- Item = 交互中的具体动作(查了数据库、打了电话、给了答案)
- Surface = 客户接入渠道(电话、微信、邮件——都走同一个调度系统)
- Approval = 需要主管审批的操作(调度中心暂停处理,等主管在任何一个渠道上点”通过”)
类比边界:传统客服系统是人驱动的,App Server 是 AI agent 驱动的——模型在 Turn 内自主决定调用哪些工具,而非人工分派。
协议设计
传输层
| Transport | 启动方式 | 状态 | 适用场景 |
|---|---|---|---|
| stdio | codex app-server --stdio(默认) |
稳定 | IDE 扩展(进程间通信) |
| Unix Socket | codex app-server --listen unix:// |
稳定 | 本地多客户端共享 |
| WebSocket | codex app-server --listen ws://IP:PORT |
实验性 | 远程访问(不推荐生产) |
[文档] 所有 transport 共享相同的 JSON-RPC 消息格式(省略 "jsonrpc":"2.0" header)。
背压机制
App Server 使用 bounded queue:
- 请求入口饱和时返回 JSON-RPC error code
-32001(”Server overloaded; retry later”) - 客户端应使用指数退避重试
[文档] 这是生产级设计——防止 IDE 高频操作打爆 agent 循环。
核心原语
erDiagram
Thread ||--o{ Turn : "contains"
Turn ||--o{ Item : "contains"
Thread {
string id
string status "notLoaded|idle|active"
string path "JSONL rollout 路径"
bool ephemeral "临时 thread"
}
Turn {
string id
string status "inProgress|completed|interrupted|failed"
int tokenUsage
}
Item {
string id
string type "userMessage|agentMessage|commandExecution|fileChange|reasoning..."
string status "inProgress|completed|failed|declined"
}
Thread 生命周期
notLoaded → thread/start|resume|fork → idle → turn/start → active → turn/completed → idle
↑___________↓
(多次 turn)
idle → 30min timeout → thread/closed → notLoaded
idle → thread/archive → archived
Turn 生命周期
turn/start → inProgress
→ item/started ... item/completed (多个 items)
→ [approval request? → 暂停等待 → client response → 继续]
→ turn/completed (completed | interrupted | failed)
API 概览(按领域分类)
Thread 管理(14 个方法)
| 方法 | 说明 | 状态 |
|---|---|---|
thread/start |
创建新 thread,自动订阅事件 | 稳定 |
thread/resume |
恢复已有 thread | 稳定 |
thread/fork |
从已有 thread 分支 | 稳定 |
thread/list |
分页列出 threads(支持 cursor/filters) | 稳定 |
thread/read |
读取 stored thread 不 resume | 稳定 |
thread/archive / unarchive / delete |
生命周期管理 | 稳定 |
thread/rollback |
回滚最后 N 个 turns | 稳定 |
thread/compact/start |
触发上下文压缩 | 稳定 |
thread/settings/update |
更新 thread 设置 | 实验性 |
thread/memoryMode/set |
设置 memory 资格 | 实验性 |
Turn 控制(3 个方法)
| 方法 | 说明 |
|---|---|
turn/start |
发送用户输入,开始新 turn |
turn/steer |
向进行中的 turn 追加输入(不打断) |
turn/interrupt |
中断进行中的 turn |
命令/文件系统(10+ 个方法)
直接操作:command/exec、fs/readFile、fs/writeFile、fs/watch 等——供 IDE 做文件预览、终端模拟。
Config/Skills/Plugins/MCP(20+ 个方法)
运行时管理:model/list、skills/list、plugin/install、mcpServer/tool/call 等。
认证/账户(6 个方法)
OAuth 登录、用量查询、速率限制。
[源码][文档] 总计 80+ 个 API 方法,是目前开源 Agent 系统中 协议最完整的。
审批机制(Server-Initiated Requests)
这是 App Server 最独特的设计:服务端主动向客户端发送 JSON-RPC request,客户端必须 response 后 turn 才能继续。
审批类型
flowchart LR
subgraph approvals["Server → Client 审批请求"]
CE[commandExecution<br/>requestApproval]
FC[fileChange<br/>requestApproval]
PM[permissions<br/>requestApproval]
EL[mcpServer<br/>elicitation]
TC[item/tool/call<br/>动态工具]
end
命令执行审批流程
1. item/started ← server 通知:pending commandExecution item
2. item/commandExecution/ ← server REQUEST(等待 client response)
requestApproval
{ command, cwd, reason,
proposedExecpolicyAmendment,
availableDecisions }
3. client response → { decision: "accept" | "acceptForSession"
| "acceptWithExecpolicyAmendment"
| "decline" | "cancel" }
4. serverRequest/resolved ← server 确认
5. item/completed ← 执行结果
审批决策持久化
acceptForSession— 本 session 内免审批acceptWithExecpolicyAmendment— 写入.rules文件,永久免审批applyNetworkPolicyAmendment— 网络规则持久化
[文档] 这种设计让 IDE 可以渲染富 UI(代码 diff 预览、命令高亮),而不仅仅是 y/n 确认。
事件流(Notifications)
App Server 输出 40+ 种 notification,按领域分组:
Thread/Turn 生命周期事件
thread/started、thread/closed、thread/status/changedturn/started、turn/completed、turn/diff/updated
Item 流式事件(核心体验)
item/started→item/agentMessage/delta(流式文本)→item/completeditem/commandExecution/outputDelta(命令输出流)item/fileChange/patchUpdated(文件 diff 流)item/reasoning/summaryTextDelta(推理过程流)
系统事件
configWarning、warning、errormcpServer/startupStatus/updatedskills/changed
[源码] 客户端可以在 initialize 时通过 optOutNotificationMethods 关闭不需要的事件类型,减少带宽。
关键架构决策
1. 请求序列化队列
RequestSerializationQueues 确保对同一 thread 的请求按序执行,避免并发竞态:
Client A: turn/start(thread_1) ──→ queue_1 ──→ 串行处理
Client B: turn/steer(thread_1) ──→ queue_1 ──→ 等 A 处理完
Client C: turn/start(thread_2) ──→ queue_2 ──→ 并行处理(不同 thread)
[源码] 这是多客户端共享 App Server 的核心保证。
2. Subscriber-based 事件分发
- 连接通过
thread/start/resume/fork自动订阅 thread/unsubscribe退出订阅- 最后一个 subscriber 离开后 30min idle 才卸载 thread
- 支持多客户端同时观察同一 thread
3. JSONL Rollout 持久化
Thread 历史存储为 JSONL rollout 文件(一行一个 ResponseItem),元数据存 SQLite。这比 JSON 单文件更适合流式追加和增量恢复。
4. 实验性 API 门控
#[experimental("some_feature_flag")]
async fn handle_experimental_method(...) { ... }
[源码] 运行时根据 capabilities.experimentalApi 决定是否暴露实验性方法,客户端可安全忽略未知 notification。
与 LangGraph 的对比
| 维度 | Codex App Server | LangGraph(LangGraph Platform) |
|---|---|---|
| 协议 | JSON-RPC 2.0 双向 | REST API + SSE |
| 原语 | Thread / Turn / Item | Thread / Run / Event |
| 审批 | Server-initiated request(阻塞 turn) | Human-in-the-loop interrupt |
| 传输 | stdio / Unix socket / WebSocket | HTTP + WebSocket |
| 多客户端 | 原生支持多连接共享 thread | 通过 checkpoint 共享 |
| 实时流 | notification 事件流 | SSE / streaming endpoint |
关键差异:Codex App Server 的审批是 协议级设计——它不是在 agent loop 外加一个 webhook,而是 turn 执行过程中原生暂停等待客户端响应。这让 IDE 可以做到 同步审批 + 富 UI 展示。
与 Claude Code 的差异(待 Agent A 核对)
- Codex App Server 是 独立进程,Surface 通过 IPC 连接;Claude Code 各 surface(CLI、VS Code、Web)更倾向于直接链接 core 模块(推测)
- Codex 有显式的 Thread/Turn/Item 三层原语和完整 CRUD API;Claude Code 的会话管理 API 不公开
- Codex 审批是协议级 server-initiated request;Claude Code 的权限弹窗是 UI 层面实现
- Codex 支持多客户端同时连接观察同一 thread;Claude Code 是否支持多客户端共享 session 未知
- Codex App Server 有 80+ API 方法(含 fs、mcp、plugins 等完整管理面);Claude Code 的管理面主要通过 CLI 参数和配置文件
局限性
- WebSocket transport 不稳定:官方标注 “experimental and unsupported”,不建议生产使用 [文档]
- 审批阻塞问题:若客户端崩溃,pending approval 将无限阻塞 turn;需要 timeout 机制 [待验证]
- API 爆炸性增长:80+ 方法 + 40+ notification 类型,客户端实现成本高 [源码]
- 实验性 API 变动风险:标注
experimental的方法可能在版本间不兼容变更 [文档] - 状态一致性:多客户端并发
turn/start和turn/steer时,序列化队列保证正确性,但用户体验可能出现延迟 [源码]
证据等级汇总
| 结论 | 来源 |
|---|---|
| JSON-RPC 2.0 双向协议,支持 stdio/unix/ws | [源码][文档] app-server/README.md |
| Thread/Turn/Item 三层原语 | [文档] Core Primitives 章节 |
| 80+ API 方法 | [源码] app-server/src/request_processors/ |
| 40+ notification 类型 | [源码][文档] Events 章节 |
| Server-initiated approval requests | [文档] Approvals 章节 |
| 请求序列化队列 | [源码] RequestSerializationQueues |
| bounded-queue 背压(-32001) | [文档] Protocol 章节 |
| 实验性 API 门控宏 | [源码] #[experimental] attribute |