Codex App Server
전체 문서 색인은 llms.txt에서 확인하세요. 문서 페이지 URL 끝에 .md을 추가하면 Markdown 버전을 이용할 수 있습니다.
Codex app-server는 Codex가 풍부한 기능을 갖춘 클라이언트(예: Codex VS Code 확장 프로그램)를 구동하는 데 사용하는 인터페이스입니다. 자체 제품에 인증, 대화 기록, 승인, 스트리밍되는 에이전트 이벤트를 긴밀하게 통합하려는 경우 사용하세요. app-server 구현은 Codex GitHub 저장소(openai/codex/codex-rs/app-server)에 오픈 소스로 공개되어 있습니다. 오픈 소스 Codex 구성 요소의 전체 목록은 Open Source 페이지를 참조하세요.
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 뒤에 배치하세요. 전달자 토큰은 환경 변수에 저장하고 토큰을 명령줄에 직접 입력하는 대신 해당 환경 변수의 이름을 전달하세요.
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 엔드포인트를 허용합니다. 일반 WebSocket은 localhost 또는 SSH
포트 포워딩 연결에만 사용하세요.
원격 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 호스트로 나가는 연결을 제어합니다. 클라이언트가 app-server에 연결하는 방식을 제어하는
--listen은 변경하지 않습니다. 동일한 app-server 프로세스의 모든 스레드는 선택한
Code Mode 호스트 연결을 공유합니다.
원격 호스트에는 wss://을 사용하세요. ws://은 localhost 또는
SSH 포워딩 연결에만 사용하세요. 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 소켓(
--listen unix://또는--listen unix://PATH): 표준 HTTP Upgrade 핸드셰이크를 사용하는 Codex 기본 app-server 제어 소켓 또는 사용자 지정 Unix 소켓 경로상의 WebSocket 연결. 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
서명된 전달자 토큰에는 --ws-issuer, --ws-audience 및
--ws-max-clock-skew-seconds도 설정할 수 있습니다. 클라이언트는 WebSocket 핸드셰이크 중에 자격 증명을
Authorization: Bearer <token> 형식으로 제시하며, app-server는 JSON-RPC initialize 전에
인증을 적용합니다.
원시 전달자 토큰을 명령줄에 전달하는 대신 --ws-token-file을 사용하세요. 클라이언트가 원시 고엔트로피 토큰을
별도의 로컬 보안 저장소에 보관하는 경우에만 --ws-token-sha256을 사용하세요.
해시는 검증자일 뿐이므로 클라이언트에는 여전히 원본 토큰이 필요합니다.
WebSocket 모드에서 app-server는 크기가 제한된 큐를 사용합니다. 요청 수신 큐가 가득 차면
서버는 새 요청을 JSON-RPC 오류 코드 -32001 및 메시지
"Server overloaded; retry later."로 거부합니다. 클라이언트는 지터를 적용해
기하급수적으로 증가하는 지연 시간으로 재시도해야 합니다.
메시지 스키마
요청에는 method, params 및 id이 포함됩니다.
{ "method": "thread/start", "id": 10, "params": { "model": "gpt-5.6-terra" } }응답은 result 또는 error과 함께 id을 그대로 반환합니다.
{ "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 스키마 또는 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 소켓)으로 서버를 시작합니다.- 선택한 전송 방식으로 클라이언트를 연결한 다음
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을, 기록을 새 스레드 ID로 분기하려면thread/fork을 호출합니다. - 턴 시작: 대상
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이 반환됩니다.
서버는 업스트림 서비스에 제시할 사용자 에이전트 문자열과 런타임 대상을 설명하는 platformFamily 및 platformOs 값을 반환합니다. 통합을 식별하려면 clientInfo을 설정하세요.
initialize.params.capabilities은 다음과 같은 클라이언트 기능도 지원합니다.
optOutNotificationMethods- 이 연결에서 억제할 정확한 알림 메서드 이름입니다. 정확히 일치해야 하며(와일드카드 또는 접두사 없음), 알 수 없는 이름은 허용된 후 무시됩니다.requestAttestation- 서버에서 시작하는attestation/generate요청을 사용합니다. 업스트림 증명을 제공하는 데스크톱 호스트는 불투명한{ "token": "..." }값으로 응답합니다.mcpServerOpenaiFormElicitation- 다운스트림 MCP 서버가mcpServer/elicitation/request의 OpenAI 확장 형식 변형을 전송하도록 허용합니다.
중요: OpenAI Compliance Logs Platform에서 클라이언트를 식별하려면 clientInfo.name을 사용하세요. 엔터프라이즈용 새 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 기능으로 제한됩니다.
- 안정적인 API 표면을 유지하려면
capabilities을 생략하거나experimentalApi을false로 설정하세요. 서버는 실험적 메서드와 필드를 거부합니다. - 실험적 메서드와 필드를 활성화하려면
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- 로드된 스레드 또는 영구 저장된 롤아웃의 사용자 표시용 이름을 설정하거나 업데이트합니다.thread/name/updated을 내보냅니다.thread/goal/set- 스레드의 목표를 설정합니다.thread/goal/updated을 내보냅니다.thread/goal/get- 스레드의 현재 목표를 읽습니다.thread/goal/clear- 스레드의 목표를 지웁니다.thread/goal/cleared을 내보냅니다.thread/metadata/update- 영구 저장된gitInfo및isPinned을 비롯하여 SQLite 기반으로 저장된 스레드 메타데이터를 패치합니다.thread/archive- 스레드의 로그 파일을 보관 디렉터리로 이동하고 아직 보관되지 않은, 생성된 하위 스레드 로그도 보관하려고 시도합니다. 성공 시{}을 반환하고 보관된 각 스레드에 대해thread/archived을 내보냅니다.thread/delete- 영구 저장된 활성 또는 보관 스레드와 생성된 모든 하위 스레드를 영구적으로 삭제합니다. 성공 시{}을 반환하고 삭제된 각 스레드에 대해thread/deleted을 내보냅니다.thread/unsubscribe- 이 연결에서 스레드의 턴/항목 이벤트 구독을 해제합니다. 마지막 구독자였다면 구독자 없음 비활성 유예 기간 후 서버가 스레드를 언로드하고thread/closed을 내보냅니다.thread/unarchive- 보관된 스레드 롤아웃을 활성 세션 디렉터리로 복원합니다. 복원된thread을 반환하고thread/unarchived을 내보냅니다.thread/status/changed- 로드된 스레드의 런타임status이 변경될 때 내보내는 알림입니다.thread/compact/start- 스레드의 대화 기록 압축을 트리거합니다. 진행 상황이turn/*및item/*알림을 통해 스트리밍되는 동안{}을 즉시 반환합니다.thread/shellCommand- 스레드에 대해 사용자가 시작한 셸 명령을 실행합니다. 이 명령은 샌드박스 외부에서 전체 접근 권한으로 실행되며 스레드 샌드박스 정책을 상속하지 않습니다.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- 실행 중인command/exec세션에stdin바이트를 쓰거나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- 실행 중인process/spawn세션에 stdin 바이트를 쓰거나 stdin을 닫습니다(실험적).process/resizePty- 실행 중인 PTY 기반 프로세스 세션의 크기를 조정합니다(실험적).process/kill- 실행 중인 프로세스 세션을 종료합니다(실험적).process/outputDelta및process/exited(알림) - 스트리밍 프로세스 출력과 프로세스 종료 상태에 대해 내보냅니다(실험적).model/list- 작업 수준 옵션, 선택적upgrade및inputModalities과 함께 사용 가능한 모델을 나열합니다(hidden: true이 있는 항목을 포함하려면includeHidden: true설정).modelProvider/capabilities/read- 모델/공급자 조합의 공급자 기능 한계를 읽습니다.experimentalFeature/list- 수명 주기 단계 메타데이터와 커서 페이지네이션을 사용해 기능 플래그를 나열합니다.experimentalFeature/enablement/set-apps및plugins같은 지원되는 기능 키의 메모리 내 런타임 설정을 패치합니다.environment/info- 실험적 기능입니다. 구성된 실행 환경에 연결하고 해당 셸과 기본 작업 디렉터리를 반환합니다.permissionProfile/list- 베타 권한 프로필과 유효 요구 사항에서 해당 프로필을 허용하는지를 커서 페이지네이션으로 나열합니다.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, 구조화된 밝은/어두운 아이콘 및 현재 원격 행에 대해null,WORKSPACE_SETTING또는IMPLICIT_CANONICAL_APP일 수 있는installPolicySource이 포함될 수 있습니다. 아직 프로덕션 클라이언트에서 이 메서드를 호출하지 마세요.plugin/read- 개발 중인 기능입니다. 마켓플레이스 경로 또는 원격 마켓플레이스 이름과 플러그인 이름으로 하나의 플러그인을 읽습니다. 번들 스킬, 앱, MCP 서버 이름 및 원격 카탈로그에서 제공하는 경우 원격 플러그인shareUrl을 포함합니다. 아직 프로덕션 클라이언트에서 이 메서드를 호출하지 마세요.plugin/install- 개발 중인 기능입니다. 마켓플레이스 경로 또는 원격 마켓플레이스 이름에서 플러그인을 설치합니다. 아직 프로덕션 클라이언트에서 이 메서드를 호출하지 마세요.plugin/uninstall- 개발 중인 기능입니다. 설치된 플러그인을 제거합니다. 아직 프로덕션 클라이언트에서 이 메서드를 호출하지 마세요.plugin/skill/read- 원격 마켓플레이스, 플러그인 ID 및 스킬 이름으로 원격 플러그인 스킬 Markdown을 필요할 때 읽습니다.app/installed- 각 앱의 유효한 활성화 및 호출 가능 상태를 포함하여 설치된 앱 런타임 상태를 읽습니다.app/list- 접근성/활성화 메타데이터와 페이지네이션을 사용해 이용 가능한 앱(커넥터)을 나열합니다.app/read- 특정 앱 ID의 메타데이터와 선택적인 표시 전용 도구 요약을 가져옵니다.skills/config/write- 경로별로 스킬을 활성화하거나 비활성화합니다.mcpServer/oauth/login- 구성된 MCP 서버의 OAuth 로그인을 시작합니다. 인증 URL을 반환하고 완료 시mcpServer/oauthLogin/completed을 내보냅니다.tool/requestUserInput- 도구 호출을 위해 사용자에게 1~3개의 짧은 질문을 표시합니다(실험적). 질문은 자유 형식 옵션에isOther을 설정할 수 있습니다.mcpServer/elicitation/request(서버 요청) - MCP 서버가 요청한 구조화된 양식 입력 또는 URL 흐름 확인을 클라이언트에 요청합니다.item/permissions/requestApproval(서버 요청) - 기본 제공request_permissions도구가 요청한 네트워크 또는 파일 시스템 권한의 일부를 부여하도록 클라이언트에 요청합니다.config/mcpServer/reload- 디스크에서 MCP 서버 구성을 다시 로드하고 로드된 스레드의 새로 고침을 대기열에 추가합니다.mcpServerStatus/list- MCP 서버, 도구, 리소스 및 인증 상태를 나열합니다(커서 + 제한 페이지네이션). 전체 데이터에는detail: "full"을 사용하고 리소스를 생략하려면detail: "toolsAndAuthOnly"를 사용합니다.mcpServer/resource/read- 초기화된 MCP 서버를 통해 단일 MCP 리소스를 읽습니다.mcpServer/tool/call- 스레드에 구성된 MCP 서버의 도구를 호출합니다.mcpServer/startupStatus/updated(알림) - 로드된 스레드에 구성된 MCP 서버의 시작 상태가 변경되면 내보냅니다.windowsSandbox/setupStart-elevated또는unelevated모드의 Windows 샌드박스 설정을 시작합니다. 신속하게 반환하며 나중에windowsSandbox/setupCompleted을 내보냅니다.feedback/upload- 피드백 보고서를 제출합니다(분류 + 선택적 이유/로그 + 대화 ID 및 선택적extraLogFiles첨부 파일).config/read- 구성 계층을 해석한 후 디스크의 유효 구성을 가져옵니다.externalAgentConfig/detect-includeHome및 선택적cwds을 사용해 마이그레이션할 수 있는 외부 에이전트 아티팩트를 감지합니다. 감지된 각 항목에는cwd(홈의 경우null)이 포함됩니다.externalAgentConfig/import-cwd(홈의 경우null)과 함께 명시적인migrationItems을 전달하여 선택한 외부 에이전트 마이그레이션 항목을 적용합니다. 지원되는 항목 유형에는 구성, 스킬,AGENTS.md, 플러그인, MCP 서버 구성, 하위 에이전트, 훅, 명령 및 세션이 포함됩니다. 비어 있지 않은 가져오기는 작업이 완료될 때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일 수 있습니다. 해당 플러그인을 읽거나 설치할 때는
marketplacePath 대신 remoteMarketplaceName을 전달하세요.
모델
모델 나열(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일 수 있습니다. 베타가 아닌 플래그의 경우 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은 보관된 스레드 롤아웃을 활성 세션 디렉터리로 복원합니다.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을 사용 설정한 베타 클라이언트는 기존 sandbox 필드 대신
permissions에 이름이 지정된 권한 프로필 ID를 전달할 수 있습니다.
permissions과 sandbox을 함께 보내지 마세요. 프로젝트 cwd와 함께
permissionProfile/list을 사용하여 사용 가능한 프로필과 관리형 요구 사항에서 각 프로필을
허용하는지 확인하세요.
thread.sessionId은 현재 라이브 세션 트리의 루트를 식별합니다. 루트 스레드는
자체 스레드 ID를 세션 ID로 사용하고, 포크된 스레드는 생성된 루트의 세션 ID를
유지합니다. 클라이언트는 스레드 ID에서 세션 ID를 유추하지 말고
thread.sessionId에서 읽어야 합니다.
저장된 세션을 계속하려면 이전에 기록한 thread.id과 함께 thread/resume을 호출하세요. 응답 형태는 thread/start과 같습니다. personality처럼 thread/start에서 지원하는 것과 동일한 구성 재정의도 전달할 수 있습니다.
{ "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(또는 롤아웃 파일의 수정 시간)이 업데이트되지 않습니다. 타임스탬프는 턴을 시작할 때 업데이트됩니다.
활성화된 MCP 서버를 구성에서 required로 표시했는데 해당 서버 초기화에 실패하면, 서버 없이 계속 진행하는 대신 thread/start 및 thread/resume이 실패합니다.
thread/start의 dynamicTools은 실험적 필드입니다(capabilities.experimentalApi = true 필요). Codex는 이러한 동적 도구를 스레드 롤아웃 메타데이터에 영구 저장하고, 새 동적 도구를 제공하지 않으면 thread/resume에서 복원합니다.
롤아웃에 기록된 모델과 다른 모델로 재개하면 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을 생략하면 사용 기록을
유지하면서 상태 또는 토큰 예산이 업데이트됩니다.
저장된 세션에서 분기하려면 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도 포함됩니다. 이를 sortDirection: "asc"과 함께 cursor로 전달하면 이전 페이지의 첫 항목보다 최신인 턴을 가져올 수 있습니다.
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을 설정하고, 영구 저장된
Git 메타데이터를 변경하려면 gitInfo을 업데이트하세요. 생략된 필드는 변경되지 않으며 명시적인
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를 사용하여 영구 저장된 활성 또는 보관 스레드와
여기에서 생성된 하위 스레드를 영구적으로 삭제합니다. 서버는 성공 응답을 반환하기 전에 기존 롤아웃 파일과
관련 메타데이터를 제거하며, 누락된 롤아웃 파일은 이미 삭제된 것으로
처리합니다. 임시 루트 스레드는 삭제할 수 없습니다.
{ "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를 사용하여 보관된 스레드 롤아웃을 활성 세션 디렉터리로 다시 이동합니다.
{ "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": {} }스레드 셸 명령 실행
스레드에 속한 사용자 시작 셸 명령에는 thread/shellCommand를 사용합니다. 표준 turn/* 및 item/* 알림을 통해 진행 상황이 스트리밍되는 동안 요청은 {}와 함께 즉시 반환됩니다.
이 API는 샌드박스 외부에서 전체 접근 권한으로 실행되며 스레드의 샌드박스 정책을 상속하지 않습니다. 클라이언트는 사용자가 명시적으로 시작한 명령에만 이 API를 노출해야 합니다.
스레드에 이미 활성 턴이 있으면 명령은 해당 턴의 보조 작업으로 실행되고, 형식이 지정된 출력이 턴의 메시지 스트림에 삽입됩니다. 스레드가 유휴 상태이면 app-server가 셸 명령을 위한 독립 실행형 턴을 시작합니다.
{ "method": "thread/shellCommand", "id": 26, "params": { "threadId": "thr_b", "command": "git status --short" } }
{ "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 } }해당 processId와 함께 thread/backgroundTerminals/terminate를 사용하여 백그라운드 터미널 하나를
중지합니다. 이 메서드는 실험적이며
capabilities.experimentalApi = true가 필요합니다.
{ "method": "thread/backgroundTerminals/terminate", "id": 29, "params": { "threadId": "thr_b", "processId": "42" } }
{ "id": 29, "result": { "terminated": true } }최근 턴 롤백
thread/rollback는 더 이상 사용되지 않으며 제거될 예정입니다. 이 메서드는 인메모리 컨텍스트에서 마지막
numTurns개 항목을 제거하고 롤아웃 로그에 롤백 마커를 저장합니다. 반환되는 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 } } }스레드에 항목 삽입
thread/inject_items를 사용하여 사용자 턴을 시작하지 않고 미리 구성된 Responses API 항목을 로드된 스레드의 프롬프트 기록에 추가합니다. 이러한 항목은 롤아웃에 저장되고 이후 모델 요청에 포함됩니다.
{ "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(브랜치와의 diff)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"
}
}
}리뷰어가 완료되면 서버는 최종 리뷰 텍스트가 있는 exitedReviewMode 항목을 포함한 item/started 및 item/completed를 내보냅니다.
{
"method": "item/completed",
"params": {
"item": {
"type": "exitedReviewMode",
"id": "turn_900",
"review": "Looks solid overall..."
}
}
}이 알림을 사용하여 클라이언트에 리뷰어 출력을 렌더링합니다.
프로세스 실행
process/*는 실험적인 명시적 프로세스 제어 API입니다. 이 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
} }입력을 보내려면 deltaBase64, closeStdin 또는 둘 다와 함께 process/writeStdin를 사용합니다.
PTY 크기 조정 이벤트에는 process/resizePty를 사용하고 실행 중인 프로세스를
종료하려면 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를 사용합니다. - 명령 실행 중에
command/exec/outputDelta알림을 받으려면streamStdoutStderr: true을 설정합니다.
관리자 요구 사항 읽기(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- 턴 ID, 비어 있는items및status: "inProgress"이 있는{ turn }.turn/completed-turn.status이completed,interrupted또는failed인{ turn }이며, 실패 시{ error: { message, codexErrorInfo?, additionalDetails? } }가 포함됩니다.turn/diff/updated- 턴에서 변경된 모든 파일에 걸친 최신 통합 diff가 있는{ threadId, turnId, diff }.turn/plan/updated- 에이전트가 계획을 공유하거나 변경할 때마다 내보내지는{ turnId, explanation?, plan }. 각plan항목은status가pending,inProgress또는completed인{ step, status }입니다.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-content이 사용자 입력(text,image또는localImage) 목록인{id, content}.agentMessage- 누적된 에이전트 응답을 포함하는{id, text, phase?}.phase가 있으면 Responses API 와이어 값(commentary,final_answer)을 사용합니다.plan- 계획 모드에서 제안된 계획 텍스트를 포함하는{id, text}.item/completed의 최종plan항목을 기준 데이터로 취급하세요.reasoning-summary에 스트리밍된 추론 요약이,content에 원시 추론 블록이 있는{id, 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가 포함될 수 있습니다. 이전에 저장된 항목에는 최신 메타데이터가 없을 수 있습니다. 더 이상 사용되지 않는 최상위mcpAppResourceUri대신appContext.resourceUri를 사용하세요.dynamicToolCall- 클라이언트에서 실행하는 동적 도구 호출을 위한{id, tool, arguments, status, contentItems?, success?, durationMs?}.collabToolCall-{id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}.webSearch- 에이전트가 실행한 웹 검색 요청을 위한{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는command,cwd및 기타 필드가 있는 보류 중인commandExecution항목을 표시합니다.item/commandExecution/requestApproval에는itemId,threadId,turnId, 선택적reason, 선택적command, 선택적cwd, 선택적commandActions, 선택적proposedExecpolicyAmendment, 선택적networkApprovalContext및 선택적availableDecisions가 포함됩니다.initialize.params.capabilities.experimentalApi = true인 경우 페이로드에 요청된 명령별 샌드박스 접근 권한을 설명하는 실험적additionalPermissions도 포함될 수 있습니다.additionalPermissions내의 모든 파일 시스템 경로는 와이어에서 절대 경로입니다.- 클라이언트가 위의 명령 실행 승인 결정 중 하나로 응답합니다.
serverRequest/resolved는 보류 중인 요청에 응답했거나 요청이 정리되었음을 확인합니다.item/completed은status: completed | failed | declined가 있는 최종commandExecution항목을 반환합니다.
networkApprovalContext이 있으면 프롬프트는 관리형 네트워크 접근을 위한 것이며 일반적인 셸 명령 승인이 아닙니다. 현재 v2 스키마는 대상 host 및 protocol을 노출합니다. 클라이언트는 네트워크 전용 프롬프트를 렌더링해야 하며 command가 사용자에게 의미 있는 셸 명령 미리 보기라고 가정해서는 안 됩니다.
Codex는 동시 네트워크 승인 프롬프트를 대상(host, 프로토콜 및 포트)별로 그룹화합니다. 따라서 app-server는 같은 대상에 대기 중인 여러 요청의 차단을 해제하는 프롬프트 하나를 보낼 수 있지만, 같은 호스트의 서로 다른 포트는 별도로 처리됩니다.
파일 변경 승인
메시지 순서:
item/started은 제안된changes및status: "inProgress"가 있는fileChange항목을 내보냅니다.item/fileChange/requestApproval에는itemId,threadId,turnId, 선택적reason및 선택적grantRoot이 포함됩니다.- 클라이언트가 위의 파일 변경 승인 결정 중 하나로 응답합니다.
serverRequest/resolved은 보류 중인 요청에 응답했거나 요청이 정리되었음을 확인합니다.item/completed는status: completed | failed | declined가 있는 최종fileChange항목을 반환합니다.
tool/requestUserInput
클라이언트가 item/tool/requestUserInput에 응답하면 app-server는 { threadId, requestId }이 있는 serverRequest/resolved을 내보냅니다. 클라이언트가 응답하기 전에 턴 시작, 턴 완료 또는 턴 중단으로 보류 중인 요청이 정리되면 서버는 해당 정리에 대해서도 같은 알림을 내보냅니다.
요청 매개변수에는 정수 밀리초 제한 시간인 autoResolutionMs 또는
null이 포함됩니다. 이 값이 있으면 사용자가 응답하지 않을 경우 호스트 클라이언트가 해당
시간이 지난 후 프롬프트를 자동으로 처리할 수 있습니다.
권한 요청
기본 제공 request_permissions 도구는
threadId, turnId, itemId,
environmentId, cwd, 선택적 reason 및 요청된 네트워크 또는 파일 시스템
권한이 포함된 item/permissions/requestApproval를 보냅니다. 부여할 권한의 하위 집합만 포함하는 permissions로 응답하세요.
같은 세션의 이후 턴에도 권한 부여를 유지하려면 scope을 "session"로 설정하고,
턴 범위의 권한 부여에는 이를 생략하거나 "turn"를 사용합니다. 요청되지 않은 권한은
무시됩니다.
MCP 서버 추가 정보 요청
MCP 서버는 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.type = "dynamicToolCall",status = "inProgress"과tool및arguments이 있는item/started.- 클라이언트에 대한 서버 요청으로
item/tool/call. - 반환된 콘텐츠 항목이 있는 클라이언트 응답 페이로드.
item.type = "dynamicToolCall", 최종status및 반환된contentItems또는success값이 있는item/completed.
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로 범위를 지정). 특정 cwd 값에 대해 추가 절대 경로를 user 범위로 검색하도록 perCwdExtraUserRoots도 포함할 수 있습니다. App-server는 cwd가 cwds에 없는 항목을 무시합니다. skills/list은 cwd별로 캐시된 결과를 재사용할 수 있습니다. 디스크에서 새로 고치려면 forceReload: true을 설정하세요. interface와 dependencies가 있으면 서버가 SKILL.json에서 이를 읽습니다.
{ "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를 사용합니다. appIds는 최대 100개까지 전달할 수 있습니다. 서버는 반복된 각 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를 설정합니다.
메타데이터 응답에는 설치된 앱 런타임 상태가 포함되지 않으며 도구 호출 권한을 부여하지도 않습니다. 유효한 enabled 및 callable 상태를 확인하려면 app/installed을 사용하세요.
텍스트 입력에 $<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는 Codex가 마이그레이션을 시도할 수 있는 각 marketplaceName와
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는 Codex 관리형 Bedrock API key에bedrockApiKey를 사용합니다.
API 개요
account/read- 현재 계정 정보를 가져옵니다. 선택적으로 토큰을 새로 고칩니다.account/login/start- 로그인을 시작합니다(apiKey,chatgpt,chatgptDeviceCode또는 실험적chatgptAuthTokens).account/login/completed(알림) - 로그인 시도가 완료되면 내보내집니다(성공 또는 오류).account/login/cancel- 보류 중인 관리형 ChatGPT 로그인을loginId로 취소합니다.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 서버의 시작 상태가 변경될 때 내보내집니다. 페이로드에는{ 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(불리언): 관리형 ChatGPT 모드에서 토큰을 강제로 새로 고치려면true으로 설정합니다. 외부 토큰 모드(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 토큰, 에이전트 ID 및 개인용 액세스 토큰 인증은 사용할 수 있지만, 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) 한도에 관해 작업 공간 소유자에게 알림
크레딧이 소진되거나 사용량 한도에 도달했을 때 ChatGPT가 작업 공간 소유자에게 이메일을 보내도록 요청하려면 account/sendAddCreditsNudgeEmail을 사용합니다.
{ "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 }
] } }