Skip to content

Instantly share code, notes, and snippets.

@thuongtin
Created February 19, 2026 00:07
Show Gist options
  • Select an option

  • Save thuongtin/4bf8af67ae05bf2b236e90dea5ab92dc to your computer and use it in GitHub Desktop.

Select an option

Save thuongtin/4bf8af67ae05bf2b236e90dea5ab92dc to your computer and use it in GitHub Desktop.
tags
type/guide
ai/concept/agent
ai/concept/automation
ai/platform/openai
ai/tool/codex
dev/protocol/json-rpc
dev/integration/api
dev/best-practices
dev/open-source
project/vibe-coding

Codex App Server – Hướng dẫn từ cơ bản đến thành thạo

Giới thiệu tổng quan

Codex App Server là giao thức giao tiếp hai chiều (bidirectional) mà OpenAI Codex sử dụng để cung cấp năng lực rich client integration — xác thực, lịch sử hội thoại, phê duyệt (approvals), và streaming sự kiện agent. Nếu bạn muốn nhúng Codex sâu vào sản phẩm của mình (tương tự cách VS Code extension tích hợp Codex), đây chính là interface bạn cần.

Thông tin dự án:

graph TB
    CENTER["🔌 Codex App Server"]

    subgraph protocol ["📡 Protocol Layer"]
        P1["JSON-RPC 2.0"]
        P2["stdio (JSONL)"]
        P3["WebSocket (experimental)"]
    end

    subgraph primitives ["🧱 Core Primitives"]
        PR1["Thread — Conversation"]
        PR2["Turn — User request + Agent work"]
        PR3["Item — Input/Output unit"]
    end

    subgraph features ["⚡ Key Features"]
        F1["Authentication (API Key / ChatGPT / External)"]
        F2["Approval Workflows"]
        F3["Streaming Events"]
        F4["Skills & Apps (Connectors)"]
    end

    subgraph lifecycle ["🔄 Lifecycle"]
        L1["initialize → thread/start"]
        L2["turn/start → stream events"]
        L3["turn/completed / interrupted"]
    end

    CENTER --- protocol
    CENTER --- primitives
    CENTER --- features
    CENTER --- lifecycle

    style CENTER fill:#10a37f,color:#fff,stroke:#0d8c6d,stroke-width:3px
    style protocol fill:#1e272e,color:#dfe6e9,stroke:#0984e3,stroke-width:2px
    style primitives fill:#1e272e,color:#dfe6e9,stroke:#00b894,stroke-width:2px
    style features fill:#1e272e,color:#dfe6e9,stroke:#e17055,stroke-width:2px
    style lifecycle fill:#1e272e,color:#dfe6e9,stroke:#fdcb6e,stroke-width:2px
    style P1 fill:#0984e3,color:#fff,stroke:#74b9ff
    style P2 fill:#0984e3,color:#fff,stroke:#74b9ff
    style P3 fill:#0984e3,color:#fff,stroke:#74b9ff
    style PR1 fill:#00b894,color:#fff,stroke:#55efc4
    style PR2 fill:#00b894,color:#fff,stroke:#55efc4
    style PR3 fill:#00b894,color:#fff,stroke:#55efc4
    style F1 fill:#e17055,color:#fff,stroke:#fab1a0
    style F2 fill:#e17055,color:#fff,stroke:#fab1a0
    style F3 fill:#e17055,color:#fff,stroke:#fab1a0
    style F4 fill:#e17055,color:#fff,stroke:#fab1a0
    style L1 fill:#fdcb6e,color:#2d3436,stroke:#f9ca24
    style L2 fill:#fdcb6e,color:#2d3436,stroke:#f9ca24
    style L3 fill:#fdcb6e,color:#2d3436,stroke:#f9ca24
Loading

Khi nào dùng App Server vs. SDK?

Tiêu chí Codex App Server Codex SDK
Use case chính Rich client integration (IDE, web app) CI/CD automation, batch jobs
Giao tiếp Bidirectional, streaming Request-response
Approvals ✅ Real-time approval workflows ❌ Non-interactive
Conversation history ✅ Thread/Turn model đầy đủ ❌ Stateless
Authentication API Key + ChatGPT OAuth + External tokens API Key
Streaming events ✅ item/started, deltas, completed
Phù hợp cho IDE extensions, web dashboards, custom agents GitHub Actions, scripts, pipelines

Triết lý thiết kế

  1. MCP-inspired — Protocol lấy cảm hứng từ MCP (Model Context Protocol), dùng JSON-RPC 2.0 bidirectional.
  2. Transport-agnostic — stdio cho local integration, WebSocket cho networked clients.
  3. Streaming-first — Mọi thứ được stream qua notifications: text deltas, command output, file changes, reasoning.
  4. Approval-aware — Sandbox policies và approval workflows là first-class citizens, không phải afterthought.
  5. Open Source — Implementation nằm trong Codex GitHub repo, bạn có thể đọc và contribute.

Kiến trúc & Protocol

Message Schema

Codex App Server sử dụng JSON-RPC 2.0 không có "jsonrpc":"2.0" header. Có 3 loại message:

graph LR
    subgraph messages ["📨 Message Types"]
        REQ["Request<br/>method + params + id"]
        RES["Response<br/>id + result/error"]
        NOT["Notification<br/>method + params (no id)"]
    end

    REQ -->|"Client → Server"| RES
    NOT -->|"Server → Client"| CLIENT["Client"]

    style REQ fill:#0984e3,color:#fff,stroke:#74b9ff
    style RES fill:#00b894,color:#fff,stroke:#55efc4
    style NOT fill:#e17055,color:#fff,stroke:#fab1a0
    style CLIENT fill:#6c5ce7,color:#fff,stroke:#a29bfe
Loading

Request — Client gửi lên server, có id:

{ "method": "thread/start", "id": 10, "params": { "model": "gpt-5.1-codex" } }

Response — Server trả về, echo id, có result hoặc error:

{ "id": 10, "result": { "thread": { "id": "thr_123" } } }
{ "id": 10, "error": { "code": 123, "message": "Something went wrong" } }

Notification — Server-initiated, không có id:

{ "method": "turn/started", "params": { "turn": { "id": "turn_456" } } }

Transport Options

Transport Cú pháp Đặc điểm
stdio --listen stdio:// (mặc định) Newline-delimited JSON (JSONL), phù hợp local integration
WebSocket --listen ws://IP:PORT (experimental) Một JSON-RPC message per WebSocket text frame, có bounded queues

Lưu ý WebSocket: Khi request queue đầy, server trả error code -32001 với message "Server overloaded; retry later.". Client nên retry với exponential backoff + jitter.

Tạo Schema tự động

Bạn có thể generate TypeScript hoặc JSON Schema từ CLI:

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

Schema được tạo ra khớp chính xác với phiên bản Codex đang chạy.


Core Primitives — 3 khái niệm cốt lõi

graph TD
    T["🧵 Thread<br/>(Conversation)"] --> TN1["Turn 1"]
    T --> TN2["Turn 2"]
    T --> TN3["Turn N..."]

    TN1 --> I1["Item: userMessage"]
    TN1 --> I2["Item: agentMessage"]
    TN1 --> I3["Item: commandExecution"]

    TN2 --> I4["Item: userMessage"]
    TN2 --> I5["Item: fileChange"]
    TN2 --> I6["Item: mcpToolCall"]

    style T fill:#10a37f,color:#fff,stroke:#0d8c6d,stroke-width:2px
    style TN1 fill:#0984e3,color:#fff,stroke:#74b9ff
    style TN2 fill:#0984e3,color:#fff,stroke:#74b9ff
    style TN3 fill:#0984e3,color:#fff,stroke:#74b9ff
    style I1 fill:#636e72,color:#fff,stroke:#b2bec3
    style I2 fill:#636e72,color:#fff,stroke:#b2bec3
    style I3 fill:#636e72,color:#fff,stroke:#b2bec3
    style I4 fill:#636e72,color:#fff,stroke:#b2bec3
    style I5 fill:#636e72,color:#fff,stroke:#b2bec3
    style I6 fill:#636e72,color:#fff,stroke:#b2bec3
Loading
Primitive Mô tả Ví dụ
Thread Một cuộc hội thoại giữa user và Codex agent thr_123 — "Refactor auth module"
Turn Một lượt request + toàn bộ agent work theo sau User gửi "Run tests" → agent chạy, trả kết quả
Item Đơn vị input/output nhỏ nhất userMessage, agentMessage, commandExecution, fileChange, mcpToolCall...

Lifecycle — Vòng đời một phiên làm việc

sequenceDiagram
    participant C as Client
    participant S as App Server

    Note over C,S: 1. Khởi tạo kết nối
    C->>S: initialize (clientInfo)
    S-->>C: result (userAgent)
    C->>S: initialized (notification)

    Note over C,S: 2. Tạo/Resume Thread
    C->>S: thread/start (model, cwd, sandbox...)
    S-->>C: result (thread.id)
    S-->>C: thread/started (notification)

    Note over C,S: 3. Bắt đầu Turn
    C->>S: turn/start (threadId, input)
    S-->>C: result (turn.id, status: inProgress)
    S-->>C: turn/started

    Note over C,S: 4. Stream Events
    S-->>C: item/started (agentMessage)
    S-->>C: item/agentMessage/delta (text chunk)
    S-->>C: item/agentMessage/delta (text chunk)
    S-->>C: item/completed (agentMessage)

    Note over C,S: 5. Hoàn thành
    S-->>C: turn/completed (status: completed)
Loading

Bước 1: Initialize (bắt buộc)

Mỗi connection phải gửi initialize trước khi gọi bất kỳ method nào, sau đó gửi initialized notification.

// Request
{
  "method": "initialize",
  "id": 0,
  "params": {
    "clientInfo": {
      "name": "my_product",
      "title": "My Product",
      "version": "0.1.0"
    }
  }
}

// Notification (sau khi nhận response)
{ "method": "initialized", "params": {} }

Lưu ý quan trọng:

  • Request trước initialize → bị reject với Not initialized
  • Gọi initialize lần 2 → bị reject với Already initialized
  • clientInfo.name dùng để identify client cho OpenAI Compliance Logs Platform

Experimental API opt-in

Một số method/field yêu cầu opt-in vào experimental API:

{
  "method": "initialize",
  "id": 1,
  "params": {
    "clientInfo": { "name": "my_client", "title": "My Client", "version": "0.1.0" },
    "capabilities": {
      "experimentalApi": true,
      "optOutNotificationMethods": [
        "codex/event/session_configured",
        "item/agentMessage/delta"
      ]
    }
  }
}

Bước 2: Start hoặc Resume Thread

// Tạo thread mới
{
  "method": "thread/start", "id": 10,
  "params": {
    "model": "gpt-5.1-codex",
    "cwd": "/Users/me/project",
    "approvalPolicy": "never",
    "sandbox": "workspaceWrite",
    "personality": "friendly"
  }
}

// Resume thread đã có
{
  "method": "thread/resume", "id": 11,
  "params": { "threadId": "thr_123", "personality": "friendly" }
}

// Fork thread (tạo bản sao lịch sử)
{
  "method": "thread/fork", "id": 12,
  "params": { "threadId": "thr_123" }
}

Bước 3: Start Turn (gửi input)

{
  "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.1-codex",
    "effort": "medium"
  }
}

Input types hỗ trợ:

Type Mô tả Ví dụ
text Văn bản { "type": "text", "text": "Explain this diff" }
image Ảnh từ URL { "type": "image", "url": "https://.../design.png" }
localImage Ảnh local { "type": "localImage", "path": "/tmp/screenshot.png" }
skill Invoke skill { "type": "skill", "name": "skill-creator", "path": "..." }
mention Invoke app { "type": "mention", "name": "Demo App", "path": "app://demo-app" }

Bước 4: Steer Turn (bổ sung input giữa chừng)

{
  "method": "turn/steer", "id": 32,
  "params": {
    "threadId": "thr_123",
    "input": [{ "type": "text", "text": "Actually focus on failing tests first." }],
    "expectedTurnId": "turn_456"
  }
}

turn/steer không tạo turn mới, không emit turn/started, và không chấp nhận overrides (model, cwd, sandbox...).

Bước 5: Interrupt Turn (huỷ nếu cần)

{ "method": "turn/interrupt", "id": 31, "params": { "threadId": "thr_123", "turnId": "turn_456" } }

Turn kết thúc với status: "interrupted".


Getting Started — Code mẫu đầy đủ

Node.js / TypeScript — stdio transport

import { spawn } from "node:child_process";
import readline from "node:readline";

// 1. Spawn app-server process
const proc = spawn("codex", ["app-server"], {
  stdio: ["pipe", "pipe", "inherit"],
});
const rl = readline.createInterface({ input: proc.stdout });

// Helper: gửi JSON-RPC message
const send = (message: unknown) => {
  proc.stdin.write(`${JSON.stringify(message)}\n`);
};

let threadId: string | null = null;

// 2. Lắng nghe messages từ server
rl.on("line", (line) => {
  const msg = JSON.parse(line) as any;
  console.log("server:", msg);

  // Khi thread được tạo → bắt đầu turn
  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." }],
      },
    });
  }
});

// 3. Handshake: initialize → initialized → thread/start
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.1-codex" } });

Flow tổng quát cho mọi client

graph TD
    A["Spawn / Connect"] --> B["send: initialize"]
    B --> C["send: initialized"]
    C --> D{"Mới hay resume?"}
    D -->|Mới| E["send: thread/start"]
    D -->|Resume| F["send: thread/resume"]
    E --> G["Nhận thread.id"]
    F --> G
    G --> H["send: turn/start"]
    H --> I["Stream: item/* events"]
    I --> J{"Cần approval?"}
    J -->|Có| K["Client trả approval decision"]
    J -->|Không| L["Tiếp tục stream"]
    K --> L
    L --> M["turn/completed"]
    M --> N{"Thêm turn?"}
    N -->|Có| H
    N -->|Không| O["Done / Cleanup"]

    style A fill:#10a37f,color:#fff
    style M fill:#00b894,color:#fff
    style O fill:#6c5ce7,color:#fff
Loading

Thread Management — Quản lý hội thoại

API Reference nhanh

Method Mô tả
thread/start Tạo thread mới, auto-subscribe events
thread/resume Mở lại thread đã có
thread/fork Fork thread thành thread mới (copy history)
thread/read Đọc thread từ storage (không resume, không subscribe)
thread/list Phân trang danh sách threads (hỗ trợ filters)
thread/loaded/list List thread IDs đang nằm trong memory
thread/archive Di chuyển thread log vào thư mục archived
thread/unarchive Khôi phục thread từ archived
thread/compact/start Trigger nén lịch sử hội thoại
thread/rollback Xoá N turns cuối khỏi context

Pagination & Filtering cho thread/list

{
  "method": "thread/list", "id": 20,
  "params": {
    "cursor": null,
    "limit": 25,
    "sortKey": "created_at",
    "modelProviders": ["openai"],
    "sourceKinds": ["cli", "vscode", "appServer"],
    "archived": false,
    "cwd": "/Users/me/project"
  }
}

sourceKinds hỗ trợ: cli, vscode, exec, appServer, subAgent, subAgentReview, subAgentCompact, subAgentThreadSpawn, subAgentOther, unknown.

Khi nextCursornull → bạn đã ở trang cuối.

Read Thread (không resume)

{
  "method": "thread/read", "id": 19,
  "params": { "threadId": "thr_123", "includeTurns": true }
}

Khác với thread/resume: không load vào memory, không emit thread/started.

Compaction & Rollback

// Nén lịch sử (async, trả {} ngay)
{ "method": "thread/compact/start", "id": 25, "params": { "threadId": "thr_b" } }

// Xoá N turns cuối
{ "method": "thread/rollback", "id": 26, "params": { "threadId": "thr_b", "n": 3 } }

Streaming Events — Hệ thống sự kiện

Event Categories

graph TB
    subgraph turn_events ["🔄 Turn Events"]
        TE1["turn/started"]
        TE2["turn/completed"]
        TE3["turn/diff/updated"]
        TE4["turn/plan/updated"]
    end

    subgraph item_lifecycle ["📦 Item Lifecycle"]
        IL1["item/started"]
        IL2["item/completed"]
    end

    subgraph item_deltas ["📝 Item Deltas (Streaming)"]
        ID1["item/agentMessage/delta"]
        ID2["item/plan/delta"]
        ID3["item/reasoning/summaryTextDelta"]
        ID4["item/commandExecution/outputDelta"]
        ID5["item/fileChange/outputDelta"]
    end

    subgraph special ["🔔 Special"]
        SP1["thread/tokenUsage/updated"]
        SP2["app/list/updated"]
        SP3["account/rateLimits/updated"]
    end

    style turn_events fill:#1e272e,color:#dfe6e9,stroke:#0984e3,stroke-width:2px
    style item_lifecycle fill:#1e272e,color:#dfe6e9,stroke:#00b894,stroke-width:2px
    style item_deltas fill:#1e272e,color:#dfe6e9,stroke:#e17055,stroke-width:2px
    style special fill:#1e272e,color:#dfe6e9,stroke:#fdcb6e,stroke-width:2px
Loading

Item Types đầy đủ

Item Type Mô tả Fields chính
userMessage Tin nhắn user id, content (text/image/localImage)
agentMessage Reply của agent id, text
plan Kế hoạch agent đề xuất id, text
reasoning Lý luận nội bộ id, summary, content
commandExecution Chạy command id, command, cwd, status, exitCode, durationMs
fileChange Thay đổi file id, changes [{path, kind, diff}], status
mcpToolCall Gọi MCP tool id, server, tool, status, arguments, result/error
collabToolCall Gọi collab tool id, tool, status, senderThreadId...
webSearch Tìm kiếm web id, query, action
imageView Xem ảnh id, path
enteredReviewMode Bắt đầu review id, review
exitedReviewMode Kết thúc review id, review (kết quả)
contextCompaction Nén context id

Notification Opt-out

Bạn có thể tắt notification cụ thể khi initialize:

{
  "capabilities": {
    "optOutNotificationMethods": [
      "item/agentMessage/delta",
      "codex/event/session_configured"
    ]
  }
}
  • Exact-match only (không hỗ trợ wildcard)
  • Method name không tồn tại → bị ignore

Approval Workflows — Phê duyệt hành động

Tuỳ vào cấu hình sandbox, Codex có thể yêu cầu approval trước khi thực thi command hoặc thay đổi file.

Flow tổng quát

sequenceDiagram
    participant S as Server
    participant C as Client

    S-->>C: item/started (commandExecution, status: pending)
    S->>C: item/commandExecution/requestApproval
    Note right of C: Client hiển thị UI cho user
    C->>S: Response (accept / decline / cancel)
    S-->>C: item/completed (status: completed / declined)
Loading

Command Execution Approvals

Decisions hỗ trợ:

Decision Ý nghĩa
accept Chấp nhận lần này
acceptForSession Chấp nhận cho cả session
decline Từ chối
cancel Huỷ turn
acceptWithExecpolicyAmendment Chấp nhận + thêm policy rule

Với acceptWithExecpolicyAmendment:

{
  "acceptWithExecpolicyAmendment": {
    "execpolicy_amendment": ["npm", "test"]
  }
}

File Change Approvals

Tương tự nhưng dùng item/fileChange/requestApproval. Decisions: accept, acceptForSession, decline, cancel.

MCP Tool-call Approvals (Apps)

App connector tool calls có side effects → server gửi tool/requestUserInput với options Accept/Decline/Cancel.


Sandbox Policies — Chính sách bảo mật

Các loại sandbox

Policy Mô tả Network
readOnly Chỉ đọc Không
workspaceWrite Ghi trong writableRoots Boolean (true/false)
externalSandbox Sandbox do host quản lý restricted / enabled
dangerFullAccess Full quyền (nguy hiểm) Full

Ví dụ chi tiết

// Chỉ đọc, full access
{ "type": "readOnly", "access": { "type": "fullAccess" } }

// Ghi trong project, đọc thêm shared folder
{
  "type": "workspaceWrite",
  "writableRoots": ["/Users/me/project"],
  "readOnlyAccess": {
    "type": "restricted",
    "includePlatformDefaults": true,
    "readableRoots": ["/Users/me/shared-read-only"]
  },
  "networkAccess": false
}

// External sandbox
{
  "type": "externalSandbox",
  "networkAccess": "restricted"
}

Authentication — Xác thực

Codex App Server hỗ trợ 3 chế độ xác thực:

graph LR
    subgraph auth ["🔐 Authentication Modes"]
        A1["API Key<br/>(apikey)"]
        A2["ChatGPT Managed<br/>(chatgpt)"]
        A3["ChatGPT External<br/>(chatgptAuthTokens)"]
    end

    A1 --> USE1["Đơn giản<br/>Dùng API key trực tiếp"]
    A2 --> USE2["OAuth Flow<br/>Codex quản lý tokens"]
    A3 --> USE3["Host App cung cấp<br/>idToken + accessToken"]

    style A1 fill:#0984e3,color:#fff,stroke:#74b9ff
    style A2 fill:#00b894,color:#fff,stroke:#55efc4
    style A3 fill:#e17055,color:#fff,stroke:#fab1a0
Loading

Auth API Reference

Method Loại Mô tả
account/read Request Kiểm tra trạng thái auth
account/login/start Request Bắt đầu login
account/login/completed Notification Login hoàn thành
account/login/cancel Request Huỷ ChatGPT login
account/logout Request Đăng xuất
account/updated Notification Auth mode thay đổi
account/chatgptAuthTokens/refresh Server Request Yêu cầu refresh tokens
account/rateLimits/read Request Xem rate limits
account/rateLimits/updated Notification Rate limits thay đổi

Login với API Key

// 1. Send
{ "method": "account/login/start", "id": 2, "params": { "type": "apiKey", "apiKey": "sk-..." } }

// 2. Response
{ "id": 2, "result": { "type": "apiKey" } }

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

Login với ChatGPT (Browser OAuth)

// 1. Start
{ "method": "account/login/start", "id": 3, "params": { "type": "chatgpt" } }

// 2. Response — nhận authUrl
{
  "id": 3,
  "result": {
    "type": "chatgpt",
    "loginId": "<uuid>",
    "authUrl": "https://chatgpt.com/...&redirect_uri=http%3A%2F%2Flocalhost%3A<port>%2Fauth%2Fcallback"
  }
}

// 3. Mở authUrl trong browser → chờ callback
// 4. Notifications
{ "method": "account/login/completed", "params": { "loginId": "<uuid>", "success": true } }
{ "method": "account/updated", "params": { "authMode": "chatgpt" } }

Login với External Tokens

// Host app cung cấp tokens trực tiếp
{
  "method": "account/login/start", "id": 7,
  "params": {
    "type": "chatgptAuthTokens",
    "idToken": "<jwt>",
    "accessToken": "<jwt>"
  }
}

Khi server gặp 401 → gửi account/chatgptAuthTokens/refresh yêu cầu host app cung cấp tokens mới (timeout ~10s).

Rate Limits

{ "method": "account/rateLimits/read", "id": 6 }

Response chứa:

  • rateLimits — backward-compatible single-bucket view
  • rateLimitsByLimitId — multi-bucket view (ví dụ: codex, codex_other)
  • Mỗi bucket có: usedPercent, windowDurationMins, resetsAt (Unix timestamp)

Review — Đánh giá code

review/start chạy Codex reviewer trên một thread.

Review Targets

Target Mô tả
uncommittedChanges Review thay đổi chưa commit
baseBranch Diff với một branch
commit Review một commit cụ thể
custom Free-form instructions

Delivery Modes

Mode Mô tả
inline (default) Review trên thread hiện tại
detached Fork thread mới cho review
{
  "method": "review/start", "id": 40,
  "params": {
    "threadId": "thr_123",
    "delivery": "inline",
    "target": { "type": "commit", "sha": "1234567deadbeef", "title": "Polish tui colors" }
  }
}

Server stream: item/started (enteredReviewMode) → ... → item/completed (exitedReviewMode với review text).


Command Execution — Chạy lệnh ngoài Thread

command/exec chạy command trực tiếp dưới sandbox, không cần tạo thread/turn.

{
  "method": "command/exec", "id": 50,
  "params": {
    "command": ["ls", "-la"],
    "cwd": "/Users/me/project",
    "sandboxPolicy": { "type": "workspaceWrite" },
    "timeoutMs": 10000
  }
}

Response:

{ "id": 50, "result": { "exitCode": 0, "stdout": "...", "stderr": "" } }

Lưu ý:

  • command array rỗng → bị reject
  • sandboxPolicy chấp nhận cùng shape với turn/start
  • timeoutMs không set → dùng server default

Skills & Apps — Mở rộng khả năng

Invoke Skill

Thêm $<skill-name> vào text input + skill item:

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

Nếu bỏ skill item, model vẫn parse $<skill-name> nhưng sẽ chậm hơn.

List Skills

{
  "method": "skills/list", "id": 25,
  "params": {
    "cwds": ["/Users/me/project"],
    "forceReload": true,
    "perCwdExtraUserRoots": [
      { "cwd": "/Users/me/project", "extraUserRoots": ["/Users/me/shared-skills"] }
    ]
  }
}

Enable/Disable Skill

{
  "method": "skills/config/write", "id": 26,
  "params": { "path": "/Users/me/.codex/skills/skill-creator/SKILL.md", "enabled": false }
}

Invoke App (Connector)

Thêm $<app-slug> vào text + mention item:

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

List Apps

{ "method": "app/list", "id": 50, "params": { "cursor": null, "limit": 50, "forceRefetch": false } }

Mỗi app entry có:

  • isAccessible — user có quyền truy cập không
  • isEnabled — đã bật trong config.toml chưa

Models & Features — Khám phá khả năng

List Models

{ "method": "model/list", "id": 6, "params": { "limit": 20, "includeHidden": false } }

Mỗi model entry chứa:

Field Mô tả
reasoningEffort Các mức effort hỗ trợ
defaultReasoningEffort Effort mặc định
upgrade Model ID khuyến nghị upgrade
hidden Ẩn khỏi picker mặc định
inputModalities Input types hỗ trợ (text, image)
supportsPersonality Có hỗ trợ /personality không
isDefault Có phải model mặc định không

List Experimental Features

{ "method": "experimentalFeature/list", "id": 7, "params": { "limit": 20 } }

stage values: beta, underDevelopment, stable, deprecated, removed.


Configuration — Đọc/ghi cấu hình

Method Mô tả
config/read Đọc config hiện hành (đã resolve layering)
config/value/write Ghi một key/value vào config.toml
config/batchWrite Ghi nhiều key/value atomically
configRequirements/read Đọc requirements (allow-lists, residency...)
config/mcpServer/reload Reload MCP server config từ disk

Error Handling — Xử lý lỗi

Error Format

Khi turn fail, server gửi error event rồi kết thúc turn với status: "failed":

{
  "turn": {
    "status": "failed",
    "error": {
      "message": "Context window exceeded",
      "codexErrorInfo": { "type": "ContextWindowExceeded", "httpStatusCode": 400 },
      "additionalDetails": "..."
    }
  }
}

Common Error Types

Error Type Mô tả Cách xử lý
ContextWindowExceeded Vượt context window Dùng thread/compact/start hoặc thread/rollback
UsageLimitExceeded Vượt quota Chờ reset hoặc upgrade plan
HttpConnectionFailed Upstream 4xx/5xx Retry với backoff
ResponseStreamConnectionFailed Mất kết nối stream Reconnect + resume thread
ResponseStreamDisconnected Stream bị ngắt Reconnect + resume thread
ResponseTooManyFailedAttempts Quá nhiều retry Kiểm tra config/auth
BadRequest Request không hợp lệ Kiểm tra params
Unauthorized Chưa auth / token hết hạn Re-authenticate
SandboxError Lỗi sandbox Kiểm tra sandbox policy
InternalServerError Lỗi server Retry hoặc report

WebSocket-specific Errors

Error Code Message Xử lý
-32001 Server overloaded; retry later. Retry với exponential backoff + jitter

Toàn bộ API Reference

Requests (Client → Server)

Method Mô tả Experimental
initialize Khởi tạo kết nối
thread/start Tạo thread mới
thread/resume Resume thread
thread/fork Fork thread
thread/read Đọc thread (không resume)
thread/list List threads (pagination)
thread/loaded/list List threads trong memory
thread/archive Archive thread
thread/unarchive Unarchive thread
thread/compact/start Trigger compaction
thread/rollback Rollback N turns
turn/start Bắt đầu turn
turn/steer Bổ sung input vào turn đang chạy
turn/interrupt Huỷ turn
review/start Bắt đầu code review
command/exec Chạy command ngoài thread
model/list List models
experimentalFeature/list List feature flags
collaborationMode/list List collaboration modes
skills/list List skills
skills/config/write Enable/disable skill
app/list List apps (connectors)
mcpServer/oauth/login Start MCP OAuth login
tool/requestUserInput Prompt user (1-3 questions)
config/mcpServer/reload Reload MCP config
mcpServerStatus/list List MCP server status
feedback/upload Gửi feedback report
config/read Đọc config
config/value/write Ghi config value
config/batchWrite Ghi config batch
configRequirements/read Đọc config requirements
account/read Kiểm tra auth state
account/login/start Bắt đầu login
account/login/cancel Huỷ ChatGPT login
account/logout Đăng xuất
account/rateLimits/read Xem rate limits

Notifications (Server → Client)

Method Mô tả
thread/started Thread đã tạo/resume
turn/started Turn bắt đầu
turn/completed Turn hoàn thành
turn/diff/updated Diff tổng hợp cập nhật
turn/plan/updated Plan cập nhật
thread/tokenUsage/updated Token usage thay đổi
item/started Item bắt đầu
item/completed Item hoàn thành
item/agentMessage/delta Agent message text chunk
item/plan/delta Plan text chunk
item/reasoning/summaryTextDelta Reasoning summary chunk
item/reasoning/summaryPartAdded Reasoning section boundary
item/reasoning/textDelta Raw reasoning chunk
item/commandExecution/outputDelta Command stdout/stderr chunk
item/fileChange/outputDelta File change tool response
item/commandExecution/requestApproval Yêu cầu approve command
item/fileChange/requestApproval Yêu cầu approve file change
account/login/completed Login hoàn thành
account/updated Auth mode thay đổi
account/rateLimits/updated Rate limits thay đổi
account/chatgptAuthTokens/refresh Yêu cầu refresh tokens
mcpServer/oauthLogin/completed MCP OAuth hoàn thành
app/list/updated App list thay đổi
fuzzyFileSearch/sessionUpdated File search results (experimental)
fuzzyFileSearch/sessionCompleted File search done (experimental)

Best Practices & Tips

1. Client Implementation Checklist

  • Gửi initialize + initialized trước mọi thứ
  • Xử lý Not initialized error gracefully
  • Implement approval UI cho commands + file changes
  • Buffer item/agentMessage/delta để render streaming text
  • Xử lý turn/completed với cả 3 status: completed, interrupted, failed
  • Implement reconnection logic (đặc biệt cho WebSocket)
  • Store thread.id để resume sessions
  • Set clientInfo.name đúng cách cho compliance logs

2. Performance Tips

  • Dùng optOutNotificationMethods để tắt notifications không cần (giảm bandwidth)
  • Dùng thread/compact/start khi context window gần đầy
  • Dùng thread/rollback thay vì tạo thread mới khi chỉ cần undo vài turns
  • Cache model/listapp/list responses, chỉ refresh khi cần

3. Security Tips

  • Luôn dùng sandboxPolicy phù hợp — tránh dangerFullAccess trong production
  • Dùng readOnlyAccess.restricted + readableRoots để giới hạn đọc
  • Validate writableRoots — chỉ cho phép ghi vào project directory
  • Dùng approvalPolicy: "unlessTrusted" cho production clients
  • Khi host app quản lý tokens (chatgptAuthTokens) — implement account/chatgptAuthTokens/refresh handler

4. WebSocket Resilience

Client                          Server
  |--- connect ws://... -------->|
  |--- initialize -------------->|
  |<-- result -------------------|
  |--- initialized -------------->|
  |--- thread/start ------------->|
  |<-- result -------------------|
  |--- turn/start --------------->|
  |<-- item/* stream ------------|
  |     (connection drops)       |
  |--- reconnect ws://... ------>|
  |--- initialize -------------->|
  |--- thread/resume ----------->|  ← Resume, không start mới
  |--- turn/start --------------->|
  |<-- item/* stream ------------|

5. Khi nào dùng method nào?

Tình huống Method
Tạo conversation mới thread/start
Tiếp tục conversation cũ thread/resume
Branch từ conversation thread/fork
Xem lịch sử (không tiếp tục) thread/read
Render danh sách conversations thread/list
Gửi input cho agent turn/start
Bổ sung context giữa chừng turn/steer
Dừng agent turn/interrupt
Review code changes review/start
Chạy lệnh nhanh command/exec
Context window đầy thread/compact/start
Undo turns thread/rollback

Troubleshooting

"Not initialized" error

Nguyên nhân: Gửi request trước khi hoàn thành handshake.

Giải pháp: Đảm bảo gửi initialize request → nhận response → gửi initialized notification → rồi mới gửi request khác.

"Already initialized" error

Nguyên nhân: Gọi initialize lần 2 trên cùng connection.

Giải pháp: Chỉ gọi initialize một lần per connection. Nếu cần reset, tạo connection mới.

" requires experimentalApi capability"

Nguyên nhân: Gọi experimental method/field mà chưa opt-in.

Giải pháp: Thêm "capabilities": { "experimentalApi": true } trong initialize.

Server overloaded (WebSocket, code -32001)

Nguyên nhân: Request queue đầy.

Giải pháp: Implement retry với exponential backoff + jitter:

const retry = async (fn: () => Promise<any>, maxRetries = 5) => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (e: any) {
      if (e.code === -32001) {
        const delay = Math.min(1000 * Math.pow(2, i), 30000);
        const jitter = Math.random() * delay * 0.3;
        await new Promise(r => setTimeout(r, delay + jitter));
        continue;
      }
      throw e;
    }
  }
};

Turn failed: ContextWindowExceeded

Nguyên nhân: Hội thoại quá dài.

Giải pháp:

  1. thread/compact/start — nén lịch sử
  2. thread/rollback — xoá turns không cần
  3. Tạo thread mới nếu compact không đủ

MCP server required but failed to initialize

Nguyên nhân: MCP server đánh dấu required nhưng không khởi tạo được.

Giải pháp: Kiểm tra MCP server config, đảm bảo server đang chạy, rồi thử config/mcpServer/reload.

Resume với model khác

Hành vi: Codex emit warning và apply one-time model-switch instruction trên turn tiếp theo. Không phải bug, là design.


Tài liệu liên quan

Tài liệu Link Mô tả
Codex Overview developers.openai.com/codex Tổng quan Codex
Codex SDK developers.openai.com/codex/sdk SDK cho CI/CD automation
MCP Server developers.openai.com/codex/guides/agents-sdk Codex as MCP Server
Non-interactive Mode developers.openai.com/codex/noninteractive Chạy Codex không tương tác
GitHub Action developers.openai.com/codex/github-action CI/CD integration
Config Reference developers.openai.com/codex/config-reference Cấu hình chi tiết
AGENTS.md developers.openai.com/codex/guides/agents-md Hướng dẫn AGENTS.md
Skills developers.openai.com/codex/skills Hệ thống Skills
Open Source developers.openai.com/codex/open-source Các component open-source
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment