Vai al contenuto principale
OpenAI

4 febbraio 2026

Ingegneria

Sfruttare Codex: come abbiamo realizzato l'App Server

Di Celia Chen, membro del personale tecnico

Caricamento in corso...

L'agente di coding di OpenAI, Codex, è disponibile su molte piattaforme diverse: l'app web(si apre in una nuova finestra), la CLI(si apre in una nuova finestra), l'estensione IDE(si apre in una nuova finestra) e la nuova app Codex per macOS. Dietro le quinte, sono tutti alimentati dalla stessa infrastruttura di Codex: il ciclo dell'agente e la logica che sono alla base di tutte le esperienze Codex. Qual è collegamento fondamentale tra di loro? Il Codex App Server(si apre in una nuova finestra), un'API JSON-RPC1 bidirezionale e pensata per i client.

In questo post, introdurremo il Codex App Server; condivideremo le nostre esperienze sui modi migliori per integrare le capacità di Codex nel tuo prodotto per aiutare i tuoi utenti a migliorare i loro flussi di lavoro. Esamineremo l'architettura e il protocollo dell'App Server e come si integra con le diverse superfici di Codex, oltre a fornire suggerimenti su come sfruttare Codex, che tu voglia trasformarlo in un revisore di codice, un agente SRE o un assistente alla programmazione.

Origine dell'App Server

Prima di addentrarci nell'architettura, è utile conoscere i retroscena dell'App Server. Inizialmente, l'App Server era un modo pratico per riutilizzare l'infrastruttura di Codex tra diversi prodotti e col tempo si è evoluto nel nostro protocollo standard.

Codex CLI è iniziato come TUI (interfaccia utente del terminale), il che significa che Codex è accessibile tramite il terminale. Quando abbiamo sviluppato l'estensione per VS Code (una modalità più integrata con l'IDE per interagire con gli agenti Codex), avevamo bisogno di un modo per riutilizzare la stessa integrazione, così da pilotare lo stesso ciclo dell'agente da un'interfaccia utente dell'IDE senza doverlo reimplementare. Ciò ha richiesto il supporto di modelli di interazione avanzati rispetto al classico request/response, come l'esplorazione dell'area di lavoro, l'aggiornamento in streaming dell'avanzamento del ragionamento dell'agente e la generazione di diff. Abbiamo inizialmente sperimentato l'esposizione di Codex come server MCP(si apre in una nuova finestra), ma mantenere la semantica MCP in un modo che avesse senso per VS Code si è rivelato difficile. Abbiamo quindi introdotto un protocollo JSON-RPC che rispecchiava il ciclo TUI, diventando così la prima versione non ufficiale(si apre in una nuova finestra) del server dell'app. All'epoca, non ci aspettavamo che altri client dipendessero dall'App Server, quindi non è stato progettato come un'API stabile.

Con la progressiva adozione di Codex nei mesi successivi, i team interni e i partner esterni desideravano di integrare lo stesso strumento nei propri prodotti per accelerare i flussi di lavoro di sviluppo software dei loro utenti. Ad esempio, JetBrains e Xcode volevano un'esperienza di agente di livello IDE, mentre l'app desktop Codex doveva orchestrare molti agenti Codex in parallelo. Queste esigenze ci hanno spinto a progettare una superficie di piattaforma su cui sia i nostri prodotti sia le integrazioni dei partner potessero fare affidamento in modo sicuro nel tempo. Doveva essere facile da integrare e retrocompatibile, dandoci la possibilità di far evolvere il protocollo senza interrompere i client esistenti.

Ora vedremo come abbiamo progettato l'architettura e il protocollo in modo che client diversi possano utilizzare la stessa integrazione.

Dentro l'infrastruttura di Codex

Per prima cosa, esaminiamo cosa c'è all'interno dell'infrastruttura di Codex e come il Codex App Server lo espone ai clienti. Nel nostro ultimo blog su Codex, abbiamo esaminato il ciclo operativo centrale dell'agente che orchestra l'interazione tra l'utente, il modello e gli strumenti. Questa rappresenta la logica centrale dell'infrastruttura di Codex, ma l'esperienza completa dell'agente va oltre:

1. Ciclo di vita e persistenza del thread. Un thread è una conversazione tra un utente e un agente Codex. Codex crea, riprende, duplica e archivia i thread, e conserva la cronologia degli eventi in modo che i client possano riconnettersi e mostrare una cronologia coerente.

2. Configurazione e autenticazione. Codex carica la configurazione, gestisce le impostazioni predefinite ed esegue flussi di autenticazione come "Accedi con ChatGPT", incluso lo stato delle credenziali.

3. Esecuzione degli strumenti ed estensioni. Codex esegue strumenti shell/file in una sandbox e collega integrazioni come i server MCP e le competenze in modo che possano partecipare al ciclo dell'agente secondo un modello di policy coerente.

Tutta la logica dell'agente che abbiamo descritto finora, incluso il ciclo centrale dell'agente, risiede in una parte del codice del CLI di Codex chiamata “Codex core(si apre in una nuova finestra)”. Codex core è sia una libreria in cui risiede tutto il codice dell'agente, sia un runtime che può essere avviato per eseguire il ciclo dell'agente e gestire la persistenza di un singolo thread (conversazione) di Codex.

Per essere utile, l'infrastruttura Codex deve essere accessibile ai clienti. È qui che entra in gioco l'App Server.

Diagramma intitolato “Flusso del processo del server dell'applicazione.” Un client invia messaggi JSON-RPC a un lettore stdio, che inoltra le richieste a un processore di messaggi Codex. Il processore interagisce con un thread manager e con i core thread tramite lookup thread, thread handle, richieste inviate ed eventi/aggiornamenti, per poi restituire le risposte al client.

L'App Server è sia il protocollo JSON-RPC tra il client e il server che un processo di lunga durata che ospita i thread core di Codex. Come possiamo vedere dal diagramma sopra, un processo App Server ha quattro componenti principali: il lettore stdio, il processore di messaggi Codex, il gestore dei thread e i thread core. Il gestore dei thread avvia una sessione core per ogni thread e il processore di messaggi Codex comunica direttamente con ciascuna sessione core per inviare le richieste del cliente e ricevere aggiornamenti.

Una richiesta del client può generare molti aggiornamenti di eventi, e questi eventi dettagliati ci permettono di costruire un'interfaccia utente completa sull'App Server. Inoltre, il lettore stdio e il processore di messaggi Codex fungono da strato di traduzione tra il client e i thread core di Codex. Traducono le richieste JSON-RPC dei client in operazioni di Codex core, ascoltano lo stream di eventi interni di Codex core e trasformano quindi quegli eventi a basso livello in un insieme ridotto di notifiche JSON-RPC stabili e pronte per la UI.

Il protocollo JSON-RPC tra il client e l'App Server è completamente bidirezionale. Un thread tipico include una richiesta del client e molte notifiche del server. Inoltre, il server può avviare richieste quando l'agente ha bisogno di input, come un'approvazione, e quindi sospendere il turno finché il client non risponde.

Le primitive di conversazione

Successivamente, analizzeremo le primitive di conversazione, i mattoni del protocollo App Server. Progettare un'API per un ciclo dell'agente è complesso perché l'interazione tra utente e agente non è una semplice richiesta/risposta. Una richiesta dell'utente può evolversi in una sequenza strutturata di azioni che il client deve rappresentare fedelmente: l'input dell'utente, i progressi incrementali dell'agente, e gli artefatti prodotti lungo il percorso (ad esempio, i diff). Per rendere quel flusso di interazione facile da integrare e resiliente tra le interfacce utente, abbiamo scelto tre primitive fondamentali con confini e cicli di vita ben definiti:

1. Elemento: Un elemento è l'unità atomica di input/output in Codex. Gli elementi sono classificati per tipo (ad es. messaggio utente, messaggio agente, esecuzione strumento, richiesta approvazione, diff) e ciascuno ha un ciclo di vita esplicito:

  • item/started quando l'item inizia
  • eventi facoltativi item/*/delta come flussi di contenuti (per i tipi di elemento di streaming)
  • item/completed quando l'elemento si completa con il suo payload finale

Questo ciclo di vita consente ai clienti di iniziare il rendering immediatamente su started, trasmettere aggiornamenti incrementali su delta e finalizzare su completed.

2. Turno: Un turno è un'unità di lavoro dell'agente avviata dall'input dell'utente. Inizia quando il client invia un input (ad esempio, “esegui i test e riassumi i fallimenti“) e termina quando l'agente finisce di produrre output per quell'input. Un turno include una sequenza di elementi che rappresentano i passaggi intermedi e i risultati prodotti lungo il percorso.

3. Thread: un thread è il contenitore durevole per una sessione Codex in corso tra un utente e un agente. Contiene più turni. I thread possono essere creati, ripresi, duplicati e archiviati. La cronologia del thread viene mantenuta affinché i client possano riconnettersi e visualizzare una sequenza temporale coerente.

Ora, esamineremo una conversazione semplificata tra un cliente e un agente, dove la conversazione è rappresentata da primitive:

Diagramma etichettato “Flusso dei messaggi del protocollo client-server: handshake di inizializzazione“. Un client invia una richiesta di inizializzazione con clientInfo al server. Il server risponde con un evento di risultato contenente la stringa userAgent “my_client/1.0“.

All'inizio della conversazione, il client e il server devono stabilire l'handshake initialize. Il client deve inviare una singola richiesta initialize prima di qualsiasi altro metodo, e il server risponde con una conferma. In questo modo il server può esporre le proprie funzionalità e le due parti possono accordarsi su versione del protocollo, feature flag e impostazioni di default prima che inizi il vero lavoro. Ecco un esempio di payload dall'estensione VS Code di OpenAI:

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
}

Questo è ciò che il server restituisce:

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
}
Diagramma intitolato “Flusso dei messaggi del protocollo client-server: ciclo di vita di thread e turno”. Il client invia richieste di avvio thread e di avvio turno al server. Il server emette eventi (thread/started, turn/started, item/started e item/completed) che mostrano un turno in cui il messaggio dell'utente è “esegui i test e riassumi gli errori“.

Quando un client effettua una nuova richiesta, creerà prima un thread e poi un turno. Il server invierà notifiche sull'avanzamento (thread/started e turn/started). Invierà anche input che registra come elementi, come il messaggio dell'utente qui.

Diagramma intitolato “Flusso dei messaggi del protocollo client-server: esecuzione dello strumento con approvazione facoltativa“. Durante una chiamata a uno strumento, il server emette item/started, quindi item/commandExecution/requestApproval con un motivo (“esegui i test“). Il client restituisce un evento di approvazione (allow/deny). Il server quindi emette item/completed che mostra l'esecuzione del comando ("pnpm test").

Le chiamate agli strumenti vengono anch'esse inviate al client come elementi. Inoltre, il server può chiedere l'approvazione del client prima di eseguire un'azione inviando una richiesta al server. L'approvazione metterà in pausa il turno finché il client non risponde con “allow” o “deny”. Ecco come appare il flusso di approvazione nell'estensione di VS Code:

Prompt in un'interfaccia a tema scuro che chiede: “Vuoi permettermi di eseguire il test pnpm per questa area di lavoro?“ Elenca le opzioni: 1) Sì, 2) Sì e non chiedere più per i comandi che iniziano con pnpm test, e 3) No, con un pulsante Invia in fondo.
Diagramma intitolato “Flusso dei messaggi del protocollo client-server: flusso dei messaggi dell'agente in streaming“. Il server trasmette in streaming un messaggio dell'assistente in più parti: item/started, due eventi agentMessage/delta (“eseguiti 3 test.”, (“tutti superati”), quindi item/completed. Il turno si conclude con turn/completed.

Alla fine, il server invia un messaggio agente e poi termina il turno con turn/completed. Gli eventi delta dei messaggi dell'agente trasmettono parti del messaggio in streaming fino a quando il messaggio non viene finalizzato con item/completed.

I messaggi nel diagramma sono semplificati per una migliore leggibilità. Se vuoi vedere il JSON di un turno completo, puoi eseguire il client di test dal repository del CLI di Codex:

Bash

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

Integrazione con i client

Ora, vediamo come le diverse interfacce client integrano Codex tramite l'App Server. Tratteremo tre modelli: app locali e IDE, il runtime web di Codex e la TUI.

Diagramma intitolato “Client Codex integrati con Codex harness tramite server app“. I client di prima parte (Codex Desktop App, TUI/CLI, Web Runtime) e le integrazioni di terze parti (JetBrains IDEs, VS Code, Xcode) comunicano con l'infrastruttura di Codex tramite chiamate JSON-RPC.

In tutti e tre i casi, il trasporto è JSON-RPC su stdio (JSONL). JSON-RPC rende semplice costruire binding client nel linguaggio che preferisci. Le superfici di Codex e le integrazioni dei partner hanno implementato client App Server in linguaggi come Go, Python, TypeScript, Swift e Kotlin. Per TypeScript, puoi generare le definizioni direttamente dal protocollo Rust eseguendo:

Bash

1
codex app-server generate-ts

Per altre lingue, puoi generare un bundle di schema JSON e inserirlo nel tuo generatore di codice preferito eseguendo:

Bash

1
codex app-server generate-json-schema
App locali e IDE
Screenshot di VS Code con l'estensione Codex in esecuzione. Si vede aperto un file di test Rust e, sotto di esso, il pannello Codex descrive l'esecuzione di solo fmt e cargo test -p codex-app-server, segnalando che la formattazione e i test sono in corso in attesa di un risultato finale di successo/fallimento.

I client locali di solito integrano o recuperano un binario dell'App Server compatibile con la piattaforma, lo lanciano come processo figlio persistente e mantengono un canale stdio bidirezionale per la comunicazione JSON-RPC. Nella nostra estensione per VS Code e nell'app desktop, ad esempio, l'artefatto distribuito include il binario Codex specifico per la piattaforma ed è fissato su una versione testata, in modo che il client esegua sempre esattamente i bit che abbiamo convalidato.

Non tutte le integrazioni possono inviare aggiornamenti del client frequentemente. Alcuni partner come Xcode disaccoppiano i cicli di rilascio mantenendo stabile il client e consentendogli di puntare a un binario più recente di App Server quando necessario. In questo modo possono adottare miglioramenti lato server (ad esempio una migliore auto-compattazione in Codex core o nuove chiavi di configurazione supportate) e distribuire correzioni di bug senza dover attendere una nuova release del client. La superficie JSON-RPC dell'App Server è progettata per essere retrocompatibile, quindi i client meno recenti possono comunicare in modo sicuro con i server più recenti.

Codex Web
Screenshot dell’interfaccia web di Codex che mostra un aggiornamento intitolato “Aggiorna messaggio di login riuscito”. Il pannello di sinistra riepiloga le modifiche, i test e i file modificati, mentre il pannello di destra mostra un diff del codice per login.rs con una formulazione aggiornata del messaggio di successo del login.

Codex Web utilizza l'integrazione di Codex, ma la esegue in un ambiente containerizzato. Un worker crea un container contenente il workspace controllato, lancia al suo interno il binario dell'App Server e mantiene un canale JSON-RPC persistente su stdio2. L'app web (in esecuzione nella scheda del browser dell'utente) comunica con il backend di Codex tramite HTTP e SSE, che trasmettono in streaming gli eventi delle attività prodotti dal worker. Questo mantiene l'interfaccia utente lato browser leggera, pur garantendoci un runtime coerente su desktop e web.

Poiché le sessioni web sono effimere (le schede si chiudono, le reti si interrompono), l'app web non può essere una fonte attendibile per attività di lunga durata. Mantenere lo stato e i progressi sul server significa che il lavoro continua anche se la scheda viene chiusa. Il protocollo di streaming e le sessioni di thread salvate rendono facile per una nuova sessione riconnettersi, riprendere da dove si era interrotta e recuperare senza dover ricostruire lo stato nel client.

TUI/CLI di Codex
Screenshot di un terminale con in esecuzione il CLI di Codex. Viene mostrato il banner di OpenAI Codex con il modello GPT-5.2-Codex medio, un comando utente “spiegami l'app server” e uno stato “in corso”. Di seguito appare un suggerimento: “scrivi test per @filename“, con opzioni per le scorciatoie.

Storicamente, la TUI era un client “nativo” che girava nello stesso processo del ciclo dell'agente e comunicava direttamente con i tipi core di Rust, invece di usare il protocollo dell'App Server. Questo ha reso rapide le prime iterazioni, ma ha anche trasformato la TUI in una superficie speciale, trattata come un caso a parte.

Ora che l'App Server esiste, prevediamo di rifattorizzare la TUI(si apre in una nuova finestra) per usarlo, così da farla comportare come qualsiasi altro client: avvierà un processo figlio dell'App Server, comunicherà tramite JSON-RPC su stdio e renderizzerà gli stessi eventi in streaming e le stesse approvazioni. Questo sblocca flussi di lavoro in cui la TUI può connettersi a un server Codex in esecuzione su una macchina remota, mantenendo l'agente vicino al calcolo e continuando a lavorare anche se il laptop va in sospensione o si disconnette, pur fornendo aggiornamenti e controlli in tempo reale localmente.

Scegliere il protocollo corretto

Il Codex App Server sarà il metodo di integrazione principale che manterremo d'ora in avanti, ma sono disponibili anche altri metodi con funzionalità più limitate. Per impostazione predefinita, consigliamo ai clienti di utilizzare Codex App Server per integrarsi con Codex, ma vale la pena esaminare diversi metodi di integrazione e comprenderne i vantaggi e gli svantaggi. Di seguito riportiamo i modi più comuni per utilizzare Codex e i casi a cui potrebbero essere più adatti.

Protocolli JSON-RPC

Codex come server MCP

Esegui codex mcp-server(si apre in una nuova finestra) e connettiti da un qualsiasi client MCP che supporta i server stdio (ad esempio, OpenAI Agents SDK(si apre in una nuova finestra)). Questa è una buona scelta se hai già un flusso di lavoro basato su MCP e desideri utilizzare Codex come uno strumento richiamabile. Lo svantaggio è che ottieni solo ciò che MCP espone, quindi le interazioni specifiche di Codex che si basano su una semantica di sessione più ricca (ad esempio, aggiornamenti differenziali) potrebbero non essere mappate in modo pulito tramite gli endpoint MCP.

Protocolli di integrazione per agenti cross-provider

Alcuni ecosistemi offrono un'interfaccia portabile in grado di supportare più provider di modelli e runtime diversi. Può essere una buona soluzione se desideri un'unica astrazione che coordini più agenti. Il compromesso è che questi protocolli spesso convergono sul sottoinsieme comune di funzionalità, il che può rendere più difficile rappresentare interazioni più ricche, soprattutto quando contano le semantiche degli strumenti e delle sessioni specifiche del fornitore. Questo settore sta evolvendo rapidamente e ci aspettiamo che emergano standard sempre più condivisi, man mano che individuiamo le primitive migliori per rappresentare i workflow degli agenti nel mondo reale (un buon esempio sono le skill(si apre in una nuova finestra)).

Server dell'app Codex

Scegli l'App Server quando desideri che l'intera infrastruttura Codex sia esposta come un flusso di eventi stabile e adatto all'interfaccia utente. Ottieni sia la piena funzionalità del ciclo dell'agente sia altre funzionalità di supporto come Accedi con ChatGPT, scoperta dei modelli e gestione della configurazione. Il costo principale è il lavoro di integrazione, dato che devi costruire il binding JSON-RPC lato client nella tua lingua. In pratica, tuttavia, Codex è in grado di svolgere gran parte del lavoro se gli fornisci lo schema JSON e la documentazione. Molti team con cui abbiamo lavorato sono riusciti a creare rapidamente un'integrazione funzionante utilizzando Codex.

Altri modi per incorporare Codex

Una modalità CLI leggera e scriptabile per attività una tantum ed esecuzioni in CI. È una buona scelta per l'automazione e le pipeline dove si desidera eseguire un singolo comando fino al completamento in modo non interattivo, trasmettere in streaming risultati strutturati per i log e terminare con un chiaro segnale di successo o fallimento.

Una libreria TypeScript per la gestione programmatica degli agenti Codex locali dall'interno della propria applicazione. È la scelta migliore quando si desidera un'interfaccia di libreria nativa per strumenti e flussi di lavoro lato server senza dover costruire un client JSON-RPC a parte. Poiché è stato distribuito prima del server delle applicazioni, attualmente supporta meno lingue e una superficie funzionale più limitata. Qualora vi sia interesse da parte degli sviluppatori, potremmo aggiungere ulteriori SDK che incapsulano il protocollo dell'App Server, permettendo ai team di gestire più superfici dell'integrazione senza scrivere binding JSON-RPC.

Sviluppi futuri

In questo articolo abbiamo raccontato come affrontiamo la progettazione di un nuovo standard per interagire con gli agenti e come trasformiamo l'integrazione di Codex in un protocollo stabile e adatto ai client. Abbiamo mostrato come l'App Server esponga il Codex core e consenta ai client di gestire l'intero ciclo dell'agente, alimentando superfici diverse come la TUI, le integrazioni IDE locali e il runtime web.

Se queste informazioni ti hanno dato idee per integrare Codex nei tuoi flussi di lavoro, vale la pena provare App Server. Tutto il codice sorgente si trova nel repository open source Codex CLI repo(si apre in una nuova finestra). Non esitare a inviarci il tuo riscontro e suggerimenti per nuove funzionalità. Saremo felici di sentirti e di continuare a rendere gli agenti più accessibili per tutti.

Autore

Celia Chen

Ringraziamenti

Un ringraziamento speciale a Michael Bolin, Owen Lin, Eric Traut e Rasmus Rygaard, che hanno contribuito a questo post, e all'intero team di Codex che ha lavorato sull'App Server.

Note di riferimento

  1. 1

    Utilizziamo una variante “JSON‑RPC lite”: mantiene la struttura di richiesta/risposta/notifica, ma omette l'header "jsonrpc": "2.0" ed è strutturata come JSONL su stdio anziché seguire rigidamente lo standard JSON‑RPC 2.0.

  2. 2

     “stdio” si riferisce allo stdin/stdout dell'app-server all'interno del container. Nelle configurazioni ospitate, questi stream vengono spesso instradati tramite un tunnel su una connessione di rete persistente (ad esempio, simile a WebSocket) verso il runtime del container: quindi si comporta come stdio anche se non è una pipe locale letterale.