Codex App Server
Codex App Server
Codex app-server 是 Codex 用於支援富客戶端(例如 Codex VS Code 擴充套件)的介面。當你希望在自己的產品中進行深度整合時,可使用它來實現身份驗證、對話歷史記錄、核准和流式智能體事件。app-server 的實現已在 Codex GitHub 儲存庫中開源(openai/codex/codex-rs/app-server)。有關 Codex 開源元件的完整列表,請參閱開源頁面。
連線 CLI 終端 UI
遠端終端 UI 模式允許你在一臺機器上執行 app-server,並從另一臺機器連線 Codex CLI 終端介面。首先啟動 WebSocket 監聽器:
codex app-server --listen ws://127.0.0.1:4500然後連線終端 UI:
codex --remote ws://127.0.0.1:4500對於非本機連線,請設定 WebSocket 身份驗證,並將 連線置於 TLS 之後。將 bearer token 儲存在環境變數中,並 傳入該變數的名稱,不要將 token 直接放在命令列中:
export CODEX_REMOTE_TOKEN="$(cat "$HOME/.codex/app-server-token")"
codex --remote wss://remote-host:4500 \
--remote-auth-token-env CODEX_REMOTE_TOKEN--remote 選項接受 ws://、wss://、unix:// 和
unix://PATH 端點。僅對 localhost 或通過 SSH
埠轉發的連線使用普通 WebSocket。
連線遠端 Code Mode 主機
預設情況下,app-server 會啟動本機 Code Mode 主機。若要改用遠端主機, 請傳入其安全 WebSocket URL:
codex app-server --code-mode-host wss://code-mode.example.com/host--code-mode-host 控制從 app-server 到其 Code
Mode 主機的出站連線。它不會更改 --listen;後者控制客戶端如何連線到
app-server。同一 app-server 程序中的所有執行緒共享所選的
Code Mode 主機連線。
遠端主機應使用 wss://。僅對 localhost 或
通過 SSH 轉發的連線使用 ws://。app-server 命令和 WebSocket 傳輸
仍處於實驗階段,不支援生產工作負載。
協議
與 MCP 類似,codex app-server 使用 JSON-RPC 2.0 訊息支援雙向通訊(線上路上傳輸時省略 "jsonrpc":"2.0" 標頭)。
支援的傳輸方式:
stdio(--listen stdio://,預設):以換行符分隔的 JSON(JSONL)。websocket(--listen ws://IP:PORT,實驗性且不受支援):每個 WebSocket 文本幀包含一條 JSON-RPC 訊息。- Unix socket(
--listen unix://或--listen unix://PATH):通過 Codex 的預設 app-server 控制套接字或自訂 Unix socket 路徑建立 WebSocket 連線,並使用標準 HTTP Upgrade 握手。 off(--listen off):不公開本機傳輸。
使用 --listen ws://IP:PORT 執行時,同一監聽器還會提供基本的
HTTP 健康探測:
- 監聽器可以接受新連線後,
GET /readyz傳回200 OK。 - 請求不包含
Origin標頭時,GET /healthz傳回200 OK。 - 帶有
Origin標頭的請求會被拒絕,並傳回403 Forbidden。
WebSocket 傳輸仍處於實驗階段且不受支援。ws://127.0.0.1:PORT 等
本機監聽器適用於 localhost 和 SSH 埠轉發
工作流程。在逐步推出期間,非環回 WebSocket 監聽器目前預設允許未經身份驗證的
連線,因此在遠端公開監聽器之前,請先設定 WebSocket 身份驗證。
支援的 WebSocket 身份驗證標誌:
--ws-auth capability-token --ws-token-file /absolute/path--ws-auth capability-token --ws-token-sha256 HEX--ws-auth signed-bearer-token --ws-shared-secret-file /absolute/path
對於已簽名的 bearer token,你還可以設定 --ws-issuer、--ws-audience 和
--ws-max-clock-skew-seconds。客戶端在 WebSocket 握手期間以
Authorization: Bearer <token> 形式提供憑據,app-server 會在處理 JSON-RPC initialize 之前
強制執行身份驗證。
應優先使用 --ws-token-file,不要在命令列中傳入原始 bearer token。僅當客戶端將原始高熵 token 儲存在
單獨的本機機密儲存中時,才使用 --ws-token-sha256;該雜湊僅用作驗證器,客戶端仍需持有
原始 token。
在 WebSocket 模式下,app-server 使用有界佇列。當請求入口已滿時,
伺服器會拒絕新請求,並傳回 JSON-RPC 錯誤程式碼 -32001 和訊息
"Server overloaded; retry later." 客戶端應採用帶抖動的指數遞增延遲進行重試。
訊息 schema
請求包含 method、params 和 id:
{ "method": "thread/start", "id": 10, "params": { "model": "gpt-5.6-terra" } }回應會回顯 id,並包含 result 或 error:
{ "id": 10, "result": { "thread": { "id": "thr_123" } } }{ "id": 10, "error": { "code": 123, "message": "Something went wrong" } }通知省略 id,僅使用 method 和 params:
{ "method": "turn/started", "params": { "turn": { "id": "turn_456" } } }你可以通過 CLI 生成 TypeScript schema 或 JSON Schema 包。每份輸出都對應你執行的具體 Codex 版本,因此生成的構件會與該版本完全匹配:
codex app-server generate-ts --out ./schemas
codex app-server generate-json-schema --out ./schemas開始使用
- 使用
codex app-server(預設 stdio 傳輸)、codex app-server --listen ws://127.0.0.1:4500(TCP WebSocket)或codex app-server --listen unix://(預設 Unix socket)啟動伺服器。 - 通過所選傳輸方式連線客戶端,然後傳送
initialize,接著傳送initialized通知。 - 啟動一個執行緒和一個輪次,然後持續從活動傳輸流中讀取通知。
範例(Node.js / TypeScript):
const proc = spawn("codex", ["app-server"], {
stdio: ["pipe", "pipe", "inherit"],
});
const rl = readline.createInterface({ input: proc.stdout });
const send = (message: unknown) => {
proc.stdin.write(`${JSON.stringify(message)}\n`);
};
let threadId: string | null = null;
rl.on("line", (line) => {
const msg = JSON.parse(line) as any;
console.log("server:", msg);
if (msg.id === 1 && msg.result?.thread?.id && !threadId) {
threadId = msg.result.thread.id;
send({
method: "turn/start",
id: 2,
params: {
threadId,
input: [{ type: "text", text: "Summarize this repo." }],
},
});
}
});
send({
method: "initialize",
id: 0,
params: {
clientInfo: {
name: "my_product",
title: "My Product",
version: "0.1.0",
},
},
});
send({ method: "initialized", params: {} });
send({ method: "thread/start", id: 1, params: { model: "gpt-5.6-terra" } });核心原語
- 執行緒:使用者與 Codex 智能體之間的對話。執行緒包含輪次。
- 輪次:單個使用者請求及其後續的智能體工作。輪次包含專案,並以流式方式傳輸增量更新。
- 專案:輸入或輸出的一個單元(使用者訊息、智能體訊息、命令執行、檔案更改、工具呼叫等)。
使用執行緒 API 建立、列出或歸檔對話。使用輪次 API 驅動對話,並通過輪次通知以流式方式取得進度。
生命週期概覽
- 每個連線初始化一次:開啟傳輸連線後,立即傳送包含客戶端後設資料的
initialize請求,然後發出initialized。伺服器會拒絕該連線上握手之前的任何請求。 - 啟動(或恢復)執行緒:呼叫
thread/start建立新對話,呼叫thread/resume繼續現有對話,或呼叫thread/fork將歷史記錄分支到新的執行緒 id。 - 開始輪次:使用目標
threadId和使用者輸入呼叫turn/start。可選欄位可覆蓋模型、個性、cwd、沙箱策略等設定。 - 引導活動輪次:呼叫
turn/steer,將使用者輸入追加到當前正在進行的輪次,而不建立新輪次。 - 流式傳輸事件:傳送
turn/start後,持續讀取 stdout 上的通知:thread/archived、thread/unarchived、item/started、item/completed、item/agentMessage/delta、工具進度及其他更新。 - 結束輪次:模型完成工作或執行
turn/interrupt取消後,伺服器會發出帶有最終狀態的turn/completed。
初始化
客戶端必須在每個傳輸連線上呼叫任何其他方法之前傳送一次 initialize 請求,然後以 initialized 通知進行確認。初始化之前傳送的請求會收到 Not initialized 錯誤;在同一連線上重複呼叫 initialize 則會傳回 Already initialized。
伺服器會傳回其向上遊服務提供的 user agent 字串,以及描述執行時目標的 platformFamily 和 platformOs 值。設定 clientInfo 以識別你的整合。
initialize.params.capabilities 還支援以下客戶端功能:
optOutNotificationMethods- 要為此連線遮蔽的確切通知方法名稱。 匹配為精確匹配(不支援萬用字元或字首);未知名稱會被接受並忽略。requestAttestation- 選擇啟用由伺服器發起的attestation/generate請求。提供上游證明的桌面主機會以不透明的{ "token": "..." }值回應。mcpServerOpenaiFormElicitation- 允許下游 MCP server 傳送mcpServer/elicitation/request的 OpenAI 擴充套件形式變體。
重要提示:使用 clientInfo.name 向 OpenAI Compliance Logs Platform 識別你的客戶端。如果你正在開發面向企業使用的新 Codex 整合,請聯絡 OpenAI,將其新增到已知客戶端列表中。有關更多背景資訊,請參閱 Codex 日誌參考。
範例(來自 Codex VS Code 擴充套件):
{
"method": "initialize",
"id": 0,
"params": {
"clientInfo": {
"name": "codex_vscode",
"title": "Codex VS Code Extension",
"version": "0.1.0"
}
}
}選擇不接收通知的範例:
{
"method": "initialize",
"id": 1,
"params": {
"clientInfo": {
"name": "my_client",
"title": "My Client",
"version": "0.1.0"
},
"capabilities": {
"experimentalApi": true,
"optOutNotificationMethods": ["thread/started", "item/agentMessage/delta"]
}
}
}選擇啟用實驗性 API
某些 app-server 方法和欄位有意受 experimentalApi 功能限制。
- 省略
capabilities(或將experimentalApi設定為false)可繼續使用穩定 API 範圍,此時伺服器會拒絕實驗性方法/欄位。 - 將
capabilities.experimentalApi設定為true可啟用實驗性方法和欄位。
{
"method": "initialize",
"id": 1,
"params": {
"clientInfo": {
"name": "my_client",
"title": "My Client",
"version": "0.1.0"
},
"capabilities": {
"experimentalApi": true
}
}
}如果客戶端未選擇啟用就傳送實驗性方法或欄位,app-server 會傳回以下錯誤:
<descriptor> requires experimentalApi capability
API 概覽
thread/start- 建立新執行緒;發出thread/started,並自動訂閱該執行緒的輪次/專案事件。thread/resume- 按 id 重新開啟現有執行緒,以便後續turn/start呼叫追加到該執行緒。thread/fork- 通過複製已儲存的歷史記錄,將執行緒派生為具有新執行緒 id 的執行緒。傳入lastTurnId可複製截至該輪次的歷史記錄並忽略後續輪次,傳入ephemeral: true則可建立記憶體中的派生執行緒。為新執行緒發出thread/started;傳回的執行緒在可用時包含forkedFromId。thread/read- 按 id 讀取已儲存的執行緒而不恢復該執行緒;設定includeTurns可傳回完整的輪次歷史記錄。傳回的thread物件包含執行時status。thread/list- 分頁瀏覽已儲存的執行緒日誌;支援基於游標的分頁,以及modelProviders、sourceKinds、archived、isPinned、cwd、useStateDbOnly、searchTerm和實驗性parentThreadId或ancestorThreadId篩選器。傳回的thread物件包含執行時status。thread/turns/list- 實驗性功能;分頁瀏覽已儲存執行緒的輪次歷史記錄,而不恢復該執行緒。itemsView控制是省略、彙總還是完整載入輪次專案。thread/items/list- 實驗性功能;分頁瀏覽持久化的執行緒專案,可選擇限制為一個turnId。當前執行緒儲存必須支援專案分頁。thread/loaded/list- 列出當前載入到記憶體中的執行緒 id。thread/name/set- 為已載入的執行緒或持久化的 rollout 設定或更新面向使用者的執行緒名稱;發出thread/name/updated。thread/goal/set- 設定執行緒目標;發出thread/goal/updated。thread/goal/get- 讀取執行緒的當前目標。thread/goal/clear- 清除執行緒目標;發出thread/goal/cleared。thread/metadata/update- 修補由 SQLite 支援的已儲存執行緒後設資料,包括持久化的gitInfo和isPinned。thread/archive- 將執行緒的日誌檔案移至歸檔目錄,並嘗試歸檔尚未歸檔的已派生後代執行緒日誌;成功時傳回{},並為每個已歸檔執行緒發出thread/archived。thread/delete- 永久刪除持久化的活動或已歸檔執行緒,以及所有已派生的後代執行緒;成功時傳回{},並為每個已刪除執行緒發出thread/deleted。thread/unsubscribe- 取消此連線對執行緒輪次/專案事件的訂閱。如果這是最後一個訂閱方,伺服器會在執行緒進入無訂閱方狀態並經過一段不活動寬限期後卸載該執行緒,同時發出thread/closed。thread/unarchive- 將已歸檔的執行緒 rollout 恢復到活動會話目錄;傳回已恢復的thread,並發出thread/unarchived。thread/status/changed- 當已載入執行緒的執行時status發生變化時發出的通知。thread/compact/start- 觸發執行緒的對話歷史記錄壓縮;立即傳回{},同時通過turn/*和item/*通知流式傳輸進度。thread/shellCommand- 針對執行緒執行使用者發起的 shell 命令。該命令在沙箱外執行,擁有完全存取權限,且不繼承執行緒的沙箱策略。thread/backgroundTerminals/clean- 停止執行緒的所有執行中後台終端(實驗性功能;需要capabilities.experimentalApi)。thread/backgroundTerminals/list- 列出已載入執行緒的執行中後台終端(實驗性功能;需要capabilities.experimentalApi)。thread/backgroundTerminals/terminate- 按 app-serverprocessId終止一個執行中的後台終端(實驗性功能;需要capabilities.experimentalApi)。thread/rollback- 已棄用;從記憶體上下文中移除最後 N 個輪次並持久化回滾標記;傳回更新後的thread。turn/start- 向執行緒新增使用者輸入或獨立工具輸出,並開始 Codex 生成;以初始turn回應並流式傳輸事件。對於collaborationMode,settings.developer_instructions: null表示“使用所選模式的內建指令”。thread/inject_items- 將原始 Responses API 專案追加到已載入執行緒中模型可見的歷史記錄,而不啟動使用者輪次。turn/steer- 將使用者輸入追加到執行緒當前正在進行的輪次;傳回已接受的turnId。turn/interrupt- 請求取消正在進行的輪次;成功時為{},且該輪次以status: "interrupted"結束。review/start- 為執行緒啟動 Codex 審查器;發出enteredReviewMode和exitedReviewMode專案。command/exec- 在伺服器沙箱下執行單條命令,而不啟動執行緒/輪次。command/exec/write- 將stdin位元組寫入執行中的command/exec會話,或關閉stdin。command/exec/resize- 調整執行中、由 PTY 支援的command/exec會話大小。command/exec/terminate- 停止執行中的command/exec會話。command/exec/outputDelta(通知)- 針對流式command/exec會話中經 base64 編碼的 stdout/stderr 資料塊發出。process/spawn- 在 Codex 沙箱外啟動顯式程序會話(實驗性功能;需要capabilities.experimentalApi)。process/writeStdin- 將 stdin 位元組寫入執行中的process/spawn會話,或關閉 stdin(實驗性功能)。process/resizePty- 調整執行中、由 PTY 支援的程序會話大小(實驗性功能)。process/kill- 終止執行中的程序會話(實驗性功能)。process/outputDelta和process/exited(通知)- 針對流式程序輸出和程序退出狀態發出(實驗性功能)。model/list- 列出可用模型(設定includeHidden: true可包含具有hidden: true的條目),以及推理強度選項、可選upgrade和inputModalities。modelProvider/capabilities/read- 讀取模型/供應商組合的能力邊界。experimentalFeature/list- 列出功能標誌及其生命週期階段後設資料,並支援游標分頁。experimentalFeature/enablement/set- 修補受支援功能鍵(例如apps和plugins)的記憶體執行時設定。environment/info- 實驗性功能;連線到已設定的執行環境,並傳回其 shell 和預設工作目錄。permissionProfile/list- 列出 beta 權限設定檔,以及生效的要求是否允許這些設定檔,並支援游標分頁。collaborationMode/list- 列出協作模式預設(實驗性功能,不分頁)。skills/list- 列出一個或多個cwd值對應的技能(支援forceReload和可選perCwdExtraUserRoots)。skills/extraRoots/set- 替換用於發現獨立技能的程序級額外根目錄,但不將其持久化。skills/changed(通知)- 當受監視的本機技能檔案發生變化時發出。hooks/list- 列出為一個或多個cwd值發現的生命週期鉤子。marketplace/add- 新增遠端外掛市場,並將其持久化到使用者的市場設定中。marketplace/remove- 移除已設定的市場及其已安裝的市場根目錄(如果存在)。marketplace/upgrade- 重新整理已設定的 Git 市場;如果省略市場名稱,則重新整理所有已設定的 Git 市場。plugin/list- 開發中;列出已發現的外掛市場和外掛狀態,包括安裝/身份驗證策略後設資料、市場載入錯誤、精選外掛 id,以及本機、Git、包登錄檔或遠端外掛源後設資料。摘要可包含遠端version、本機localVersion、結構化淺色/深色圖示和installPolicySource;對於當前的遠端行,後者可以是null、WORKSPACE_SETTING或IMPLICIT_CANONICAL_APP。暫勿從生產客戶端呼叫此方法。plugin/read- 開發中;按市場路徑讀取一個外掛,或按遠端市場名稱和外掛名稱讀取一個外掛,包括捆綁的技能、應用、MCP server 名稱,以及遠端目錄提供的遠端外掛shareUrl。暫勿從生產客戶端呼叫此方法。plugin/install- 開發中;從市場路徑或遠端市場名稱安裝外掛。暫勿從生產客戶端呼叫此方法。plugin/uninstall- 開發中;解除安裝已安裝的外掛。暫勿從生產客戶端呼叫此方法。plugin/skill/read- 按需讀取遠端外掛技能 Markdown,需指定遠端市場、外掛 id 和技能名稱。app/installed- 讀取已安裝應用的執行時狀態,包括每個應用實際生效的啟用狀態和可呼叫狀態。app/list- 分頁列出可用應用(連接器),以及可存取性/啟用狀態後設資料。app/read- 取得指定應用 id 的後設資料和可選的僅供顯示的工具摘要。skills/config/write- 按路徑啟用或停用技能。mcpServer/oauth/login- 為已設定的 MCP server 啟動 OAuth 登入;傳回授權 URL,並在完成時發出mcpServer/oauthLogin/completed。tool/requestUserInput- 通過工具呼叫向用戶提出 1–3 個簡短問題(實驗性功能);問題可設定isOther以提供自由填寫選項。mcpServer/elicitation/request(伺服器請求)- 請求客戶端提供結構化表單輸入,或確認 MCP server 所請求的 URL 流程。item/permissions/requestApproval(伺服器請求)- 請求客戶端授予內建request_permissions工具所請求的網路或檔案系統權限子集。config/mcpServer/reload- 從磁碟重新載入 MCP server 設定,並為已載入執行緒將重新整理加入佇列。mcpServerStatus/list- 列出 MCP server 、工具、資源和身份驗證狀態(游標 + 限制分頁)。使用detail: "full"取得完整資料,或使用detail: "toolsAndAuthOnly"省略資源。mcpServer/resource/read- 通過已初始化的 MCP server 讀取單個 MCP 資源。mcpServer/tool/call- 呼叫執行緒所設定的 MCP server 上的工具。mcpServer/startupStatus/updated(通知)- 當已載入執行緒所設定的 MCP server 啟動狀態發生變化時發出。windowsSandbox/setupStart- 為elevated或unelevated模式啟動 Windows 沙箱設定;該呼叫會快速傳回,隨後發出windowsSandbox/setupCompleted。feedback/upload- 提交回饋報告(分類 + 可選原因/日誌 + 對話 id,以及可選的extraLogFiles附件)。config/read- 在解析設定分層後,取得磁碟上的生效設定。externalAgentConfig/detect- 檢測可使用includeHome和可選cwds遷移的外部智能體工件;每個檢測到的專案都包含cwd(主目錄使用null)。externalAgentConfig/import- 通過傳入帶有cwd的顯式migrationItems(主目錄使用null),應用選定的外部智能體遷移專案。支援的專案類型包括設定、技能、AGENTS.md、外掛、MCP server 設定、子智能體、鉤子、命令和會話;非空匯入會在工作完成時發出externalAgentConfig/import/progress和externalAgentConfig/import/completed。外掛和會話匯入可以非同步完成。config/value/write- 將單個設定鍵/值寫入磁碟上的使用者config.toml。config/batchWrite- 以原子方式將設定編輯應用到磁碟上的使用者config.toml。configRequirements/read- 從requirements.toml和/或 MDM 取得要求,包括確切的託管設定、允許列表、固定的featureRequirements和網路要求(如果尚未設定,則為null)。fs/readFile、fs/writeFile、fs/createDirectory、fs/getMetadata、fs/readDirectory、fs/remove、fs/copy、fs/watch、fs/unwatch和fs/changed(通知)- 通過 app-server v2 檔案系統 API 對絕對檔案系統路徑執行操作。
外掛摘要包含一個 source 聯合類型。本機外掛傳回
{ "type": "local", "path": ... },由 Git 支援的市場條目傳回
{ "type": "git", "url": ..., "path": ..., "refName": ..., "sha": ... },
包登錄檔條目傳回
{ "type": "npm", "package": ..., "version": ..., "registry": ... },遠端目錄條目傳回 { "type": "remote" }。對於僅存在於遠端目錄的
條目,PluginMarketplaceEntry.path 可以是 null;讀取或安裝
這些外掛時,請傳入 remoteMarketplaceName,而不是 marketplacePath。
模型
列出模型(model/list)
在呈現模型或個性選擇器之前,呼叫 model/list 以發現可用模型及其功能。
{ "method": "model/list", "id": 6, "params": { "limit": 20, "includeHidden": false } }
{ "id": 6, "result": {
"data": [{
"id": "gpt-5.6-sol",
"model": "gpt-5.6-sol",
"displayName": "GPT-5.6-Sol",
"hidden": false,
"defaultReasoningEffort": "low",
"supportedReasoningEfforts": [{
"reasoningEffort": "low",
"description": "Fast responses with lighter reasoning"
}],
"inputModalities": ["text", "image"],
"supportsPersonality": true,
"isDefault": true
}],
"nextCursor": null
} }每個模型條目可以包含:
supportedReasoningEfforts- 模型支援的推理強度選項。defaultReasoningEffort- 建議客戶端使用的預設推理強度。upgrade- 可選的建議升級模型 id,用於客戶端中的遷移提示。upgradeInfo- 可選的升級後設資料,用於客戶端中的遷移提示。hidden- 是否在預設選擇器列表中隱藏該模型。inputModalities- 模型支援的輸入類型(例如text、image)。supportsPersonality- 模型是否支援/personality等特定於個性的指令。isDefault- 模型是否為建議的預設模型。
預設情況下,model/list 僅傳回在選擇器中可見的模型。如果你需要完整列表,並希望使用 hidden 在客戶端進行篩選,請設定 includeHidden: true。
如果缺少 inputModalities(較舊的模型目錄),為保持向後相容,請將其視為 ["text", "image"]。
列出實驗性功能(experimentalFeature/list)
使用此端點發現帶有後設資料和生命週期階段的功能標誌:
{ "method": "experimentalFeature/list", "id": 7, "params": { "limit": 20 } }
{ "id": 7, "result": {
"data": [{
"name": "unified_exec",
"stage": "beta",
"displayName": "Unified exec",
"description": "Use the unified PTY-backed execution tool.",
"announcement": "Beta rollout for improved command execution reliability.",
"enabled": false,
"defaultEnabled": false
}],
"nextCursor": null
} }stage 可以是 beta、underDevelopment、stable、deprecated 或 removed。對於非 beta 標誌,displayName、description 和 announcement 可以是 null。
檢查執行環境(實驗性)
在已設定的遠端環境中開始工作之前,使用 environment/info 檢查該環境。
此方法需要 capabilities.experimentalApi = true。
{ "method": "environment/info", "id": 8, "params": { "environmentId": "devbox" } }
{ "id": 8, "result": {
"shell": { "name": "zsh", "path": "/bin/zsh" },
"cwd": "file:///workspace/project"
} }cwd 可以是 null。存在時,它是使用該
環境原生路徑語法的規範 file: URI。未知環境 ID 以及連線或
協議故障會傳回請求錯誤。
執行緒
thread/read讀取已儲存執行緒但不訂閱;設定includeTurns可包含輪次。thread/turns/list是實驗性的,用於分頁瀏覽已儲存執行緒的輪次歷史記錄,但不 恢復該執行緒。使用itemsView選擇省略、彙總還是完整載入輪次專案。thread/items/list是實驗性的,用於分頁瀏覽持久化的執行緒專案,可選擇限定為某一輪次。thread/list支援游標分頁,以及modelProviders、sourceKinds、archived、isPinned、cwd、useStateDbOnly、searchTerm和實驗性parentThreadId或ancestorThreadId篩選。thread/loaded/list傳回當前位於記憶體中的執行緒 ID。thread/archive將執行緒的持久化 JSONL 日誌移入歸檔目錄,並嘗試歸檔尚未歸檔的衍生後代執行緒日誌。thread/delete永久刪除持久化的活動或已歸檔執行緒及其衍生後代執行緒。thread/metadata/update修補已儲存執行緒的後設資料,包括持久化的gitInfo和isPinned。thread/unsubscribe取消當前連線對已載入執行緒的訂閱,並可能在非活動寬限期後觸發thread/closed。thread/unarchive將已歸檔的執行緒 rollout 恢復到活動會話目錄。thread/compact/start觸發壓縮並立即傳回{}。thread/rollback已棄用。它會從記憶體上下文中移除最後 N 個輪次,並在執行緒的持久化 JSONL 日誌中記錄回滾標記。thread/inject_items將原始 Responses API 專案追加到已載入執行緒中模型可見的歷史記錄,而不啟動使用者輪次。
啟動或恢復執行緒
需要新的 Codex 對話時,請啟動一個新執行緒。
{ "method": "thread/start", "id": 10, "params": {
"model": "gpt-5.6-terra",
"cwd": "/Users/me/project",
"approvalPolicy": "never",
"sandbox": "workspaceWrite",
"personality": "friendly",
"serviceName": "my_app_server_client"
} }
{ "id": 10, "result": {
"thread": {
"id": "thr_123",
"sessionId": "thr_123",
"preview": "",
"ephemeral": false,
"modelProvider": "openai",
"createdAt": 1730910000
}
} }
{ "method": "thread/started", "params": { "thread": { "id": "thr_123" } } }serviceName 是可選的。如果你希望 app-server 使用整合的服務名稱標記執行緒級指標,請設定此項。
thread/start、thread/resume 和 thread/fork 傳回
instructionSources,即已載入的指令檔案路徑陣列。每個路徑都使用
其源環境的原生絕對路徑語法,遠端
環境也不例外。
實驗性客戶端可以將 thread/start 上的 historyMode 設定為 "legacy"
(預設)或 "paginated"。目前不支援分頁執行緒建立,
並會傳回 JSON-RPC 錯誤 -32601。app-server 可以列出和讀取
現有分頁記錄的摘要,但在支援分頁歷史記錄之前,完整歷史記錄讀取、輪次分頁和恢復
會以失敗關閉方式處理。
選擇啟用 capabilities.experimentalApi 的 beta 客戶端可以在 permissions 中傳入命名的
權限設定檔 id,而不是舊版 sandbox 欄位。
不要同時傳送 permissions 和 sandbox。使用
帶專案 cwd 的 permissionProfile/list,可發現可用的設定檔,
以及託管要求是否允許每個設定檔。
thread.sessionId 識別當前即時會話樹的根。根執行緒
使用自己的執行緒 id 作為會話 id;分支執行緒保留其來源根執行緒的會話 id。
客戶端應從 thread.sessionId 讀取會話 id,而不是根據執行緒 id 推導。
若要繼續已儲存的會話,請使用之前記錄的 thread.id 呼叫 thread/resume。回應結構與 thread/start 相同。你還可以傳入 thread/start 支援的相同設定覆蓋項,例如 personality:
{ "method": "thread/resume", "id": 11, "params": {
"threadId": "thr_123",
"personality": "friendly"
} }
{ "id": 11, "result": { "thread": { "id": "thr_123", "name": "Bug bash notes", "ephemeral": false } } }恢復執行緒本身不會更新 thread.updatedAt(也不會更新 rollout 檔案的修改時間)。時間戳會在你啟動輪次時更新。
如果在設定中將已啟用的 MCP server 標記為 required,而該伺服器初始化失敗,thread/start 和 thread/resume 會失敗,而不是在缺少該伺服器的情況下繼續執行。
thread/start 上的 dynamicTools 是實驗性欄位(需要 capabilities.experimentalApi = true)。Codex 會將這些動態工具持久化到執行緒 rollout 後設資料中,並在你未提供新動態工具時通過 thread/resume 恢復它們。
如果你使用與 rollout 中記錄不同的模型恢復執行緒,Codex 會發出警告,並在下一輪次應用一次性模型切換指令。
管理執行緒目標
使用 thread/goal/set、thread/goal/get 和 thread/goal/clear 管理
與 TUI 中 /goal 所呈現內容相同的持久化目標狀態。
{ "method": "thread/goal/set", "id": 13, "params": {
"threadId": "thr_123",
"objective": "Finish the migration and keep tests green",
"status": "active",
"tokenBudget": 40000
} }
{ "id": 13, "result": { "goal": {
"threadId": "thr_123",
"objective": "Finish the migration and keep tests green",
"status": "active",
"tokenBudget": 40000,
"tokensUsed": 0,
"timeUsedSeconds": 0
} } }
{ "method": "thread/goal/updated", "params": {
"threadId": "thr_123",
"goal": {
"threadId": "thr_123",
"objective": "Finish the migration and keep tests green",
"status": "active",
"tokenBudget": 40000,
"tokensUsed": 0,
"timeUsedSeconds": 0
}
} }目標內容不得為空,且最多為 4,000 個字元。提供新
目標會替換原目標並重置用量統計。提供當前尚未終止的
目標或省略 objective,會在保留用量歷史記錄的同時更新狀態或 token 預算。
若要從已儲存會話建立分支,請使用 thread.id 呼叫 thread/fork。這會建立新的執行緒 id,並為其發出 thread/started 通知。傳入
lastTurnId 可複製截至該輪次(含該輪次)的歷史記錄,並省略後續
輪次:
{ "method": "thread/fork", "id": 12, "params": { "threadId": "thr_123", "lastTurnId": "turn_456" } }
{ "id": 12, "result": { "thread": { "id": "thr_456", "sessionId": "thr_123", "forkedFromId": "thr_123" } } }
{ "method": "thread/started", "params": { "thread": { "id": "thr_456" } } }app-server 會拒絕正在進行的 lastTurnId。如果在源執行緒處於輪次中途時省略該欄位,
分支會記錄中斷標記,而不會保留未標記的部分輪次。
傳入 ephemeral: true 可建立記憶體中分支,而不將其新增到已儲存的
執行緒列表:
{
"method": "thread/fork",
"id": 13,
"params": {
"threadId": "thr_123",
"ephemeral": true
}
}
{
"id": 13,
"result": {
"thread": {
"id": "thr_789",
"sessionId": "thr_789",
"forkedFromId": "thr_123",
"ephemeral": true
}
}
}分頁執行緒的臨時分支還需要 excludeTurns: true。該
欄位是實驗性的,需要 capabilities.experimentalApi = true。
設定面向使用者的執行緒標題後,app-server 會在 thread/list、thread/read、thread/resume、thread/unarchive 和 thread/rollback 回應中填充 thread.name。在稍後設定標題之前,thread/start 和 thread/fork 可能會省略 name(或傳回 null)。
讀取已儲存執行緒(不恢復)
如果你需要已儲存的執行緒資料,但不想恢復該執行緒或訂閱其事件,請使用 thread/read。
includeTurns- 為true時,回應包含執行緒的輪次;為false或省略時,僅傳回執行緒摘要。- 傳回的
thread物件包含執行時status(notLoaded、idle、systemError,或帶有activeFlags的active)。
{ "method": "thread/read", "id": 19, "params": { "threadId": "thr_123", "includeTurns": true } }
{ "id": 19, "result": { "thread": { "id": "thr_123", "name": "Bug bash notes", "ephemeral": false, "status": { "type": "notLoaded" }, "turns": [] } } }與 thread/resume 不同,thread/read 不會將執行緒載入到記憶體中,也不會發出 thread/started。
列出執行緒輪次
thread/turns/list 是實驗性的。使用它可分頁瀏覽已儲存執行緒的輪次歷史記錄,而不恢復該執行緒。結果預設按從新到舊排序,因此客戶端可以使用 nextCursor 取得更早的輪次。回應還包含 backwardsCursor;將它作為 cursor 與 sortDirection: "asc" 一起傳入,可取得比上一頁第一項更新的輪次。
itemsView 控制回應包含多少輪次專案資料:
notLoaded省略專案。summary傳回彙總後的專案資料,並且在省略時為預設值。full傳回完整的專案資料。
{ "method": "thread/turns/list", "id": 20, "params": {
"threadId": "thr_123",
"limit": 50,
"sortDirection": "desc",
"itemsView": "summary"
} }
{ "id": 20, "result": {
"data": [],
"nextCursor": "older-turns-cursor-or-null",
"backwardsCursor": "newer-turns-cursor-or-null"
} }thread/items/list 也是實驗性的。它會分頁瀏覽持久化專案,但不
恢復執行緒。傳入 turnId 可將結果限定為某一輪次,也可省略該欄位
以分頁瀏覽整個執行緒中的專案。活動執行緒儲存必須支援專案
分頁;否則,伺服器會傳回方法不受支援錯誤。
列出執行緒(支援分頁和篩選)
thread/list 可用於呈現歷史記錄 UI。結果預設按 createdAt 從新到舊排序。篩選會在分頁之前應用。可傳入以下任意組合:
cursor- 上一次回應中的不透明字串;第一頁應省略。limit- 未設定時,伺服器預設為合理的頁大小。sortKey-created_at(預設)、updated_at或recency_at。sortDirection-desc(預設)或asc。modelProviders- 將結果限定為特定供應商;未設定、為 null 或為空陣列時包含所有供應商。sourceKinds- 將結果限定為特定執行緒來源。省略或為[]時,伺服器預設僅包含互動式來源:cli和vscode。archived- 為true時,僅列出已歸檔執行緒。為false或省略時,列出未歸檔執行緒(預設)。isPinned- 提供時,僅傳回持久化置頂狀態匹配的執行緒。省略時同時傳回已置頂和未置頂執行緒。cwd- 將結果限定為會話當前工作目錄與此路徑或陣列中的某個路徑完全匹配的執行緒。相對路徑從 app-server 程序的工作目錄解析。useStateDbOnly- 為true時,傳回狀態資料庫結果,而不掃描 JSONL 執行緒日誌來修復後設資料。省略或傳入false時,使用預設的掃描並修復行為。searchTerm- 將結果限定為提取出的標題包含此區分大小寫文本片段的執行緒。parentThreadId- 將結果限定為給定父執行緒的直接子執行緒。此篩選條件是實驗性的,需要capabilities.experimentalApi = true。ancestorThreadId- 將結果限定為給定執行緒任意深度的衍生後代。此篩選條件是實驗性的,需要capabilities.experimentalApi = true;請勿將其與parentThreadId組合使用。
sourceKinds 接受以下值:
clivscodeexecappServersubAgentsubAgentReviewsubAgentCompactsubAgentThreadSpawnsubAgentOtherunknown
範例:
{ "method": "thread/list", "id": 20, "params": {
"cursor": null,
"limit": 25,
"sortKey": "created_at"
} }
{ "id": 20, "result": {
"data": [
{ "id": "thr_a", "preview": "Create a TUI", "ephemeral": false, "isPinned": true, "modelProvider": "openai", "createdAt": 1730831111, "updatedAt": 1730831111, "name": "TUI prototype", "status": { "type": "notLoaded" } },
{ "id": "thr_b", "preview": "Fix tests", "ephemeral": false, "isPinned": false, "modelProvider": "openai", "createdAt": 1730750000, "updatedAt": 1730750000, "status": { "type": "notLoaded" } }
],
"nextCursor": "opaque-token-or-null"
} }當 nextCursor 為 null 時,表示已到達最後一頁。
更新已儲存執行緒的後設資料
使用 thread/metadata/update 修補已儲存執行緒的後設資料,而不恢復
執行緒。設定 isPinned 可置頂或取消置頂執行緒,更新 gitInfo 可更改
持久化的 Git 後設資料。省略的欄位保持不變;顯式傳入 null 會清除
已儲存的 Git 後設資料值。
{ "method": "thread/metadata/update", "id": 21, "params": {
"threadId": "thr_123",
"isPinned": true,
"gitInfo": { "branch": "feature/sidebar-pr" }
} }
{ "id": 21, "result": {
"thread": {
"id": "thr_123",
"isPinned": true,
"gitInfo": { "sha": null, "branch": "feature/sidebar-pr", "originUrl": null }
}
} }跟蹤執行緒狀態變化
已載入執行緒的執行時狀態發生變化時會發出 thread/status/changed。有效載荷包含 threadId 和新的 status。
{
"method": "thread/status/changed",
"params": {
"threadId": "thr_123",
"status": { "type": "active", "activeFlags": ["waitingOnApproval"] }
}
}列出已載入執行緒
thread/loaded/list 傳回當前已載入到記憶體中的執行緒 ID。
{ "method": "thread/loaded/list", "id": 21 }
{ "id": 21, "result": { "data": ["thr_123", "thr_456"] } }取消訂閱已載入執行緒
thread/unsubscribe 會移除當前連線對執行緒的訂閱。回應狀態為以下值之一:
- 連線之前已訂閱且現已移除時為
unsubscribed。 - 連線未訂閱該執行緒時為
notSubscribed。 - 執行緒未載入時為
notLoaded。
如果這是最後一個訂閱者,伺服器會讓執行緒保持載入,直到該執行緒 30 分鐘內既無訂閱者也無活動。寬限期到期後,app-server 會卸載該執行緒,並發出一個到 notLoaded 的 thread/status/changed 轉換以及 thread/closed。
{ "method": "thread/unsubscribe", "id": 22, "params": { "threadId": "thr_123" } }
{ "id": 22, "result": { "status": "unsubscribed" } }如果執行緒稍後過期:
{ "method": "thread/status/changed", "params": {
"threadId": "thr_123",
"status": { "type": "notLoaded" }
} }
{ "method": "thread/closed", "params": { "threadId": "thr_123" } }歸檔執行緒
使用 thread/archive 將持久化的執行緒日誌(以 JSONL 檔案形式儲存在磁碟上)移入已歸檔會話目錄。歸檔執行緒時,還會嘗試歸檔尚未歸檔的衍生後代執行緒。
{ "method": "thread/archive", "id": 22, "params": { "threadId": "thr_b" } }
{ "id": 22, "result": {} }
{ "method": "thread/archived", "params": { "threadId": "thr_b" } }
{ "method": "thread/archived", "params": { "threadId": "thr_child" } }除非傳入 archived: true,否則已歸檔執行緒不會出現在後續的 thread/list 呼叫中。伺服器會為實際歸檔的每個執行緒發出一條 thread/archived 通知;如果某個衍生後代無法歸檔,請求仍可能成功,但不會為該後代發出歸檔通知。
刪除執行緒
使用 thread/delete 可永久刪除已持久化的活躍或已歸檔執行緒
及其派生的後代執行緒。伺服器會先移除現有的 rollout 檔案和
關聯後設資料,然後再傳回成功;缺失的 rollout 檔案會被視為
已經刪除。臨時根執行緒無法刪除。
{ "method": "thread/delete", "id": 23, "params": { "threadId": "thr_b" } }
{ "id": 23, "result": {} }
{ "method": "thread/deleted", "params": { "threadId": "thr_b" } }
{ "method": "thread/deleted", "params": { "threadId": "thr_child" } }取消歸檔執行緒
使用 thread/unarchive 可將已歸檔執行緒的 rollout 移回活躍會話目錄。
{ "method": "thread/unarchive", "id": 24, "params": { "threadId": "thr_b" } }
{ "id": 24, "result": { "thread": { "id": "thr_b", "name": "Bug bash notes" } } }
{ "method": "thread/unarchived", "params": { "threadId": "thr_b" } }觸發執行緒壓縮
使用 thread/compact/start 可手動觸發執行緒的歷史記錄壓縮。請求會立即傳回 {}。
App-server 會在同一 threadId 上通過標準 turn/* 和 item/* 通知傳送進度,其中包括 contextCompaction 項的生命週期(先是 item/started,然後是 item/completed)。
{ "method": "thread/compact/start", "id": 25, "params": { "threadId": "thr_b" } }
{ "id": 25, "result": {} }線上程中執行 shell 命令
對於屬於某個執行緒、由使用者發起的 shell 命令,請使用 thread/shellCommand。請求會立即傳回 {},進度則通過標準 turn/* 和 item/* 通知流式傳輸。
此 API 在沙箱外執行,擁有完整存取權限,並且不會繼承執行緒的沙箱策略。客戶端應僅針對使用者明確發起的命令提供此功能。
如果執行緒已有活躍的輪次,該命令會作為該輪次的輔助操作執行,其格式化輸出將注入該輪次的訊息流。如果執行緒處於空閒狀態,app-server 會為該 shell 命令啟動一個獨立輪次。
設定 timeoutMs 可限制執行時間(以毫秒為單位)。省略該參數或傳入
null 時使用預設的一小時。0 表示請求立即超時;負
值會被拒絕。超時設定不會延遲即時 RPC 確認。
{ "method": "thread/shellCommand", "id": 26, "params": { "threadId": "thr_b", "command": "git status --short", "timeoutMs": 10000 } }
{ "id": 26, "result": {} }清理後台終端
使用 thread/backgroundTerminals/clean 可停止與某個執行緒關聯的所有正在執行的後台終端。此方法為實驗性方法,需要 capabilities.experimentalApi = true。
{ "method": "thread/backgroundTerminals/clean", "id": 27, "params": { "threadId": "thr_b" } }
{ "id": 27, "result": {} }使用 thread/backgroundTerminals/list 可檢查已載入執行緒中正在執行的後台終端。
請求支援標準的 cursor 和 limit 分頁,傳回的 processId 是
app-server 的程序 ID。此方法為實驗性方法,需要 capabilities.experimentalApi = true:
{ "method": "thread/backgroundTerminals/list", "id": 28, "params": { "threadId": "thr_b" } }
{ "id": 28, "result": { "data": [
{
"itemId": "item_456",
"processId": "42",
"command": "python3 -m http.server",
"cwd": "/workspace",
"osPid": null,
"cpuPercent": null,
"rssKb": null
}
], "nextCursor": null } }使用 thread/backgroundTerminals/terminate 並傳入該 processId,可停止一個
後台終端。此方法為實驗性方法,需要
capabilities.experimentalApi = true:
{ "method": "thread/backgroundTerminals/terminate", "id": 29, "params": { "threadId": "thr_b", "processId": "42" } }
{ "id": 29, "result": { "terminated": true } }回滾最近的輪次
thread/rollback 已棄用,並將在未來移除。它會從記憶體上下文中移除最後
numTurns 個條目,並在 rollout 日誌中持久化一個回滾標記。傳回的 thread 中,
turns 會在回滾後填充。
{ "method": "thread/rollback", "id": 30, "params": { "threadId": "thr_b", "numTurns": 1 } }
{ "id": 30, "result": { "thread": { "id": "thr_b", "name": "Bug bash notes", "ephemeral": false } } }輪次
input 欄位接受一個專案列表:
{ "type": "text", "text": "Explain this diff" }{ "type": "image", "url": "https://.../design.png" }{ "type": "localImage", "path": "/tmp/screenshot.png" }
你可以為每個輪次覆蓋設定(模型、推理強度、個性、cwd、沙箱策略、摘要)。指定後,這些設定會成為同一執行緒後續輪次的預設值。outputSchema 僅應用於當前輪次。對於 sandboxPolicy.type = "externalSandbox",請將 networkAccess 設定為 restricted 或 enabled;對於 workspaceWrite,networkAccess 仍為布林值。
對於 turn/start.collaborationMode,settings.developer_instructions: null 表示“使用所選模式的內建指令”,而不是清除模式指令。
沙箱讀取權限(ReadOnlyAccess)
sandboxPolicy 支援顯式的讀取權限控制:
readOnly:可選的access(預設為{ "type": "fullAccess" },也可設為受限根目錄)。workspaceWrite:可選的readOnlyAccess(預設為{ "type": "fullAccess" },也可設為受限根目錄)。
受限讀取權限的結構:
{
"type": "restricted",
"includePlatformDefaults": true,
"readableRoots": ["/Users/me/shared-read-only"]
}在 macOS 上,includePlatformDefaults: true 會為受限讀取會話追加一組經過篩選的平台預設 Seatbelt 策略。這樣可以提高工具相容性,同時不會寬泛地允許存取整個 /System。
範例:
{ "type": "readOnly", "access": { "type": "fullAccess" } }{
"type": "workspaceWrite",
"writableRoots": ["/Users/me/project"],
"readOnlyAccess": {
"type": "restricted",
"includePlatformDefaults": true,
"readableRoots": ["/Users/me/shared-read-only"]
},
"networkAccess": false
}啟動輪次
{ "method": "turn/start", "id": 30, "params": {
"threadId": "thr_123",
"input": [ { "type": "text", "text": "Run tests" } ],
"cwd": "/Users/me/project",
"approvalPolicy": "unlessTrusted",
"sandboxPolicy": {
"type": "workspaceWrite",
"writableRoots": ["/Users/me/project"],
"networkAccess": true
},
"model": "gpt-5.6-terra",
"effort": "medium",
"summary": "concise",
"personality": "friendly",
"outputSchema": {
"type": "object",
"properties": { "answer": { "type": "string" } },
"required": ["answer"],
"additionalProperties": false
}
} }
{ "id": 30, "result": { "turn": { "id": "turn_456", "status": "inProgress", "items": [], "error": null } } }若要使用客戶端所執行工具的輸出來啟動輪次,請傳入 toolOutput,
其中包含非空的 name、可選的 namespace,以及作為字串或
內容專案陣列的 output。將 input 設定為空陣列;不能將
toolOutput 與非空使用者輸入結合使用。
{
"method": "turn/start",
"id": 31,
"params": {
"threadId": "thr_123",
"input": [],
"toolOutput": {
"name": "run_tests",
"namespace": null,
"output": "All 42 tests passed."
}
}
}該輸出在對話中仍作為工具輸出,並在通知和持久化歷史記錄中顯示為
functionCallOutput 專案。如果常規輪次已在進行中,Codex 會將該輸出加入該輪次的佇列。
向執行緒注入專案
使用 thread/inject_items 可將預先建置的 Responses API 專案追加到已載入執行緒的提示詞歷史記錄中,而無需啟動使用者輪次。這些專案會持久化到 rollout,並包含在後續模型請求中。
{ "method": "thread/inject_items", "id": 31, "params": {
"threadId": "thr_123",
"items": [
{
"type": "message",
"role": "assistant",
"content": [{ "type": "output_text", "text": "Previously computed context." }]
}
]
} }
{ "id": 31, "result": {} }引導活躍輪次
使用 turn/steer 可向正在進行的活躍輪次追加更多使用者輸入。
- 包含
expectedTurnId;它必須與活躍輪次 ID 匹配。 - 如果執行緒沒有活躍輪次,請求將失敗。
turn/steer不會發出新的turn/started通知。turn/steer不接受輪次級覆蓋項(model、cwd、sandboxPolicy或outputSchema)。
{ "method": "turn/steer", "id": 32, "params": {
"threadId": "thr_123",
"input": [ { "type": "text", "text": "Actually focus on failing tests first." } ],
"expectedTurnId": "turn_456"
} }
{ "id": 32, "result": { "turnId": "turn_456" } }啟動輪次(呼叫技能)
要顯式呼叫技能,請在文本輸入中包含 $<skill-name>,並在旁邊新增一個 skill 輸入專案。
{ "method": "turn/start", "id": 33, "params": {
"threadId": "thr_123",
"input": [
{ "type": "text", "text": "$skill-creator Add a new skill for triaging flaky CI and include step-by-step usage." },
{ "type": "skill", "name": "skill-creator", "path": "/Users/me/.codex/skills/skill-creator/SKILL.md" }
]
} }
{ "id": 33, "result": { "turn": { "id": "turn_457", "status": "inProgress", "items": [], "error": null } } }中斷輪次
{ "method": "turn/interrupt", "id": 31, "params": { "threadId": "thr_123", "turnId": "turn_456" } }
{ "id": 31, "result": {} }成功後,該輪次將以 status: "interrupted" 狀態結束。
審查
review/start 會為執行緒執行 Codex 審查器,並流式傳輸審查專案。目標包括:
uncommittedChangesbaseBranch(與某個分支比較差異)commit(審查特定提交)custom(自由格式指令)
使用 delivery: "inline"(預設)可在現有執行緒上執行審查,或使用 delivery: "detached" 派生一個新的審查執行緒。
請求/回應範例:
{ "method": "review/start", "id": 40, "params": {
"threadId": "thr_123",
"delivery": "inline",
"target": { "type": "commit", "sha": "1234567deadbeef", "title": "Polish tui colors" }
} }
{ "id": 40, "result": {
"turn": {
"id": "turn_900",
"status": "inProgress",
"items": [
{ "type": "userMessage", "id": "turn_900", "content": [ { "type": "text", "text": "Review commit 1234567: Polish tui colors" } ] }
],
"error": null
},
"reviewThreadId": "thr_123"
} }對於分離式審查,請使用 "delivery": "detached"。回應結構相同,但 reviewThreadId 將是新審查執行緒的 ID(與原始 threadId 不同)。在流式傳輸審查輪次之前,伺服器還會為該新執行緒發出 thread/started 通知。
Codex 會先流式傳輸常規的 turn/started 通知,然後傳送一個帶有 enteredReviewMode 項的 item/started:
{
"method": "item/started",
"params": {
"item": {
"type": "enteredReviewMode",
"id": "turn_900",
"review": "current changes"
}
}
}審查器完成後,伺服器會發出 item/started 和 item/completed,其中包含帶有最終審查文本的 exitedReviewMode 項:
{
"method": "item/completed",
"params": {
"item": {
"type": "exitedReviewMode",
"id": "turn_900",
"review": "Looks solid overall..."
}
}
}使用此通知在客戶端中呈現審查器輸出。
程序執行
process/* 是一個實驗性的顯式程序控制 API。它需要
capabilities.experimentalApi = true,並在 Codex 沙箱外執行。僅當你的客戶端有意提供
不受沙箱保護的本機程序控制時,才使用它。
使用 process/spawn 啟動程序並提供一個 processHandle,然後使用
該控制代碼傳送 stdin、調整大小和終止請求。輸出通過
process/outputDelta 通知流式傳輸,完成狀態通過
process/exited 流式傳輸。
{ "method": "process/spawn", "id": 48, "params": {
"command": ["python3", "-m", "pytest", "-q"],
"processHandle": "pytest-1",
"cwd": "/Users/me/project",
"tty": true
} }
{ "id": 48, "result": {} }
{ "method": "process/outputDelta", "params": {
"processHandle": "pytest-1",
"stream": "stdout",
"deltaBase64": "Li4u"
} }
{ "method": "process/exited", "params": {
"processHandle": "pytest-1",
"exitCode": 0
} }使用 process/writeStdin 並傳入 deltaBase64、closeStdin 或兩者來傳送
輸入。使用 process/resizePty 處理 PTY 大小調整事件,並使用 process/kill
終止正在執行的程序。
命令執行
command/exec 在伺服器沙箱中執行單條命令(argv 陣列),且不建立執行緒。
{ "method": "command/exec", "id": 50, "params": {
"command": ["ls", "-la"],
"cwd": "/Users/me/project",
"sandboxPolicy": { "type": "workspaceWrite" },
"timeoutMs": 10000
} }
{ "id": 50, "result": { "exitCode": 0, "stdout": "...", "stderr": "" } }如果你已對伺服器程序進行沙箱隔離,並希望 Codex 跳過自身的沙箱強制執行,請使用 sandboxPolicy.type = "externalSandbox"。對於外部沙箱模式,請將 networkAccess 設定為 restricted(預設)或 enabled。對於 readOnly 和 workspaceWrite,請使用上文所示的相同可選 access / readOnlyAccess 結構。
注意:
- 伺服器會拒絕空的
command陣列。 sandboxPolicy接受與turn/start相同的結構(例如dangerFullAccess、readOnly、workspaceWrite、externalSandbox)。- 省略時,
timeoutMs會回退到伺服器預設值。 - 對於由 PTY 支援的會話,請設定
tty: true;如果計劃後續呼叫command/exec/write、command/exec/resize或command/exec/terminate,請使用processId。 - 設定
streamStdoutStderr: true,可在命令執行時接收command/exec/outputDelta通知。
讀取管理員要求(configRequirements/read)
使用 configRequirements/read 可檢查從 requirements.toml 和/或 MDM 載入的有效管理員要求。
{ "method": "configRequirements/read", "id": 52, "params": {} }
{ "id": 52, "result": {
"requirements": {
"allowedApprovalPolicies": ["onRequest", "unlessTrusted"],
"allowedSandboxModes": ["readOnly", "workspaceWrite"],
"featureRequirements": {
"personality": true,
"unified_exec": false
},
"network": {
"enabled": true,
"allowedDomains": ["api.openai.com"],
"allowUnixSockets": ["/tmp/example.sock"],
"dangerouslyAllowAllUnixSockets": false
}
}
} }未設定要求時,result.requirements 為 null。有關支援的鍵和值的詳細資訊,請參閱 requirements.toml 文件。
Windows 沙箱設定(windowsSandbox/setupStart)
自訂 Windows 客戶端可以非同步觸發沙箱設定,而不必阻塞啟動檢查。
{ "method": "windowsSandbox/setupStart", "id": 53, "params": { "mode": "elevated" } }
{ "id": 53, "result": { "started": true } }App-server 會在後台啟動設定,稍後再發出完成通知:
{
"method": "windowsSandbox/setupCompleted",
"params": { "mode": "elevated", "success": true, "error": null }
}模式:
elevated- 執行需要提升權限的 Windows 沙箱設定流程。unelevated- 執行舊版設定/預檢流程。
檔案系統
v2 檔案系統 API 使用絕對路徑。當檔案或目錄發生變化後,客戶端需要使 UI 狀態失效時,請使用 fs/watch。
{ "method": "fs/watch", "id": 54, "params": {
"watchId": "0195ec6b-1d6f-7c2e-8c7a-56f2c4a8b9d1",
"path": "/Users/me/project/.git/HEAD"
} }
{ "id": 54, "result": { "path": "/Users/me/project/.git/HEAD" } }
{ "method": "fs/changed", "params": {
"watchId": "0195ec6b-1d6f-7c2e-8c7a-56f2c4a8b9d1",
"changedPaths": ["/Users/me/project/.git/HEAD"]
} }
{ "method": "fs/unwatch", "id": 55, "params": {
"watchId": "0195ec6b-1d6f-7c2e-8c7a-56f2c4a8b9d1"
} }
{ "id": 55, "result": {} }監視檔案時,該檔案路徑會發出 fs/changed,其中包括通過替換或重新命名操作產生的更新。
事件
事件通知是伺服器發起的流,用於傳輸執行緒生命週期、輪次生命週期及其中的專案。啟動或恢復執行緒後,請繼續讀取活躍傳輸流中的 thread/started、thread/archived、thread/unarchived、thread/closed、thread/status/changed、turn/*、item/* 和 serverRequest/resolved 通知。
選擇不接收通知
客戶端可以在 initialize.params.capabilities.optOutNotificationMethods 中傳送準確的方法名稱,按連線禁止特定通知。
- 僅精確匹配:
item/agentMessage/delta只會禁止該方法。 - 未知的方法名稱將被忽略。
- 適用於當前的
thread/*、turn/*、item/*及相關 v2 通知。 - 不適用於請求、回應或錯誤。
模糊檔案搜尋事件(實驗性)
模糊檔案搜尋會話 API 會按查詢發出通知:
fuzzyFileSearch/sessionUpdated-{ sessionId, query, files },包含活躍查詢的當前匹配項。fuzzyFileSearch/sessionCompleted- 為該查詢完成索引和匹配後發出一次{ sessionId }。
警告事件
configWarning- 針對可恢復的設定或初始化問題發出{ summary, details?, path?, range? }。warning- 針對非致命執行時警告發出{ threadId?, message }。
Windows 沙箱設定事件
windowsSandbox/setupCompleted- 在windowsSandbox/setupStart請求完成後發出{ mode, success, error }。
輪次事件
turn/started-{ turn },包含輪次 ID、空的items和status: "inProgress"。turn/completed-{ turn },其中turn.status為completed、interrupted或failed;失敗時會攜帶{ error: { message, codexErrorInfo?, additionalDetails? } }。turn/diff/updated-{ threadId, turnId, diff },包含該輪次所有檔案更改的最新聚合統一差異。turn/plan/updated- 每當智能體共享或更改其計劃時發出{ turnId, explanation?, plan };每個plan條目都是{ step, status },其中status為pending、inProgress或completed。hook/started和hook/completed- 在同步生命週期鉤子啟動時以及其最終執行摘要可用時發出{ threadId, turnId?, run }。非同步鉤子不會發出這些通知。model/safetyBuffering/updated- 回應進入暫時性安全緩衝時發出{ threadId, turnId, model, useCases, reasons, showBufferingUi, fasterModel }。model/rerouted- 服務將請求路由到另一模型時發出{ threadId, turnId, fromModel, toModel, reason }。model/verification- 服務要求進行額外帳戶驗證時發出{ threadId, turnId, verifications }。thread/tokenUsage/updated- 活躍執行緒的用量更新。
即使專案事件以流式方式傳輸,turn/diff/updated 和 turn/plan/updated 目前仍包含空的 items 陣列。請將 item/* 通知作為輪次專案的事實來源。
專案
ThreadItem 是輪次回應和 item/* 通知中攜帶的帶標籤聯合類型。常見專案類型包括:
userMessage-{id, content},其中content是使用者輸入列表(text、image或localImage)。functionCallOutput-{id, name, namespace, output},用於表示通過turn/start.toolOutput提供的獨立工具輸出。namespace可以是null。agentMessage- 包含累積智能體回覆的{id, text, phase?}。如果存在,phase使用 Responses API 傳輸值(commentary、final_answer)。plan- 包含規劃模式下所提議計劃文本的{id, text}。應以item/completed中最後一個plan專案為準。reasoning-{id, summary, content},其中summary儲存流式推理摘要,content儲存原始推理塊。commandExecution-{id, command, cwd, status, commandActions, aggregatedOutput?, exitCode?, durationMs?}。fileChange- 描述所提議編輯的{id, changes, status};changes列出{path, kind, diff}。mcpToolCall-{id, server, tool, status, arguments, appContext?, pluginId?, result?, error?}。對於受信任的 MCP 應用,appContext可以包含connectorId、linkId、resourceUri、appName、templateId和穩定的連接器actionName。較舊的持久化專案可能省略較新的後設資料。請使用appContext.resourceUri,而不是已棄用的頂層mcpAppResourceUri。dynamicToolCall- 用於客戶端執行的動態工具呼叫的{id, tool, arguments, status, contentItems?, success?, durationMs?}。collabToolCall-{id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}。webSearch- 用於智能體發出的 Web 搜尋請求的{id, query, action?}。imageView- 智能體呼叫影像檢視器工具時發出的{id, path}。enteredReviewMode- 審查器啟動時傳送的{id, review}。exitedReviewMode- 審查器完成時發出的{id, review}。contextCompaction- Codex 壓縮對話歷史記錄時發出的{id}。
對於 webSearch.action,操作 type 可以是 search(query?、queries?)、openPage(url?)或 findInPage(url?、pattern?)。
App server 已棄用舊版 thread/compacted 通知;請改用 contextCompaction 項。
所有專案都會發出兩個共享生命週期事件:
item/started- 新工作單元開始時發出完整的item;item.id與增量所用的itemId匹配。item/completed- 工作完成後傳送最終的item;應以此狀態為準。
專案增量
item/agentMessage/delta- 追加智能體訊息的流式文本。item/plan/delta- 流式傳輸建議的計劃文本。最終的plan項可能與拼接後的增量並不完全相同。item/reasoning/summaryTextDelta- 流式傳輸可讀的推理摘要;開啟新的摘要區段時,summaryIndex會遞增。item/reasoning/summaryPartAdded- 標記推理摘要區段之間的邊界。item/reasoning/textDelta- 流式傳輸原始推理文本(模型支援時)。item/commandExecution/outputDelta- 流式傳輸命令的 stdout/stderr;按順序追加增量。item/fileChange/outputDelta- 用於舊版apply_patch文本輸出的已棄用相容性通知。當前 app-server 版本不再發出此通知;請改用fileChange項和turn/diff/updated。
錯誤
如果輪次失敗,伺服器會發出帶有 { error: { message, codexErrorInfo?, additionalDetails? } } 的 error 事件,然後以 status: "failed" 狀態結束該輪次。如果上游 HTTP 狀態可用,它會出現在 codexErrorInfo.httpStatusCode 中。
常見的 codexErrorInfo 值包括:
ContextWindowExceededUsageLimitExceededHttpConnectionFailed(上游 4xx/5xx 錯誤)ResponseStreamConnectionFailedResponseStreamDisconnectedResponseTooManyFailedAttemptsBadRequest、Unauthorized、SandboxError、InternalServerError、Other
如果上游 HTTP 狀態可用,伺服器會通過相關 codexErrorInfo 變體中的 httpStatusCode 轉發該狀態。
核准
根據使用者的 Codex 設定,命令執行和檔案更改可能需要核准。App-server 會向客戶端傳送由伺服器發起的 JSON-RPC 請求,客戶端則以決策載荷回應。
命令執行決策:
accept、acceptForSession、decline、cancel或{ "acceptWithExecpolicyAmendment": { "execpolicy_amendment": ["cmd", "..."] } }。檔案更改決策:
accept、acceptForSession、decline、cancel。請求包含
threadId和turnId——使用它們可將 UI 狀態限定到活躍對話。伺服器會恢復或拒絕相關工作,並以
item/completed結束該專案。
命令執行核准
訊息順序:
item/started顯示待處理的commandExecution項,其中包含command、cwd和其他欄位。item/commandExecution/requestApproval包含itemId、threadId、turnId、可選的reason、可選的command、可選的cwd、可選的commandActions、可選的proposedExecpolicyAmendment、可選的networkApprovalContext以及可選的availableDecisions。當initialize.params.capabilities.experimentalApi = true時,載荷還可以包含實驗性的additionalPermissions,用於描述請求的逐命令沙箱權限。additionalPermissions內的所有檔案系統路徑在線上傳輸時均為絕對路徑。- 客戶端使用上述某個命令執行核准決策進行回應。
serverRequest/resolved確認待處理請求已得到回應或已清除。item/completed傳回最終的commandExecution項,其中包含status: completed | failed | declined。
當存在 networkApprovalContext 時,該提示針對的是託管網路存取,而不是一般 shell 命令核准。當前 v2 schema 會公開目標 host 和 protocol;客戶端應呈現網路專用提示,不應依賴 command 作為對使用者有意義的 shell 命令預覽。
Codex 會按目標(host、協議和埠)對並發網路核准提示進行分組。因此,app-server 可能傳送一個提示,解除對發往同一目標的多個排隊請求的阻塞;而同一主機上的不同埠會被分別處理。
檔案更改核准
訊息順序:
item/started發出一個fileChange項,其中包含建議的changes和status: "inProgress"。item/fileChange/requestApproval包含itemId、threadId、turnId、可選的reason和可選的grantRoot。- 客戶端使用上述某個檔案更改核准決策進行回應。
serverRequest/resolved確認待處理請求已得到回應或已清除。item/completed傳回最終的fileChange項,其中包含status: completed | failed | declined。
tool/requestUserInput
當客戶端回應 item/tool/requestUserInput 時,app-server 會發出帶有 { threadId, requestId } 的 serverRequest/resolved。如果待處理請求在客戶端回應前因輪次啟動、輪次完成或輪次中斷而被清除,伺服器也會為該清理操作發出相同通知。
請求參數包含 autoResolutionMs(整數毫秒超時值)或
null。如果存在,且使用者未作答,宿主客戶端可以在該
時間間隔後自動處理提示。
權限請求
內建的 request_permissions 工具會傳送
item/permissions/requestApproval,其中包含 threadId、turnId、itemId、
environmentId、cwd、可選的 reason,以及請求的網路或檔案系統
權限。請使用 permissions 進行回應,其中僅包含授予的子集。
將 scope 設定為 "session",可在同一會話的後續輪次中保留授權;
省略它或使用 "turn",則授權僅限當前輪次。未請求的權限
將被忽略。
MCP server 資訊徵詢請求
MCP server 可以使用 mcpServer/elicitation/request 中斷輪次。該
請求包含 threadId、可選的 turnId、serverName,以及以下
某種請求結構:
mode: "form"或mode: "openai/form",包含message和requestedSchema。mode: "url",包含message、url和elicitationId。
使用 action: "accept" 和請求的 content 進行回應,或使用
action: "decline" 或 "cancel" 以及 content: null 進行回應。隨後 app-server 會發出
serverRequest/resolved。要接收 openai/form 變體,請通過
initialize.params.capabilities.mcpServerOpenaiFormElicitation 選擇加入。
動態工具呼叫(實驗性)
thread/start 上的 dynamicTools 以及相應的 item/tool/call 請求或回應流程均為實驗性 API。
動態工具名稱和名稱空間名稱必須遵循 Responses API 的命名 約束。請避免使用 Codex 內建工具所用的保留名稱空間名稱。
在輪次中呼叫動態工具時,app-server 會發出:
item/started,包含item.type = "dynamicToolCall"、status = "inProgress",以及tool和arguments。item/tool/call,作為伺服器傳送給客戶端的請求。- 包含傳回內容專案的客戶端回應載荷。
item/completed,包含item.type = "dynamicToolCall"、最終的status,以及傳回的任何contentItems或success值。
MCP 工具呼叫核准(應用)
應用(連接器)工具呼叫也可能需要核准。當應用工具呼叫具有副作用時,伺服器可能會通過 tool/requestUserInput 徵求核准,並提供 接受、拒絕 和 取消 等選項。即使工具同時聲明瞭權限較低的提示,破壞性工具註解也始終會觸發核准。如果使用者拒絕或取消,相關的 mcpToolCall 項將以錯誤狀態完成,而不會執行該工具。
技能
在使用者文本輸入中包含 $<skill-name> 可呼叫技能。新增一個 skill 輸入專案(推薦),這樣伺服器會注入完整的技能指令,而不是依賴模型解析名稱。
{
"method": "turn/start",
"id": 101,
"params": {
"threadId": "thread-1",
"input": [
{
"type": "text",
"text": "$skill-creator Add a new skill for triaging flaky CI."
},
{
"type": "skill",
"name": "skill-creator",
"path": "/Users/me/.codex/skills/skill-creator/SKILL.md"
}
]
}
}如果省略 skill 項,模型仍會解析 $<skill-name> 標記並嘗試定位技能,這可能會增加延遲。
範例:
$skill-creator Add a new skill for triaging flaky CI and include step-by-step usage.使用 skills/list 取得可用技能(可以通過帶有 forceReload 的 cwds 限定範圍)。你還可以包含 perCwdExtraUserRoots,將額外的絕對路徑作為特定 cwd 值的 user 範圍進行掃描。如果條目的 cwd 不在 cwds 中,app-server 會將其忽略。skills/list 可以按 cwd 複用快取結果;將 forceReload: true 設定為從磁碟重新整理。SKILL.json 存在時,伺服器會從中讀取 interface 和 dependencies。
{ "method": "skills/list", "id": 25, "params": {
"cwds": ["/Users/me/project", "/Users/me/other-project"],
"forceReload": true,
"perCwdExtraUserRoots": [
{
"cwd": "/Users/me/project",
"extraUserRoots": ["/Users/me/shared-skills"]
}
]
} }
{ "id": 25, "result": {
"data": [{
"cwd": "/Users/me/project",
"skills": [
{
"name": "skill-creator",
"description": "Create or update a Codex skill",
"enabled": true,
"interface": {
"displayName": "Skill Creator",
"shortDescription": "Create or update a Codex skill"
},
"dependencies": {
"tools": [
{
"type": "env_var",
"value": "GITHUB_TOKEN",
"description": "GitHub API token"
},
{
"type": "mcp",
"value": "github",
"transport": "streamable_http",
"url": "https://example.com/mcp"
}
]
}
}
],
"errors": []
}]
} }受監視的本機技能檔案發生變化時,伺服器也會發出 skills/changed 通知。請將其視為失效訊號,並在需要時使用當前參數重新執行 skills/list。
要按路徑啟用或停用技能:
{
"method": "skills/config/write",
"id": 26,
"params": {
"path": "/Users/me/.codex/skills/skill-creator/SKILL.md",
"enabled": false
}
}應用(連接器)
使用 app/installed 可讀取最新提交的已安裝應用執行時快照。
每個結果都包含應用的 id、runtimeName(或 null)、有效的
enabled 狀態以及 callable 狀態。僅當有效
設定啟用了應用,並且至少有一個對模型可見的工具符合應用和工具策略時,
該應用才可呼叫。
{
"method": "app/installed",
"id": 49,
"params": {
"threadId": "thread-1",
"forceRefresh": false
}
}
{
"id": 49,
"result": {
"apps": [
{
"id": "demo-app",
"runtimeName": "Demo App",
"enabled": true,
"callable": true
}
]
}
}省略 threadId,可使用全域設定而不是已載入執行緒的
設定。將 forceRefresh: true 設定為在讀取前重新整理連接器執行時
快照。當全域或工作區策略阻止應用存取時,已觀測到的應用仍可能出現,
其 enabled 和 callable 會被設定為 false。
使用 app/list 取得可用應用。在 CLI/TUI 中,/apps 是面向使用者的選擇器;在自訂客戶端中,請直接呼叫 app/list。每個條目都同時包含 isAccessible(對使用者可用)和 isEnabled(已在 config.toml 中啟用),以便客戶端區分安裝/存取狀態與本機啟用狀態。應用條目還可以包含可選的 branding、appMetadata 和 labels 欄位。
{ "method": "app/list", "id": 50, "params": {
"cursor": null,
"limit": 50,
"threadId": "thread-1",
"forceRefetch": false
} }
{ "id": 50, "result": {
"data": [
{
"id": "demo-app",
"name": "Demo App",
"description": "Example connector for documentation.",
"logoUrl": "https://example.com/demo-app.png",
"logoUrlDark": null,
"distributionChannel": null,
"branding": null,
"appMetadata": null,
"labels": null,
"installUrl": "https://chatgpt.com/apps/demo-app/demo-app",
"isAccessible": true,
"isEnabled": true
}
],
"nextCursor": null
} }如果提供 threadId,應用功能門控(features.apps)會使用該執行緒的設定快照。如果省略,app-server 會使用最新的全域設定。
app/list 會在可存取應用和目錄應用都載入完成後傳回。設定 forceRefetch: true 可繞過應用快取並取得最新資料。只有重新整理成功時,快取條目才會被替換。
任一來源(可存取應用或目錄應用)完成載入時,伺服器也會發出 app/list/updated 通知。每條通知都包含最新合並的應用列表。
{
"method": "app/list/updated",
"params": {
"data": [
{
"id": "demo-app",
"name": "Demo App",
"description": "Example connector for documentation.",
"logoUrl": "https://example.com/demo-app.png",
"logoUrlDark": null,
"distributionChannel": null,
"branding": null,
"appMetadata": null,
"labels": null,
"installUrl": "https://chatgpt.com/apps/demo-app/demo-app",
"isAccessible": true,
"isEnabled": true
}
]
}
}當你已知應用 ID 並且需要應用後設資料而不是已安裝的執行時狀態時,
請使用 app/read。最多傳入 100 個 appIds。伺服器僅保留
每個重複 ID 第一次出現的位置,並在 apps 和 missingAppIds 中
保留該順序。未知或無法存取的應用會在 missingAppIds 中傳回,
而不會導致整個請求失敗。
{
"method": "app/read",
"id": 52,
"params": {
"appIds": ["demo-app", "missing-app"],
"includeTools": true
}
}
{
"id": 52,
"result": {
"apps": [
{
"id": "demo-app",
"name": "Demo App",
"description": "Example connector for documentation.",
"iconUrl": null,
"iconUrlDark": null,
"distributionChannel": null,
"installUrl": null,
"pluginDisplayNames": [],
"toolSummaries": [
{
"name": "search",
"title": "Search",
"description": "Search the app.",
"isEnabled": true,
"disabledReason": null,
"isReadOnly": true
}
]
}
],
"missingAppIds": ["missing-app"]
}
}設定 includeTools: true 可請求僅供顯示的公開工具摘要。該
後設資料回應不包含已安裝應用的執行時狀態,也不會授權
工具呼叫;請使用 app/installed 檢查有效的 enabled 和 callable
狀態。
要呼叫應用,請在文本輸入中插入 $<app-slug>,並新增一個包含 app://<id> 路徑的 mention 輸入專案(推薦)。
{
"method": "turn/start",
"id": 51,
"params": {
"threadId": "thread-1",
"input": [
{
"type": "text",
"text": "$demo-app Pull the latest updates from the team."
},
{
"type": "mention",
"name": "Demo App",
"path": "app://demo-app"
}
]
}
}應用設定的設定 RPC 範例
使用 config/read、config/value/write 和 config/batchWrite 可檢查或更新 config.toml 中的應用控制項。
讀取有效的應用設定結構(包括 _default 和逐工具覆蓋項):
{ "method": "config/read", "id": 60, "params": { "includeLayers": false } }
{ "id": 60, "result": {
"config": {
"apps": {
"_default": {
"enabled": true,
"destructive_enabled": true,
"open_world_enabled": true,
"approvals_reviewer": "user",
"default_tools_approval_mode": "auto"
},
"google_drive": {
"enabled": true,
"destructive_enabled": false,
"approvals_reviewer": "auto_review",
"default_tools_approval_mode": "prompt",
"tools": {
"files/delete": { "enabled": false, "approval_mode": "approve" }
}
}
}
}
} }除非逐應用值將其覆蓋,否則 apps._default.approvals_reviewer 會為所有應用設定審查器。如果兩者都省略,應用會繼承頂層的 approvals_reviewer 值。apps._default.default_tools_approval_mode 會為沒有逐應用或逐工具覆蓋項的工具設定回退核准模式。託管核准模式要求會覆蓋工具核准模式設定。
更新單個應用設定:
{
"method": "config/value/write",
"id": 61,
"params": {
"keyPath": "apps.google_drive.default_tools_approval_mode",
"value": "prompt",
"mergeStrategy": "replace"
}
}以原子方式應用多項應用編輯:
{
"method": "config/batchWrite",
"id": 62,
"params": {
"edits": [
{
"keyPath": "apps._default.destructive_enabled",
"value": false,
"mergeStrategy": "upsert"
},
{
"keyPath": "apps.google_drive.tools.files/delete.approval_mode",
"value": "approve",
"mergeStrategy": "upsert"
}
]
}
}檢測並匯入外部智能體設定
使用 externalAgentConfig/detect 可發現能夠遷移的外部智能體製品,然後將選定條目傳遞給 externalAgentConfig/import。
檢測範例:
{ "method": "externalAgentConfig/detect", "id": 63, "params": {
"includeHome": true,
"cwds": ["/Users/me/project"]
} }
{ "id": 63, "result": {
"items": [
{
"itemType": "AGENTS_MD",
"description": "Import /Users/me/project/CLAUDE.md to /Users/me/project/AGENTS.md.",
"cwd": "/Users/me/project"
},
{
"itemType": "SKILLS",
"description": "Copy skill folders from /Users/me/.claude/skills to /Users/me/.agents/skills.",
"cwd": null
}
]
} }匯入範例:
{ "method": "externalAgentConfig/import", "id": 64, "params": {
"migrationItems": [
{
"itemType": "AGENTS_MD",
"description": "Import /Users/me/project/CLAUDE.md to /Users/me/project/AGENTS.md.",
"cwd": "/Users/me/project"
}
],
"source": "claude-code"
} }
{ "id": 64, "result": { "importId": "8ae96ff3-3425-4f4c-8772-b6fd61502868" } }可選的頂層 source 匯入參數用於標記生成所選遷移專案的
產品。
各專案類型完成時,伺服器會發出 externalAgentConfig/import/progress;
所有同步和後台匯入完成後,會發出 externalAgentConfig/import/completed。
這些通知包含回應中的同一個 importId,以及帶有逐類型 successes 和 failures 的
itemTypeResults。完成通知可能緊隨回應到達,也可能在後台遠端
匯入完成後到達。
{ "method": "externalAgentConfig/import/progress", "params": {
"importId": "8ae96ff3-3425-4f4c-8772-b6fd61502868",
"itemTypeResults": [
{
"itemType": "AGENTS_MD",
"successes": [
{ "itemType": "AGENTS_MD", "cwd": "/Users/me/project", "source": null, "target": "/Users/me/project/AGENTS.md" }
],
"failures": []
}
]
} }
{ "method": "externalAgentConfig/import/completed", "params": {
"importId": "8ae96ff3-3425-4f4c-8772-b6fd61502868",
"itemTypeResults": [
{
"itemType": "AGENTS_MD",
"successes": [
{ "itemType": "AGENTS_MD", "cwd": "/Users/me/project", "source": null, "target": "/Users/me/project/AGENTS.md" }
],
"failures": []
}
]
} }讀取先前已完成的匯入:
{ "method": "externalAgentConfig/import/readHistories", "id": 65 }
{ "id": 65, "result": { "data": [
{
"importId": "8ae96ff3-3425-4f4c-8772-b6fd61502868",
"completedAtMs": 1781784000000,
"successes": [
{ "itemType": "AGENTS_MD", "cwd": "/Users/me/project", "source": null, "target": "/Users/me/project/AGENTS.md" }
],
"failures": []
}
] } }支援的 itemType 值包括 AGENTS_MD、CONFIG、SKILLS、PLUGINS、
MCP_SERVER_CONFIG、SUBAGENTS、HOOKS、COMMANDS 和 SESSIONS。對於
PLUGINS 項,details.plugins 會列出每個 marketplaceName 以及
Codex 可以嘗試遷移的 pluginNames。檢測只傳回仍有工作待完成的專案。
例如,當 AGENTS.md 已存在且非空時,Codex 會跳過 AGENTS 遷移;
技能匯入也不會覆蓋現有技能目錄。
從 .claude/settings.json 檢測外掛時,Codex 會從
extraKnownMarketplaces 讀取已設定的市場來源。如果 enabledPlugins 包含
來自 claude-plugins-official 的外掛,但缺少市場來源,
Codex 會推斷以 anthropics/claude-plugins-official 作為來源。
身份驗證端點
JSON-RPC 身份驗證/帳戶介面提供請求/回應方法和伺服器發起的通知(無 id)。使用這些介面可確定身份驗證狀態、啟動或取消登入、退出登入、檢查 ChatGPT 速率限制,以及在點數耗盡或達到用量限制時通知工作區所有者。
身份驗證模式
Codex 支援以下身份驗證模式。account/updated.authMode 會顯示活躍模式,並在可用時包含當前 ChatGPT planType。account/read 還會報告帳戶和套餐詳細資訊。
- API key(
apikey) - 呼叫方通過type: "apiKey"提供 OpenAI API key,Codex 會儲存該金鑰以用於 API 請求。 - ChatGPT 託管(
chatgpt) - Codex 負責 ChatGPT OAuth 流程、持久化令牌並自動重新整理。瀏覽器流程使用type: "chatgpt"啟動,裝置程式碼流程使用type: "chatgptDeviceCode"啟動。 - ChatGPT 外部令牌(
chatgptAuthTokens) - 此功能為實驗性功能,適用於已經負責使用者 ChatGPT 身份驗證生命週期的宿主應用。宿主應用直接提供accessToken、chatgptAccountId和可選的chatgptPlanType,並且必須在收到請求時重新整理令牌。 - Amazon Bedrock -
account/read將 Bedrock 帳戶報告為type: "amazonBedrock",並指明憑據來自 Codex 管理的 Bedrock API key(credentialSource: "codexManaged")還是外部 AWS 憑據鏈(credentialSource: "awsManaged")。account/updated.authMode使用bedrockApiKey處理 Codex 管理的 Bedrock API key。
API 概覽
account/read- 取得當前帳戶資訊;可以選擇重新整理令牌。account/login/start- 開始登入(apiKey、chatgpt、chatgptDeviceCode或實驗性的chatgptAuthTokens)。account/login/completed(通知)- 登入嘗試完成(成功或出錯)時發出。account/login/cancel- 通過loginId取消待處理的託管 ChatGPT 登入。account/logout- 退出登入;會觸發account/updated。account/updated(通知)- 身份驗證模式發生變化時發出(authMode:apikey、chatgpt、chatgptAuthTokens、agentIdentity、personalAccessToken、bedrockApiKey或null),並在可用時包含planType。account/chatgptAuthTokens/refresh(伺服器請求)- 發生授權錯誤後,請求新的外部託管 ChatGPT 令牌。account/rateLimits/read- 取得 ChatGPT 速率限制。account/rateLimits/updated(通知)- 使用者的 ChatGPT 速率限制發生變化時發出。account/sendAddCreditsNudgeEmail- 請求 ChatGPT 在點數耗盡或達到用量限制時向工作區所有者傳送電子郵件。account/rateLimitResetCredit/consume- 使用呼叫方提供的idempotencyKey值消耗一次已獲得的速率限制重置機會。account/usage/read- 取得 ChatGPT 帳戶令牌活動摘要和每日分桶。account/workspaceMessages/read- 取得活躍的工作區訊息,包括可用的通知標題。mcpServer/oauthLogin/completed(通知)-mcpServer/oauth/login流程完成後發出;載荷包含{ name, threadId, success, error? }。對於應用範圍或外掛 OAuth 流程,threadId可以是null。mcpServer/startupStatus/updated(通知)- 已設定 MCP server 的啟動狀態發生變化時發出;載荷包含{ threadId, name, status, error, failureReason }。對於應用範圍的啟動,threadId為null。啟動失敗時,failureReason: "reauthenticationRequired"表示儲存的 OAuth 憑據已過期且無法重新整理,因此客戶端應提供重新連線伺服器的選項。
1)檢查身份驗證狀態
請求:
{ "method": "account/read", "id": 1, "params": { "refreshToken": false } }回應範例:
{ "id": 1, "result": { "account": null, "requiresOpenaiAuth": false } }{ "id": 1, "result": { "account": null, "requiresOpenaiAuth": true } }{
"id": 1,
"result": { "account": { "type": "apiKey" }, "requiresOpenaiAuth": true }
}{
"id": 1,
"result": {
"account": {
"type": "amazonBedrock",
"credentialSource": "codexManaged"
},
"requiresOpenaiAuth": false
}
}{
"id": 1,
"result": {
"account": {
"type": "amazonBedrock",
"credentialSource": "awsManaged"
},
"requiresOpenaiAuth": false
}
}{
"id": 1,
"result": {
"account": {
"type": "chatgpt",
"email": "user@example.com",
"planType": "pro"
},
"requiresOpenaiAuth": true
}
}欄位說明:
refreshToken(布林值):將true設定為強制在託管 ChatGPT 模式下重新整理令牌。在外部令牌模式(chatgptAuthTokens)下,app-server 會忽略此標誌。- 當 ChatGPT 帳戶沒有電子郵件地址時,
email為null。 requiresOpenaiAuth反映活躍的供應商;當其為false時,Codex 無需 OpenAI 憑據即可執行。- 當 Amazon Bedrock 使用由 Codex 管理的
Bedrock API key 時,會報告
credentialSource: "codexManaged"。對於外部 AWS 憑據路徑, 它會報告credentialSource: "awsManaged"。這用於識別所選的憑據 來源,並不會驗證 AWS 憑據鏈是否能夠解析出 憑據。
2)使用 API key 登入
- 傳送:
{
"method": "account/login/start",
"id": 2,
"params": { "type": "apiKey", "apiKey": "sk-..." }
}- 預期回應:
{ "id": 2, "result": { "type": "apiKey" } }- 通知:
{
"method": "account/login/completed",
"params": { "loginId": null, "success": true, "error": null }
} {
"method": "account/updated",
"params": { "authMode": "apikey", "planType": null }
}3)使用 ChatGPT 登入(瀏覽器流程)
- 啟動:
{
"method": "account/login/start",
"id": 3,
"params": {
"type": "chatgpt",
"useHostedLoginSuccessPage": true,
"appBrand": "chatgpt"
}
} 預設情況下,瀏覽器回撥成功後會重定向到本機成功頁面。
如果不需要進行組織設定,請設定 useHostedLoginSuccessPage: true 以使用託管的成功頁面。
啟用託管成功頁面後,appBrand 可以是 "codex" 或 "chatgpt";
省略該值或設為 null 時,預設為
"codex"。
{
"id": 3,
"result": {
"type": "chatgpt",
"loginId": "<uuid>",
"authUrl": "https://chatgpt.com/...&redirect_uri=http%3A%2F%2Flocalhost%3A<port>%2Fauth%2Fcallback"
}
}- 在瀏覽器中開啟
authUrl;app-server 會託管本機回撥。 - 等待通知:
{
"method": "account/login/completed",
"params": { "loginId": "<uuid>", "success": true, "error": null }
} {
"method": "account/updated",
"params": { "authMode": "chatgpt", "planType": "plus" }
}3b)使用 ChatGPT 登入(裝置程式碼流程)
如果客戶端負責登入互動,或瀏覽器回撥不穩定,請使用此流程。
- 啟動:
{
"method": "account/login/start",
"id": 4,
"params": { "type": "chatgptDeviceCode" }
} {
"id": 4,
"result": {
"type": "chatgptDeviceCode",
"loginId": "<uuid>",
"verificationUrl": "https://auth.openai.com/codex/device",
"userCode": "ABCD-1234"
}
}- 向用戶顯示
verificationUrl和userCode;前端負責 UX。 - 等待通知:
{
"method": "account/login/completed",
"params": { "loginId": "<uuid>", "success": true, "error": null }
} {
"method": "account/updated",
"params": { "authMode": "chatgpt", "planType": "plus" }
}3c)使用外部管理的 ChatGPT 令牌登入(chatgptAuthTokens)
僅當宿主應用負責使用者的 ChatGPT 身份驗證生命週期並直接提供令牌時,才使用此實驗性模式。使用此登入類型之前,客戶端必須在 initialize 期間設定 capabilities.experimentalApi = true。
- 傳送:
{
"method": "account/login/start",
"id": 7,
"params": {
"type": "chatgptAuthTokens",
"accessToken": "<jwt>",
"chatgptAccountId": "org-123",
"chatgptPlanType": "business"
}
}- 預期回應:
{ "id": 7, "result": { "type": "chatgptAuthTokens" } }- 通知:
{
"method": "account/login/completed",
"params": { "loginId": null, "success": true, "error": null }
} {
"method": "account/updated",
"params": { "authMode": "chatgptAuthTokens", "planType": "business" }
}伺服器收到 401 Unauthorized 時,可能會向宿主應用請求重新整理後的令牌:
{
"method": "account/chatgptAuthTokens/refresh",
"id": 8,
"params": { "reason": "unauthorized", "previousAccountId": "org-123" }
}
{ "id": 8, "result": { "accessToken": "<jwt>", "chatgptAccountId": "org-123", "chatgptPlanType": "business" } }重新整理回應成功後,伺服器會重試原始請求。請求會在約 10 秒後超時。
4)取消 ChatGPT 登入
{ "method": "account/login/cancel", "id": 4, "params": { "loginId": "<uuid>" } }
{ "method": "account/login/completed", "params": { "loginId": "<uuid>", "success": false, "error": "..." } }5)退出登入
{ "method": "account/logout", "id": 5 }
{ "id": 5, "result": {} }
{ "method": "account/updated", "params": { "authMode": null, "planType": null } }6)速率限制(ChatGPT)
{ "method": "account/rateLimits/read", "id": 6 }
{ "id": 6, "result": {
"rateLimits": {
"limitId": "codex",
"limitName": null,
"primary": { "usedPercent": 25, "windowDurationMins": 15, "resetsAt": 1730947200 },
"secondary": null,
"rateLimitReachedType": null
},
"rateLimitsByLimitId": {
"codex": {
"limitId": "codex",
"limitName": null,
"primary": { "usedPercent": 25, "windowDurationMins": 15, "resetsAt": 1730947200 },
"secondary": null,
"rateLimitReachedType": null
},
"codex_other": {
"limitId": "codex_other",
"limitName": "codex_other",
"primary": { "usedPercent": 42, "windowDurationMins": 60, "resetsAt": 1730950800 },
"secondary": null,
"rateLimitReachedType": null
}
},
"rateLimitResetCredits": {
"availableCount": 2,
"credits": [{
"id": "RateLimitResetCredit_1",
"resetType": "codexRateLimits",
"status": "available",
"grantedAt": 1781654400,
"expiresAt": 1784246400,
"title": "Rate-limit reset",
"description": "Reset an eligible Codex rate-limit window."
}]
}
} }
{ "method": "account/rateLimits/updated", "params": {
"rateLimits": {
"limitId": "codex",
"primary": { "usedPercent": 31, "windowDurationMins": 15, "resetsAt": 1730948100 }
}
} }欄位說明:
rateLimits是向後相容的單分桶檢視。rateLimitsByLimitId(如果存在)是按計量的limit_id(例如codex)設鍵的多分桶檢視。limitId是計量分桶識別符。limitName是分桶的可選使用者可見標籤。usedPercent是配額視窗內的當前用量。windowDurationMins是配額視窗長度。resetsAt是下一次重置時間的 Unix 時間戳(秒)。- 當伺服器傳回與分桶關聯的 ChatGPT 套餐時,會包含
planType。 - 當伺服器傳回工作區剩餘點數詳情時,會包含
credits。 - 達到限制時,
rateLimitReachedType用於識別伺服器分類的限制狀態。 - 當服務提供可用的已獲得重置次數時,
rateLimitResetCredits包含該次數;否則為null。 - 當僅知道數量時,
rateLimitResetCredits.credits為null。空陣列表示服務已取得詳情,但沒有傳回可用點數。服務可能會限制詳細資訊行數,因此應以availableCount為準。 - 每個詳情行都包含不透明的
id、resetType、status、grantedAt、expiresAt(可以是null)、title(可以是null)和description(可以是null)。 - 消耗重置機會後,取得
account/rateLimits/read。
7)令牌用量(ChatGPT)
使用 account/usage/read 取得 ChatGPT 令牌活動摘要欄位和
可選的每日分桶。
{ "method": "account/usage/read", "id": 7 }
{ "id": 7, "result": {
"summary": {
"lifetimeTokens": 1234567,
"peakDailyTokens": 45678,
"longestRunningTurnSec": 540,
"currentStreakDays": 8,
"longestStreakDays": 14
},
"dailyUsageBuckets": [
{ "startDate": "2026-06-18", "tokens": 12345 }
]
} }欄位說明:
- 如果服務尚未傳回相應指標,
summary值可能為null。 dailyUsageBuckets可能為null;如果存在,每個分桶都包含startDate和tokens。- 此端點需要由 Codex 服務支援的身份驗證。支援 ChatGPT、 外部 ChatGPT 令牌、智能體身份和個人存取令牌身份驗證; 僅使用 API key 和 Bedrock 身份驗證則不支援。
8)已獲得的速率限制重置機會(ChatGPT)
使用 account/rateLimitResetCredit/consume 可消耗一次已獲得的重置機會。
{ "method": "account/rateLimitResetCredit/consume", "id": 8, "params": { "idempotencyKey": "8ae96ff3-3425-4f4c-8772-b6fd61502868", "creditId": "RateLimitResetCredit_1" } }
{ "id": 8, "result": { "outcome": "reset" } }欄位說明:
idempotencyKey不得為空。為每次邏輯兌換嘗試使用一個 UUID;重試同一次嘗試時,請複用相同的值。creditId是可選的。如果提供,它必須是來自account/rateLimits/read的非空不透明 ID。如果省略,服務會選擇下一個可用點數。reset表示已消耗一個點數。alreadyRedeemed表示同一兌換之前已經完成。請將其視為冪等成功,並重新整理帳戶限制。nothingToReset表示沒有符合條件的速率限制視窗可供重置。noCredit表示帳戶沒有可用的已獲得重置點數。- 消耗重置機會後,請取得
account/rateLimits/read,不要根據此回應推斷更新後的視窗。
9)向工作區所有者傳送限制通知
使用 account/sendAddCreditsNudgeEmail 可請求 ChatGPT 在點數耗盡或達到用量限制時向工作區所有者傳送電子郵件。
{ "method": "account/sendAddCreditsNudgeEmail", "id": 9, "params": { "creditType": "credits" } }
{ "id": 9, "result": { "status": "sent" } }工作區點數耗盡時使用 creditType: "credits",達到工作區用量限制時使用 creditType: "usage_limit"。如果最近已經通知過所有者,回應狀態為 cooldown_active。
10)工作區訊息(ChatGPT)
使用 account/workspaceMessages/read 取得當前工作區的活躍訊息,
包括可用的通知標題。
{ "method": "account/workspaceMessages/read", "id": 10 }
{ "id": 10, "result": { "featureEnabled": true, "messages": [
{ "messageId": "msg_123", "messageType": "headline", "messageBody": "Workspace maintenance starts at 5pm.", "createdAt": 1781395200, "archivedAt": null }
] } }