Codex SDK 让 Node.js 程序启动、继续和恢复本地 Codex 线程。第一次接入时,先完成一次只读任务,再接事件日志和线程恢复;不要一开始就让程序自动改代码或发布结果。本文聚焦 @openai/codex-sdk 的 TypeScript 接口,资料核对于 2026 年 10 月 12 日。
SDK 与普通模型 API 有什么区别
TypeScript SDK 包装 Codex CLI,并通过标准输入输出交换 JSONL 事件。它运行的是具备项目上下文和工具能力的编码 Agent,并非向模型发送一条普通聊天请求。官方 SDK 页面将 CI 自动化列为适用场景;需要构建包含认证、审批和会话管理的完整客户端时,应另外评估 Codex app server。
准备 Node.js、项目目录与认证
官方要求 Node.js 18 或以上。先在临时 Git 项目中试用,准备一份 README.md,并确认当前运行用户的 Codex 认证可用。SDK 默认继承 Node.js 进程环境;服务进程与终端使用不同账户或环境时,登录和配置可能不同。
node --version
npm init -y
npm install @openai/codex-sdk
git init
已是 Git 仓库时不要重复初始化。记录 npm ls @openai/codex-sdk 的输出并保留锁文件,后续排错应对照已安装版本。
运行第一个只读线程
将下列各行依次保存为 example.mjs,在项目目录运行 node example.mjs。示例依据官方接口编写,未进行真实模型调用验证;只读要求写入任务,同时应使用运行环境的权限限制约束工具。
import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread({ workingDirectory: process.cwd() });
try {
const turn = await thread.run("只读取 README.md,使用中文说明启动方法;不修改文件,不执行安装命令。");
console.log(turn.finalResponse);
console.log('thread ID:', thread.id);
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exitCode = 1;
}
验收时检查最终回答是否引用实际 README,并确认 git status --short 没有意外变化。得到一段回答只说明该轮返回了结果,不代表任务内容正确,也不证明所有工具权限符合预期。
用 runStreamed 接收中途事件
run() 会缓冲事件直到该轮结束。希望显示中途状态时,换成 runStreamed() 并遍历 events。将下面完整示例保存为 stream.mjs,再运行 node stream.mjs;不要把它追加到上一个文件造成重复变量声明。
import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread({ workingDirectory: process.cwd() });
let completed = false;
try {
const { events } = await thread.runStreamed("只读取 README.md,概述启动方法;不修改文件,不执行命令。");
for await (const event of events) {
if (event.type === "thread.started") console.log("thread ID:", event.thread_id);
if (event.type === "item.completed" && event.item.type === "agent_message") {
console.log(event.item.text);
}
if (event.type === "turn.completed") {
completed = true;
console.log("usage:", event.usage);
}
if (event.type === "turn.failed") throw new Error(event.error.message);
if (event.type === "error") throw new Error(event.message);
}
if (!completed) throw new Error("本轮没有收到 turn.completed");
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exitCode = 1;
}
成功时应得到线程 ID、Agent 的文本以及 turn.completed 对应的 usage;失败事件、异常和缺失完成事件都按失败处理。空文本不应被当成完成任务。这里打印回答只用于不含敏感资料的示例项目,生产日志应脱敏并限制保留范围。
继续线程与重启后恢复
同一进程内,再次调用同一 thread 的 run() 会继续该线程。例如先问启动方法,再要求仅解释测试命令。独立项目或无关任务应新建线程,避免旧上下文影响回答。
const next = await thread.run("根据刚才读取的资料,只解释测试命令,不执行。");
console.log(next.finalResponse);
进程重启后,用保存的线程 ID 调用 resumeThread()。线程保存在 ~/.codex/sessions;恢复还依赖同一运行账户和相应会话文件,单独保存一个 ID 并不能把线程迁移到另一台服务器。
const savedId = process.env.CODEX_THREAD_ID;
if (!savedId) throw new Error("请设置 CODEX_THREAD_ID");
const resumed = codex.resumeThread(savedId);
const resumedTurn = await resumed.run("继续说明测试步骤,只读,不执行命令。");
console.log(resumedTurn.finalResponse);
线程 ID 是历史会话的入口,不是业务任务的幂等键。建议分别保存 business_task_id、thread_id、SDK 版本、最近一轮成功或失败状态。恢复一个线程只续接上下文,不会替你证明上次写入是否完成;写操作重试前应检查已有产物。
常见失败怎么定位
认证失败:确认启动 Node.js 的账户、环境变量和 Codex 登录路线,按完整错误排查,不要把第三方 Key 当作官方凭证。工作目录错误:确认 workingDirectory 存在且对应目标 Git 仓库;skipGitRepoCheck 只跳过仓库检查,不会修复目录或权限。无最终结果:区分 turn.failed、异常、进程退出与超时,不应把没有 turn.completed 的任务记为成功。
若服务设置了等待超时,还需明确它是否真正终止底层任务。重新提交会写文件的任务前,先检查工作区和已有产物,防止重复执行。本文不把网络重连等同于安全重试。
从入门示例到可维护的自动化
先验收一次只读任务、一次流式事件和一次线程恢复。之后再增加业务任务 ID、日志脱敏和写操作的重复执行检查。模型 Provider 配置属于独立接入层,可继续阅读站内 API Key 配置指南;SDK 本身不要求接入第三方平台。
如果 SDK 能启动但模型认证失败,先核对运行进程实际读取的 Provider 配置。需要使用 AICodeWith 的服务端接入时,可沿用其 Codex 专用配置并按时间核对调用记录;这不改变 SDK 的线程 API,也不表示任意模型都兼容 Codex。



