Tiếng Việt

Codex App Server

Để xem chỉ mục tài liệu đầy đủ, hãy xem llms.txt. Bạn có thể truy cập phiên bản Markdown của các trang tài liệu bằng cách thêm .md vào URL của trang.

Codex app-server là giao diện mà Codex sử dụng để vận hành các ứng dụng khách giàu tính năng (ví dụ: tiện ích mở rộng Codex cho VS Code). Hãy sử dụng giao diện này khi bạn muốn tích hợp sâu vào sản phẩm của mình, bao gồm xác thực, lịch sử hội thoại, phê duyệt và các sự kiện agent được truyền trực tiếp. Phần triển khai app-server có mã nguồn mở trong kho lưu trữ Codex trên GitHub (openai/codex/codex-rs/app-server). Xem trang Mã nguồn mở để biết danh sách đầy đủ các thành phần Codex có mã nguồn mở.

Kết nối giao diện đầu cuối của CLI

Chế độ giao diện đầu cuối từ xa cho phép bạn chạy app-server trên một máy và kết nối giao diện đầu cuối Codex CLI từ một máy khác. Khởi động một trình lắng nghe WebSocket:

codex app-server --listen ws://127.0.0.1:4500

Sau đó kết nối giao diện đầu cuối:

codex --remote ws://127.0.0.1:4500

Đối với kết nối không phải cục bộ, hãy cấu hình xác thực WebSocket và đặt kết nối phía sau TLS. Lưu bearer token trong một biến môi trường và truyền tên biến thay vì đưa token vào dòng lệnh:

export CODEX_REMOTE_TOKEN="$(cat "$HOME/.codex/app-server-token")"
codex --remote wss://remote-host:4500 \
  --remote-auth-token-env CODEX_REMOTE_TOKEN

Tùy chọn --remote chấp nhận các điểm cuối ws://, wss://, unix://unix://PATH. Chỉ sử dụng WebSocket thuần cho localhost hoặc kết nối được chuyển tiếp cổng qua SSH.

Kết nối máy chủ Code Mode từ xa

Theo mặc định, app-server khởi động một máy chủ Code Mode cục bộ. Để sử dụng máy chủ từ xa thay thế, hãy truyền URL WebSocket bảo mật của máy chủ đó:

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

--code-mode-host kiểm soát kết nối đi từ app-server đến máy chủ Code Mode của nó. Tùy chọn này không thay đổi --listen, vốn kiểm soát cách ứng dụng khách kết nối với app-server. Mọi luồng trong cùng một tiến trình app-server đều dùng chung kết nối đến máy chủ Code Mode đã chọn.

Sử dụng wss:// cho máy chủ từ xa. Chỉ sử dụng ws:// cho localhost hoặc kết nối được chuyển tiếp qua SSH. Lệnh app-server và phương thức truyền tải WebSocket đang ở trạng thái thử nghiệm và không được hỗ trợ cho khối lượng công việc sản xuất.

Giao thức

Tương tự MCP, codex app-server hỗ trợ giao tiếp hai chiều bằng thông điệp JSON-RPC 2.0 (bỏ tiêu đề "jsonrpc":"2.0" khi truyền trên đường dây).

Các phương thức truyền tải được hỗ trợ:

  • stdio (--listen stdio://, mặc định): JSON được phân tách bằng dòng mới (JSONL).
  • websocket (--listen ws://IP:PORT, thử nghiệm và không được hỗ trợ): một thông điệp JSON-RPC trên mỗi khung văn bản WebSocket.
  • Unix socket (--listen unix:// hoặc --listen unix://PATH): các kết nối WebSocket qua socket điều khiển app-server mặc định của Codex hoặc một đường dẫn Unix socket tùy chỉnh, sử dụng quy trình bắt tay HTTP Upgrade tiêu chuẩn.
  • off (--listen off): không cung cấp phương thức truyền tải cục bộ.

Khi bạn chạy với --listen ws://IP:PORT, cùng một trình lắng nghe cũng phục vụ các đầu dò tình trạng HTTP cơ bản:

  • GET /readyz trả về 200 OK sau khi trình lắng nghe chấp nhận kết nối mới.
  • GET /healthz trả về 200 OK khi yêu cầu không chứa tiêu đề Origin.
  • Các yêu cầu có tiêu đề Origin bị từ chối với 403 Forbidden.

Phương thức truyền tải WebSocket đang ở trạng thái thử nghiệm và không được hỗ trợ. Các trình lắng nghe cục bộ như ws://127.0.0.1:PORT phù hợp với quy trình làm việc dùng localhost và chuyển tiếp cổng qua SSH. Trong quá trình triển khai, các trình lắng nghe WebSocket không thuộc loopback hiện cho phép kết nối không cần xác thực theo mặc định, vì vậy hãy cấu hình xác thực WebSocket trước khi cung cấp từ xa.

Các cờ xác thực WebSocket được hỗ trợ:

  • --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

Đối với bearer token đã ký, bạn cũng có thể đặt --ws-issuer, --ws-audience--ws-max-clock-skew-seconds. Ứng dụng khách cung cấp thông tin xác thực dưới dạng Authorization: Bearer <token> trong quá trình bắt tay WebSocket, và app-server thực thi xác thực trước initialize của JSON-RPC.

Ưu tiên --ws-token-file thay vì truyền bearer token thô trên dòng lệnh. Chỉ sử dụng --ws-token-sha256 khi ứng dụng khách lưu token thô có entropy cao trong một kho bí mật cục bộ riêng biệt; hàm băm chỉ là giá trị xác minh, và ứng dụng khách vẫn cần token gốc.

Trong chế độ WebSocket, app-server sử dụng các hàng đợi có giới hạn. Khi hàng đợi yêu cầu đến đã đầy, máy chủ từ chối yêu cầu mới bằng mã lỗi JSON-RPC -32001 và thông báo "Server overloaded; retry later." Ứng dụng khách nên thử lại với độ trễ tăng theo cấp số nhân và có thêm độ lệch ngẫu nhiên.

Lược đồ thông điệp

Yêu cầu bao gồm method, paramsid:

{ "method": "thread/start", "id": 10, "params": { "model": "gpt-5.6-terra" } }

Phản hồi lặp lại id cùng với result hoặc error:

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

Thông báo bỏ qua id và chỉ sử dụng method cùng params:

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

Bạn có thể tạo lược đồ TypeScript hoặc một gói JSON Schema từ CLI. Mỗi đầu ra dành riêng cho phiên bản Codex mà bạn đã chạy, vì vậy các thành phần được tạo sẽ khớp chính xác với phiên bản đó:

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

Bắt đầu

  1. Khởi động máy chủ bằng codex app-server (phương thức truyền tải stdio mặc định), codex app-server --listen ws://127.0.0.1:4500 (TCP WebSocket) hoặc codex app-server --listen unix:// (Unix socket mặc định).
  2. Kết nối một ứng dụng khách qua phương thức truyền tải đã chọn, sau đó gửi initialize rồi đến thông báo initialized.
  3. Khởi động một luồng và một lượt, sau đó tiếp tục đọc thông báo từ luồng truyền tải đang hoạt động.

Ví dụ (Node.js / TypeScript):




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

const send = (message: unknown) => {
  proc.stdin.write(`${JSON.stringify(message)}\n`);
};

let threadId: string | null = null;

rl.on("line", (line) => {
  const msg = JSON.parse(line) as any;
  console.log("server:", msg);

  if (msg.id === 1 && msg.result?.thread?.id && !threadId) {
    threadId = msg.result.thread.id;
    send({
      method: "turn/start",
      id: 2,
      params: {
        threadId,
        input: [{ type: "text", text: "Summarize this repo." }],
      },
    });
  }
});

send({
  method: "initialize",
  id: 0,
  params: {
    clientInfo: {
      name: "my_product",
      title: "My Product",
      version: "0.1.0",
    },
  },
});
send({ method: "initialized", params: {} });
send({ method: "thread/start", id: 1, params: { model: "gpt-5.6-terra" } });

Các thành phần cốt lõi

  • Luồng: Một cuộc hội thoại giữa người dùng và agent Codex. Luồng chứa các lượt.
  • Lượt: Một yêu cầu riêng lẻ của người dùng và phần công việc tiếp theo của agent. Lượt chứa các mục và truyền trực tiếp những cập nhật tăng dần.
  • Mục: Một đơn vị đầu vào hoặc đầu ra (thông điệp của người dùng, thông điệp của agent, lần chạy lệnh, thay đổi tệp, lệnh gọi công cụ và nhiều loại khác).

Sử dụng API luồng để tạo, liệt kê hoặc lưu trữ cuộc hội thoại. Điều khiển cuộc hội thoại bằng API lượt và truyền trực tiếp tiến độ qua thông báo lượt.

Tổng quan về vòng đời

  • Khởi tạo một lần cho mỗi kết nối: Ngay sau khi mở kết nối truyền tải, hãy gửi yêu cầu initialize cùng siêu dữ liệu ứng dụng khách, rồi phát initialized. Máy chủ từ chối mọi yêu cầu trên kết nối đó trước khi quy trình bắt tay này hoàn tất.
  • Bắt đầu (hoặc tiếp tục) một luồng: Gọi thread/start cho cuộc hội thoại mới, thread/resume để tiếp tục cuộc hội thoại hiện có hoặc thread/fork để phân nhánh lịch sử sang một id luồng mới.
  • Bắt đầu một lượt: Gọi turn/start với threadId đích và đầu vào của người dùng. Các trường tùy chọn có thể ghi đè mô hình, tính cách, cwd, chính sách sandbox và nhiều thiết lập khác.
  • Điều hướng một lượt đang hoạt động: Gọi turn/steer để nối thêm đầu vào của người dùng vào lượt hiện đang xử lý mà không tạo lượt mới.
  • Truyền trực tiếp sự kiện: Sau turn/start, hãy tiếp tục đọc thông báo trên stdout: thread/archived, thread/unarchived, item/started, item/completed, item/agentMessage/delta, tiến độ công cụ và các cập nhật khác.
  • Kết thúc lượt: Máy chủ phát turn/completed cùng trạng thái cuối cùng khi mô hình hoàn tất hoặc sau khi hủy bằng turn/interrupt.

Khởi tạo

Ứng dụng khách phải gửi một yêu cầu initialize duy nhất cho mỗi kết nối truyền tải trước khi gọi bất kỳ phương thức nào khác trên kết nối đó, rồi xác nhận bằng thông báo initialized. Yêu cầu được gửi trước khi khởi tạo sẽ nhận lỗi Not initialized, và các lệnh gọi initialize lặp lại trên cùng kết nối sẽ trả về Already initialized.

Máy chủ trả về chuỗi user agent mà nó sẽ cung cấp cho các dịch vụ thượng nguồn, cùng các giá trị platformFamilyplatformOs mô tả đích thời gian chạy. Đặt clientInfo để nhận diện tích hợp của bạn.

initialize.params.capabilities cũng hỗ trợ các khả năng ứng dụng khách sau:

  • optOutNotificationMethods - tên phương thức thông báo chính xác cần chặn đối với kết nối này. Việc so khớp phải chính xác (không có ký tự đại diện hoặc tiền tố); các tên không xác định được chấp nhận và bỏ qua.
  • requestAttestation - chọn tham gia yêu cầu attestation/generate do máy chủ khởi tạo. Các máy chủ desktop cung cấp chứng thực thượng nguồn sẽ phản hồi bằng một giá trị { "token": "..." } không trong suốt.
  • mcpServerOpenaiFormElicitation - cho phép các máy chủ MCP hạ nguồn gửi biến thể dạng mở rộng của OpenAI cho mcpServer/elicitation/request.

Quan trọng: Sử dụng clientInfo.name để nhận diện ứng dụng khách của bạn với OpenAI Compliance Logs Platform. Nếu bạn đang phát triển một tích hợp Codex mới dành cho doanh nghiệp, vui lòng liên hệ OpenAI để tích hợp đó được thêm vào danh sách ứng dụng khách đã biết. Để biết thêm ngữ cảnh, hãy xem tài liệu tham khảo về nhật ký Codex.

Ví dụ (từ tiện ích mở rộng Codex cho VS Code):

{
  "method": "initialize",
  "id": 0,
  "params": {
    "clientInfo": {
      "name": "codex_vscode",
      "title": "Codex VS Code Extension",
      "version": "0.1.0"
    }
  }
}

Ví dụ với tùy chọn không nhận thông báo:

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

Chọn tham gia API thử nghiệm

Một số phương thức và trường của app-server được chủ ý đặt sau khả năng experimentalApi.

  • Bỏ qua capabilities (hoặc đặt experimentalApi thành false) để duy trì trên bề mặt API ổn định; máy chủ sẽ từ chối các phương thức/trường thử nghiệm.
  • Đặt capabilities.experimentalApi thành true để bật các phương thức và trường thử nghiệm.
{
  "method": "initialize",
  "id": 1,
  "params": {
    "clientInfo": {
      "name": "my_client",
      "title": "My Client",
      "version": "0.1.0"
    },
    "capabilities": {
      "experimentalApi": true
    }
  }
}

Nếu ứng dụng khách gửi một phương thức hoặc trường thử nghiệm mà chưa chọn tham gia, app-server sẽ từ chối bằng:

<descriptor> requires experimentalApi capability

Tổng quan về API

  • thread/start - tạo luồng mới; phát thread/started và tự động đăng ký cho bạn nhận sự kiện lượt/mục của luồng đó.
  • thread/resume - mở lại một luồng hiện có theo id để các lệnh gọi turn/start sau đó nối thêm vào luồng.
  • thread/fork - phân nhánh một luồng thành id luồng mới bằng cách sao chép lịch sử đã lưu. Truyền lastTurnId để sao chép lịch sử đến hết lượt đó và bỏ qua các lượt sau, hoặc ephemeral: true để tạo nhánh trong bộ nhớ. Phát thread/started cho luồng mới; các luồng được trả về bao gồm forkedFromId khi có.
  • thread/read - đọc một luồng đã lưu theo id mà không tiếp tục luồng; đặt includeTurns để trả về toàn bộ lịch sử lượt. Các đối tượng thread được trả về bao gồm status thời gian chạy.
  • thread/list - phân trang qua nhật ký luồng đã lưu; hỗ trợ phân trang dựa trên con trỏ cùng modelProviders, sourceKinds, archived, isPinned, cwd, useStateDbOnly, searchTerm và các bộ lọc thử nghiệm parentThreadId hoặc ancestorThreadId. Các đối tượng thread được trả về bao gồm status thời gian chạy.
  • thread/turns/list - thử nghiệm; phân trang qua lịch sử lượt của một luồng đã lưu mà không tiếp tục luồng. itemsView kiểm soát việc các mục của lượt bị bỏ qua, tóm tắt hay tải đầy đủ.
  • thread/items/list - thử nghiệm; phân trang qua các mục luồng được lưu bền vững, có thể giới hạn ở một turnId. Kho lưu trữ luồng đang hoạt động phải hỗ trợ phân trang mục.
  • thread/loaded/list - liệt kê id của các luồng hiện được tải trong bộ nhớ.
  • thread/name/set - đặt hoặc cập nhật tên hiển thị cho người dùng của một luồng đã tải hoặc rollout được lưu bền vững; phát thread/name/updated.
  • thread/goal/set - đặt mục tiêu cho một luồng; phát thread/goal/updated.
  • thread/goal/get - đọc mục tiêu hiện tại của một luồng.
  • thread/goal/clear - xóa mục tiêu của một luồng; phát thread/goal/cleared.
  • thread/metadata/update - vá siêu dữ liệu luồng đã lưu dựa trên SQLite, bao gồm gitInfoisPinned được lưu bền vững.
  • thread/archive - di chuyển tệp nhật ký của một luồng vào thư mục lưu trữ và cố gắng lưu trữ nhật ký của các luồng hậu duệ được tạo ra mà chưa được lưu trữ; trả về {} khi thành công và phát thread/archived cho từng luồng được lưu trữ.
  • thread/delete - xóa vĩnh viễn một luồng đang hoạt động hoặc đã lưu trữ được lưu bền vững và mọi luồng hậu duệ được tạo ra; trả về {} khi thành công và phát thread/deleted cho từng luồng bị xóa.
  • thread/unsubscribe - hủy đăng ký kết nối này khỏi các sự kiện lượt/mục của luồng. Nếu đây là người đăng ký cuối cùng, máy chủ dỡ luồng sau khoảng thời gian gia hạn không hoạt động khi không có người đăng ký và phát thread/closed.
  • thread/unarchive - khôi phục rollout của một luồng đã lưu trữ về thư mục phiên đang hoạt động; trả về thread đã khôi phục và phát thread/unarchived.
  • thread/status/changed - thông báo được phát khi status thời gian chạy của một luồng đã tải thay đổi.
  • thread/compact/start - kích hoạt thu gọn lịch sử hội thoại cho một luồng; trả về {} ngay lập tức trong khi tiến độ được truyền trực tiếp qua các thông báo turn/*item/*.
  • thread/shellCommand - chạy lệnh shell do người dùng khởi tạo đối với một luồng. Lệnh này chạy bên ngoài sandbox với quyền truy cập đầy đủ và không kế thừa chính sách sandbox của luồng.
  • thread/backgroundTerminals/clean - dừng mọi đầu cuối nền đang chạy cho một luồng (thử nghiệm; yêu cầu capabilities.experimentalApi).
  • thread/backgroundTerminals/list - liệt kê các đầu cuối nền đang chạy cho một luồng đã tải (thử nghiệm; yêu cầu capabilities.experimentalApi).
  • thread/backgroundTerminals/terminate - chấm dứt một đầu cuối nền đang chạy theo processId của app-server (thử nghiệm; yêu cầu capabilities.experimentalApi).
  • thread/rollback - không còn được khuyến nghị; loại bỏ N lượt cuối khỏi ngữ cảnh trong bộ nhớ và lưu bền vững một dấu mốc hoàn tác; trả về thread đã cập nhật.
  • turn/start - thêm đầu vào của người dùng vào một luồng và bắt đầu quá trình tạo của Codex; phản hồi bằng turn ban đầu và truyền trực tiếp các sự kiện. Đối với collaborationMode, settings.developer_instructions: null có nghĩa là "sử dụng hướng dẫn tích hợp sẵn cho chế độ đã chọn".
  • thread/inject_items - nối thêm các mục Responses API thô vào lịch sử hiển thị cho mô hình của một luồng đã tải mà không bắt đầu lượt người dùng.
  • turn/steer - nối thêm đầu vào của người dùng vào lượt đang xử lý của một luồng; trả về turnId đã được chấp nhận.
  • turn/interrupt - yêu cầu hủy một lượt đang xử lý; thành công là {} và lượt kết thúc bằng status: "interrupted".
  • review/start - khởi động trình đánh giá Codex cho một luồng; phát các mục enteredReviewModeexitedReviewMode.
  • command/exec - chạy một lệnh riêng lẻ trong sandbox của máy chủ mà không bắt đầu luồng/lượt.
  • command/exec/write - ghi các byte stdin vào một phiên command/exec đang chạy hoặc đóng stdin.
  • command/exec/resize - thay đổi kích thước một phiên command/exec đang chạy có PTY hỗ trợ.
  • command/exec/terminate - dừng một phiên command/exec đang chạy.
  • command/exec/outputDelta (thông báo) - được phát cho các khối stdout/stderr được mã hóa base64 từ một phiên command/exec truyền trực tiếp.
  • process/spawn - bắt đầu một phiên tiến trình rõ ràng bên ngoài sandbox của Codex (thử nghiệm; yêu cầu capabilities.experimentalApi).
  • process/writeStdin - ghi byte stdin vào một phiên process/spawn đang chạy hoặc đóng stdin (thử nghiệm).
  • process/resizePty - thay đổi kích thước một phiên tiến trình có PTY hỗ trợ đang chạy (thử nghiệm).
  • process/kill - chấm dứt một phiên tiến trình đang chạy (thử nghiệm).
  • process/outputDeltaprocess/exited (thông báo) - được phát cho đầu ra tiến trình truyền trực tiếp và trạng thái thoát của tiến trình (thử nghiệm).
  • model/list - liệt kê các mô hình có sẵn (đặt includeHidden: true để bao gồm các mục có hidden: true) cùng tùy chọn mức độ nỗ lực, upgrade tùy chọn và inputModalities.
  • modelProvider/capabilities/read - đọc giới hạn khả năng của nhà cung cấp cho các tổ hợp mô hình/nhà cung cấp.
  • experimentalFeature/list - liệt kê cờ tính năng cùng siêu dữ liệu giai đoạn vòng đời và phân trang bằng con trỏ.
  • experimentalFeature/enablement/set - vá thiết lập thời gian chạy trong bộ nhớ cho các khóa tính năng được hỗ trợ như appsplugins.
  • environment/info - thử nghiệm; kết nối với một môi trường thực thi đã cấu hình và trả về shell cùng thư mục làm việc mặc định của môi trường đó.
  • permissionProfile/list - liệt kê các hồ sơ quyền beta và liệu yêu cầu có hiệu lực có cho phép chúng hay không, kèm phân trang bằng con trỏ.
  • collaborationMode/list - liệt kê các cấu hình sẵn chế độ cộng tác (thử nghiệm, không phân trang).
  • skills/list - liệt kê kỹ năng cho một hoặc nhiều giá trị cwd (hỗ trợ forceReloadperCwdExtraUserRoots tùy chọn).
  • skills/extraRoots/set - thay thế các thư mục gốc bổ sung ở cấp tiến trình dùng để khám phá kỹ năng độc lập mà không lưu bền vững chúng.
  • skills/changed (thông báo) - được phát khi các tệp kỹ năng cục bộ đang được theo dõi thay đổi.
  • hooks/list - liệt kê các hook vòng đời đã phát hiện cho một hoặc nhiều giá trị cwd.
  • marketplace/add - thêm marketplace plugin từ xa và lưu bền vững vào cấu hình marketplace của người dùng.
  • marketplace/remove - xóa một marketplace đã cấu hình và thư mục gốc marketplace đã cài đặt của nó nếu có.
  • marketplace/upgrade - làm mới một marketplace Git đã cấu hình, hoặc tất cả marketplace Git đã cấu hình khi bạn bỏ qua tên marketplace.
  • plugin/list - đang được phát triển; liệt kê các marketplace plugin đã phát hiện và trạng thái plugin, bao gồm siêu dữ liệu chính sách cài đặt/xác thực, lỗi tải marketplace, id plugin nổi bật và siêu dữ liệu nguồn plugin cục bộ, Git, kho đăng ký gói hoặc từ xa. Bản tóm tắt có thể bao gồm version từ xa, localVersion cục bộ, biểu tượng sáng/tối có cấu trúc và installPolicySource, có thể là null, WORKSPACE_SETTING hoặc IMPLICIT_CANONICAL_APP cho các hàng từ xa hiện tại. Chưa gọi phương thức này từ ứng dụng khách sản xuất.
  • plugin/read - đang được phát triển; đọc một plugin theo đường dẫn marketplace hoặc tên marketplace từ xa và tên plugin, bao gồm các kỹ năng đi kèm, ứng dụng, tên máy chủ MCP và shareUrl của plugin từ xa khi danh mục từ xa cung cấp. Chưa gọi phương thức này từ ứng dụng khách sản xuất.
  • plugin/install - đang được phát triển; cài đặt plugin từ đường dẫn marketplace hoặc tên marketplace từ xa. Chưa gọi phương thức này từ ứng dụng khách sản xuất.
  • plugin/uninstall - đang được phát triển; gỡ cài đặt một plugin đã cài. Chưa gọi phương thức này từ ứng dụng khách sản xuất.
  • plugin/skill/read - đọc Markdown kỹ năng của plugin từ xa theo yêu cầu bằng marketplace từ xa, id plugin và tên kỹ năng.
  • app/installed - đọc trạng thái thời gian chạy của ứng dụng đã cài đặt, bao gồm trạng thái bật và có thể gọi thực tế của từng ứng dụng.
  • app/list - liệt kê các ứng dụng (connector) có sẵn, kèm phân trang và siêu dữ liệu về khả năng truy cập/trạng thái bật.
  • app/read - tìm nạp siêu dữ liệu và bản tóm tắt công cụ chỉ để hiển thị tùy chọn cho các id ứng dụng cụ thể.
  • skills/config/write - bật hoặc tắt kỹ năng theo đường dẫn.
  • mcpServer/oauth/login - bắt đầu đăng nhập OAuth cho một máy chủ MCP đã cấu hình; trả về URL ủy quyền và phát mcpServer/oauthLogin/completed khi hoàn tất.
  • tool/requestUserInput - nhắc người dùng bằng 1-3 câu hỏi ngắn cho một lệnh gọi công cụ (thử nghiệm); câu hỏi có thể đặt isOther cho tùy chọn nhập tự do.
  • mcpServer/elicitation/request (yêu cầu máy chủ) - yêu cầu ứng dụng khách cung cấp đầu vào biểu mẫu có cấu trúc hoặc xác nhận luồng URL do máy chủ MCP yêu cầu.
  • item/permissions/requestApproval (yêu cầu máy chủ) - yêu cầu ứng dụng khách cấp một tập con quyền mạng hoặc hệ thống tệp do công cụ request_permissions tích hợp sẵn yêu cầu.
  • config/mcpServer/reload - tải lại cấu hình máy chủ MCP từ đĩa và đưa yêu cầu làm mới cho các luồng đã tải vào hàng đợi.
  • mcpServerStatus/list - liệt kê máy chủ MCP, công cụ, tài nguyên và trạng thái xác thực (phân trang bằng con trỏ + giới hạn). Sử dụng detail: "full" để lấy dữ liệu đầy đủ hoặc detail: "toolsAndAuthOnly" để bỏ qua tài nguyên.
  • mcpServer/resource/read - đọc một tài nguyên MCP riêng lẻ thông qua máy chủ MCP đã khởi tạo.
  • mcpServer/tool/call - gọi một công cụ trên máy chủ MCP đã cấu hình của một luồng.
  • mcpServer/startupStatus/updated (thông báo) - được phát khi trạng thái khởi động của máy chủ MCP đã cấu hình thay đổi đối với một luồng đã tải.
  • windowsSandbox/setupStart - bắt đầu thiết lập sandbox Windows cho chế độ elevated hoặc unelevated; trả về nhanh chóng và sau đó phát windowsSandbox/setupCompleted.
  • feedback/upload - gửi báo cáo phản hồi (phân loại + lý do/nhật ký tùy chọn + id hội thoại, cùng các tệp đính kèm extraLogFiles tùy chọn).
  • config/read - tìm nạp cấu hình thực tế trên đĩa sau khi phân giải các lớp cấu hình.
  • externalAgentConfig/detect - phát hiện các thành phần của agent bên ngoài có thể di chuyển bằng includeHomecwds tùy chọn; mỗi mục được phát hiện bao gồm cwd (null cho thư mục home).
  • externalAgentConfig/import - áp dụng các mục di chuyển agent bên ngoài đã chọn bằng cách truyền migrationItems rõ ràng cùng cwd (null cho thư mục home). Các loại mục được hỗ trợ bao gồm cấu hình, kỹ năng, AGENTS.md, plugin, cấu hình máy chủ MCP, tác nhân phụ, hook, lệnh và phiên; các lần nhập không rỗng phát externalAgentConfig/import/progressexternalAgentConfig/import/completed khi công việc hoàn tất. Việc nhập plugin và phiên có thể hoàn tất bất đồng bộ.
  • config/value/write - ghi một khóa/giá trị cấu hình riêng lẻ vào config.toml của người dùng trên đĩa.
  • config/batchWrite - áp dụng nguyên tử các chỉnh sửa cấu hình vào config.toml của người dùng trên đĩa.
  • configRequirements/read - tìm nạp yêu cầu từ requirements.toml và/hoặc MDM, bao gồm cấu hình được quản lý chính xác, danh sách cho phép, featureRequirements được ghim và yêu cầu về nơi lưu trú dữ liệu/mạng (hoặc null nếu bạn chưa thiết lập yêu cầu nào).
  • fs/readFile, fs/writeFile, fs/createDirectory, fs/getMetadata, fs/readDirectory, fs/remove, fs/copy, fs/watch, fs/unwatchfs/changed (thông báo) - thao tác trên các đường dẫn hệ thống tệp tuyệt đối thông qua API hệ thống tệp v2 của app-server.

Bản tóm tắt plugin bao gồm một union source. Plugin cục bộ trả về { "type": "local", "path": ... }, các mục marketplace dựa trên Git trả về { "type": "git", "url": ..., "path": ..., "refName": ..., "sha": ... }, các mục trong kho đăng ký gói trả về { "type": "npm", "package": ..., "version": ..., "registry": ... }, và các mục danh mục từ xa trả về { "type": "remote" }. Đối với các mục danh mục chỉ có từ xa, PluginMarketplaceEntry.path có thể là null; hãy truyền remoteMarketplaceName thay vì marketplacePath khi đọc hoặc cài đặt các plugin đó.

Mô hình

Liệt kê mô hình (model/list)

Gọi model/list để khám phá các mô hình có sẵn và khả năng của chúng trước khi hiển thị bộ chọn mô hình hoặc tính cách.

{ "method": "model/list", "id": 6, "params": { "limit": 20, "includeHidden": false } }
{ "id": 6, "result": {
  "data": [{
    "id": "gpt-5.6-sol",
    "model": "gpt-5.6-sol",
    "displayName": "GPT-5.6-Sol",
    "hidden": false,
    "defaultReasoningEffort": "low",
    "supportedReasoningEfforts": [{
      "reasoningEffort": "low",
      "description": "Fast responses with lighter reasoning"
    }],
    "inputModalities": ["text", "image"],
    "supportsPersonality": true,
    "isDefault": true
  }],
  "nextCursor": null
} }

Mỗi mục mô hình có thể bao gồm:

  • supportedReasoningEfforts - các tùy chọn mức độ nỗ lực mà mô hình hỗ trợ.
  • defaultReasoningEffort - mức độ nỗ lực mặc định được đề xuất cho ứng dụng khách.
  • upgrade - id mô hình nâng cấp được đề xuất tùy chọn cho lời nhắc di chuyển trong ứng dụng khách.
  • upgradeInfo - siêu dữ liệu nâng cấp tùy chọn cho lời nhắc di chuyển trong ứng dụng khách.
  • hidden - mô hình có bị ẩn khỏi danh sách bộ chọn mặc định hay không.
  • inputModalities - các loại đầu vào mà mô hình hỗ trợ (ví dụ: text, image).
  • supportsPersonality - mô hình có hỗ trợ hướng dẫn dành riêng cho tính cách như /personality hay không.
  • isDefault - mô hình có phải là lựa chọn mặc định được đề xuất hay không.

Theo mặc định, model/list chỉ trả về các mô hình hiển thị trong bộ chọn. Đặt includeHidden: true nếu bạn cần danh sách đầy đủ và muốn lọc ở phía ứng dụng khách bằng hidden.

Khi thiếu inputModalities (danh mục mô hình cũ), hãy coi giá trị đó là ["text", "image"] để tương thích ngược.

Liệt kê tính năng thử nghiệm (experimentalFeature/list)

Sử dụng điểm cuối này để khám phá các cờ tính năng cùng siêu dữ liệu và giai đoạn vòng đời:

{ "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 có thể là beta, underDevelopment, stable, deprecated hoặc removed. Đối với cờ không phải beta, displayName, descriptionannouncement có thể là null.

Kiểm tra môi trường thực thi (thử nghiệm)

Sử dụng environment/info để kiểm tra một môi trường từ xa đã cấu hình trước khi bắt đầu làm việc tại đó. Phương thức này yêu cầu 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 có thể là null. Khi có, đây là URI file: chuẩn hóa sử dụng cú pháp đường dẫn gốc của môi trường. ID môi trường không xác định và lỗi kết nối hoặc giao thức sẽ trả về lỗi yêu cầu.

Luồng

  • thread/read đọc một luồng đã lưu mà không đăng ký theo dõi; đặt includeTurns để bao gồm các lượt.
  • thread/turns/list đang ở trạng thái thử nghiệm và phân trang qua lịch sử lượt của một luồng đã lưu mà không tiếp tục luồng. Sử dụng itemsView để chọn bỏ qua, tóm tắt hoặc tải đầy đủ các mục của lượt.
  • thread/items/list đang ở trạng thái thử nghiệm và phân trang qua các mục luồng được lưu bền vững, có thể giới hạn ở một lượt.
  • thread/list hỗ trợ phân trang bằng con trỏ cùng modelProviders, sourceKinds, archived, isPinned, cwd, useStateDbOnly, searchTerm và bộ lọc thử nghiệm parentThreadId hoặc ancestorThreadId.
  • thread/loaded/list trả về ID của các luồng hiện có trong bộ nhớ.
  • thread/archive di chuyển nhật ký JSONL được lưu bền vững của luồng vào thư mục lưu trữ và cố gắng lưu trữ nhật ký của các luồng hậu duệ được tạo ra mà chưa được lưu trữ.
  • thread/delete xóa vĩnh viễn một luồng đang hoạt động hoặc đã lưu trữ được lưu bền vững và các luồng hậu duệ được tạo ra của nó.
  • thread/metadata/update vá siêu dữ liệu luồng đã lưu, bao gồm gitInfoisPinned được lưu bền vững.
  • thread/unsubscribe hủy đăng ký kết nối hiện tại khỏi một luồng đã tải và có thể kích hoạt thread/closed sau khoảng thời gian gia hạn không hoạt động.
  • thread/unarchive khôi phục rollout của một luồng đã lưu trữ về thư mục phiên đang hoạt động.
  • thread/compact/start kích hoạt thu gọn và trả về {} ngay lập tức.
  • thread/rollback không còn được khuyến nghị. Phương thức này loại bỏ N lượt cuối khỏi ngữ cảnh trong bộ nhớ và ghi lại một dấu mốc hoàn tác trong nhật ký JSONL được lưu bền vững của luồng.
  • thread/inject_items nối thêm các mục Responses API thô vào lịch sử hiển thị cho mô hình của một luồng đã tải mà không bắt đầu lượt người dùng.

Bắt đầu hoặc tiếp tục một luồng

Bắt đầu một luồng mới khi bạn cần một cuộc hội thoại Codex mới.

{ "method": "thread/start", "id": 10, "params": {
  "model": "gpt-5.6-terra",
  "cwd": "/Users/me/project",
  "approvalPolicy": "never",
  "sandbox": "workspaceWrite",
  "personality": "friendly",
  "serviceName": "my_app_server_client"
} }
{ "id": 10, "result": {
  "thread": {
    "id": "thr_123",
    "sessionId": "thr_123",
    "preview": "",
    "ephemeral": false,
    "modelProvider": "openai",
    "createdAt": 1730910000
  }
} }
{ "method": "thread/started", "params": { "thread": { "id": "thr_123" } } }

serviceName là tùy chọn. Hãy đặt giá trị này khi bạn muốn app-server gắn thẻ các chỉ số ở cấp luồng bằng tên dịch vụ của tích hợp.

thread/start, thread/resumethread/fork trả về instructionSources, một mảng đường dẫn tệp hướng dẫn đã tải. Mỗi đường dẫn sử dụng cú pháp tuyệt đối gốc của môi trường nguồn, kể cả đối với môi trường từ xa.

Ứng dụng khách thử nghiệm có thể đặt historyMode trên thread/start thành "legacy" (mặc định) hoặc "paginated". Việc tạo luồng có phân trang chưa được hỗ trợ và trả về lỗi JSON-RPC -32601. App-server có thể liệt kê và đọc bản tóm tắt của các bản ghi phân trang hiện có, nhưng việc đọc toàn bộ lịch sử, phân trang lượt và tiếp tục luồng sẽ đóng an toàn cho đến khi lịch sử phân trang được hỗ trợ.

Ứng dụng khách beta chọn tham gia capabilities.experimentalApi có thể truyền id hồ sơ quyền có tên trong permissions thay cho trường sandbox cũ. Không gửi permissionssandbox cùng nhau. Sử dụng permissionProfile/list cùng cwd của dự án để khám phá các hồ sơ có sẵn và liệu các yêu cầu được quản lý có cho phép từng hồ sơ hay không.

thread.sessionId nhận diện thư mục gốc của cây phiên đang hoạt động. Các luồng gốc sử dụng id luồng của chính chúng làm id phiên; các luồng phân nhánh giữ nguyên id phiên của luồng gốc mà chúng xuất phát. Ứng dụng khách nên đọc id phiên từ thread.sessionId thay vì suy ra từ id luồng.

Để tiếp tục một phiên đã lưu, hãy gọi thread/resume với thread.id mà bạn đã ghi lại trước đó. Cấu trúc phản hồi khớp với thread/start. Bạn cũng có thể truyền cùng các ghi đè cấu hình mà thread/start hỗ trợ, chẳng hạn như personality:

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

Việc tiếp tục một luồng tự nó không cập nhật thread.updatedAt (hoặc thời gian sửa đổi của tệp rollout). Dấu thời gian được cập nhật khi bạn bắt đầu một lượt.

Nếu bạn đánh dấu một máy chủ MCP đã bật là required trong cấu hình và máy chủ đó không khởi tạo được, thread/startthread/resume sẽ thất bại thay vì tiếp tục mà không có máy chủ đó.

dynamicTools trên thread/start là một trường thử nghiệm (yêu cầu capabilities.experimentalApi = true). Codex lưu bền vững các công cụ động này trong siêu dữ liệu rollout của luồng và khôi phục chúng trên thread/resume khi bạn không cung cấp công cụ động mới.

Nếu bạn tiếp tục bằng một mô hình khác với mô hình được ghi trong rollout, Codex sẽ phát cảnh báo và áp dụng hướng dẫn chuyển đổi mô hình một lần ở lượt tiếp theo.

Quản lý mục tiêu của luồng

Sử dụng thread/goal/set, thread/goal/getthread/goal/clear để quản lý cùng trạng thái mục tiêu được lưu bền vững mà /goal hiển thị trong TUI.

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

Mục tiêu phải có nội dung và dài tối đa 4.000 ký tự. Việc cung cấp một mục tiêu mới sẽ thay thế mục tiêu hiện tại và đặt lại số liệu sử dụng. Việc cung cấp mục tiêu hiện tại chưa ở trạng thái kết thúc, hoặc bỏ qua objective, sẽ cập nhật trạng thái hoặc ngân sách token trong khi vẫn giữ lịch sử sử dụng.

Để phân nhánh từ một phiên đã lưu, hãy gọi thread/fork với thread.id. Thao tác này tạo một id luồng mới và phát thông báo thread/started cho luồng đó. Truyền lastTurnId để sao chép lịch sử đến hết lượt đó và bỏ qua các lượt sau:

{ "method": "thread/fork", "id": 12, "params": { "threadId": "thr_123", "lastTurnId": "turn_456" } }
{ "id": 12, "result": { "thread": { "id": "thr_456", "sessionId": "thr_123", "forkedFromId": "thr_123" } } }
{ "method": "thread/started", "params": { "thread": { "id": "thr_456" } } }

App-server từ chối một lastTurnId đang xử lý. Nếu bạn bỏ qua trường này khi luồng nguồn đang ở giữa một lượt, nhánh sẽ ghi lại dấu mốc gián đoạn thay vì giữ lại một lượt chưa hoàn chỉnh mà không được đánh dấu.

Truyền ephemeral: true để tạo một nhánh trong bộ nhớ mà không thêm vào danh sách luồng đã lưu:

{
  "method": "thread/fork",
  "id": 13,
  "params": {
    "threadId": "thr_123",
    "ephemeral": true
  }
}
{
  "id": 13,
  "result": {
    "thread": {
      "id": "thr_789",
      "sessionId": "thr_789",
      "forkedFromId": "thr_123",
      "ephemeral": true
    }
  }
}

Các nhánh tạm thời của luồng phân trang cũng yêu cầu excludeTurns: true. Trường này đang ở trạng thái thử nghiệm và yêu cầu capabilities.experimentalApi = true.

Khi đã đặt tiêu đề luồng hiển thị cho người dùng, app-server điền thread.name vào các phản hồi thread/list, thread/read, thread/resume, thread/unarchivethread/rollback. thread/startthread/fork có thể bỏ qua name (hoặc trả về null) cho đến khi tiêu đề được đặt sau đó.

Đọc một luồng đã lưu (không tiếp tục)

Sử dụng thread/read khi bạn muốn lấy dữ liệu luồng đã lưu nhưng không muốn tiếp tục luồng hoặc đăng ký nhận sự kiện của luồng.

  • includeTurns - khi là true, phản hồi bao gồm các lượt của luồng; khi là false hoặc bị bỏ qua, bạn chỉ nhận được bản tóm tắt luồng.
  • Các đối tượng thread được trả về bao gồm status thời gian chạy (notLoaded, idle, systemError hoặc active cùng activeFlags).
{ "method": "thread/read", "id": 19, "params": { "threadId": "thr_123", "includeTurns": true } }
{ "id": 19, "result": { "thread": { "id": "thr_123", "name": "Bug bash notes", "ephemeral": false, "status": { "type": "notLoaded" }, "turns": [] } } }

Không giống thread/resume, thread/read không tải luồng vào bộ nhớ hoặc phát thread/started.

Liệt kê các lượt của luồng

thread/turns/list đang ở trạng thái thử nghiệm. Sử dụng phương thức này để phân trang qua lịch sử lượt của một luồng đã lưu mà không tiếp tục luồng. Theo mặc định, kết quả được sắp xếp từ mới nhất đến cũ nhất để ứng dụng khách có thể tìm nạp các lượt cũ hơn bằng nextCursor. Phản hồi cũng bao gồm backwardsCursor; hãy truyền giá trị này dưới dạng cursor cùng sortDirection: "asc" để tìm nạp các lượt mới hơn mục đầu tiên của trang trước đó.

itemsView kiểm soát lượng dữ liệu mục của lượt được đưa vào phản hồi:

  • notLoaded bỏ qua các mục.
  • summary trả về dữ liệu mục đã tóm tắt và là giá trị mặc định khi bị bỏ qua.
  • full trả về toàn bộ dữ liệu mục.
{ "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 cũng đang ở trạng thái thử nghiệm. Phương thức này phân trang qua các mục được lưu bền vững mà không tiếp tục luồng. Truyền turnId để giới hạn kết quả ở một lượt, hoặc bỏ qua trường này để phân trang qua các mục trên toàn luồng. Kho lưu trữ luồng đang hoạt động phải hỗ trợ phân trang mục; nếu không, máy chủ sẽ trả về lỗi phương thức không được hỗ trợ.

Liệt kê luồng (có phân trang và bộ lọc)

thread/list cho phép bạn hiển thị giao diện lịch sử. Theo mặc định, kết quả được sắp xếp từ mới nhất đến cũ nhất theo createdAt. Bộ lọc được áp dụng trước khi phân trang. Truyền bất kỳ tổ hợp nào sau đây:

  • cursor - chuỗi không trong suốt từ phản hồi trước; bỏ qua cho trang đầu tiên.
  • limit - máy chủ sử dụng kích thước trang hợp lý theo mặc định nếu chưa đặt.
  • sortKey - created_at (mặc định), updated_at hoặc recency_at.
  • sortDirection - desc (mặc định) hoặc asc.
  • modelProviders - giới hạn kết quả ở các nhà cung cấp cụ thể; khi chưa đặt, là null hoặc là mảng rỗng thì bao gồm tất cả nhà cung cấp.
  • sourceKinds - giới hạn kết quả ở các nguồn luồng cụ thể. Khi bị bỏ qua hoặc là [], máy chủ mặc định chỉ dùng các nguồn tương tác: clivscode.
  • archived - khi là true, chỉ liệt kê các luồng đã lưu trữ. Khi là false hoặc bị bỏ qua, liệt kê các luồng chưa lưu trữ (mặc định).
  • isPinned - khi được cung cấp, chỉ trả về các luồng có trạng thái ghim được lưu bền vững tương ứng. Bỏ qua để trả về cả luồng đã ghim và chưa ghim.
  • cwd - giới hạn kết quả ở các luồng có thư mục làm việc hiện tại của phiên khớp chính xác với đường dẫn này hoặc một trong các đường dẫn trong mảng. Đường dẫn tương đối được phân giải từ thư mục làm việc của tiến trình app-server.
  • useStateDbOnly - khi là true, trả về kết quả cơ sở dữ liệu trạng thái mà không quét nhật ký luồng JSONL để sửa chữa siêu dữ liệu. Bỏ qua hoặc truyền false để sử dụng hành vi quét và sửa chữa mặc định.
  • searchTerm - giới hạn kết quả ở các luồng có tiêu đề được trích xuất chứa đoạn văn bản phân biệt chữ hoa chữ thường này.
  • parentThreadId - giới hạn kết quả ở các luồng con trực tiếp của luồng cha được cung cấp. Bộ lọc này đang ở trạng thái thử nghiệm và yêu cầu capabilities.experimentalApi = true.
  • ancestorThreadId - giới hạn kết quả ở các hậu duệ được tạo ra của luồng đã cho ở bất kỳ độ sâu nào. Bộ lọc này đang ở trạng thái thử nghiệm và yêu cầu capabilities.experimentalApi = true; không kết hợp với parentThreadId.

sourceKinds chấp nhận các giá trị sau:

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

Ví dụ:

{ "method": "thread/list", "id": 20, "params": {
  "cursor": null,
  "limit": 25,
  "sortKey": "created_at"
} }
{ "id": 20, "result": {
  "data": [
    { "id": "thr_a", "preview": "Create a TUI", "ephemeral": false, "isPinned": true, "modelProvider": "openai", "createdAt": 1730831111, "updatedAt": 1730831111, "name": "TUI prototype", "status": { "type": "notLoaded" } },
    { "id": "thr_b", "preview": "Fix tests", "ephemeral": false, "isPinned": false, "modelProvider": "openai", "createdAt": 1730750000, "updatedAt": 1730750000, "status": { "type": "notLoaded" } }
  ],
  "nextCursor": "opaque-token-or-null"
} }

Khi nextCursornull, bạn đã đến trang cuối cùng.

Cập nhật siêu dữ liệu luồng đã lưu

Sử dụng thread/metadata/update để vá siêu dữ liệu luồng đã lưu mà không tiếp tục luồng. Đặt isPinned để ghim hoặc bỏ ghim luồng, hoặc cập nhật gitInfo để thay đổi siêu dữ liệu Git được lưu bền vững. Các trường bị bỏ qua không thay đổi; null rõ ràng sẽ xóa một giá trị siêu dữ liệu Git đã lưu.

{ "method": "thread/metadata/update", "id": 21, "params": {
  "threadId": "thr_123",
  "isPinned": true,
  "gitInfo": { "branch": "feature/sidebar-pr" }
} }
{ "id": 21, "result": {
  "thread": {
    "id": "thr_123",
    "isPinned": true,
    "gitInfo": { "sha": null, "branch": "feature/sidebar-pr", "originUrl": null }
  }
} }

Theo dõi thay đổi trạng thái luồng

thread/status/changed được phát mỗi khi trạng thái thời gian chạy của một luồng đã tải thay đổi. Payload bao gồm threadIdstatus mới.

{
  "method": "thread/status/changed",
  "params": {
    "threadId": "thr_123",
    "status": { "type": "active", "activeFlags": ["waitingOnApproval"] }
  }
}

Liệt kê các luồng đã tải

thread/loaded/list trả về ID của các luồng hiện được tải trong bộ nhớ.

{ "method": "thread/loaded/list", "id": 21 }
{ "id": 21, "result": { "data": ["thr_123", "thr_456"] } }

Hủy đăng ký khỏi một luồng đã tải

thread/unsubscribe xóa đăng ký của kết nối hiện tại khỏi một luồng. Trạng thái phản hồi là một trong các giá trị sau:

  • unsubscribed khi kết nối đã đăng ký và hiện được xóa.
  • notSubscribed khi kết nối chưa đăng ký luồng đó.
  • notLoaded khi luồng chưa được tải.

Nếu đây là người đăng ký cuối cùng, máy chủ sẽ giữ luồng ở trạng thái đã tải cho đến khi luồng không còn người đăng ký và không có hoạt động trong 30 phút. Khi thời gian gia hạn hết hạn, app-server dỡ luồng và phát một chuyển đổi thread/status/changed sang notLoaded cùng thread/closed.

{ "method": "thread/unsubscribe", "id": 22, "params": { "threadId": "thr_123" } }
{ "id": 22, "result": { "status": "unsubscribed" } }

Nếu luồng hết hạn sau đó:

{ "method": "thread/status/changed", "params": {
    "threadId": "thr_123",
    "status": { "type": "notLoaded" }
} }
{ "method": "thread/closed", "params": { "threadId": "thr_123" } }

Lưu trữ một luồng

Sử dụng thread/archive để di chuyển nhật ký luồng được lưu bền vững (được lưu dưới dạng tệp JSONL trên đĩa) vào thư mục phiên đã lưu trữ. Việc lưu trữ một luồng cũng cố gắng lưu trữ các luồng hậu duệ được tạo ra mà chưa được lưu trữ.

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

Các luồng đã lưu trữ sẽ không xuất hiện trong những lần gọi thread/list sau này, trừ khi bạn truyền archived: true. Máy chủ phát một thông báo thread/archived cho mỗi luồng mà nó thực sự lưu trữ; nếu không thể lưu trữ một luồng con được tạo, yêu cầu vẫn có thể thành công mà không có thông báo đã lưu trữ cho luồng con đó.

Xóa một luồng

Sử dụng thread/delete để xóa vĩnh viễn một luồng đang hoạt động hoặc đã lưu trữ cùng các luồng con được tạo từ luồng đó. Máy chủ xóa các tệp rollout hiện có và siêu dữ liệu liên quan trước khi trả về thành công; các tệp rollout bị thiếu được xem là đã bị xóa. Không thể xóa các luồng gốc tạm thời.

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

Hủy lưu trữ một luồng

Sử dụng thread/unarchive để chuyển rollout của một luồng đã lưu trữ trở lại thư mục phiên đang hoạt động.

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

Kích hoạt việc thu gọn luồng

Sử dụng thread/compact/start để kích hoạt thủ công việc thu gọn lịch sử của một luồng. Yêu cầu trả về ngay lập tức với {}.

App-server phát tiến trình dưới dạng các thông báo turn/*item/* tiêu chuẩn trên cùng threadId, bao gồm vòng đời của một mục contextCompaction (item/started rồi đến item/completed).

{ "method": "thread/compact/start", "id": 25, "params": { "threadId": "thr_b" } }
{ "id": 25, "result": {} }

Chạy lệnh shell trong một luồng

Sử dụng thread/shellCommand cho các lệnh shell do người dùng khởi tạo và thuộc về một luồng. Yêu cầu trả về ngay lập tức với {}, trong khi tiến trình được truyền trực tuyến qua các thông báo turn/*item/* tiêu chuẩn.

API này chạy bên ngoài sandbox với toàn quyền truy cập và không kế thừa chính sách sandbox của luồng. Client chỉ nên cung cấp API này cho các lệnh do người dùng khởi tạo một cách rõ ràng.

Nếu luồng đã có một lượt đang hoạt động, lệnh sẽ chạy như một hành động phụ trợ trong lượt đó và đầu ra đã định dạng của lệnh được chèn vào luồng thông báo của lượt. Nếu luồng đang rảnh, app-server sẽ bắt đầu một lượt độc lập cho lệnh shell.

{ "method": "thread/shellCommand", "id": 26, "params": { "threadId": "thr_b", "command": "git status --short" } }
{ "id": 26, "result": {} }

Dọn dẹp terminal chạy nền

Sử dụng thread/backgroundTerminals/clean để dừng tất cả terminal chạy nền đang hoạt động được liên kết với một luồng. Phương thức này đang trong giai đoạn thử nghiệm và yêu cầu capabilities.experimentalApi = true.

{ "method": "thread/backgroundTerminals/clean", "id": 27, "params": { "threadId": "thr_b" } }
{ "id": 27, "result": {} }

Sử dụng thread/backgroundTerminals/list để kiểm tra các terminal chạy nền đang hoạt động của một luồng đã tải. Yêu cầu hỗ trợ phân trang tiêu chuẩn bằng cursorlimit, còn processId được trả về là id tiến trình của app-server. Phương thức này đang trong giai đoạn thử nghiệm và yêu cầu 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 } }

Sử dụng thread/backgroundTerminals/terminate cùng với processId đó để dừng một terminal chạy nền. Phương thức này đang trong giai đoạn thử nghiệm và yêu cầu capabilities.experimentalApi = true:

{ "method": "thread/backgroundTerminals/terminate", "id": 29, "params": { "threadId": "thr_b", "processId": "42" } }
{ "id": 29, "result": { "terminated": true } }

Hoàn tác các lượt gần đây

thread/rollback đã ngừng được khuyến nghị và sẽ bị loại bỏ. Phương thức này xóa numTurns mục cuối cùng khỏi ngữ cảnh trong bộ nhớ và lưu một dấu mốc hoàn tác vào nhật ký rollout. thread được trả về bao gồm turns đã được điền sau khi hoàn tác.

{ "method": "thread/rollback", "id": 30, "params": { "threadId": "thr_b", "numTurns": 1 } }
{ "id": 30, "result": { "thread": { "id": "thr_b", "name": "Bug bash notes", "ephemeral": false } } }

Lượt

Trường input chấp nhận một danh sách các mục:

  • { "type": "text", "text": "Explain this diff" }
  • { "type": "image", "url": "https://.../design.png" }
  • { "type": "localImage", "path": "/tmp/screenshot.png" }

Bạn có thể ghi đè cài đặt cấu hình theo từng lượt (model, mức độ nỗ lực, tính cách, cwd, chính sách sandbox, bản tóm tắt). Khi được chỉ định, các cài đặt này trở thành giá trị mặc định cho các lượt tiếp theo trong cùng luồng. outputSchema chỉ áp dụng cho lượt hiện tại. Đối với sandboxPolicy.type = "externalSandbox", hãy đặt networkAccess thành restricted hoặc enabled; đối với workspaceWrite, networkAccess vẫn là một giá trị boolean.

Đối với turn/start.collaborationMode, settings.developer_instructions: null có nghĩa là "sử dụng hướng dẫn tích hợp sẵn cho chế độ đã chọn", thay vì xóa hướng dẫn của chế độ.

Quyền đọc trong sandbox (ReadOnlyAccess)

sandboxPolicy hỗ trợ các cơ chế kiểm soát quyền đọc tường minh:

  • readOnly: access tùy chọn (mặc định là { "type": "fullAccess" } hoặc các thư mục gốc bị hạn chế).
  • workspaceWrite: readOnlyAccess tùy chọn (mặc định là { "type": "fullAccess" } hoặc các thư mục gốc bị hạn chế).

Cấu trúc quyền đọc bị hạn chế:

{
  "type": "restricted",
  "includePlatformDefaults": true,
  "readableRoots": ["/Users/me/shared-read-only"]
}

Trên macOS, includePlatformDefaults: true nối thêm một chính sách Seatbelt mặc định của nền tảng đã được tuyển chọn cho các phiên có quyền đọc bị hạn chế. Điều này cải thiện khả năng tương thích của công cụ mà không cho phép rộng rãi toàn bộ /System.

Ví dụ:

{ "type": "readOnly", "access": { "type": "fullAccess" } }
{
  "type": "workspaceWrite",
  "writableRoots": ["/Users/me/project"],
  "readOnlyAccess": {
    "type": "restricted",
    "includePlatformDefaults": true,
    "readableRoots": ["/Users/me/shared-read-only"]
  },
  "networkAccess": false
}

Bắt đầu một lượt

{ "method": "turn/start", "id": 30, "params": {
  "threadId": "thr_123",
  "input": [ { "type": "text", "text": "Run tests" } ],
  "cwd": "/Users/me/project",
  "approvalPolicy": "unlessTrusted",
  "sandboxPolicy": {
    "type": "workspaceWrite",
    "writableRoots": ["/Users/me/project"],
    "networkAccess": true
  },
  "model": "gpt-5.6-terra",
  "effort": "medium",
  "summary": "concise",
  "personality": "friendly",
  "outputSchema": {
    "type": "object",
    "properties": { "answer": { "type": "string" } },
    "required": ["answer"],
    "additionalProperties": false
  }
} }
{ "id": 30, "result": { "turn": { "id": "turn_456", "status": "inProgress", "items": [], "error": null } } }

Chèn các mục vào một luồng

Sử dụng thread/inject_items để nối các mục Responses API được dựng sẵn vào lịch sử lời nhắc của một luồng đã tải mà không bắt đầu lượt người dùng. Các mục này được lưu vào rollout và được đưa vào những yêu cầu model tiếp theo.

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

Điều hướng một lượt đang hoạt động

Sử dụng turn/steer để nối thêm đầu vào của người dùng vào lượt đang diễn ra.

  • Bao gồm expectedTurnId; giá trị này phải khớp với id của lượt đang hoạt động.
  • Yêu cầu sẽ thất bại nếu luồng không có lượt đang hoạt động.
  • turn/steer không phát thông báo turn/started mới.
  • turn/steer không chấp nhận các giá trị ghi đè ở cấp lượt (model, cwd, sandboxPolicy hoặc 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" } }

Bắt đầu một lượt (gọi một skill)

Gọi một skill một cách tường minh bằng cách đưa $<skill-name> vào đầu vào văn bản và thêm một mục đầu vào skill bên cạnh.

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

Ngắt một lượt

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

Khi thành công, lượt kết thúc với status: "interrupted".

Đánh giá

review/start chạy trình đánh giá Codex cho một luồng và truyền trực tuyến các mục đánh giá. Các mục tiêu bao gồm:

  • uncommittedChanges
  • baseBranch (diff so với một nhánh)
  • commit (đánh giá một commit cụ thể)
  • custom (hướng dẫn dạng tự do)

Sử dụng delivery: "inline" (mặc định) để chạy đánh giá trên luồng hiện có hoặc delivery: "detached" để phân nhánh thành một luồng đánh giá mới.

Ví dụ về yêu cầu/phản hồi:

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

Đối với một đánh giá tách rời, hãy sử dụng "delivery": "detached". Phản hồi có cùng cấu trúc, nhưng reviewThreadId sẽ là id của luồng đánh giá mới (khác với threadId ban đầu). Máy chủ cũng phát một thông báo thread/started cho luồng mới đó trước khi truyền trực tuyến lượt đánh giá.

Codex truyền trực tuyến thông báo turn/started thông thường, sau đó là một item/started chứa mục enteredReviewMode:

{
  "method": "item/started",
  "params": {
    "item": {
      "type": "enteredReviewMode",
      "id": "turn_900",
      "review": "current changes"
    }
  }
}

Khi trình đánh giá hoàn tất, máy chủ phát item/starteditem/completed chứa một mục exitedReviewMode với nội dung đánh giá cuối cùng:

{
  "method": "item/completed",
  "params": {
    "item": {
      "type": "exitedReviewMode",
      "id": "turn_900",
      "review": "Looks solid overall..."
    }
  }
}

Sử dụng thông báo này để hiển thị đầu ra của trình đánh giá trong client của bạn.

Thực thi tiến trình

process/* là một API điều khiển tiến trình tường minh đang trong giai đoạn thử nghiệm. API này yêu cầu capabilities.experimentalApi = true và chạy bên ngoài sandbox của Codex. Chỉ sử dụng API này khi client của bạn chủ động cung cấp khả năng điều khiển tiến trình cục bộ mà không có sandbox.

Khởi động một tiến trình bằng process/spawn và cung cấp một processHandle, sau đó sử dụng handle đó cho các yêu cầu stdin, thay đổi kích thước và kết thúc. Đầu ra được truyền trực tuyến qua các thông báo process/outputDelta và trạng thái hoàn tất được truyền trực tuyến qua 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
} }

Sử dụng process/writeStdin với deltaBase64, closeStdin hoặc cả hai để gửi đầu vào. Sử dụng process/resizePty cho các sự kiện thay đổi kích thước PTY và process/kill để kết thúc một tiến trình đang chạy.

Thực thi lệnh

command/exec chạy một lệnh duy nhất (mảng argv) trong sandbox của máy chủ mà không tạo luồng.

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

Sử dụng sandboxPolicy.type = "externalSandbox" nếu bạn đã đặt tiến trình máy chủ trong sandbox và muốn Codex bỏ qua việc thực thi sandbox riêng. Đối với chế độ sandbox bên ngoài, đặt networkAccess thành restricted (mặc định) hoặc enabled. Với readOnlyworkspaceWrite, hãy sử dụng cùng cấu trúc access / readOnlyAccess tùy chọn như ở trên.

Lưu ý:

  • Máy chủ từ chối các mảng command rỗng.
  • sandboxPolicy chấp nhận cùng cấu trúc được turn/start sử dụng (ví dụ: dangerFullAccess, readOnly, workspaceWrite, externalSandbox).
  • Khi bị lược bỏ, timeoutMs quay về giá trị mặc định của máy chủ.
  • Đặt tty: true cho các phiên dựa trên PTY và sử dụng processId khi bạn định tiếp tục với command/exec/write, command/exec/resize hoặc command/exec/terminate.
  • Đặt streamStdoutStderr: true để nhận thông báo command/exec/outputDelta trong khi lệnh đang chạy.

Đọc các yêu cầu quản trị (configRequirements/read)

Sử dụng configRequirements/read để kiểm tra các yêu cầu quản trị có hiệu lực được tải từ requirements.toml và/hoặc MDM.

{ "method": "configRequirements/read", "id": 52, "params": {} }
{ "id": 52, "result": {
  "requirements": {
    "allowedApprovalPolicies": ["onRequest", "unlessTrusted"],
    "allowedSandboxModes": ["readOnly", "workspaceWrite"],
    "featureRequirements": {
      "personality": true,
      "unified_exec": false
    },
    "network": {
      "enabled": true,
      "allowedDomains": ["api.openai.com"],
      "allowUnixSockets": ["/tmp/example.sock"],
      "dangerouslyAllowAllUnixSockets": false
    }
  }
} }

result.requirementsnull khi không có yêu cầu nào được cấu hình. Xem tài liệu về requirements.toml để biết chi tiết về các khóa và giá trị được hỗ trợ.

Thiết lập sandbox Windows (windowsSandbox/setupStart)

Các client Windows tùy chỉnh có thể kích hoạt việc thiết lập sandbox theo cách bất đồng bộ thay vì chặn khi kiểm tra lúc khởi động.

{ "method": "windowsSandbox/setupStart", "id": 53, "params": { "mode": "elevated" } }
{ "id": 53, "result": { "started": true } }

App-server bắt đầu thiết lập trong nền và sau đó phát một thông báo hoàn tất:

{
  "method": "windowsSandbox/setupCompleted",
  "params": { "mode": "elevated", "success": true, "error": null }
}

Các chế độ:

  • elevated - chạy quy trình thiết lập sandbox Windows với quyền nâng cao.
  • unelevated - chạy quy trình thiết lập/kiểm tra trước kiểu cũ.

Hệ thống tệp

Các API hệ thống tệp v2 hoạt động trên đường dẫn tuyệt đối. Sử dụng fs/watch khi client cần vô hiệu hóa trạng thái UI sau khi một tệp hoặc thư mục thay đổi.

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

Theo dõi một tệp sẽ phát fs/changed cho đường dẫn tệp đó, bao gồm cả các cập nhật được chuyển đến thông qua thao tác thay thế hoặc đổi tên.

Sự kiện

Thông báo sự kiện là luồng do máy chủ khởi tạo cho vòng đời luồng, vòng đời lượt và các mục bên trong. Sau khi bắt đầu hoặc tiếp tục một luồng, hãy tiếp tục đọc luồng truyền tải đang hoạt động để nhận các thông báo thread/started, thread/archived, thread/unarchived, thread/closed, thread/status/changed, turn/*, item/*serverRequest/resolved.

Không nhận thông báo

Client có thể chặn các thông báo cụ thể theo từng kết nối bằng cách gửi tên phương thức chính xác trong initialize.params.capabilities.optOutNotificationMethods.

  • Chỉ khớp chính xác: item/agentMessage/delta chỉ chặn phương thức đó.
  • Tên phương thức không xác định sẽ bị bỏ qua.
  • Áp dụng cho thread/*, turn/*, item/* hiện tại và các thông báo v2 liên quan.
  • Không áp dụng cho yêu cầu, phản hồi hoặc lỗi.

Sự kiện tìm kiếm tệp gần đúng (thử nghiệm)

API phiên tìm kiếm tệp gần đúng phát thông báo theo từng truy vấn:

  • fuzzyFileSearch/sessionUpdated - { sessionId, query, files } với các kết quả khớp hiện tại cho truy vấn đang hoạt động.
  • fuzzyFileSearch/sessionCompleted - { sessionId } sau khi hoàn tất lập chỉ mục và đối sánh cho truy vấn đó.

Sự kiện cảnh báo

  • configWarning - { summary, details?, path?, range? } cho các vấn đề về cấu hình hoặc khởi tạo có thể khôi phục.
  • warning - { threadId?, message } cho các cảnh báo thời gian chạy không nghiêm trọng.

Sự kiện thiết lập sandbox Windows

  • windowsSandbox/setupCompleted - { mode, success, error } được phát sau khi một yêu cầu windowsSandbox/setupStart hoàn tất.

Sự kiện lượt

  • turn/started - { turn } với id lượt, items rỗng và status: "inProgress".
  • turn/completed - { turn }, trong đó turn.statuscompleted, interrupted hoặc failed; trường hợp thất bại chứa { error: { message, codexErrorInfo?, additionalDetails? } }.
  • turn/diff/updated - { threadId, turnId, diff } với unified diff tổng hợp mới nhất trên mọi thay đổi tệp trong lượt.
  • turn/plan/updated - { turnId, explanation?, plan } bất cứ khi nào tác nhân chia sẻ hoặc thay đổi kế hoạch; mỗi mục plan{ step, status } với status thuộc pending, inProgress hoặc completed.
  • hook/startedhook/completed - { threadId, turnId?, run } khi một hook vòng đời bắt đầu và khi bản tóm tắt lần chạy cuối cùng của hook có sẵn.
  • model/safetyBuffering/updated - { threadId, turnId, model, useCases, reasons, showBufferingUi, fasterModel } khi một phản hồi đi vào vùng đệm an toàn tạm thời.
  • model/rerouted - { threadId, turnId, fromModel, toModel, reason } khi dịch vụ định tuyến một yêu cầu sang model khác.
  • model/verification - { threadId, turnId, verifications } khi dịch vụ yêu cầu xác minh tài khoản bổ sung.
  • thread/tokenUsage/updated - thông tin cập nhật về mức sử dụng cho luồng đang hoạt động.

turn/diff/updatedturn/plan/updated hiện chứa các mảng items rỗng ngay cả khi các sự kiện mục được truyền trực tuyến. Hãy sử dụng thông báo item/* làm nguồn dữ liệu chuẩn cho các mục của lượt.

Mục

ThreadItem là tagged union được mang trong các phản hồi lượt và thông báo item/*. Các loại mục phổ biến bao gồm:

  • userMessage - {id, content}, trong đó content là danh sách đầu vào của người dùng (text, image hoặc localImage).
  • agentMessage - {id, text, phase?} chứa phản hồi tích lũy của tác nhân. Khi có, phase sử dụng các giá trị wire của Responses API (commentary, final_answer).
  • plan - {id, text} chứa nội dung kế hoạch được đề xuất trong chế độ kế hoạch. Hãy xem mục plan cuối cùng từ item/completed là dữ liệu chuẩn.
  • reasoning - {id, summary, content}, trong đó summary chứa các bản tóm tắt suy luận được truyền trực tuyến và content chứa các khối suy luận thô.
  • commandExecution - {id, command, cwd, status, commandActions, aggregatedOutput?, exitCode?, durationMs?}.
  • fileChange - {id, changes, status} mô tả các chỉnh sửa được đề xuất; danh sách changes chứa {path, kind, diff}.
  • mcpToolCall - {id, server, tool, status, arguments, appContext?, pluginId?, result?, error?}. Đối với các ứng dụng MCP đáng tin cậy, appContext có thể bao gồm connectorId, linkId, resourceUri, appName, templateId và connector ổn định actionName. Các mục cũ đã lưu có thể không chứa siêu dữ liệu mới hơn. Hãy sử dụng appContext.resourceUri thay cho mcpAppResourceUri cấp cao nhất đã ngừng được khuyến nghị.
  • dynamicToolCall - {id, tool, arguments, status, contentItems?, success?, durationMs?} cho các lệnh gọi công cụ động do client thực thi.
  • collabToolCall - {id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}.
  • webSearch - {id, query, action?} cho các yêu cầu tìm kiếm web do tác nhân gửi.
  • imageView - {id, path} được phát khi tác nhân gọi công cụ xem ảnh.
  • enteredReviewMode - {id, review} được gửi khi trình đánh giá bắt đầu.
  • exitedReviewMode - {id, review} được phát khi trình đánh giá hoàn tất.
  • contextCompaction - {id} được phát khi Codex thu gọn lịch sử hội thoại.

Đối với webSearch.action, hành động type có thể là search (query?, queries?), openPage (url?) hoặc findInPage (url?, pattern?).

App server ngừng khuyến nghị thông báo thread/compacted kiểu cũ; hãy sử dụng mục contextCompaction thay thế.

Tất cả các mục đều phát hai sự kiện vòng đời dùng chung:

  • item/started - phát toàn bộ item khi một đơn vị công việc mới bắt đầu; item.id khớp với itemId được các delta sử dụng.
  • item/completed - gửi item cuối cùng khi công việc hoàn tất; hãy xem đây là trạng thái chuẩn.

Delta của mục

  • item/agentMessage/delta - nối thêm văn bản được truyền trực tuyến cho thông báo của tác nhân.
  • item/plan/delta - truyền trực tuyến nội dung kế hoạch được đề xuất. Mục plan cuối cùng có thể không hoàn toàn bằng các delta được nối lại.
  • item/reasoning/summaryTextDelta - truyền trực tuyến các bản tóm tắt suy luận dễ đọc; summaryIndex tăng khi một phần tóm tắt mới mở ra.
  • item/reasoning/summaryPartAdded - đánh dấu ranh giới giữa các phần tóm tắt suy luận.
  • item/reasoning/textDelta - truyền trực tuyến văn bản suy luận thô (khi model hỗ trợ).
  • item/commandExecution/outputDelta - truyền trực tuyến stdout/stderr của một lệnh; nối các delta theo thứ tự.
  • item/fileChange/outputDelta - thông báo tương thích đã ngừng được khuyến nghị dành cho đầu ra văn bản apply_patch kiểu cũ. Các phiên bản app-server hiện tại không còn phát thông báo này; hãy sử dụng các mục fileChangeturn/diff/updated thay thế.

Lỗi

Nếu một lượt thất bại, máy chủ phát sự kiện error chứa { error: { message, codexErrorInfo?, additionalDetails? } }, sau đó kết thúc lượt với status: "failed". Khi có trạng thái HTTP từ upstream, trạng thái này xuất hiện trong codexErrorInfo.httpStatusCode.

Các giá trị codexErrorInfo phổ biến bao gồm:

  • ContextWindowExceeded
  • UsageLimitExceeded
  • HttpConnectionFailed (lỗi upstream 4xx/5xx)
  • ResponseStreamConnectionFailed
  • ResponseStreamDisconnected
  • ResponseTooManyFailedAttempts
  • BadRequest, Unauthorized, SandboxError, InternalServerError, Other

Khi có trạng thái HTTP từ upstream, máy chủ chuyển tiếp trạng thái đó trong httpStatusCode trên biến thể codexErrorInfo tương ứng.

Phê duyệt

Tùy thuộc vào cài đặt Codex của người dùng, việc thực thi lệnh và thay đổi tệp có thể cần được phê duyệt. App-server gửi một yêu cầu JSON-RPC do máy chủ khởi tạo đến client, và client phản hồi bằng payload quyết định.

  • Quyết định phê duyệt thực thi lệnh: accept, acceptForSession, decline, cancel hoặc { "acceptWithExecpolicyAmendment": { "execpolicy_amendment": ["cmd", "..."] } }.

  • Quyết định phê duyệt thay đổi tệp: accept, acceptForSession, decline, cancel.

  • Các yêu cầu bao gồm threadIdturnId - hãy sử dụng chúng để giới hạn trạng thái UI trong hội thoại đang hoạt động.

  • Máy chủ tiếp tục hoặc từ chối công việc và kết thúc mục với item/completed.

Phê duyệt thực thi lệnh

Thứ tự thông báo:

  1. item/started hiển thị mục commandExecution đang chờ với command, cwd và các trường khác.
  2. item/commandExecution/requestApproval bao gồm itemId, threadId, turnId, reason tùy chọn, command tùy chọn, cwd tùy chọn, commandActions tùy chọn, proposedExecpolicyAmendment tùy chọn, networkApprovalContext tùy chọn và availableDecisions tùy chọn. Khi initialize.params.capabilities.experimentalApi = true, payload cũng có thể bao gồm additionalPermissions thử nghiệm mô tả quyền truy cập sandbox được yêu cầu theo từng lệnh. Mọi đường dẫn hệ thống tệp bên trong additionalPermissions đều là đường dẫn tuyệt đối trên wire.
  3. Client phản hồi bằng một trong các quyết định phê duyệt thực thi lệnh ở trên.
  4. serverRequest/resolved xác nhận rằng yêu cầu đang chờ đã được trả lời hoặc xóa.
  5. item/completed trả về mục commandExecution cuối cùng với status: completed | failed | declined.

Khi có networkApprovalContext, lời nhắc dành cho quyền truy cập mạng được quản lý (không phải phê duyệt lệnh shell nói chung). Schema v2 hiện tại cung cấp đích hostprotocol; client nên hiển thị lời nhắc dành riêng cho mạng và không dựa vào việc command là bản xem trước lệnh shell có ý nghĩa với người dùng.

Codex nhóm các lời nhắc phê duyệt mạng đồng thời theo đích (host, giao thức và cổng). Vì vậy, app-server có thể gửi một lời nhắc để bỏ chặn nhiều yêu cầu đang xếp hàng đến cùng một đích, trong khi các cổng khác nhau trên cùng máy chủ được xử lý riêng.

Phê duyệt thay đổi tệp

Thứ tự thông báo:

  1. item/started phát một mục fileChange với changesstatus: "inProgress" được đề xuất.
  2. item/fileChange/requestApproval bao gồm itemId, threadId, turnId, reason tùy chọn và grantRoot tùy chọn.
  3. Client phản hồi bằng một trong các quyết định phê duyệt thay đổi tệp ở trên.
  4. serverRequest/resolved xác nhận rằng yêu cầu đang chờ đã được trả lời hoặc xóa.
  5. item/completed trả về mục fileChange cuối cùng với status: completed | failed | declined.

tool/requestUserInput

Khi client phản hồi item/tool/requestUserInput, app-server phát serverRequest/resolved với { threadId, requestId }. Nếu yêu cầu đang chờ bị xóa do lượt bắt đầu, hoàn tất hoặc bị ngắt trước khi client trả lời, máy chủ sẽ phát cùng thông báo đó cho thao tác dọn dẹp.

Các tham số yêu cầu bao gồm autoResolutionMs dưới dạng thời gian chờ tính bằng mili giây kiểu số nguyên hoặc null. Khi có, client máy chủ có thể tự động xử lý lời nhắc sau khoảng thời gian đó nếu người dùng không trả lời.

Yêu cầu cấp quyền

Công cụ request_permissions tích hợp sẵn gửi item/permissions/requestApproval với threadId, turnId, itemId, environmentId, cwd, reason tùy chọn và các quyền truy cập mạng hoặc hệ thống tệp được yêu cầu. Phản hồi bằng permissions chỉ chứa tập con đã được cấp. Đặt scope thành "session" để duy trì quyền cấp cho các lượt sau trong cùng phiên; lược bỏ hoặc sử dụng "turn" để chỉ cấp quyền trong một lượt. Các quyền không được yêu cầu sẽ bị bỏ qua.

Yêu cầu thu thập thông tin của máy chủ MCP

Một máy chủ MCP có thể ngắt một lượt bằng mcpServer/elicitation/request. Yêu cầu bao gồm threadId, một turnId tùy chọn, serverName và một trong các cấu trúc yêu cầu sau:

  • mode: "form" hoặc mode: "openai/form", với messagerequestedSchema.
  • mode: "url", với message, urlelicitationId.

Phản hồi bằng action: "accept"content được yêu cầu, hoặc bằng action: "decline" hay "cancel" cùng content: null. Sau đó, app-server phát serverRequest/resolved. Để nhận biến thể openai/form, hãy đăng ký bằng initialize.params.capabilities.mcpServerOpenaiFormElicitation.

Lệnh gọi công cụ động (thử nghiệm)

dynamicTools trên thread/start và quy trình yêu cầu hoặc phản hồi item/tool/call tương ứng là các API thử nghiệm.

Tên công cụ động và tên namespace phải tuân theo các ràng buộc đặt tên của Responses API. Tránh các tên namespace dành riêng được công cụ Codex tích hợp sẵn sử dụng.

Khi một công cụ động được gọi trong một lượt, app-server phát:

  1. item/started với item.type = "dynamicToolCall", status = "inProgress", cùng toolarguments.
  2. item/tool/call dưới dạng yêu cầu từ máy chủ đến client.
  3. Payload phản hồi của client chứa các mục nội dung được trả về.
  4. item/completed với item.type = "dynamicToolCall", status cuối cùng và mọi giá trị contentItems hoặc success được trả về.

Phê duyệt lệnh gọi công cụ MCP (ứng dụng)

Các lệnh gọi công cụ của ứng dụng (connector) cũng có thể cần được phê duyệt. Khi một lệnh gọi công cụ ứng dụng có tác dụng phụ, máy chủ có thể yêu cầu phê duyệt bằng tool/requestUserInput và các lựa chọn như Chấp nhận, Từ chốiHủy. Chú thích công cụ có tính phá hủy luôn kích hoạt phê duyệt, ngay cả khi công cụ cũng công bố các gợi ý ít đặc quyền hơn. Nếu người dùng từ chối hoặc hủy, mục mcpToolCall liên quan sẽ hoàn tất với lỗi thay vì chạy công cụ.

Skill

Gọi một skill bằng cách đưa $<skill-name> vào đầu vào văn bản của người dùng. Thêm một mục đầu vào skill (khuyến nghị) để máy chủ chèn đầy đủ hướng dẫn của skill thay vì dựa vào model để phân giải tên.

{
  "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ạn lược bỏ mục skill, model vẫn sẽ phân tích dấu mốc $<skill-name> và cố định vị skill, điều này có thể làm tăng độ trễ.

Ví dụ:

$skill-creator Add a new skill for triaging flaky CI and include step-by-step usage.

Sử dụng skills/list để truy xuất các skill có sẵn (có thể giới hạn phạm vi bằng cwds, với forceReload). Bạn cũng có thể bao gồm perCwdExtraUserRoots để quét các đường dẫn tuyệt đối bổ sung dưới dạng phạm vi user cho các giá trị cwd cụ thể. App-server bỏ qua các mục có cwd không xuất hiện trong cwds. skills/list có thể tái sử dụng kết quả được lưu trong bộ nhớ đệm theo cwd; đặt forceReload: true để làm mới từ đĩa. Khi có, máy chủ đọc interfacedependencies từ 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": []
  }]
} }

Máy chủ cũng phát thông báo skills/changed khi các tệp skill cục bộ đang được theo dõi thay đổi. Hãy xem đây là tín hiệu vô hiệu hóa và chạy lại skills/list với các tham số hiện tại khi cần.

Để bật hoặc tắt một skill theo đường dẫn:

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

Ứng dụng (connector)

Sử dụng app/installed để đọc bản chụp nhanh runtime mới nhất đã được commit của ứng dụng đã cài đặt. Mỗi kết quả bao gồm id, runtimeName (hoặc null), trạng thái enabled có hiệu lực và trạng thái callable của ứng dụng. Một ứng dụng chỉ có thể được gọi khi cấu hình có hiệu lực bật ứng dụng đó và ít nhất một công cụ hiển thị với model tuân thủ các chính sách ứng dụng và công cụ.

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

Lược bỏ threadId để sử dụng cấu hình toàn cục thay vì cấu hình của luồng đã tải. Đặt forceRefresh: true để làm mới bản chụp nhanh runtime của connector trước khi đọc. Khi chính sách toàn cục hoặc workspace chặn quyền truy cập ứng dụng, một ứng dụng được quan sát vẫn có thể xuất hiện với enabledcallable được đặt thành false.

Sử dụng app/list để truy xuất các ứng dụng có sẵn. Trong CLI/TUI, /apps là bộ chọn dành cho người dùng; trong client tùy chỉnh, hãy gọi trực tiếp app/list. Mỗi mục bao gồm cả isAccessible (có sẵn cho người dùng) và isEnabled (được bật trong config.toml), nhờ đó client có thể phân biệt trạng thái cài đặt/quyền truy cập với trạng thái bật cục bộ. Các mục ứng dụng cũng có thể bao gồm các trường tùy chọn branding, appMetadatalabels.

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

Nếu bạn cung cấp threadId, cơ chế giới hạn tính năng ứng dụng (features.apps) sẽ sử dụng bản chụp nhanh cấu hình của luồng đó. Khi bị lược bỏ, app-server sử dụng cấu hình toàn cục mới nhất.

app/list trả về sau khi cả ứng dụng có thể truy cập và ứng dụng trong danh mục đã được tải. Đặt forceRefetch: true để bỏ qua bộ nhớ đệm ứng dụng và truy xuất dữ liệu mới. Các mục trong bộ nhớ đệm chỉ được thay thế khi việc làm mới thành công.

Máy chủ cũng phát thông báo app/list/updated bất cứ khi nào một trong hai nguồn (ứng dụng có thể truy cập hoặc ứng dụng trong danh mục) tải xong. Mỗi thông báo chứa danh sách ứng dụng đã hợp nhất mới nhất.

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

Sử dụng app/read khi bạn đã biết id ứng dụng và cần siêu dữ liệu ứng dụng thay vì trạng thái runtime đã cài đặt. Truyền tối đa 100 appIds. Máy chủ chỉ giữ lần xuất hiện đầu tiên của mỗi id lặp lại và bảo toàn thứ tự đó trong cả appsmissingAppIds. Các ứng dụng không xác định hoặc không thể truy cập được trả về trong missingAppIds mà không làm toàn bộ yêu cầu thất bại.

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

Đặt includeTools: true để yêu cầu các bản tóm tắt công khai của công cụ chỉ dùng cho mục đích hiển thị. Phản hồi siêu dữ liệu không bao gồm trạng thái runtime của ứng dụng đã cài đặt và không cấp quyền cho lệnh gọi công cụ; hãy sử dụng app/installed để kiểm tra trạng thái enabledcallable có hiệu lực.

Gọi một ứng dụng bằng cách chèn $<app-slug> vào đầu vào văn bản và thêm một mục đầu vào mention với đường dẫn app://<id> (khuyến nghị).

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

Ví dụ Config RPC cho cài đặt ứng dụng

Sử dụng config/read, config/value/writeconfig/batchWrite để kiểm tra hoặc cập nhật các tùy chọn kiểm soát ứng dụng trong config.toml.

Đọc cấu trúc cấu hình ứng dụng có hiệu lực (bao gồm _default và các giá trị ghi đè theo từng công cụ):

{ "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 đặt trình đánh giá cho tất cả ứng dụng, trừ khi một giá trị theo từng ứng dụng ghi đè lên nó. Khi cả hai đều bị lược bỏ, ứng dụng kế thừa giá trị approvals_reviewer cấp cao nhất. apps._default.default_tools_approval_mode đặt chế độ phê duyệt dự phòng cho các công cụ không có giá trị ghi đè theo từng ứng dụng hoặc từng công cụ. Các yêu cầu về chế độ phê duyệt được quản lý sẽ ghi đè cài đặt chế độ phê duyệt của công cụ.

Cập nhật một cài đặt ứng dụng:

{
  "method": "config/value/write",
  "id": 61,
  "params": {
    "keyPath": "apps.google_drive.default_tools_approval_mode",
    "value": "prompt",
    "mergeStrategy": "replace"
  }
}

Áp dụng nhiều chỉnh sửa ứng dụng theo cách nguyên tử:

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

Phát hiện và nhập cấu hình tác nhân bên ngoài

Sử dụng externalAgentConfig/detect để khám phá các thành phần của tác nhân bên ngoài có thể di chuyển, sau đó truyền các mục đã chọn vào externalAgentConfig/import.

Ví dụ phát hiện:

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

Ví dụ nhập:

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

Tham số nhập source tùy chọn ở cấp cao nhất gắn nhãn sản phẩm đã tạo ra các mục di chuyển được chọn.

Máy chủ phát externalAgentConfig/import/progress khi từng loại mục hoàn tất, và externalAgentConfig/import/completed sau khi tất cả thao tác nhập đồng bộ và chạy nền hoàn tất. Các thông báo này bao gồm cùng importId từ phản hồi và itemTypeResults với successesfailures theo từng loại. Thông báo hoàn tất có thể đến ngay sau phản hồi hoặc sau khi các thao tác nhập từ xa chạy nền hoàn tất.

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

Đọc các lần nhập đã hoàn tất trước đó:

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

Các giá trị itemType được hỗ trợ là AGENTS_MD, CONFIG, SKILLS, PLUGINS, MCP_SERVER_CONFIG, SUBAGENTS, HOOKS, COMMANDSSESSIONS. Đối với các mục PLUGINS, details.plugins liệt kê từng marketplaceNamepluginNames mà Codex có thể thử di chuyển. Việc phát hiện chỉ trả về các mục vẫn còn công việc cần thực hiện. Ví dụ: Codex bỏ qua việc di chuyển AGENTS khi AGENTS.md đã tồn tại và không rỗng, còn thao tác nhập skill không ghi đè các thư mục skill hiện có.

Khi phát hiện plugin từ .claude/settings.json, Codex đọc các nguồn marketplace đã cấu hình từ extraKnownMarketplaces. Nếu enabledPlugins chứa plugin từ claude-plugins-official nhưng thiếu nguồn marketplace, Codex suy ra anthropics/claude-plugins-official làm nguồn.

Điểm cuối xác thực

Bề mặt tài khoản/xác thực JSON-RPC cung cấp các phương thức yêu cầu/phản hồi cùng các thông báo do máy chủ khởi tạo (không có id). Sử dụng chúng để xác định trạng thái xác thực, bắt đầu hoặc hủy đăng nhập, đăng xuất, kiểm tra giới hạn tốc độ ChatGPT và thông báo cho chủ sở hữu workspace khi hết tín dụng hoặc đạt giới hạn sử dụng.

Chế độ xác thực

Codex hỗ trợ các chế độ xác thực sau. account/updated.authMode hiển thị chế độ đang hoạt động và bao gồm planType ChatGPT hiện tại khi có. account/read cũng báo cáo chi tiết tài khoản và gói dịch vụ.

  • API key (apikey) - bên gọi cung cấp một OpenAI API key bằng type: "apiKey" và Codex lưu khóa đó cho các yêu cầu API.
  • Được ChatGPT quản lý (chatgpt) - Codex sở hữu quy trình OAuth của ChatGPT, lưu trữ token và tự động làm mới chúng. Bắt đầu bằng type: "chatgpt" cho quy trình trình duyệt hoặc type: "chatgptDeviceCode" cho quy trình mã thiết bị.
  • Token ChatGPT bên ngoài (chatgptAuthTokens) - đang trong giai đoạn thử nghiệm và dành cho các ứng dụng máy chủ đã sở hữu vòng đời xác thực ChatGPT của người dùng. Ứng dụng máy chủ cung cấp trực tiếp accessToken, chatgptAccountIdchatgptPlanType tùy chọn, đồng thời phải làm mới token khi được yêu cầu.
  • Amazon Bedrock - account/read báo cáo các tài khoản Bedrock dưới dạng type: "amazonBedrock" và cho biết thông tin xác thực đến từ Bedrock API key do Codex quản lý (credentialSource: "codexManaged") hay chuỗi thông tin xác thực AWS bên ngoài (credentialSource: "awsManaged"). account/updated.authMode sử dụng bedrockApiKey cho các Bedrock API key do Codex quản lý.

Tổng quan về API

  • account/read - truy xuất thông tin tài khoản hiện tại; có thể làm mới token.
  • account/login/start - bắt đầu đăng nhập (apiKey, chatgpt, chatgptDeviceCode hoặc chatgptAuthTokens thử nghiệm).
  • account/login/completed (thông báo) - được phát khi một lần đăng nhập hoàn tất (thành công hoặc lỗi).
  • account/login/cancel - hủy một lần đăng nhập ChatGPT được quản lý đang chờ theo loginId.
  • account/logout - đăng xuất; kích hoạt account/updated.
  • account/updated (thông báo) - được phát bất cứ khi nào chế độ xác thực thay đổi (authMode: apikey, chatgpt, chatgptAuthTokens, agentIdentity, personalAccessToken, bedrockApiKey hoặc null) và bao gồm planType khi có.
  • account/chatgptAuthTokens/refresh (yêu cầu từ máy chủ) - yêu cầu token ChatGPT mới được quản lý bên ngoài sau lỗi ủy quyền.
  • account/rateLimits/read - truy xuất giới hạn tốc độ ChatGPT.
  • account/rateLimits/updated (thông báo) - được phát bất cứ khi nào giới hạn tốc độ ChatGPT của người dùng thay đổi.
  • account/sendAddCreditsNudgeEmail - yêu cầu ChatGPT gửi email cho chủ sở hữu workspace về việc hết tín dụng hoặc đã đạt giới hạn sử dụng.
  • account/rateLimitResetCredit/consume - sử dụng một lượt đặt lại giới hạn tốc độ đã kiếm được bằng giá trị idempotencyKey do bên gọi cung cấp.
  • account/usage/read - truy xuất bản tóm tắt hoạt động token của tài khoản ChatGPT và các nhóm dữ liệu hằng ngày.
  • account/workspaceMessages/read - truy xuất các thông báo workspace đang hoạt động, bao gồm tiêu đề thông báo khi có.
  • mcpServer/oauthLogin/completed (thông báo) - được phát sau khi quy trình mcpServer/oauth/login hoàn tất; payload bao gồm { name, threadId, success, error? }. threadId có thể là null đối với quy trình OAuth trong phạm vi ứng dụng hoặc plugin.
  • mcpServer/startupStatus/updated (thông báo) - được phát khi trạng thái khởi động của một máy chủ MCP đã cấu hình thay đổi; payload bao gồm { threadId, name, status, error, failureReason }. threadIdnull đối với quá trình khởi động trong phạm vi ứng dụng. Khi khởi động thất bại, failureReason: "reauthenticationRequired" có nghĩa là thông tin xác thực OAuth đã lưu đã hết hạn và không thể làm mới, vì vậy client nên cung cấp tùy chọn kết nối lại máy chủ.

1) Kiểm tra trạng thái xác thực

Yêu cầu:

{ "method": "account/read", "id": 1, "params": { "refreshToken": false } }

Ví dụ phản hồi:

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

Ghi chú về trường:

  • refreshToken (boolean): đặt true để buộc làm mới token trong chế độ ChatGPT được quản lý. Trong chế độ token bên ngoài (chatgptAuthTokens), app-server bỏ qua cờ này.
  • emailnull khi tài khoản ChatGPT không có địa chỉ email.
  • requiresOpenaiAuth phản ánh nhà cung cấp đang hoạt động; khi là false, Codex có thể chạy mà không cần thông tin xác thực OpenAI.
  • Amazon Bedrock báo cáo credentialSource: "codexManaged" khi sử dụng một Bedrock API key do Codex quản lý. Dịch vụ báo cáo credentialSource: "awsManaged" cho đường dẫn thông tin xác thực AWS bên ngoài. Giá trị này xác định nguồn thông tin xác thực đã chọn; nó không xác thực rằng chuỗi thông tin xác thực AWS có thể phân giải thông tin xác thực.

2) Đăng nhập bằng API key

  1. Gửi:
   {
     "method": "account/login/start",
     "id": 2,
     "params": { "type": "apiKey", "apiKey": "sk-..." }
   }
  1. Chờ nhận:
   { "id": 2, "result": { "type": "apiKey" } }
  1. Thông báo:
   {
     "method": "account/login/completed",
     "params": { "loginId": null, "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "apikey", "planType": null }
   }

3) Đăng nhập bằng ChatGPT (quy trình trình duyệt)

  1. Bắt đầu:
   {
     "method": "account/login/start",
     "id": 3,
     "params": {
       "type": "chatgpt",
       "useHostedLoginSuccessPage": true,
       "appBrand": "chatgpt"
     }
   }

Theo mặc định, callback trình duyệt thành công sẽ chuyển hướng đến một trang thông báo thành công cục bộ. Đặt useHostedLoginSuccessPage: true để sử dụng trang thông báo thành công được lưu trữ khi không cần thiết lập tổ chức. Khi bật trang thông báo thành công được lưu trữ, appBrand có thể là "codex" hoặc "chatgpt"; các giá trị bị lược bỏ hoặc bằng null mặc định là "codex".

   {
     "id": 3,
     "result": {
       "type": "chatgpt",
       "loginId": "<uuid>",
       "authUrl": "https://chatgpt.com/...&redirect_uri=http%3A%2F%2Flocalhost%3A<port>%2Fauth%2Fcallback"
     }
   }
  1. Mở authUrl trong trình duyệt; app-server lưu trữ callback cục bộ.
  2. Chờ thông báo:
   {
     "method": "account/login/completed",
     "params": { "loginId": "<uuid>", "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "chatgpt", "planType": "plus" }
   }

3b) Đăng nhập bằng ChatGPT (quy trình mã thiết bị)

Sử dụng quy trình này khi client của bạn sở hữu trải nghiệm đăng nhập hoặc khi callback trình duyệt không ổn định.

  1. Bắt đầu:
   {
     "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"
     }
   }
  1. Hiển thị verificationUrluserCode cho người dùng; frontend sở hữu UX.
  2. Chờ thông báo:
   {
     "method": "account/login/completed",
     "params": { "loginId": "<uuid>", "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "chatgpt", "planType": "plus" }
   }

3c) Đăng nhập bằng token ChatGPT được quản lý bên ngoài (chatgptAuthTokens)

Chỉ sử dụng chế độ thử nghiệm này khi một ứng dụng máy chủ sở hữu vòng đời xác thực ChatGPT của người dùng và trực tiếp cung cấp token. Client phải đặt capabilities.experimentalApi = true trong initialize trước khi sử dụng kiểu đăng nhập này.

  1. Gửi:
   {
     "method": "account/login/start",
     "id": 7,
     "params": {
       "type": "chatgptAuthTokens",
       "accessToken": "<jwt>",
       "chatgptAccountId": "org-123",
       "chatgptPlanType": "business"
     }
   }
  1. Chờ nhận:
   { "id": 7, "result": { "type": "chatgptAuthTokens" } }
  1. Thông báo:
   {
     "method": "account/login/completed",
     "params": { "loginId": null, "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "chatgptAuthTokens", "planType": "business" }
   }

Khi máy chủ nhận được 401 Unauthorized, máy chủ có thể yêu cầu token đã làm mới từ ứng dụng máy chủ:

{
  "method": "account/chatgptAuthTokens/refresh",
  "id": 8,
  "params": { "reason": "unauthorized", "previousAccountId": "org-123" }
}
{ "id": 8, "result": { "accessToken": "<jwt>", "chatgptAccountId": "org-123", "chatgptPlanType": "business" } }

Máy chủ thử lại yêu cầu ban đầu sau khi nhận được phản hồi làm mới thành công. Yêu cầu hết thời gian chờ sau khoảng 10 giây.

4) Hủy đăng nhập ChatGPT

{ "method": "account/login/cancel", "id": 4, "params": { "loginId": "<uuid>" } }
{ "method": "account/login/completed", "params": { "loginId": "<uuid>", "success": false, "error": "..." } }

5) Đăng xuất

{ "method": "account/logout", "id": 5 }
{ "id": 5, "result": {} }
{ "method": "account/updated", "params": { "authMode": null, "planType": null } }

6) Giới hạn tốc độ (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 }
  }
} }

Ghi chú về trường:

  • rateLimits là chế độ xem một nhóm dữ liệu tương thích ngược.
  • rateLimitsByLimitId (khi có) là chế độ xem nhiều nhóm dữ liệu được lập khóa theo limit_id có đo lường (ví dụ: codex).
  • limitId là mã định danh nhóm dữ liệu có đo lường.
  • limitName là nhãn tùy chọn hiển thị cho người dùng của nhóm dữ liệu.
  • usedPercent là mức sử dụng hiện tại trong khoảng hạn mức.
  • windowDurationMins là độ dài của khoảng hạn mức.
  • resetsAt là dấu thời gian Unix (giây) của lần đặt lại tiếp theo.
  • planType được bao gồm khi máy chủ trả về gói ChatGPT được liên kết với một nhóm dữ liệu.
  • credits được bao gồm khi máy chủ trả về chi tiết tín dụng workspace còn lại.
  • rateLimitReachedType xác định trạng thái giới hạn do máy chủ phân loại khi đã đạt một giới hạn.
  • rateLimitResetCredits chứa số lượt đặt lại đã kiếm được đang khả dụng khi dịch vụ cung cấp giá trị này; nếu không, giá trị là null.
  • rateLimitResetCredits.creditsnull khi chỉ biết số lượng. Mảng rỗng có nghĩa là dịch vụ đã truy xuất chi tiết và trả về không có tín dụng khả dụng. Dịch vụ có thể giới hạn số hàng chi tiết, vì vậy availableCount là dữ liệu chuẩn.
  • Mỗi hàng chi tiết bao gồm một id không trong suốt, resetType, status, grantedAt, expiresAt (có thể là null), title (có thể là null) và description (có thể là null).
  • Truy xuất account/rateLimits/read sau khi sử dụng một lượt đặt lại.

7) Mức sử dụng token (ChatGPT)

Sử dụng account/usage/read để truy xuất các trường tóm tắt hoạt động token ChatGPT và các nhóm dữ liệu hằng ngày tùy chọn.

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

Ghi chú về trường:

  • Các giá trị summary có thể là null khi dịch vụ chưa trả về chỉ số đó.
  • dailyUsageBuckets có thể là null; khi có, mỗi nhóm dữ liệu bao gồm startDatetokens.
  • Điểm cuối yêu cầu xác thực dựa trên các dịch vụ Codex. Xác thực bằng ChatGPT, token ChatGPT bên ngoài, danh tính tác nhân và personal access token đều hoạt động; xác thực chỉ bằng API key và xác thực Bedrock thì không.

8) Lượt đặt lại giới hạn tốc độ đã kiếm được (ChatGPT)

Sử dụng account/rateLimitResetCredit/consume để sử dụng một lượt đặt lại đã kiếm được.

{ "method": "account/rateLimitResetCredit/consume", "id": 8, "params": { "idempotencyKey": "8ae96ff3-3425-4f4c-8772-b6fd61502868", "creditId": "RateLimitResetCredit_1" } }
{ "id": 8, "result": { "outcome": "reset" } }

Ghi chú về trường:

  • idempotencyKey không được để trống. Sử dụng một UUID cho mỗi lần thử quy đổi logic và tái sử dụng cùng giá trị đó khi thử lại lần quy đổi ấy.
  • creditId là tùy chọn. Khi được cung cấp, giá trị này phải là một ID không trong suốt, không rỗng từ account/rateLimits/read. Khi bị lược bỏ, dịch vụ chọn tín dụng khả dụng tiếp theo.
  • reset có nghĩa là một tín dụng đã được sử dụng.
  • alreadyRedeemed có nghĩa là cùng lần quy đổi này đã hoàn tất trước đó. Hãy xử lý đây là một lần thành công có tính lũy đẳng và làm mới giới hạn tài khoản.
  • nothingToReset có nghĩa là không có khoảng giới hạn tốc độ đủ điều kiện để đặt lại.
  • noCredit có nghĩa là tài khoản không còn tín dụng đặt lại đã kiếm được nào.
  • Truy xuất account/rateLimits/read sau khi sử dụng một lượt đặt lại, thay vì suy luận các khoảng đã cập nhật từ phản hồi này.

9) Thông báo cho chủ sở hữu workspace về một giới hạn

Sử dụng account/sendAddCreditsNudgeEmail để yêu cầu ChatGPT gửi email cho chủ sở hữu workspace khi hết tín dụng hoặc đã đạt giới hạn sử dụng.

{ "method": "account/sendAddCreditsNudgeEmail", "id": 9, "params": { "creditType": "credits" } }
{ "id": 9, "result": { "status": "sent" } }

Sử dụng creditType: "credits" khi tín dụng workspace đã hết hoặc creditType: "usage_limit" khi đã đạt giới hạn sử dụng của workspace. Nếu chủ sở hữu đã được thông báo gần đây, trạng thái phản hồi là cooldown_active.

10) Thông báo workspace (ChatGPT)

Sử dụng account/workspaceMessages/read để truy xuất các thông báo đang hoạt động của workspace hiện tại, bao gồm tiêu đề thông báo khi có.

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