OpenAI Codex 三大开源组件:exec、SDK、app-server 用法全解
很多人以为"强大的 AI Agent = 好模型 + 好 Prompt"。但实际上,模型之上还叠着一整套底层执行系统(Harness):理解任务、维护对话记忆、调用工具、实时展示进度、处理失败、请求人类审批。这部分决定了 Agent 能不能真正"干活",也决定了把 Agent 嵌进产品时的体验上限。
OpenAI 在开源仓库 openai/codex 里把这套 harness 的三个组件开放了出来,分层恰好对应三种不同的接入方式:
| 组件 | 形态 | 一句话 | 适合场景 |
|---|---|---|---|
| codex exec | CLI 子命令 | 非交互式跑完一个任务 | 脚本、CI、一次性后台任务 |
| Codex SDK | TypeScript / Python 库 | 在应用代码里启动/恢复/流式监听任务 | CI/CD、内部工具、应用集成 |
| Codex app-server | 本地 JSON-RPC 服务 | 把 Agent 变成你产品的"一等公民" | 持久对话、实时事件、打断、自定义工具、审批 |
下面逐个过用法,代码片段可以直接跑。
说明:Codex 演进很快,本文所有命令均以 openai/codex 当前源码(
rust-v0.132+)为准;旧文章里的参数可能已经变了,拿不准时先跑codex exec --help。
一、codex exec:非交互式自动化
安装
npm install -g @openai/codex
装完先登录一次(codex login,或复用已有的 Codex 会话)。
基本用法
# 跑一个一次性任务,在当前目录下
codex exec "Diagnose the CI failure and propose a fix"
# 指定工作目录
codex exec -C /path/to/project "Fix the failing tests"
# 从 stdin 读提示词(管道场景很方便)
echo "Add unit tests for the auth module" | codex exec -
codex exec 还有几个子命令:codex exec resume <SESSION_ID>(恢复上次会话)、codex exec fork <SESSION_ID>(从某次会话分叉)、codex exec review(对当前仓库跑一次 code review)。
关键参数(以当前版本为准)
| 参数 | 说明 |
|---|---|
-s, --sandbox <MODE> | 沙箱策略:read-only / workspace-write / danger-full-access |
--approve-for-me(别名 --not-so-yolo) | 把审批交给自动审查(auto-review),同时强制 workspace-write |
--dangerously-bypass-approvals-and-sandbox(--yolo) | 危险:跳过所有确认与沙箱,仅在外部已有沙箱的环境用 |
-m, --model <MODEL> | 指定模型 |
-C, --cd <DIR> | 工作根目录 |
--add-dir <DIR> | 额外可写目录(配合 workspace-write) |
--json | 把事件以 JSONL 打到 stdout,机器可读 |
-o, --output-last-message <FILE> | 把 Agent 的最后一条回复写到文件 |
--output-schema <FILE> | 传一个 JSON Schema 文件,约束 Agent 结构化输出 |
--ephemeral | 不把会话持久化到磁盘 |
--skip-git-repo-check | 允许在非 Git 仓库里运行 |
-i, --image <FILE> | 附加图片输入 |
⚠️ 版本提示:网上不少教程提到的
--approval-policy、--max-turns、--timeout在当前源码里已经不存在了——审批和沙箱改由--sandbox/--approve-for-me以及config.toml里的approval_policy、sandbox_mode控制。老版本迁移过来时注意。
结构化输出:把结果喂给下游程序
# schema.json 例如 {"type":"object","properties":{"summary":{"type":"string"},"status":{"type":"string"}},"required":["summary","status"]}
codex exec "Summarize repository status" --output-schema ./schema.json --json | jq 'select(.type=="turn/completed")'
--json 时,每一行是一个带 "type" 标签的事件(thread/started、turn/started、item/started、item/completed、turn/completed…),item 类型包括 agentMessage、reasoning、commandExecution、fileChange、mcpToolCall 等。下游脚本按事件类型过滤即可拿到最终结果与执行痕迹。
典型 CI 场景
- GitHub Actions:PR 时对 diff 跑一次
codex exec review或codex exec "Review the diff",把结论贴成评论; - GitLab CI:自动生成文档 / CHANGELOG,再自动提交;
- Jenkins / CircleCI:用一段可移植的 shell 脚本包一层
codex exec,把结构化结果透传给通知系统。
CI 里建议固定版本(npm install -g @openai/codex@<version>),避免上游行为变化导致流水线不稳定。
二、Codex SDK:把 Codex 嵌进应用
SDK 的目标是"编程式启动、恢复、流式监听 Codex 任务"。TypeScript 版包住 codex CLI(子进程 + stdio 上交换 JSONL);Python 版走本地 app-server(JSON-RPC),并且自带一份配套的 Codex CLI 运行时,不需要单独装 CLI。
2.1 TypeScript(@openai/codex-sdk)
npm install @openai/codex-sdk # 需要 Node.js 18+
快速开始:
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);
console.log(turn.items);
在同一线程上继续对话(复用 Thread 实例即可):
const nextTurn = await thread.run("Implement the fix");
流式监听(做 UI 进度条、实时渲染工具调用时用):
const { events } = await thread.runStreamed("Diagnose the test failure and propose a fix");
for await (const event of events) {
switch (event.type) {
case "item.completed":
console.log("item", event.item);
break;
case "turn.completed":
console.log("usage", event.usage);
break;
}
}
结构化输出(传 JSON Schema,或从 Zod 生成):
const schema = {
type: "object",
properties: {
summary: { type: "string" },
status: { type: "string", enum: ["ok", "action_required"] },
},
required: ["summary", "status"],
additionalProperties: false,
} as const;
const turn = await thread.run("Summarize repository status", { outputSchema: schema });
console.log(turn.finalResponse);
附加图片(文本 + 本地图片混排):
const turn = await thread.run([
{ type: "text", text: "Describe these screenshots" },
{ type: "local_image", path: "./ui.png" },
]);
恢复历史会话(线程持久化在 ~/.codex/sessions):
const savedThreadId = process.env.CODEX_THREAD_ID!;
const thread = codex.resumeThread(savedThreadId);
await thread.run("Implement the fix");
指定工作目录 / 跳过 Git 检查 / 控制子进程环境:
const thread = codex.startThread({
workingDirectory: "/path/to/project",
skipGitRepoCheck: true,
});
// 完全接管传给 CLI 的环境变量(适合 Electron 等沙箱宿主)
const codex = new Codex({
env: { PATH: "/usr/local/bin" },
});
2.2 Python(openai-codex)
pip install openai-codex # 需要 Python >= 3.10,自带 Codex CLI 运行时
快速开始:
from openai_codex import Codex
with Codex() as codex:
thread = codex.thread_start()
result = thread.run("Explain this repository in three bullets.")
print(result.final_response)
thread.run(...) 返回 TurnResult,含最终回复、收集的 items 和 token 用量。
沙箱预设(对线程或单次 turn 指定文件系统访问):
from openai_codex import Codex, Sandbox
with Codex() as codex:
thread = codex.thread_start(sandbox=Sandbox.workspace_write)
thread.run("Make the requested changes.")
review = thread.run("Review the diff only.", sandbox=Sandbox.read_only) # turn 级覆盖
三个预设:Sandbox.read_only(只读)、Sandbox.workspace_write(工作区可写,日常默认)、Sandbox.full_access(不限制)。
继续 / 恢复线程:
with Codex() as codex:
thread = codex.thread_start()
thread.run("Summarize Rust ownership in two bullets.")
result = thread.run("Now explain it to a Python developer.")
# 之后任何时刻按 id 恢复
with Codex() as codex:
thread = codex.thread_resume("thr_123")
print(thread.run("Continue where we left off.").final_response)
异步客户端:
import asyncio
from openai_codex import AsyncCodex, Sandbox
async def main() -> None:
async with AsyncCodex() as codex:
thread = await codex.thread_start(sandbox=Sandbox.workspace_write)
result = await thread.run("Continue where we left off.")
print(result.final_response)
asyncio.run(main())
登录(默认复用已有 Codex 会话,必要时显式登录):
with Codex() as codex:
codex.login_api_key("sk-...") # API key
# 或 ChatGPT 浏览器登录 / 设备码登录:
# codex.login_chatgpt()
# codex.login_chatgpt_device_code()
Python SDK 还内置了完整帮助:help(openai_codex)、help(Codex),或 python -m pydoc openai_codex。
三、Codex app-server:让 Agent 成为你产品的一部分
前面两个是"调用 Codex 干一次活",app-server 是反过来——你连上一个常驻的 Codex 进程,把 Agent 直接嵌进产品 UI。它本质是一个有状态的本地 JSON-RPC 2.0 服务,负责持久对话、实时事件流、中途打断、把自研工具暴露给 Agent、以及请求人类审批。官方的 VS Code 扩展就是它的一个客户端。
启动与传输层
# 默认 stdio 传输:JSONL over stdin/stdout,适合父进程直接拉起
codex app-server
# WebSocket 传输(实验性,带健康探针 /readyz、/healthz)
codex app-server --listen ws://127.0.0.1:4242
# Unix socket(供本地控制面客户端用)
codex app-server --listen unix://
# 不暴露任何本地传输
codex app-server --listen off
协议和 MCP 类似:JSON-RPC 2.0(线上省略 "jsonrpc":"2.0" 头)。服务端过载时会回 -32001 + "Server overloaded; retry later.",客户端应按指数退避重试。
核心概念:Thread / Turn / Item
- Thread:用户与 Agent 的一段对话,包含多个 turn;
- Turn:一轮对话,通常从一条用户消息开始、到一条 Agent 消息结束,包含多个 item;
- Item:turn 里的输入/输出单元——用户消息、Agent 推理、Agent 消息、shell 命令、文件编辑等,会持久化作为后续上下文。
一次完整对话的生命周期
1. initialize → 连接建立后先发 initialize(带 clientInfo)
2. initialized → 客户端回一个 initialized 通知,完成握手
3. thread/start → 开新会话(或 thread/resume 恢复、thread/fork 分叉)
4. turn/start → 提交用户输入,立即返回 turn 对象
5. (事件流) → 持续收到 item/started、item/completed、item/agentMessage/delta …
6. turn/completed → 收到最终 turn 状态与 token 用量(或用 turn/interrupt 打断)
握手示例(参考官方 VS Code 扩展):
{ "method": "initialize", "id": 0, "params": {
"clientInfo": { "name": "codex_vscode", "title": "Codex VS Code Extension", "version": "0.1.0" }
} }
开一个新会话:
{ "method": "thread/start", "id": 10, "params": {
"model": "gpt-5.1-codex",
"cwd": "/Users/me/project",
"approvalPolicy": "never",
"sandbox": "workspaceWrite"
} }
提交一轮对话(支持 text / image / audio 输入,以及 outputSchema 约束结构化输出):
{ "method": "turn/start", "id": 30, "params": {
"threadId": "thr_123",
"input": [ { "type": "text", "text": "Run tests" } ],
"sandboxPolicy": { "type": "workspaceWrite", "writableRoots": ["/Users/me/project"] }
} }
打断进行中的 turn:
{ "method": "turn/interrupt", "id": 31, "params": {
"threadId": "thr_123",
"turnId": "turn_456"
} }
服务端会为每个 item 发一条
item/started(完整 item)→ 若干 delta →item/completed(最终状态)。UI 就按这个节奏逐条渲染,进度是实时可见的。
Human-in-the-loop:审批流
这是 app-server 最"产品化"的能力。当 Agent 要执行 shell 命令或改文件、且按用户配置需要审批时,服务端会主动向客户端发一个 JSON-RPC 请求,而不是等轮询:
{ "method": "item/commandExecution/requestApproval", "id": 50, "params": {
"itemId": "item_123",
"threadId": "thr_123",
"turnId": "turn_456",
"command": "rm -rf /tmp/cache",
"cwd": "/Users/me/project",
"reason": "Clear build cache"
} }
客户端在 UI 里展示这个命令/文件 diff,由用户决定后回一条:
{ "id": 50, "result": { "decision": "accept" } }
可选的 decision 还有 acceptForSession(本次会话内放行)、acceptWithExecpolicyAmendment(放行并写入规则)、decline、cancel。文件变更审批走 item/fileChange/requestApproval,流程一样。这就是把"人在环上"做进产品的方式:命令是否执行、diff 是否落地,都由你 UI 里的用户拍板。
暴露自研工具:dynamicTools(实验性)
把业务工具注册给 Agent,Agent 干活时由客户端执行并回结果——工具逻辑不出你的进程。
在 thread/start 里声明工具:
{ "method": "thread/start", "id": 10, "params": {
"dynamicTools": [{
"type": "namespace",
"name": "tickets",
"description": "Ticket management tools",
"tools": [{
"type": "function",
"name": "lookup_ticket",
"description": "Fetch a ticket by id",
"inputSchema": {
"type": "object",
"properties": { "id": { "type": "string" } },
"required": ["id"]
}
}]
}]
} }
Agent 调用时,服务端发 item/tool/call 请求,你执行后回 contentItems 和 success:
{ "method": "item/tool/call", "id": 60, "params": {
"threadId": "thr_123",
"turnId": "turn_123",
"callId": "call_123",
"namespace": "tickets",
"tool": "lookup_ticket",
"arguments": { "id": "ABC-123" }
} }
{ "id": 60, "result": {
"contentItems": [ { "type": "inputText", "text": "Ticket ABC-123 is open." } ],
"success": true
} }
实验特性需要握手时声明
"capabilities": { "experimentalApi": true }。同理还有thread/goal/*(给线程挂长期目标)、review/start(自动化代码评审)、command/exec(不建线程直接跑命令)等一批接口。
生成协议 Schema
协议按版本演进,不要手写类型。直接用配套命令从当前二进制导出,保证和版本一致:
codex app-server generate-ts --out DIR # TypeScript 类型
codex app-server generate-json-schema --out DIR # JSON Schema bundle
给接入方的一个提醒
initialize 里的 clientInfo.name 会用于 OpenAI 的合规日志平台。如果你做的是面向企业的集成,需要联系 OpenAI 把你加进已知客户端列表,否则合规日志里就是陌生的 client 名。
四、选型建议:什么时候用哪个
| 需求 | 选哪个 |
|---|---|
| 跑一次脚本/CI 任务,拿到结构化结果 | codex exec |
| 应用代码里按需启动、恢复、流式监听 Codex | Codex SDK |
| Agent 就是产品的一部分:持久对话、实时进度、可打断、要审批、要接自研工具 | codex app-server |
| 只是想把 Codex 作为多 Agent 编排里的一个"专家" | 建议用 Codex CLI 作为 MCP server,交给 Agents SDK 编排,而不是直接操作 app-server |
官方文档的一句话总结:exec 面向脚本/CI,SDK 面向应用代码,app-server 面向把 Agent 做进产品。
参考
- 仓库:https://github.com/openai/codex
- 官方文档:https://learn.chatgpt.com/docs/codex-sdk 、https://learn.chatgpt.com/docs/app-server 、https://learn.chatgpt.com/docs/codex-cli
本文命令与参数均核对自 openai/codex 当前源码;若与你在用版本的 --help 不一致,以你本机版本为准。
