For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
기본 탐색 메뉴
Theme

Codex App Server

app-server 프로토콜로 제품에 Codex 통합하기

Codex app-server는 Codex가 VS Code용 Codex 확장 프로그램처럼 다양한 기능을 갖춘 클라이언트를 구동하는 데 사용하는 인터페이스입니다. 인증, 대화 기록, 승인, 에이전트 이벤트 스트리밍을 제품에 직접 통합하려면 이 인터페이스를 사용하세요. app-server 구현은 Codex GitHub 리포지터리에 오픈 소스로 공개되어 있습니다(openai/codex/codex-rs/app-server). Codex의 전체 오픈 소스 구성 요소 목록은 오픈 소스 페이지에서 확인하세요.

작업을 자동화하거나 CI에서 Codex를 실행하려면 Codex SDK를 사용하세요.

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 토큰은 환경 변수에 저장하고 명령줄에는 토큰 대신 변수 이름을 전달하세요.

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은 로컬호스트나 SSH 포트 포워딩 연결에서만 사용하세요.

원격 Code Mode 호스트 연결하기

기본적으로 app-server는 로컬 Code Mode 호스트를 시작합니다. 같은 app-server 프로세스의 여러 스레드에서 원격 호스트를 공유하려면 해당 호스트의 HTTP/2 gRPC 엔드포인트를 --code-mode-host에 전달하세요.

codex app-server --code-mode-host https://code-mode.example.com

도구 인수와 결과를 보호하려면 원격 호스트에 HTTPS를 사용하세요. HTTP는 루프백 연결이나 보안 터널에서만 사용하세요. URL에는 호스트 이름과 선택적 포트를 지정할 수 있습니다. 자격 증명, 경로, 쿼리 문자열, 프래그먼트는 생략하세요. 클라이언트에서 app-server로 연결하는 방식은 --listen으로 별도로 구성하세요.

프로토콜

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를 반환합니다.
  • GET /healthz는 200 OK를 반환하되, 요청에 Origin 헤더가 없어야 합니다.
  • Origin 헤더가 있는 요청은 403 Forbidden으로 거부합니다.

WebSocket 전송 방식은 실험적이며 지원되지 않습니다. ws://127.0.0.1:PORT 같은 로컬 리스너는 로컬호스트 및 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 토큰을 사용한다면 --ws-issuer, --ws-audience, --ws-max-clock-skew-seconds도 설정할 수 있습니다. 클라이언트는 WebSocket 핸드셰이크 중에 Authorization: Bearer <token> 형식으로 자격 증명을 전달합니다. app-server는 JSON-RPC initialize 전에 인증을 수행합니다.

명령줄에 Bearer 토큰 원문을 전달하기보다 --ws-token-file을 사용하세요. --ws-token-sha256은 클라이언트가 엔트로피가 높은 토큰 원문을 별도의 로컬 시크릿 저장소에 보관하는 경우에만 사용하세요. 해시는 검증에만 쓰이므로 클라이언트에는 여전히 원래 토큰이 필요합니다.

WebSocket 모드에서 app-server는 크기가 제한된 큐를 사용합니다. 수신 요청 큐가 가득 차면 서버는 JSON-RPC 오류 코드 -32001과 메시지 "Server overloaded; retry later."를 반환하고 새 요청을 거부합니다. 클라이언트는 재시도 간격을 지수적으로 늘리고 지터를 적용해야 합니다.

메시지 스키마

요청에는 method, params, id가 포함됩니다.

예제에서는 GPT-6.1 Sol을 사용합니다. 로그인한 계정 또는 워크스페이스에 이 모델의 접근 권한이 있어야 합니다. 필요하면 model/list를 사용해 이용 가능한 모델을 선택하세요.

{ "method": "thread/start", "id": 10, "params": { "model": "gpt-6.1-sol" } }

응답은 요청의 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 스키마 또는 JSON Schema 번들을 생성할 수 있습니다. 각 출력은 실행한 Codex 버전에 맞춰 생성되므로 결과물이 해당 버전과 정확히 일치합니다.

codex app-server generate-ts --out ./schemas
codex app-server generate-json-schema --out ./schemas

시작하기

  1. codex app-server(기본 stdio 전송), codex app-server --listen ws://127.0.0.1:4500(TCP WebSocket) 또는 codex app-server --listen unix://(기본 Unix 소켓)로 서버를 시작하세요.
  2. 선택한 전송 방식으로 클라이언트를 연결하고 initialize 요청을 보낸 뒤 initialized 알림을 보내세요.
  3. 스레드와 턴을 시작한 뒤 활성 전송 스트림에서 알림을 계속 읽으세요.

예제(Node.js / TypeScript)

import { spawn } from "node:child_process";
import readline from "node:readline";
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 === 0 && msg.result) {
    send({ method: "initialized", params: {} });
    send({
      method: "thread/start",
      id: 1,
      params: { model: "gpt-6.1-sol" },
    });
  }
  if (msg.method === "turn/completed") {
    if (msg.params?.turn?.status !== "completed") {
      console.error(msg.params?.turn?.error ?? "The turn did not complete.");
      process.exitCode = 1;
    }
    proc.stdin.end();
    rl.close();
  }
  if (msg.error) {
    console.error(msg.error);
    process.exitCode = 1;
    proc.stdin.end();
    rl.close();
  }
  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",
    },
  },
});
proc.on("error", (error) => {
  console.error(error);
  process.exitCode = 1;
  rl.close();
});
proc.on("exit", (code) => {
  if (code !== 0) process.exitCode = code ?? 1;
});

기본 개념

  • 스레드는 사용자와 Codex 에이전트 사이의 대화입니다. 스레드는 턴으로 구성됩니다.
  • 턴은 사용자 요청 하나와 그에 따라 에이전트가 수행하는 작업입니다. 턴은 항목으로 구성되며 진행 중에 변경 사항을 스트리밍합니다.
  • 항목은 사용자 메시지, 에이전트 메시지, 명령어 실행, 파일 변경, 도구 호출 등 입력 또는 출력의 단위입니다.

스레드 API로 대화를 생성하거나 목록을 조회하거나 대화를 보관하세요. 턴 API로 대화를 진행하고 턴 알림으로 진행 상황을 스트리밍하세요.

수명 주기 개요

  • 연결마다 한 번 초기화하기 — 전송 연결을 연 직후 클라이언트 메타데이터를 담은 initialize 요청을 보내고 initialized 알림을 보내세요. 서버는 이 핸드셰이크 전에 해당 연결로 들어오는 요청을 모두 거부합니다.
  • 스레드 시작 또는 재개하기 — 새 대화는 thread/start, 기존 대화는 thread/resume을 호출하세요. 대화 기록을 분기해 새 스레드 ID를 만들려면 thread/fork를 호출하세요.
  • 턴 시작하기 — turn/start를 호출할 때 대상 threadId와 사용자 입력을 전달하세요. 선택적 필드로 모델, 작업 디렉터리, 샌드박스 정책을 재정의할 수 있습니다.
  • 진행 중인 턴 조정하기 — turn/steer를 호출하면 새 턴을 만들지 않고 진행 중인 턴에 사용자 입력을 추가합니다.
  • 이벤트 스트리밍하기 — turn/start 이후에는 stdout에서 thread/archived, thread/unarchived, item/started, item/completed, item/agentMessage/delta, 도구 진행 상황 등 업데이트 알림을 계속 읽으세요.
  • 턴 종료하기 — 서버는 최종 상태를 담은 turn/completed 알림을 보냅니다. 모델이 작업을 마치거나 turn/interrupt로 턴이 취소되면 이 알림이 발생합니다.

초기화

클라이언트는 전송 연결마다 다른 메서드를 호출하기 전에 initialize 요청을 한 번 보내고 initialized 알림으로 확인해야 합니다. 초기화 전에 보낸 요청은 Not initialized 오류를 받습니다. 같은 연결에서 initialize를 다시 호출하면 Already initialized가 반환됩니다.

서버는 업스트림 서비스에 전달할 사용자 에이전트 문자열과 런타임 대상을 나타내는 platformFamily 및 platformOs 값을 반환합니다. 통합 클라이언트를 식별할 수 있도록 clientInfo를 설정하세요.

initialize.params.capabilities는 다음 클라이언트 기능도 지원합니다.

  • optOutNotificationMethods - 이 연결에서 수신하지 않을 알림 메서드의 정확한 이름을 지정합니다. 이름이 완전히 일치해야 하며 와일드카드나 접두사는 사용할 수 없습니다. 알 수 없는 이름은 허용하지만 무시합니다.
  • requestAttestation - 서버가 보내는 attestation/generate 요청을 수신하도록 설정합니다. 업스트림 증명을 제공하는 데스크톱 호스트는 내부 형식을 해석할 필요가 없는 { "token": "..." } 값으로 응답합니다.
  • mcpServerOpenaiFormElicitation - 다운스트림 MCP 서버가 mcpServer/elicitation/request의 OpenAI 확장 양식 베리언트를 보낼 수 있도록 허용합니다.

중요 — 컴플라이언스 로그 플랫폼에서 클라이언트를 식별할 수 있도록 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
    }
  }
}

클라이언트가 실험적 API를 활성화하지 않고 실험적 메서드나 필드를 보내면 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로 저장된 메타데이터를 읽습니다. 기록을 불러오려면 thread/turns/list와 thread/items/list를 사용하세요. 반환된 thread 객체에는 런타임 status가 포함됩니다.
  • thread/list - 저장된 스레드와 각 스레드의 런타임 상태를 페이지 단위로 조회합니다. 페이지네이션 및 필터를 참고하세요.
  • 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 - 스레드에 저장된 Git 메타데이터를 업데이트합니다.
  • 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-server의 processId로 실행 중인 백그라운드 터미널 하나를 종료합니다(실험적 기능, capabilities.experimentalApi 필요).
  • thread/revert - 페이지네이션을 사용하는 영구 스레드의 기록에서 지정한 턴과 이후 모든 턴을 제거합니다. 업데이트된 메타데이터와 기록 커서를 반환한 뒤 thread/reverted 알림을 보냅니다.
  • 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 세션의 stdout/stderr 청크를 base64로 인코딩해 보냅니다.
  • process/spawn - Codex 샌드박스 외부에서 프로세스 세션을 명시적으로 시작합니다(실험적 기능, capabilities.experimentalApi 필요).
  • process/writeStdin - 실행 중인 process/spawn 세션의 stdin에 바이트를 쓰거나 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 - 구성된 실행 환경에 연결해 셸과 기본 작업 디렉터리를 반환합니다(실험적 기능).
  • 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, 라이트 및 다크 모드용 구조화된 아이콘, installPolicySource가 포함될 수 있습니다. 현재 원격 항목의 설치 정책 출처는 null, WORKSPACE_SETTING 또는 IMPLICIT_CANONICAL_APP일 수 있습니다. 아직 프로덕션 클라이언트에서 호출하지 마세요.
  • 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 로그인을 시작합니다. 응답으로 받은 HTTP 또는 HTTPS authorizationUrl을 열고 loginId로 해당 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"를 사용하세요. 두 모드 모두 서버가 알린 serverCapabilities를 포함하며, 초기화에 성공하기 전에는 이 값이 null입니다. 서버 하나를 조회하려면 serverName을 전달하세요. threadId를 전달하면 해당 스레드의 MCP 연결을 재사용합니다.
  • mcpServer/resource/read - 초기화된 MCP 서버를 통해 MCP 리소스 하나를 읽습니다.
  • mcpServer/tool/call - 스레드에 구성된 MCP 서버의 도구를 호출합니다.
  • mcpServer/startupStatus/updated(알림) - 로드된 스레드에서 구성된 MCP 서버의 시작 상태가 바뀌면 보냅니다.
  • windowsSandbox/readiness - Windows 샌드박스가 준비되었는지 확인합니다. updateRequired가 반환되면 windowsSandbox/setupStart를 호출하고 windowsSandbox/setupCompleted 알림을 기다리세요.
  • feedback/upload - 분류, 선택적 사유 및 로그, 대화 ID를 담은 피드백 보고서를 제출합니다. extraLogFiles로 파일을 추가로 첨부할 수 있습니다.
  • config/read - 설정 계층을 모두 적용한 뒤 디스크의 유효 설정을 가져옵니다.
  • externalAgentConfig/detect - includeHome과 선택적 cwds를 사용해 마이그레이션할 수 있는 외부 에이전트 파일 및 설정을 찾습니다. 발견한 항목에는 cwd가 포함됩니다(홈 디렉터리인 경우 null).
  • externalAgentConfig/import - 선택한 외부 에이전트 마이그레이션 항목을 적용하려면 명시적으로 migrationItems를 전달하고 각 항목에 cwd(홈 디렉터리인 경우 null)를 지정하세요. 지원하는 유형은 설정, 스킬, AGENTS.md, 플러그인, MCP 서버 설정, 하위 에이전트, 훅, 명령어, 세션입니다. 가져올 항목이 있으면 작업이 진행되면서 externalAgentConfig/import/progress와 externalAgentConfig/import/completed 알림을 보냅니다. 플러그인 및 세션 가져오기는 비동기적으로 완료될 수 있습니다.
  • config/value/write - 설정 키와 값 한 쌍을 디스크에 있는 사용자의 config.toml에 씁니다.
  • config/batchWrite - 여러 설정 변경을 디스크에 있는 사용자의 config.toml에 원자적으로 적용합니다.
  • configRequirements/read - requirements.toml이나 MDM 또는 둘 다에서 허용 목록과 고정된 featureRequirements를 포함한 요구 사항을 가져옵니다. experimentalApi를 활성화한 클라이언트는 관리형 네트워크 요구 사항도 읽을 수 있습니다.
  • 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-6.1-sol",
    "model": "gpt-6.1-sol",
    "displayName": "GPT-6.1 Sol",
    "hidden": false,
    "defaultReasoningEffort": "medium",
    "supportedReasoningEfforts": [{
      "reasoningEffort": "medium",
      "description": "Balances speed and reasoning depth for everyday tasks"
    }],
    "inputModalities": ["text", "image"],
    "supportsPersonality": false,
    "isDefault": true
  }],
  "nextCursor": null
} }

각 모델 항목에는 다음 필드가 포함될 수 있습니다.

  • supportedReasoningEfforts - 모델이 지원하는 추론 수준 옵션입니다.
  • defaultReasoningEffort - 클라이언트에 권장하는 기본 추론 수준입니다.
  • upgrade - 클라이언트의 마이그레이션 안내에 사용할 권장 업그레이드 모델 ID입니다(선택 사항).
  • upgradeInfo - 클라이언트의 마이그레이션 안내에 사용할 업그레이드 메타데이터입니다(선택 사항).
  • hidden - 기본 모델 선택 목록에서 모델을 숨길지 나타냅니다.
  • inputModalities - 모델이 지원하는 입력 유형입니다(예: text, image).
  • supportsPersonality - 사용 중단 예정(deprecated)인 호환성 필드로, 항상 false입니다. 모델은 더 이상 성격 선택을 지원하지 않습니다.
  • isDefault - 권장 기본 모델인지 나타냅니다.

시작할 때 사용한 제공자가 더 이상 관리형 요구 사항을 충족하지 않으면 model/list는 -32600을 반환하고 클라이언트에 Codex를 다시 시작하도록 요청합니다.

기본적으로 model/list는 선택기에 표시되는 모델만 반환합니다. 전체 목록을 가져와 클라이언트에서 필터링하려면 includeHidden: true로 설정한 뒤 hidden 값을 사용하세요.

이전 모델 카탈로그에 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는 스레드를 구독하지 않고 저장된 메타데이터를 읽습니다.
  • thread/turns/list는 저장된 스레드를 재개하지 않고 턴 기록을 페이지 단위로 조회합니다. itemsView로 턴 항목을 생략할지, 요약할지, 전체를 불러올지 선택하세요.
  • thread/items/list는 저장된 스레드 항목을 페이지 단위로 조회합니다. 필요하면 한 턴으로 범위를 제한할 수 있습니다.
  • thread/list는 저장된 스레드를 페이지 단위로 조회합니다. 한 섹션의 스레드를 조회하려면 sectionId를, 이미 화면에 표시된 스레드를 제외하려면 excludedThreadIds를 사용하세요.
  • thread/loaded/list는 현재 메모리에 있는 스레드 ID를 반환합니다.
  • thread/archive는 저장된 스레드 JSONL 로그를 보관 디렉터리로 옮깁니다. 이 스레드에서 생성된 하위 스레드 중 아직 보관되지 않은 스레드의 로그도 보관하려고 시도합니다.
  • thread/delete는 저장된 활성 또는 보관 스레드와 여기서 생성된 하위 스레드를 영구 삭제합니다.
  • thread/metadata/update는 스레드에 저장된 gitInfo를 업데이트합니다.
  • thread/unsubscribe는 현재 연결에서 로드된 스레드의 구독을 해제합니다. 비활성 유예 기간이 지나면 thread/closed 알림이 발생할 수 있습니다.
  • thread/unarchive는 보관된 스레드 실행 기록을 활성 세션 디렉터리로 복원합니다.
  • thread/compact/start는 컨텍스트 압축을 시작하고 즉시 {}를 반환합니다.
  • thread/revert는 페이지네이션을 사용하는 영구 스레드의 기록에서 지정한 턴과 이후 모든 턴을 제거합니다. 로컬 파일에는 영향을 주지 않습니다.
  • thread/inject_items는 사용자 턴을 시작하지 않고 로드된 스레드에서 모델이 볼 수 있는 기록에 Responses API 원본 항목을 추가합니다.

스레드 시작 또는 재개하기

새 Codex 대화가 필요하면 새 스레드를 시작하세요.

{ "method": "thread/start", "id": 10, "params": {
"model": "gpt-6.1-sol",
"cwd": "/Users/me/project",
"approvalPolicy": "never",
"sandbox": "workspace-write",
"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/turns/list와 thread/items/list로 기록을 불러오세요. historyMode를 "legacy" 또는 "paginated"로 명시하려면 thread/start에서 설정하세요. 이 기능은 실험적이며 capabilities.experimentalApi = true가 필요합니다.

capabilities.experimentalApi를 활성화한 베타 클라이언트는 permissions에 이름이 지정된 권한 프로필 ID를 전달해 기존 sandbox 필드를 대체할 수 있습니다. permissions와 sandbox를 함께 보내지 마세요. permissionProfile/list에 프로젝트의 cwd를 전달하면 사용 가능한 프로필과 관리형 요구 사항에서 각 프로필을 허용하는지 확인할 수 있습니다.

thread.sessionId는 현재 실행 중인 세션 트리의 루트를 식별합니다. 루트 스레드는 자체 스레드 ID를 세션 ID로 사용하며, 포크된 스레드는 원래 루트의 세션 ID를 유지합니다. 클라이언트에서는 스레드 ID에서 세션 ID를 유추하지 말고 thread.sessionId에서 읽으세요.

저장된 세션을 이어가려면 thread/resume에 앞서 기록한 thread.id를 전달하세요. excludeTurns: true를 전달해 스레드 메타데이터와 현재 세션 상태를 받은 뒤 페이지네이션 메서드로 기록을 불러오세요.

{ "method": "thread/resume", "id": 11, "params": {
  "threadId": "thr_123",
  "excludeTurns": true
} }
{ "id": 11, "result": { "thread": { "id": "thr_123", "name": "Bug bash notes", "ephemeral": false } } }

페이지네이션을 사용하는 스레드에서 thread/resume과 thread/fork의 전체 기록 응답은 사용 중단 예정(deprecated)이며 deprecationNotice 알림이 발생합니다. 두 메서드 모두 실험적 API를 활성화하지 않아도 excludeTurns: true를 받습니다. thread/resume 응답에는 turnsBackwardsCursor와 itemsBackwardsCursor도 포함될 수 있습니다. 각 커서를 해당 페이지네이션 메서드에 sortDirection: "desc"와 함께 전달하세요. 첫 페이지에는 커서의 기준 항목이 포함됩니다.

스레드를 재개하는 것만으로는 thread.updatedAt이나 실행 기록 파일의 수정 시각이 바뀌지 않습니다. 턴을 시작할 때 타임스탬프가 업데이트됩니다.

설정에서 활성화된 MCP 서버를 required로 지정했는데 해당 서버를 초기화하지 못하면 thread/start와 thread/resume은 실패합니다.

dynamicTools는 thread/start의 실험적 필드입니다(capabilities.experimentalApi = true 필요). Codex는 이 동적 도구들을 스레드 실행 기록 메타데이터에 저장합니다. 새 동적 도구를 지정하지 않고 thread/resume을 호출하면 저장된 도구를 복원합니다.

현재 설정된 모델 제공자가 스레드에 저장된 제공자와 다르면 thread/resume 호출과 새 입력 요청은 -32600을 반환하며 data.type은 modelProviderMismatch입니다. 스레드 기록을 표시하려면 턴을 페이지 단위로 조회하는 thread/turns/list를 사용하세요. 스레드를 계속 사용하려면 저장된 제공자로 다시 전환하세요. 현재 제공자로 기존 기록에서 새 스레드를 시작하려면 thread/fork를 호출하세요.

실행 기록에 저장된 모델과 다른 모델로 재개하면 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/fork에 thread.id를 전달하세요. 새 스레드 ID가 생성되고 해당 스레드에 대해 thread/started 알림이 발생합니다. lastTurnId를 전달하면 지정한 턴까지 포함해 기록을 복사하고 이후 턴은 제외합니다.

{ "method": "thread/fork", "id": 12, "params": { "threadId": "thr_123", "lastTurnId": "turn_456", "excludeTurns": true } }
{ "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,
    "excludeTurns": true
  }
}
{
  "id": 13,
  "result": {
    "thread": {
      "id": "thr_789",
      "sessionId": "thr_789",
      "forkedFromId": "thr_123",
      "ephemeral": true
    }
  }
}

페이지네이션을 사용하는 스레드의 임시 포크에는 excludeTurns: true가 필요합니다.

사용자에게 표시할 스레드 제목을 설정하면 app-server는 thread.name을 thread/list, thread/read, thread/resume, thread/unarchive 응답에 채워 넣습니다. thread/start와 thread/fork는 제목을 설정하기 전까지 name을 생략하거나 null을 반환할 수 있습니다.

저장된 스레드를 재개하지 않고 읽기

스레드를 재개하거나 이벤트를 구독할 필요 없이 저장된 데이터만 읽으려면 thread/read를 사용하세요.

  • includeTurns - false이거나 생략하면 스레드 요약만 반환합니다. true로 설정하면 전체 기록을 불러옵니다. 페이지네이션을 사용하는 스레드에서 이 방식은 사용 중단 예정(deprecated)이며 deprecationNotice 알림이 발생합니다. 대신 페이지네이션 메서드를 사용하세요.
  • 반환된 thread 객체에는 런타임 status가 포함됩니다. 값은 notLoaded, idle, systemError 또는 active이며, 마지막 경우에는 activeFlags가 함께 제공됩니다.
{ "method": "thread/read", "id": 19, "params": { "threadId": "thr_123" } }
{ "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을 반대로 설정하세요. 이때 기준 턴을 다시 포함하므로 해당 턴의 변경 사항도 확인할 수 있습니다.

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를 전달하면 한 턴으로 범위를 제한하고 생략하면 스레드 전체에서 조회합니다. 기본 정렬은 오래된 항목부터입니다(sortDirection: "asc"). 활성 스레드 저장소가 항목 페이지네이션을 지원해야 합니다. 그렇지 않으면 서버가 지원되지 않는 메서드 오류를 반환합니다.

다음 페이지를 조회하려면 이전 응답에서 받은 불투명 커서 nextCursor를 그대로 전달하세요. 알고 있는 항목 바로 다음부터 조회하려면 기준 항목과 비어 있지 않은 turnId를 전달하세요.

{ "method": "thread/items/list", "id": 21, "params": {
  "threadId": "thr_123",
  "turnId": "turn_456",
  "cursor": { "type": "item", "itemId": "item_123" },
  "sortDirection": "asc",
  "limit": 50
} }
{ "id": 21, "result": {
  "data": [],
  "nextCursor": null,
  "backwardsCursor": null
} }

기준 항목 자체는 결과에서 제외됩니다. 오름차순이면 더 새로운 항목을, 내림차순이면 더 오래된 항목을 반환합니다. 기준 항목은 요청한 턴의 조회 가능한 기록에 속해야 합니다. turnId가 없거나 항목 ID가 비어 있거나 항목을 찾을 수 없거나 범위를 벗어나면 잘못된 매개변수 오류(-32602)를 반환합니다. 다음 페이지에는 반환된 문자열 nextCursor를 사용하세요. 각 결과 항목에는 turnId, item이 포함되며 기록된 시작 및 완료 타임스탬프가 선택적으로 포함됩니다.

스레드 목록 조회하기(페이지네이션 및 필터)

thread/list로 기록 UI를 구성할 수 있습니다. 기본적으로 createdAt 기준 최신순으로 반환하며 페이지네이션 전에 필터를 적용합니다. 다음 매개변수를 조합해 전달하세요.

  • cursor - 이전 응답에서 받은 불투명 문자열입니다. 첫 페이지에서는 생략하세요.
  • limit - 설정하지 않으면 서버가 적절한 기본 페이지 크기를 사용합니다.
  • sortKey - created_at(기본값), updated_at, recency_at, section_position 중 하나입니다. section_position을 사용하려면 sectionId에 유효한 섹션 ID를 지정해야 합니다.
  • sortDirection - asc 또는 desc입니다. sortDirection을 생략하면 section_position은 오름차순으로, 시간 기준 키는 내림차순으로 정렬합니다.
  • sectionId - 특정 섹션의 스레드를 조회하려면 섹션 ID를, 어느 섹션에도 속하지 않은 스레드만 조회하려면 null을 전달하세요. 생략하면 모든 섹션의 스레드와 미할당 스레드를 함께 조회합니다.
  • excludedThreadIds - 조회에서 제외할 스레드 ID를 최대 100개까지 지정합니다. 중복 ID도 100개 한도에 포함됩니다. 서버는 일치하는 스레드를 제외한 뒤 페이지 크기 제한을 적용합니다. 커서를 전달할 때마다 같은 제외 목록을 보내세요.
  • modelProviders - 특정 제공자로 결과를 제한합니다. 모든 제공자를 포함하려면 []를 전달하세요. 이 필드를 생략하거나 null을 전달하면 서버는 현재 설정된 제공자를 사용합니다. 단, 스레드 간 관계로 필터링할 때는 모든 제공자를 포함합니다.
  • sourceKinds - 특정 출처의 스레드로 결과를 제한합니다. 생략하거나 []를 전달하면 기본적으로 대화형 출처인 cli와 vscode만 포함합니다.
  • archived - true이면 보관된 스레드만 조회합니다. false이거나 생략하면 보관되지 않은 스레드를 조회합니다(기본값).
  • cwd - 세션의 현재 작업 디렉터리가 지정한 경로 또는 배열에 있는 경로 중 하나와 정확히 일치하는 스레드만 반환합니다. 상대 경로는 app-server 프로세스의 작업 디렉터리를 기준으로 해석합니다.
  • useStateDbOnly - true이면 메타데이터 복구를 위해 JSONL 스레드 로그를 스캔하지 않고 상태 데이터베이스의 결과를 반환합니다. 기본 스캔 및 복구 동작을 사용하려면 생략하거나 false를 전달하세요.
  • searchTerm - 추출된 제목에 지정한 문자열이 포함된 스레드만 반환합니다. 대소문자를 구분합니다.
  • parentThreadId - 지정한 부모 스레드의 직계 자식 스레드만 반환합니다. 실험적 필터이며 capabilities.experimentalApi = true가 필요합니다.
  • ancestorThreadId - 지정한 스레드에서 생성된 모든 깊이의 하위 스레드만 반환합니다. 실험적 필터이며 capabilities.experimentalApi = true가 필요합니다. parentThreadId와 함께 사용하지 마세요.

sourceKinds는 다음 값을 받습니다.

  • cli
  • vscode
  • exec
  • appServer
  • subAgent
  • subAgentReview
  • subAgentCompact
  • subAgentThreadSpawn
  • subAgentOther
  • unknown

예제

{ "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, "section": { "id": "01984de2-8f74-7c91-a3b2-5c5e937cf318", "name": "Pinned", "appearance": null }, "modelProvider": "openai", "createdAt": 1730831111, "updatedAt": 1730831111, "name": "TUI prototype", "status": { "type": "notLoaded" } },
    { "id": "thr_b", "preview": "Fix tests", "ephemeral": false, "section": null, "modelProvider": "openai", "createdAt": 1730750000, "updatedAt": 1730750000, "status": { "type": "notLoaded" } }
  ],
  "nextCursor": "opaque-token-or-null"
} }

nextCursor가 null이면 마지막 페이지입니다.

스레드를 섹션별로 정리하기

threadSection/create로 이름이 있는 섹션을 만들고 반환된 section.id를 thread/section/move에 전달하세요. 섹션의 다른 스레드 바로 앞에 삽입하려면 beforeThreadId를 전달하고, 맨 뒤에 추가하려면 생략하세요. 스레드를 섹션에서 빼려면 sectionId: null을 전달하세요. 사용자 지정 섹션을 페이지 단위로 조회하거나 이름을 바꾸거나 삭제하려면 각각 threadSection/list, threadSection/update, threadSection/delete를 사용하세요. 스레드를 고정하려면 threadSection/list가 반환하는 기본 제공 Pinned 섹션으로 옮기세요.

스레드 첨부 항목 관리하기

첨부 항목을 사용하면 Pull Request 같은 리소스를 저장된 스레드에 연결할 수 있습니다. 스레드를 재개하지 않고도 이 참조를 관리할 수 있습니다.

  • thread/attachment/add는 threadId, attachmentType, identityKey, JSON payload를 받습니다. 같은 스레드에 유형과 키가 같은 항목을 다시 추가하면 기존 첨부 항목을 반환합니다.
  • thread/attachment/list는 스레드의 첨부 항목을 페이지 단위로 조회합니다. 특정 리소스를 참조하는 스레드를 찾으려면 thread/attachmentOwner/list에 해당 리소스의 attachmentType과 identityKey를 전달하세요.
  • thread/attachment/remove는 threadId, attachmentType, identityKey를 받습니다. 연결을 해제한 뒤에도 원본 리소스는 계속 사용할 수 있습니다.
  • thread/attachment/updated는 연결이 변경되면 created 또는 deleted 작업을 알립니다.

저장된 스레드 메타데이터 업데이트하기

thread/metadata/update를 사용하면 스레드를 재개하지 않고 저장된 메타데이터를 부분 업데이트할 수 있습니다. 업데이트할 Git 필드를 gitInfo에 담아 전달하세요. 필드를 생략하면 기존 값을 유지하고 null을 전달하면 해당 값을 지웁니다.

{ "method": "thread/metadata/update", "id": 21, "params": {
  "threadId": "thr_123",
  "gitInfo": { "branch": "feature/sidebar-pr" }
} }
{ "id": 21, "result": {
  "thread": {
    "id": "thr_123",
    "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는 해당 스레드가 로드되지 않았음을 나타냅니다.

마지막 구독자가 구독을 해제한 뒤 스레드가 기본 60초 동안 유휴 상태이면 app-server가 스레드를 메모리에서 내립니다. 이 시간을 변경하려면 thread_unload_delay_secs를 설정하세요. 스레드를 메모리에서 내릴 때 app-server는 thread/status/changed에 notLoaded 상태를 담아 보내고 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" } }

보관된 스레드는 이후 thread/list를 호출할 때 archived: true를 전달해야 표시됩니다. 서버는 실제로 보관한 스레드마다 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는 표준 turn/* 및 item/* 알림으로 진행 상황을 보냅니다. 이 알림은 모두 같은 threadId를 사용하며 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가 셸 명령어를 위한 독립적인 턴을 시작합니다.

실행 시간을 밀리초 단위로 제한하려면 timeoutMs를 설정하세요. 생략하거나 null을 전달하면 기본값인 1시간을 사용합니다. 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/revert를 사용하면 페이지네이션을 사용하는 영구 스레드의 대화 기록에서 beforeTurnId로 지정한 턴과 이후 모든 턴을 제거합니다. 로컬 파일 변경 사항은 되돌리지 않습니다. 스레드가 로드되지 않았다면 먼저 재개하세요. 임시 스레드와 기존 기록 형식의 스레드는 지원하지 않습니다.

{ "method": "thread/revert", "id": 30, "params": { "threadId": "thr_b", "beforeTurnId": "turn_456" } }
{ "id": 30, "result": {
  "thread": { "id": "thr_b", "ephemeral": false, "turns": [] },
  "turnsBackwardsCursor": "retained-turn-cursor-or-null",
  "itemsBackwardsCursor": "retained-item-cursor-or-null"
} }
{ "method": "thread/reverted", "params": { "threadId": "thr_b" } }

반환된 thread.turns는 항상 비어 있습니다. 커서의 기준 항목을 포함해 남은 기록을 불러오려면 반환된 커서를 thread/turns/list 또는 thread/items/list에 sortDirection: "desc"와 함께 전달하세요.

thread/rollback은 제거되었으며 호출하면 알 수 없는 메서드 오류를 반환합니다. 이전에 저장한 스레드의 기존 롤백 표시는 계속 읽을 수 있습니다.

턴

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": "on-request",
"sandboxPolicy": {
  "type": "workspaceWrite",
  "writableRoots": ["/Users/me/project"],
  "networkAccess": true
},
"model": "gpt-6.1-sol",
"effort": "medium",
"summary": "concise",
"outputSchema": {
  "type": "object",
  "properties": { "answer": { "type": "string" } },
  "required": ["answer"],
  "additionalProperties": false
}
} }
{ "id": 30, "result": { "turn": { "id": "turn_456", "status": "inProgress", "items": [], "error": null } } }

새로 시작하는 턴 하나에만 서비스 등급을 재정의하려면 serviceTierForTurn을 설정하세요. 표준 속도를 사용하려면 "default"를 지정하고, 스레드의 등급을 상속하려면 필드를 생략하세요. 이번 턴과 이후 턴의 등급을 함께 변경하려면 serviceTier를 설정하세요.

클라이언트가 실행한 도구의 출력으로 턴을 시작하려면 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 항목을 추가할 수 있습니다. 이 항목은 실행 기록에 저장되며 이후 모델 요청에 포함됩니다.

{ "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 리뷰어를 실행하고 리뷰 항목을 스트리밍합니다. 다음 대상을 지정할 수 있습니다.

  • uncommittedChanges
  • baseBranch(브랜치와의 차이 비교)
  • commit(특정 커밋 리뷰)
  • custom(자유 형식 지침)

review/start는 지정한 스레드에서 리뷰를 실행합니다. delivery는 생략하거나 "inline"을 전달하세요. 별도 스레드에서 리뷰할 때 기존 기록을 포함하려면 thread/fork를, 빈 스레드에서 시작하려면 thread/start를 사용하세요. 그런 다음 새 스레드 ID로 review/start를 호출하세요.

요청 및 응답 예제

{ "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"
} }

Codex는 일반적인 turn/started 알림을 보낸 뒤 item/started 알림에 enteredReviewMode 항목을 담아 보냅니다.

{
  "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 또는 둘 다 전달하세요. 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를 설정하세요. 이후 processId를 사용해 command/exec/write, command/exec/resize 또는 command/exec/terminate를 호출할 수 있습니다.
  • 명령어 실행 중에 출력 알림을 받으려면 streamStdoutStderr: true를 설정하세요. 출력은 command/exec/outputDelta로 전달됩니다.

관리자 요구 사항 읽기 (configRequirements/read)

configRequirements/read를 사용하면 requirements.toml이나 MDM 또는 둘 다에서 로드한 유효 관리자 요구 사항을 확인할 수 있습니다.

{ "method": "configRequirements/read", "id": 52, "params": {} }
{ "id": 52, "result": {
  "requirements": {
    "allowedApprovalPolicies": ["on-request", "never"],
    "allowedSandboxModes": ["read-only", "workspace-write"],
    "featureRequirements": {
      "unified_exec": false
    }
  }
} }

구성된 요구 사항이 없으면 result.requirements는 null입니다. result.supportsIndependentSpeedModes가 true이면 fast_mode와 ultrafast_mode의 요구 사항이 각각 독립적으로 적용됩니다. 이전 서버는 이 필드를 생략하고 두 모드 모두에 fast_mode를 사용합니다. 지원하는 키와 값은 requirements.toml 레퍼런스를 참고하세요.

Windows 샌드박스 설정 (windowsSandbox/setupStart)

사용자에게 설정을 요청하기 전에 windowsSandbox/readiness를 호출하세요. MXC와 설정을 마친 기존 샌드박스는 모두 ready를 반환할 수 있습니다. 기존 샌드박스가 updateRequired를 반환하면 windowsSandbox/setupStart를 호출해 비동기적으로 설정을 시작하세요. Windows 샌드박스가 비활성화되어 있거나 호스트가 다른 운영 체제를 사용하면 준비 상태 검사 결과는 notConfigured입니다.

{ "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 - { mode, success, error }를 windowsSandbox/setupStart 요청 완료 후 보냅니다.

턴 이벤트

  • 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 }에 턴의 모든 파일 변경을 합친 최신 통합 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, partial_answer, final_answer)을 사용합니다. partial_answer는 내용이 확정된 답변 텍스트이며 이후 출력이나 도구 호출이 이어질 수 있습니다.
  • plan - {id, text}에 플랜 모드에서 제안한 계획 텍스트를 담습니다. 최종 plan 항목은 item/completed에서 받은 값을 기준으로 삼으세요.
  • 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, mcpAppUi, pluginId, readOnlyHint, result, error, durationMs도 포함되며 이 필드들은 각각 null일 수 있습니다. 기존 mcpAppResourceUri 필드는 선택 사항입니다. 신뢰할 수 있는 MCP 앱의 appContext에는 connectorId가 포함됩니다. 나머지 필드(linkId, resourceUri, appName, actionName)는 null일 수 있습니다. 도구 설명자가 리소스 URI와 표시 모드(inline 또는 fullscreen)를 지정하면 mcpAppUi에 resourceUri와 preferredModelDisplayMode가 포함됩니다. 이 표시 메타데이터 없이 저장된 호출의 경우 app-server는 null을 mcpAppUi 값으로 반환합니다.
  • 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 알림은 사용 중단 예정(deprecated)입니다. 대신 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 텍스트 출력과의 호환성을 위한 사용 중단 예정(deprecated) 알림입니다. 현재 app-server 버전에서는 더 이상 이 알림을 보내지 않습니다. 대신 fileChange 항목과 turn/diff/updated를 사용하세요.

오류

app-server가 정상 종료 절차 중에 새 작업을 거부하면 코드가 -32600이고 data.reason이 serverShuttingDown인 JSON-RPC 오류를 반환합니다.

error 알림에는 중첩된 error 객체가 있으며, 이 객체에는 message와 선택적 additionalDetails가 포함됩니다. codexErrorInfo 필드는 null일 수 있습니다. willRetry가 true이면 서버가 재시도하며 턴은 활성 상태를 유지합니다. 실패한 턴은 status: "failed"로 끝납니다. 일반적인 codexErrorInfo 값으로는 contextWindowExceeded, usageLimitExceeded, badRequest, unauthorized, sandboxError가 있습니다. 업스트림 요청 실패 시 이 값은 { "httpConnectionFailed": { "httpStatusCode": 503 } }와 같은 객체일 수 있습니다.

승인

사용자의 Codex 설정에 따라 명령어 실행과 파일 변경에 승인이 필요할 수 있습니다. app-server가 클라이언트에 JSON-RPC 요청을 보내면 클라이언트는 결정 내용을 담은 페이로드로 응답합니다.

  • 명령어 실행에 대한 결정은 accept, acceptForSession, decline, cancel 또는 { "acceptWithExecpolicyAmendment": { "execpolicy_amendment": ["cmd", "..."] } }입니다.

  • 파일 변경에 대한 결정은 accept, acceptForSession, decline, cancel입니다.

  • 요청에는 threadId와 turnId가 포함됩니다. 이 값으로 UI 상태의 범위를 활성 대화로 한정하세요.

  • 서버는 작업을 재개하거나 거부하고 item/completed로 항목을 종료합니다.

명령어 실행 승인

메시지는 다음 순서로 전달됩니다.

  1. item/started는 대기 중인 commandExecution 항목과 command, cwd 등 필드를 표시합니다.
  2. item/commandExecution/requestApproval에는 itemId, threadId, turnId가 포함됩니다. reason, command, cwd, commandActions, proposedExecpolicyAmendment, networkApprovalContext, availableDecisions는 선택 사항입니다. initialize.params.capabilities.experimentalApi = true이면 페이로드에 명령어별로 요청한 샌드박스 접근 권한을 설명하는 실험적 additionalPermissions도 포함될 수 있습니다. additionalPermissions 안의 파일 시스템 경로는 모두 절대 경로로 전송됩니다.
  3. 클라이언트가 앞서 설명한 명령어 실행 승인 결정 중 하나로 응답합니다.
  4. serverRequest/resolved는 대기 중이던 요청에 응답했거나 요청이 해제되었음을 확인합니다.
  5. item/completed는 최종 commandExecution 항목을 status: completed | failed | declined와 함께 반환합니다.

networkApprovalContext가 있으면 관리형 네트워크 접근을 승인하는 요청입니다. 일반 셸 명령어 승인과는 구분하세요. 현재 v2 스키마는 대상 host와 protocol을 제공합니다. 클라이언트는 네트워크 전용 승인 프롬프트를 표시해야 합니다. command가 사용자에게 의미 있는 셸 명령어 미리보기라고 가정하지 마세요.

Codex는 동시에 발생하는 네트워크 승인 프롬프트를 대상(host, 프로토콜, 포트)별로 묶습니다. 따라서 app-server가 보낸 프롬프트 하나로 같은 대상에 대기 중인 여러 요청을 진행할 수 있습니다. 같은 호스트라도 포트가 다르면 별도로 처리합니다.

파일 변경 승인

메시지는 다음 순서로 전달됩니다.

  1. item/started는 fileChange 항목에 제안된 changes와 status: "inProgress"를 담아 보냅니다.
  2. item/fileChange/requestApproval에는 itemId, threadId, turnId가 포함되며 reason과 grantRoot는 선택 사항입니다.
  3. 클라이언트가 앞서 설명한 파일 변경 승인 결정 중 하나로 응답합니다.
  4. serverRequest/resolved는 대기 중이던 요청에 응답했거나 요청이 해제되었음을 확인합니다.
  5. item/completed는 최종 fileChange 항목을 status: completed | failed | declined와 함께 반환합니다.

tool/requestUserInput

클라이언트가 item/tool/requestUserInput에 응답하면 app-server는 serverRequest/resolved에 { threadId, requestId }를 담아 보냅니다. 클라이언트가 응답하기 전에 턴이 시작, 완료 또는 중단되어 대기 중인 요청이 해제되는 경우에도 서버는 같은 알림을 보냅니다.

요청 매개변수에는 autoResolutionMs가 포함되며, 값은 밀리초 단위의 정수 제한 시간 또는 null입니다. 제한 시간이 지정되어 있고 사용자가 응답하지 않으면 호스트 클라이언트가 해당 시간이 지난 후 프롬프트를 자동으로 처리할 수 있습니다.

권한 요청

기본 제공 request_permissions 도구는 item/permissions/requestApproval에 threadId, turnId, itemId, environmentId, cwd, 선택적 reason, 요청하는 네트워크 또는 파일 시스템 권한을 담아 보냅니다. 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을 활성화하세요.

동적 도구 호출(실험적 기능)

dynamicTools는 thread/start의 실험적 필드이며, 이에 대응하는 item/tool/call 요청 및 응답 플로우도 실험적 API입니다.

동적 도구 이름과 네임스페이스 이름은 Responses API의 이름 지정 제약 조건을 따라야 합니다. Codex 기본 제공 도구가 사용하는 예약된 네임스페이스 이름은 피하세요.

턴 중에 동적 도구를 호출하면 app-server와 클라이언트가 다음 순서로 메시지를 주고받습니다.

  1. item/started 알림에 item.type = "dynamicToolCall", status = "inProgress", tool, arguments가 포함됩니다.
  2. 서버가 클라이언트에 item/tool/call 요청을 보냅니다.
  3. 클라이언트가 반환할 콘텐츠 항목을 담은 페이로드로 응답합니다.
  4. 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 간헐적으로 실패하는 CI 작업을 분류하는 스킬을 새로 추가하고 단계별 사용법도 포함해 줘.

skills/list를 사용해 이용 가능한 스킬을 가져오세요. 필요하면 cwds로 범위를 지정하고 forceReload를 사용할 수 있습니다. perCwdExtraUserRoots를 포함하면 추가 절대 경로를 user 범위로 지정해 특정 cwd 값에 대해 스캔할 수 있습니다. 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를 설정하세요. 메타데이터 응답에는 설치된 앱의 런타임 상태가 포함되지 않으며, 응답 자체가 도구 호출 권한을 부여하지도 않습니다. app/installed로 실제 enabled 및 callable 상태를 확인하세요.

앱을 호출하려면 텍스트 입력에 $<app-slug>를 넣으세요. mention 입력 항목을 추가하고 app://<id> 경로를 지정하는 것이 좋습니다.

{
  "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와 itemTypeResults가 포함됩니다. 결과는 유형별 successes 및 failures로 나뉩니다. 완료 알림은 응답 직후 또는 백그라운드 원격 가져오기가 끝난 후에 도착할 수 있습니다.

{ "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을 소스로 간주합니다.

인증 엔드포인트

Codex app-server 인증을 사용하는 로컬 또는 오픈 소스 애플리케이션을 개발했다면 이 인증 방식을 계속 사용할 수 있습니다. 다만 사용자가 자신의 사용량을 더 쉽게 확인하고 관리할 수 있도록 ChatGPT로 로그인하는 방식으로 마이그레이션하는 것을 권장합니다. ChatGPT로 로그인 개발자 문서와 구현 쿡북을 참고하세요. app-server 인증은 처음부터 상업용 또는 호스팅 서비스에서 허용되지 않았습니다. 이러한 용도를 지원하기 위해 ChatGPT로 로그인 기능을 출시했습니다. 여러분이 만들 제품을 기대합니다. 파트너 대기 목록에 등록하세요.

JSON-RPC 인증 및 계정 API는 요청·응답 메서드와 서버가 시작하는 알림(id 없음)을 제공합니다. 이 API로 인증 상태를 확인하고, 로그인을 시작하거나 취소하고, 로그아웃하고, ChatGPT 요청 한도를 조회할 수 있습니다. 크레딧이 소진되었거나 사용량 한도에 도달하면 워크스페이스 소유자에게 알릴 수도 있습니다.

인증 모드

Codex는 다음 인증 모드를 지원합니다. account/updated.authMode는 활성 모드를 표시하며, 확인할 수 있으면 현재 ChatGPT planType도 함께 제공됩니다. account/read도 계정 및 요금제 정보를 반환합니다.

  • API 키(apikey) - 호출자가 type: "apiKey"와 함께 OpenAI API 키를 제공하면 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 키(credentialSource: "codexManaged")인지 외부 AWS 자격 증명 체인(credentialSource: "awsManaged")인지도 표시합니다. account/updated.authMode는 Codex 관리형 Bedrock API 키에 bedrockApiKey를 사용합니다.

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, loginId?, success, error? }가 포함됩니다. 이전 서버는 loginId를 생략합니다. 앱 범위 또는 플러그인 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가 이 플래그를 무시합니다.
  • email은 ChatGPT 계정에 이메일 주소가 없으면 null입니다.
  • requiresOpenaiAuth는 활성 제공자의 인증 요구 사항을 나타냅니다. false이면 OpenAI 자격 증명 없이 Codex를 실행할 수 있습니다.
  • Amazon Bedrock은 Codex 관리형 Bedrock API 키를 사용할 때 credentialSource: "codexManaged"를 반환합니다. 외부 AWS 자격 증명 경로를 사용하면 credentialSource: "awsManaged"를 반환합니다. 이 값은 선택한 자격 증명 출처를 식별하며, AWS 자격 증명 체인이 실제로 자격 증명을 찾을 수 있는지는 검증하지 않습니다.

2) API 키로 로그인하기

  1. 요청을 보내세요.

    {
      "method": "account/login/start",
      "id": 2,
      "params": { "type": "apiKey", "apiKey": "sk-..." }
    }
  2. 다음 응답을 확인하세요.

    { "id": 2, "result": { "type": "apiKey" } }
  3. 다음 알림을 확인하세요.

    {
      "method": "account/login/completed",
      "params": { "loginId": null, "success": true, "error": null }
    }
    {
      "method": "account/updated",
      "params": { "authMode": "apikey", "planType": null }
    }

3) ChatGPT로 로그인하기(브라우저 플로우)

  1. 로그인을 시작하세요.

    {
      "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"
      }
    }
  2. 브라우저에서 authUrl을 여세요. 로컬 콜백은 app-server가 호스팅합니다.

  3. 다음 알림을 기다리세요.

    {
      "method": "account/login/completed",
      "params": { "loginId": "<uuid>", "success": true, "error": null }
    }
    {
      "method": "account/updated",
      "params": { "authMode": "chatgpt", "planType": "plus" }
    }

3b) ChatGPT로 로그인하기(기기 코드 플로우)

클라이언트가 로그인 절차를 직접 관리하거나 브라우저 콜백이 불안정하다면 이 플로우를 사용하세요.

  1. 로그인을 시작하세요.

    {
      "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"
      }
    }
  2. 사용자에게 verificationUrl과 userCode를 표시하세요. 사용자 인터페이스는 프런트엔드에서 구현합니다.

  3. 다음 알림을 기다리세요.

    {
      "method": "account/login/completed",
      "params": { "loginId": "<uuid>", "success": true, "error": null }
    }
    {
      "method": "account/updated",
      "params": { "authMode": "chatgpt", "planType": "plus" }
    }

3c) 외부에서 관리하는 ChatGPT 토큰으로 로그인하기 (chatgptAuthTokens)

호스트 애플리케이션이 사용자의 ChatGPT 인증 수명 주기를 관리하고 토큰을 직접 제공하는 경우에만 이 실험적 모드를 사용하세요. 이 로그인 유형을 사용하려면 클라이언트가 capabilities.experimentalApi = true를 initialize 단계에서 설정해야 합니다.

  1. 요청을 보내세요.

    {
      "method": "account/login/start",
      "id": 7,
      "params": {
        "type": "chatgptAuthTokens",
        "accessToken": "<jwt>",
        "chatgptAccountId": "org-123",
        "chatgptPlanType": "business"
      }
    }
  2. 다음 응답을 확인하세요.

    { "id": 7, "result": { "type": "chatgptAuthTokens" } }
  3. 다음 알림을 확인하세요.

    {
      "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 타임스탬프입니다.
  • planType은 서버가 버킷에 연결된 ChatGPT 요금제를 반환할 때 포함됩니다.
  • 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 키만 사용하는 인증과 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는 선택 사항입니다. 지정한다면 비어 있지 않은 불투명 ID여야 하며 account/rateLimits/read에서 받은 값이어야 합니다. 생략하면 서비스가 다음 사용 가능 크레딧을 선택합니다.
  • 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 }
] } }