Үндсэн агуулга руу алгасах
OpenAI

2026 оны хоёрдугаар сарын 4

Инженерчлэл

Unlocking the Codex harness: how we built the App Server

By Celia Chen, Member of the Technical Staff

Ачаалж байна…

OpenAI’s coding agent Codex exists across many different surfaces: the web app(шинэ цонхонд нээгдэнэ), the CLI(шинэ цонхонд нээгдэнэ), the IDE extension(шинэ цонхонд нээгдэнэ), and the new Codex macOS app. Under the hood, they’re all powered by the same Codex harness—the agent loop and logic that underlies all Codex experiences. The critical link between them? The Codex App Server(шинэ цонхонд нээгдэнэ), a client-friendly, bidirectional JSON-RPC1 API.

In this post, we’ll introduce the Codex App Server; we’ll share our learnings so far on the best ways to bring Codex’s capabilities into your product to help your users supercharge their workflows. We’ll cover the App Server’s architecture and protocol and how it integrates with different Codex surfaces, as well as tips on leveraging Codex, whether you want to turn Codex into a code reviewer, an SRE agent, or a coding assistant.

Origin of the App Server

Before diving into architecture, it’s helpful to know the App Server’s backstory. Initially, the App Server was a practical way to reuse the Codex harness across products that gradually evolved into our standard protocol.

Codex CLI started as a TUI (terminal user interface), meaning Codex is accessed through the terminal. When we built the VS Code extension (a more IDE-friendly way to interact with Codex agents), we needed a way to use the same harness so as to drive the same agent loop from an IDE UI without re-implementing it. That meant supporting rich interaction patterns beyond request/response, such as exploring the workspace, streaming progress as the agent reasons, and emitting diffs. We first experimented with exposing Codex as an MCP server(шинэ цонхонд нээгдэнэ), but maintaining MCP semantics in a way that made sense for VS Code proved difficult. Instead, we introduced a JSON-RPC protocol that mirrored the TUI loop, which became the unofficial first version(шинэ цонхонд нээгдэнэ) of the App Server. At the time, we didn’t expect other clients to depend on the App Server, so it wasn’t designed as a stable API.

As Codex adoption grew over the next few months, internal teams and external partners wanted the ability to embed the same harness in their own products in order to accelerate their users’ software development workflows. For example, JetBrains and Xcode wanted an IDE-grade agent experience, while the Codex desktop app needed to orchestrate many Codex agents in parallel. Those demands pushed us to design a platform surface that both our products and partner integrations could safely depend on over time. It needed to be easy to integrate and backward compatible, meaning we could evolve the protocol without breaking existing clients.

Next, we’ll walk through how we designed the architecture and protocol so different clients can use the same harness.

Inside the Codex harness

First, let’s zoom in on what’s inside the Codex harness and how the Codex App Server exposes it to clients. In our last Codex blog, we broke down the core agent loop that orchestrates the interaction between the user, the model, and the tools. This is the core logic of the Codex harness, but there’s more to the full agent experience:

1. Thread lifecycle and persistence. A thread is a Codex conversation between a user and an agent. Codex creates, resumes, forks, and archives threads, and persists the event history so clients can reconnect and render a consistent timeline.

2. Config and auth. Codex loads configuration, manages defaults, and runs authentication flows like “Sign in with ChatGPT,” including credential state.

3. Tool execution and extensions. Codex executes shell/file tools in a sandbox and wires up integrations like MCP servers and skills so they can participate in the agent loop under a consistent policy model.

All the agent logic we mentioned here, including the core agent loop, lives in a part of the Codex CLI codebase called “Codex core(шинэ цонхонд нээгдэнэ).” Codex core is both a library where all the agent code lives and a runtime that can be spun up to run the agent loop and manage the persistence of one Codex thread (conversation).

To be useful, the Codex harness needs to be accessible to clients. That’s where the App Server comes in.

«App server process flow» гэсэн диаграм. Клиент JSON-RPC мессежүүдийг stdio reader рүү илгээж, тэр нь хүсэлтүүдийг Codex message processor руу дамжуулна. Processor нь lookup threads, thread handle-ууд, илгээсэн хүсэлтүүд, event/update-уудаар thread manager болон core thread-тэй харилцаад, дараа нь хариуг клиент рүү буцаана.

The App Server is both the JSON-RPC protocol between the client and the server and a long-lived process that hosts the Codex core threads. As we can see from the diagram above, an App Server process has four main components: the stdio reader, the Codex message processor, the thread manager, and core threads. The thread manager spins up one core session for each thread, and the Codex message processor then communicates with each core session directly to submit client requests and receive updates.

One client request can result in many event updates, and these detailed events are what allow us to build a rich UI on top of the App Server. Furthermore, the stdio reader and the Codex message processor serve as the translation layer between the client and Codex core threads. They translate client JSON-RPC requests into Codex core operations, listen to Codex core’s internal event stream, and then transform those low-level events into a small set of stable, UI-ready JSON-RPC notifications.

The JSON-RPC protocol between the client and the App Server is fully bidirectional. A typical thread has a client request and many server notifications. In addition, the server can initiate requests when the agent needs input, like an approval, and then pause the turn until the client responds.

The conversation primitives

Next, we’ll break down the conversation primitives, the building blocks of the App Server protocol. Designing an API for an agent loop is tricky because the user/agent interaction is not a simple request/response. One user request can unfold into a structured sequence of actions that the client needs to represent faithfully: the user’s input, the agent’s incremental progress, artifacts produced along the way (e.g., diffs). To make that interaction stream easy to integrate and resilient across UIs, we landed on three core primitives with clear boundaries and lifecycles:

1. Item: An item is the atomic unit of input/output in Codex. Items are typed (e.g., user message, agent message, tool execution, approval request, diff) and each has an explicit lifecycle:

  • item/started when the item begins
  • optional item/*/delta events as content streams in (for streaming item types)
  • item/completed when the item finalizes with its terminal payload

This lifecycle lets clients start rendering immediately on started, stream incremental updates on delta, and finalize on completed.

2. Turn: A turn is one unit of agent work initiated by user input. It begins when the client submits an input (for example, “run tests and summarize failures”) and ends when the agent finishes producing outputs for that input. A turn contains a sequence of items that represent the intermediate steps and outputs produced along the way.

3. Thread: A thread is the durable container for an ongoing Codex session between a user and an agent. It contains multiple turns. Threads can be created, resumed, forked, and archived. Thread history is persisted so clients can reconnect and render a consistent timeline.

Now, we’ll look at a simplified conversation between a client and an agent, where the conversation is represented by primitives:

«Клиент-сервер протоколын мессежийн урсгал: Эхлүүлэх handshake» гэсэн шошготой диаграм. Клиент clientInfo-той initialize хүсэлтийг сервер рүү илгээнэ. Сервер “my_client/1.0” гэсэн userAgent мөр агуулсан result эвентээр хариулна.

At the beginning of the conversation, the client and the server need to establish the initialize handshake. The client must send a single initialize request before any other method, and the server acknowledges with a response. This gives the server a chance to advertise capabilities and lets both sides agree on protocol versioning, feature flags, and defaults before the real work begins. Here’s an example payload from OpenAI’s VS Code extension:

JSON

1
{
2
"method": "initialize",
3
"id": 0,
4
"params": {
5
"clientInfo": {
6
"name": "codex_vscode",
7
"title": "Codex VS Code Extension",
8
"version": "0.1.0"
9
}
10
}
11
}

This is what the server returns:

JSON

1
{
2
"id": 0,
3
"result": {
4
"userAgent": "codex_vscode/0.94.0-alpha.7 (Mac OS 26.2.0; arm64) vscode/2.4.22 (codex_vscode; 0.1.0)"
5
}
6
}
«Клиент-сервер протоколын мессежийн урсгал: Thread ба turn-ийн амьдралын мөчлөг» нэртэй диаграм. Клиент thread/start болон turn/start хүсэлтүүдийг сервер рүү илгээнэ. Сервер thread/started, turn/started, item/started, item/completed гэсэн эвентүүдийг гаргаж, хэрэглэгчийн “тест ажиллуулаад алдаануудыг хураангуйл” гэсэн мессежтэй нэг turn-ийг харуулна.

When a client makes a new request, it will first create a thread and then a turn. The server will send back notifications for progress (thread/started and turn/started). It will also send back inputs it registers as items, like the user message here.

«Клиент-сервер протоколын мессежийн урсгал: Нэмэлт зөвшөөрөлтэй хэрэгсэл ажиллуулалт» гэсэн диаграм. Tool call-ийн үед сервер эхлээд item/started, дараа нь шалтгаантай (“тест ажиллуулах”) item/commandExecution/requestApproval-г гаргана. Клиент зөвшөөрлийн эвент (allow/deny) буцаана. Дараа нь сервер командын ажиллуулалтыг (“pnpm test”) харуулсан item/completed-г гаргана.

Tool calls are also sent back to the client as items. Additionally, the server may ask for client approval before it can run an action by sending a server request. The approval will pause the turn until the client replies with either “allow” or “deny.” This is what the approval flow looks like in the VS Code extension:

Харанхуй загвартай интерфэйс дээрх зөвшөөрөл хүсэх цонх: «Энэ ажлын талбарт pnpm test ажиллуулахыг зөвшөөрөх үү?» Сонголтууд: 1) Тийм, 2) Тийм, мөн pnpm test-ээр эхэлсэн командуудад дахин бүү асуу, 3) Үгүй. Доод хэсэгт Submit товчтой.
«Клиент-сервер протоколын мессежийн урсгал: Агентын мессежийг стриймээр дамжуулах урсгал» гэсэн диаграм. Сервер assistant мессежийг хэсэгчлэн стриймлэнэ: item/started, хоёр agentMessage/delta эвент (“3 тест ажиллууллаа.”, “бүгд амжилттай”), дараа нь item/completed. Turn нь turn/completed-ээр дуусна.

In the end, the server sends an agent message and then ends the turn with turn/completed. The agent message delta events stream pieces of the message back until the message is finalized with item/completed.

Диаграм дээрх мессежүүдийг уншихад хялбар болгох үүднээс хялбаршуулсан. Хэрэв та бүтэн turn-ийн JSON-ийг харахыг хүсвэл Codex CLI репозитороос тест клиент ажиллуулж болно:

Bash

1
codex debug app-server send-message-v2 "run tests and summarize failures"

Клиентүүдтэй нэгтгэх нь

Одоо өөр өөр клиент интерфейсүүд Codex-ийг App Server-ээр дамжуулан хэрхэн суулгаж ашигладгийг харцгаая. Бид гурван хэв маягийг авч үзнэ: локал аппууд ба IDE-үүд, Codex web runtime, мөн TUI.

«App server-ээр дамжин Codex harness-тэй нэгтгэсэн Codex клиентүүд» гэсэн диаграм. Эхний талын клиентүүд (Codex Desktop App, TUI/CLI, Web Runtime) болон гуравдагч талын интеграцүүд (JetBrains IDE-үүд, VS Code, Xcode) JSON-RPC дуудлагаар Codex harness-тай харилцдаг.

Эдгээр гурвууланд нь тээвэр нь stdio (JSONL)-ээрх JSON-RPC юм. JSON-RPC нь өөрийн сонгосон хэл дээр клиент binding бүтээхийг хялбар болгодог. Codex интерфейсүүд болон түнш интеграцуудад Go, Python, TypeScript, Swift, Kotlin зэрэг хэлээр App Server клиент хэрэгжүүлсэн. TypeScript-ийн хувьд та Rust протоколоос тодорхойлолтуудыг шууд дараах байдлаар үүсгэж болно:

Bash

1
codex app-server generate-ts

Бусад хэлний хувьд JSON Schema bundle үүсгээд, үүнийг хүссэн код үүсгэгчдээ дараах байдлаар өгч болно:

Bash

1
codex app-server generate-json-schema
Локал аппууд ба IDE-үүд
Ажиллаж буй Codex өргөтгөлтэй VS Code-ийн дэлгэцийн зураг. Rust тестийн файл нээлттэй бөгөөд доорх Codex самбарт зөвхөн fmt болон cargo test -p codex-app-server ажиллуулж байгааг тайлбарлаж, форматлалт ба тестүүд үргэлжилж, эцсийн амжилттай/амжилтгүй үр дүнг хүлээж байгааг харуулна.

Локал клиентүүд ихэвчлэн платформд тохирсон App Server бинарийг багцалж эсвэл татаж авч, урт хугацаанд ажиллах child process болгон асаагаад, JSON-RPC-д зориулсан хоёр чиглэлт stdio сувгийг нээлттэй байлгадаг. Жишээлбэл, манай VS Code өргөтгөл болон Desktop App-д түгээгддэг артефакт нь платформд тохирсон Codex бинарийг агуулдаг бөгөөд шалгагдсан хувилбарт pin хийгдсэн байдаг тул клиент нь бидний баталгаажуулсан яг тэр binary-г үргэлж ажиллуулдаг.

Бүх интеграциуд клиент шинэчлэлтийг ойр ойрхон түгээж чаддаггүй. Xcode зэрэг зарим түншүүд клиентээ тогтвортой байлгаж, шаардлагатай үед илүү шинэ App Server binary руу заах боломж олгосноор хувилбарын мөчлөгөө салгадаг. Ингэснээр тэд сервер талын сайжруулалтуудыг (жишээлбэл, Codex core дахь илүү сайн auto-compaction эсвэл шинээр дэмжигдсэн config key-үүд) нэвтрүүлж, алдааны засварыг клиент шинэчлэл хүлээлгүй гаргаж чадна. App Server-ийн JSON-RPC интерфейс нь backward compatible байхаар зохиогдсон тул хуучин клиентүүд шинэ серверүүдтэй аюулгүй харилцаж чадна.

Codex Web
“Update login success message” гэсэн шинэчлэлттэй Codex веб интерфейсийн дэлгэцийн зураг. Зүүн самбар нь өөрчлөлтүүд, тестүүд, засварлагдсан файлуудыг хураангуйлж, баруун самбар нь login.rs файлын кодын diff-ийг шинэ логин амжилтын мессежийн хэллэгтэйгээр харуулна.

Codex Web нь Codex harness-ийг ашигладаг боловч контейнер орчинд ажиллуулдаг. Worker нь checkout хийгдсэн ажлын талбартай контейнер бэлдэж, дотор нь App Server binary-г асаагаад, stdio2 дээрх урт настай JSON-RPC сувгийг хадгалдаг. Web апп (хэрэглэгчийн браузерын tab дээр ажиллаж буй) нь HTTP болон SSE-ээр Codex backend-тэй ярьдаг бөгөөд worker-ээс үүсгэсэн task event-үүдийг стриймээр дамжуулдаг. Ингэснээр браузер талын UI хөнгөн хэвээр байх атлаа desktop болон web дээр ижил runtime-тай байж чадна.

Web session-ууд түр зуурынх байдаг тул (tab хаагдах, сүлжээ тасрах) урт хугацааны task-уудын үнэн зөв эх сурвалж нь web апп байж чаддаггүй. Төлөв ба явцыг сервер дээр хадгалснаар tab алга болсон ч ажил үргэлжилнэ. Стрийминг протокол болон хадгалсан thread session-ууд нь шинэ session-д дахин холбогдож, орхисон газраасаа үргэлжлүүлж, клиент дээр төлөвийг дахин бүтээхгүйгээр хоцорсноо нөхөхөд хялбар болгодог.

TUI/Codex CLI
Codex CLI ажиллаж буй терминалын дэлгэцийн зураг. Үүнд OpenAI Codex баннер, gpt-5.2-codex medium загвар, хэрэглэгчийн “explain app server to me” команд, мөн “Working” төлөв харагдана. Доор “@filename-д тест бич” гэсэн санал болон shortcut сонголтууд гарч ирнэ.

Түүхийн хувьд TUI нь агент loop-тэй ижил process дотор ажилладаг бөгөөд app-server протоколын оронд Rust core type-уудтай шууд ярьдаг “төрөлх” клиент байсан. Энэ нь эхний үеийн хурдан туршилтад тустай байсан ч TUI-г онцгой тохиолдлын интерфейс болгож байв.

Одоо App Server бий болсон тул бид TUI-г дахин бүтэцлэхээр(шинэ цонхонд нээгдэнэ) төлөвлөж байгаа бөгөөд ингэснээр бусад клиентүүдтэй адилхан ажиллана: App Server child process асаах, stdio-оор JSON-RPC ярих, мөн ижил стрийминг эвентүүд болон зөвшөөрлүүдийг дүрслэх. Ингэснээр TUI нь алсын машин дээр ажиллаж буй Codex серверт холбогдож, агент-ийг тооцоололд ойр байлгаж, зөөврийн компьютер унтсан эсвэл тасарсан ч ажлыг үргэлжлүүлэхийн зэрэгцээ локал талд шууд шинэчлэлт ба удирдлагуудыг хүргэх workflow-ууд нээгдэнэ.

Зөв протоколыг сонгох нь

Codex App Server нь цаашид бидний үндсэнд нь дэмжих интеграцийн арга байх болно, гэхдээ илүү хязгаарлагдмал боломжтой өөр аргууд ч бий. Анхдагчаар бол клиентүүд Codex-тэй нэгтгэхдээ Codex App Server ашиглахыг бид зөвлөнө, гэхдээ янз бүрийн интеграцийн аргуудыг харж, тэдгээрийн давуу болон сул талыг ойлгох нь зүйтэй. Доор Codex-ийг ажиллуулах хамгийн түгээмэл аргууд болон аль нь ямар үед тохиромжтойг харуулав.

JSON-RPC протоколууд

MCP сервер хэлбэртэй Codex

codex mcp-server(шинэ цонхонд нээгдэнэ)-ийг ажиллуулаад stdio сервер дэмждэг дурын MCP клиентээс (жишээ нь, OpenAI Agents SDK(шинэ цонхонд нээгдэнэ)) холбоно уу. Хэрэв танд MCP-д суурилсан workflow аль хэдийн байгаа бөгөөд Codex-ийг дуудагдах хэрэгсэл болгон ашиглахыг хүсэж байвал энэ нь тохиромжтой. Сул тал нь MCP юу гаргаж өгнө, зөвхөн тэрийг л авна. Тиймээс илүү баялаг session семантик дээр тулгуурладаг Codex-т тусгай харилцан үйлчлэлүүд (жишээлбэл, diff шинэчлэлтүүд) MCP эцсийн цэгүүдээр цэвэрхэн илэрхийлэгдэхгүй байж магадгүй.

Олон provider дэмждэг агент harness протоколууд

Зарим экосистемүүд олон загвар provider болон runtime-ыг чиглүүлж чаддаг зөөврийн интерфейс санал болгодог. Хэрэв та олон агент-ийг зохицуулдаг нэг абстракц хүсэж байвал энэ нь тохиромжтой байж болно. Харин эсрэгээрээ эдгээр протоколууд нь боломжуудын нийтлэг дэд олонлог дээр төвлөрөх хандлагатай тул, ялангуяа provider-т тусгай хэрэгсэл болон session семантик чухал үед, илүү баялаг харилцан үйлчлэлийг илэрхийлэхэд хүндрэлтэй болгодог. Энэ талбар маш хурдан хөгжиж байгаа бөгөөд бодит агент workflow-г илэрхийлэх хамгийн сайн primitive-үүдийг тодорхойлохын хэрээр илүү нийтлэг стандартууд гарч ирнэ гэж бид үзэж байна (skills(шинэ цонхонд нээгдэнэ) үүний сайн жишээ).

Codex App Server

Тогтвортой, UI-д ээлтэй event stream хэлбэрээр бүтэн Codex harness-ийг гаргаж авахыг хүсвэл App Server-ийг сонгоорой. Та агент loop-ийн бүрэн боломжуудыг төдийгүй ChatGPT‑ээр нэвтрэх, загвар илрүүлэх, тохиргооны удирдлага зэрэг нэмэлт боломжуудыг авна. Гол өртөг нь интеграцийн ажил бөгөөд та өөрийн хэл дээр клиент талын JSON-RPC binding бүтээх хэрэгтэй. Гэхдээ практикт JSON схем болон баримтжуулалтыг өгвөл Codex хүнд ажлын ихэнхийг хийж чадна. Бидэнтэй хамтарсан олон баг Codex ашиглан богино хугацаанд ажиллах интеграци хийж чадсан.

Codex-ийг суулгаж ашиглах өөр аргууд

Нэг удаагийн task болон CI ажиллуулалтад зориулсан хөнгөн, скриптчилж болох CLI горим. Интерактив бус байдлаар нэг команд бүрэн дуусах хүртэл ажиллуулах, логт зориулж бүтэцтэй гаралтыг стриймээр авах, мөн амжилт эсвэл алдааг тодорхой дохиогоор төгсгөхийг хүсдэг автоматжуулалт ба pipeline-уудад тохиромжтой.

Өөрийн аппликейшн дотроос локал Codex агент-үүдийг програмчилж удирдахад зориулсан TypeScript сан. Хэрэв та тусдаа JSON-RPC клиент хийхгүйгээр сервер талын хэрэгсэл, workflow-д зориулсан төрөлх сангийн интерфейс хүсэж байвал хамгийн тохиромжтой. Энэ нь App Server-ээс өмнө гарсан тул одоогоор цөөн хэл, бага хэмжээний интерфейс дэмждэг. Хэрэв хөгжүүлэгчдийн сонирхол байвал багууд JSON-RPC binding бичихгүйгээр harness-ийн илүү өргөн интерфейсийг хамруулахын тулд App Server протоколыг ороосон нэмэлт SDK-үүдийг бид нэмж магадгүй.

Үүнийг цааш нь хөгжүүлэх нь

Энэ нийтлэлээр бид агент-үүдтэй харилцах шинэ стандарт зохиохдоо хэрхэн ханддаг, мөн Codex harness-ийг тогтвортой, клиентэд ээлтэй протокол болгох талаар хуваалцлаа. App Server Codex core-ийг хэрхэн ил гаргадаг, клиентүүдэд бүтэн агент loop-ийг удирдах боломж олгодог, мөн TUI, локал IDE интеграци, web runtime зэрэг өргөн хүрээний интерфейсүүдийг хэрхэн тэтгэдгийг бид авч үзлээ.

Хэрэв энэ нь Codex-ийг өөрийн workflow-д нэгтгэх санаа төрүүлсэн бол App Server-ийг туршаад үзэх нь зүйтэй. Бүх эх код Codex CLI-ийн нээлттэй эхийн репо(шинэ цонхонд нээгдэнэ)-д бий. Санал хүсэлт болон feature request-ээ чөлөөтэй хуваалцаарай. Та бүхнээс сонсохдоо бид баяртай байх бөгөөд агент-үүдийг хүн бүрт илүү хүртээмжтэй болгохын төлөө үргэлжлүүлэн ажиллахдаа догдолж байна.

Зохиогч

Celia Chen

Талархал

Энэ нийтлэлд хувь нэмэр оруулсан Майкл Болин, Оуэн Лин, Эрик Траут, Расмус Рюгор нарт, мөн App Server дээр ажилласан бүх Codex багт онцгой талархал илэрхийлье.

Тайлбар тэмдэглэл

  1. 1

    Бид “JSON‑RPC lite” хувилбар ашигладаг: энэ нь хүсэлт/хариулт/мэдэгдлийн хэлбэрийг хадгалдаг ч "jsonrpc": "2.0" толгойг хасаж, хатуу JSON‑RPC 2.0 биш stdio дээрх JSONL байдлаар хүрээлэгддэг.

  2. 2

    “stdio” нь контейнер доторх app-server-ийн stdin/stdout-ыг хэлнэ. Хостолсон орчинд эдгээр stream-үүдийг контейнер runtime руу байнгын сүлжээний холболтоор (жишээлбэл, WebSocket-тэй төстэй) туннелддэг тул яг локал pipe биш байсан ч stdio шиг ажилладаг.