你跟同事聊 Codex 的时候,有没有过这种体验?你说「我用 Codex 写了个脚本」,「我用 Codex 审查了 PR」,他说「我在 VS Code 里用 Codex 重构了模块」。听起来都是 Codex,但背后走的路径完全不同。

你用的是 CLI,他是 IDE 插件,运维那边用 codex exec 跑 CI,平台组在往自己的产品里嵌入 Codex SDK。七种入口,七种交互方式,但底层跑的是同一套东西:一个 Agent 循环。

这篇文章把 Codex 的嵌入架构从里到外拆开:先从 Agent 循环讲起,然后看 Sandbox 和 Approval 两个关键控制点,最后深入 App Server 协议和两个 SDK 的本质差异。读完你就知道什么时候该用 SDK,什么时候必须直接上 App Server。

Codex 的七扇门#

先看全局。Codex 的入口可以分成三类:

交互式入口(给人用的)

  • CLI:在终端里直接跟 Codex 对话,检查代码、做修改、跑命令,沙箱和审批策略按会话配置。
  • IDE 扩展:支持 VS Code 和 JetBrains,直接把打开的文件和选中内容送进 Prompt,就地审查修改,还能把长任务丢到云端。
  • 桌面应用:2026 年 7 月 9 日起合并进了 ChatGPT 桌面应用,像一个指挥中心,可以同时管理多个项目和 Agent。
  • Codex Cloud:完全跳过你的本地机器,在隔离的云端环境里执行任务。你可以从网页、GitHub、Linear 或 Slack 派发任务,等结果就行。

编程式入口(用来集成和构建的)

  • codex exec:把 CLI 变成一行命令,给 CI 和自动化脚本用。进度以行分隔的 JSON 流输出。GitHub Action 本质上就是套了一层 CI 壳的 codex exec
  • Codex SDK:Python 和 TypeScript 两个版本。SDK 在你的机器上启动 codex 二进制作为子进程,然后通过代码来开始和恢复对话。适合把 Codex 嵌入 CI/CD 系统,或者构建自定义 Agent 宿主。
  • codex app-server:一个 JSON-RPC 接口,IDE 扩展和 Python SDK 的底层都在用。它定义了「跟 Codex 对话」到底意味着什么。当你需要自定义 UI、自己的审批逻辑,或者用非 Node/Python 的语言做宿主时,这就是你要走的路。
  • codex mcp-server(实验性):把 Codex 暴露为一个 MCP 工具,让其他 Agent 像调用普通工具一样调用 Codex。

前四个是给人用的,中间两个是给平台工程师和 CI 用的,最后两个才是真正的嵌入路径。很多人搞混的,就是 App Server 和 SDK。一个是原始协议,一个是预制的客户端。下面我们一步步说清楚。

Agent 循环:一次请求 = 多次行动#

在我解释 App Server 协议之前,得先理解它包裹的是什么。所有入口,无论 CLI、IDE 还是 Cloud,底层跑的都是同一个 Agent 循环。

很多人第一次用 Codex 会有一个错觉:我发一条消息,模型生成一个回复,结束。不是这样的。一次「回合」(turn)是一次完整的迭代过程:

  1. 模型读取你的请求
  2. 模型提出一个行动(比如运行测试、编辑文件、执行命令)
  3. 运行时在沙箱里执行这个行动
  4. 结果返回给模型
  5. 模型根据结果决定下一步
  6. 重复 2-5,直到模型认为任务完成
  7. 模型发出最终消息,回合结束

一条「诊断失败测试并修复它」的请求,可能在一次回合里展开成多次推理调用、多次 shell 命令和多次文件编辑。模型不是一次性想好所有步骤然后执行,它是一步一步试探,每步都根据前一步的结果来调整。

这个过程背后有两个关键优化。一是前缀缓存(prefix caching),让重复的上下文保持廉价;二是历史压缩(history compaction),当上下文超过阈值时自动压缩。但这些对你不可见,你看到的就是这个循环:提出 → 执行 → 观察 → 重复

下面这张图描述了整个循环:你发送一条消息,模型在循环中反复执行,直到最终回复。理解了这个循环,后面看 App Server 协议的每个方法就清楚了,每个方法都对应这个循环的某个节点。

两道闸门:Sandbox 和 Approval#

在嵌入 Codex 之前,你必须理解两个独立但又常常被混淆的控制机制。一个是技术边界(Sandbox),一个是决策边界(Approval)。混用它们,要么给 Agent 过多自由,要么束缚得太紧。

Sandbox:技术边界#

Sandbox 定义 Agent 物理上能做什么,由运行时强制执行,不是靠 Agent 自觉。三个级别:

  • read-only:Agent 可以查看文件,但不能编辑,不能运行命令。
  • workspace-write(默认):可以在工作区内读写、编辑、运行常规本地命令。网络访问默认关闭,需要显式开启。
  • danger-full-access:Agent 能做任何事情,包括访问网络、修改系统文件。慎用。

Sandbox 是一道围栏,围住了 Agent 的「能力范围」。Agent 天生就想干活,你不设围栏,它会帮你把整个项目目录清理了(别问我怎么知道的)。

Approval:决策边界#

Approval 决定 Agent 在跨过某些边界之前必须停下来问你。即使它在 workspace-write 沙箱里运行,有些操作你还是想看一眼。

  • auto-accept:全部自动放行,Agent 永远不需要问你。
  • ask-everything:每次操作都问你,包括读文件。安全但非常烦人。
  • default:按照风险分级,常规操作自动放行,高风险操作(如 rm -rfgit push --force、网络请求)弹窗让你确认。

Sandbox 和 Approval 是正交的。你可以给 Agent workspace-write 的沙箱,但把 Approval 设成 ask-everything,让它在每次编辑前都征求你的意见。反过来,你也可以给 danger-full-access 但设 auto-accept,这就像把车钥匙交给一个不认识的人并告诉他「随便开」,技术上允许,但大概率你会后悔。

理解了这两个控制点,我们来看 App Server 协议本身。

App Server 协议:JSON-RPC 的本质#

codex app-server 是 Codex 真正的「语言」。CLI、IDE 扩展、Python SDK,最终都在说这门语言。它基于 JSON-RPC,通过标准输入输出(stdio)通信,定义了三个核心概念:线程(thread)、回合(turn)、事项(item)。

线程:持久化的对话容器#

一个线程就是一个对话容器,有唯一 ID。你用 thread/start 开启一个新线程,或者用 thread/resume 恢复一个已有线程。线程跨进程持久化,你可以断开连接,过几天再通过同一个线程 ID 把对话接回来。

还有一个 thread/fork,可以从某个线程的某个点分叉出去,创建一条平行的对话路径。这在探索不同方案时非常有用。

回合:一个完整的循环#

回合在线程内运行。你发送 turn/start,带上用户输入,服务器立刻返回 status: "inProgress"。注意,这里只是接受了请求,还没执行。

接下来你的宿主代码停止发送请求,转为读取服务器推送的通知流:

  1. turn/started:回合开始
  2. 一系列 item/starteditem/agentMessage/delta(逐 token 流式推送)→ item/completed
  3. turn/completed:回合结束,包含 token 用量

每个事项(item)可以是推理步骤、shell 命令、文件编辑或消息。所有事项都走同样的 start-delta-complete 序列,所以宿主可以实况渲染进度,而不是等整个回合跑完。

审批往返:协议里最重要的时刻#

当 Agent 想做一件 Approval 策略不放行的事情时,App Server 不会自己决定。它向你的宿主发送一个请求:

  • item/commandExecution/requestApproval(命令审批)
  • item/fileChange/requestApproval(文件编辑审批)

请求里面包含命令内容、工作目录和理由。回合在这里阻塞,直到你的宿主回复决策。

你的宿主回复一个简单的 payload:{"decision": "accept"} 通过,或者 decline 拒绝,或者 acceptForSession 本次会话内记住。服务器收到后发送 serverRequest/resolved,事项继续执行直到 item/completed

这就是 App Server 给你而 codex exec 给不了的东西:一个实时的、逐项决定的、你可以插入自己逻辑的决策席位。你的宿主不是旁观者,是参与者。

两个 SDK:名似而实异#

大多数人不需要手写 JSON-RPC 宿主。你只想调一个函数,传一个 prompt,拿一个结果。这就是 SDK 的定位:预制的宿主客户端。

Codex 提供了 Python 和 TypeScript 两个 SDK。它们暴露的 API 表面很像:startThread()run(prompt)finalResponse。但底层实现完全不同,这个差异决定了你能做什么、不能做什么。

TypeScript SDK:codex exec 的语法糖#

TypeScript SDK 的实现出人意料地简单:它不跟 App Server 协议对话,它直接 spawn codex exec --experimental-json 进程,然后读取行分隔的事件流。

import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread();
const turn = await thread.run("Diagnose the test failure and propose a fix");
console.log(turn.finalResponse);

它暴露的事件是 codex exec 的 schema:thread.starteditem.completedturn.completed 这种点分隔的命名,而不是 App Server 的斜线命名。runStreamed() 方法让你拿到结构化事件流,但这套事件里根本没有 approval-request 这个东西,审批策略在进程启动时就锁死了,你无法中途介入。

Sandbox 控制也是通过 CLI 的 --sandbox 参数,不是类型化的枚举。一句话,TypeScript SDK 就是给 codex exec 套了一层好看的皮。

Python SDK:真正的协议封装#

Python SDK 是另一种东西。它的 CodexClient 明确定义自己是一个「针对 codex app-server 的 JSON-RPC stdio 客户端」,start() 方法 spawn 的也正是 App Server。

from openai_codex import Codex, Sandbox
with Codex() as codex:
    thread = codex.thread_start(sandbox=Sandbox.workspace_write)
    result = thread.run("Explain this repository in three bullets.")
    print(result.final_response)

Python SDK 给你一等公民的 Sandbox 枚举(read_onlyworkspace_writefull_access)、ApprovalMode,以及通过 thread.turn(...).stream() 获取的原始协议通知流,不是 codex exec 的粗糙事件。

当你在协议交互图中切换「宿主」为「Python SDK」模式时,它把整个握手、回合、流式事项全部折叠成了一次阻塞调用,返回一个 TurnResult

选择的关键:审批权在谁手里#

两个 SDK 都帮你处理了连接生命周期、消息关联和版本锁定。但它们也都吸收了你最想拿到的东西:审批决定权。

TypeScript SDK 根本不暴露审批事件。Python SDK 虽然能拿到原始协议流,但它的公开 API 只支持用预设的 ApprovalMode 策略自动回答审批,不允许你的代码在单个审批请求上做决定。

这就画出了一条清晰的分界线:

场景用 SDK用 App Server
CI 脚本,一次性跑完❌ 太重
批量处理,不需要人工干预
内部工具,启动后读结果
需要实况渲染 Agent 工作过程
需要在每个审批决策上介入
宿主语言不是 Python 或 Node

如果你选 SDK,Python 版比 TypeScript 版更强大:它直接说 App Server 协议,暴露了 Sandbox 枚举和原始事件流。TypeScript 版只是在 codex exec 外面包了一层。

为什么这很重要#

Codex 的开放架构正在改变我们对「AI 编程工具」的认知。它不是一个你只能通过官方 UI 访问的黑盒,而是一个可以嵌入任何产品、任何流水线的 Agent 运行时。

OpenAI 在 2026 年 6 月宣布收购 Ona(原 Gitpod),获取其安全云执行技术,让 Codex 能在持久化、快照化的云环境中执行长时间任务。「Agent 在笔记本合上之后还在工作」不再是一个科幻场景。

但无论 Agent 在哪里执行,你的笔记本、CI 容器、还是你永远看不到的云端数据中心,它的对话模型不变。 线程和回合的概念、事项流、审批往返,这套协议是稳定的基础设施。你学会一次,在哪都能用。

如果你只是想写个脚本跑完拉倒,SDK 够用。如果你想构建一个真正的 Agent 驱动产品,让用户在关键时刻做决策,去学 App Server 协议。它不复杂,只是一个 JSON-RPC 循环,但它是你真正「拥有」Codex 的方式。


参考来源:Akash Tandon, “Embedding OpenAI Codex: The App Server and SDKs”, July 2026.