Français

Serveur d’application Codex

Serveur d’application Codex

Le serveur d’application Codex est l’interface qu’utilise Codex pour alimenter des clients riches (par exemple, l’extension Codex pour VS Code). Utilisez-le lorsque vous souhaitez intégrer étroitement Codex à votre propre produit : authentification, historique des conversations, approbations et événements de l’agent diffusés en continu. L’implémentation du serveur d’application est open source dans le dépôt GitHub de Codex (openai/codex/codex-rs/app-server). Consultez la page Open Source pour obtenir la liste complète des composants open source de Codex.

Connecter l’interface de terminal de la CLI

Le mode d’interface de terminal à distance vous permet d’exécuter le serveur d’application sur une machine et de connecter l’interface de terminal de la CLI Codex depuis une autre. Démarrez un écouteur WebSocket :

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

Connectez ensuite l’interface de terminal :

codex --remote ws://127.0.0.1:4500

Pour une connexion non locale, configurez l’authentification WebSocket et placez la connexion derrière TLS. Stockez le jeton bearer dans une variable d’environnement et transmettez son nom au lieu de placer le jeton sur la ligne de commande :

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

L’option --remote accepte les points de terminaison ws://, wss://, unix:// et unix://PATH. N’utilisez des WebSockets sans chiffrement que pour localhost ou une connexion transférée par port SSH.

Connecter un hôte Code Mode distant

Par défaut, le serveur d’application démarre un hôte Code Mode local. Pour utiliser plutôt un hôte distant, transmettez son URL WebSocket sécurisée :

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

--code-mode-host contrôle la connexion sortante du serveur d’application vers son hôte Code Mode. Cela ne modifie pas --listen, qui contrôle la manière dont les clients se connectent au serveur d’application. Tous les threads d’un même processus de serveur d’application partagent la connexion à l’hôte Code Mode sélectionné.

Utilisez wss:// pour un hôte distant. N’utilisez ws:// que pour localhost ou une connexion transférée par SSH. La commande du serveur d’application et le transport WebSocket sont expérimentaux et ne sont pas pris en charge pour les charges de travail de production.

Protocole

Comme MCP, codex app-server prend en charge la communication bidirectionnelle au moyen de messages JSON-RPC 2.0 (avec l’en-tête "jsonrpc":"2.0" omis lors de la transmission).

Transports pris en charge :

  • stdio (--listen stdio://, par défaut) : JSON délimité par des retours à la ligne (JSONL).
  • websocket (--listen ws://IP:PORT, expérimental et non pris en charge) : un message JSON-RPC par trame de texte WebSocket.
  • Socket Unix (--listen unix:// ou --listen unix://PATH) : connexions WebSocket via le socket de contrôle par défaut du serveur d’application de Codex ou un socket Unix personnalisé, en utilisant la négociation HTTP Upgrade standard.
  • off (--listen off) : n’expose aucun transport local.

Lorsque vous exécutez le serveur avec --listen ws://IP:PORT, le même écouteur fournit également des sondes d’intégrité HTTP élémentaires :

  • GET /readyz renvoie 200 OK dès que l’écouteur accepte de nouvelles connexions.
  • GET /healthz renvoie 200 OK lorsque la requête ne contient pas d’en-tête Origin.
  • Les requêtes comportant un en-tête Origin sont rejetées avec 403 Forbidden.

Le transport WebSocket est expérimental et non pris en charge. Les écouteurs locaux tels que ws://127.0.0.1:PORT conviennent aux workflows localhost et de transfert de port SSH. Pendant le déploiement, les écouteurs WebSocket qui ne sont pas limités à l’interface loopback autorisent actuellement les connexions non authentifiées par défaut ; configurez donc l’authentification WebSocket avant d’en exposer un à distance.

Options d’authentification WebSocket prises en charge :

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

Pour les jetons bearer signés, vous pouvez également définir --ws-issuer, --ws-audience et --ws-max-clock-skew-seconds. Les clients présentent l’identifiant comme Authorization: Bearer <token> pendant la négociation WebSocket, et le serveur d’application impose l’authentification avant l’opération JSON-RPC initialize.

Préférez --ws-token-file à la transmission de jetons bearer bruts sur la ligne de commande. Utilisez --ws-token-sha256 uniquement lorsque le client conserve le jeton brut à forte entropie dans un magasin de secrets local distinct ; le hachage ne sert que de vérificateur et les clients ont toujours besoin du jeton d’origine.

En mode WebSocket, le serveur d’application utilise des files d’attente de taille limitée. Lorsque la file d’entrée des requêtes est pleine, le serveur rejette les nouvelles requêtes avec le code d’erreur JSON-RPC -32001 et le message "Server overloaded; retry later." Les clients doivent réessayer avec un délai croissant de manière exponentielle et une gigue aléatoire.

Schéma des messages

Les requêtes comprennent method, params et id :

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

Les réponses reprennent le champ id avec soit result, soit error :

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

Les notifications omettent id et utilisent uniquement method et params :

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

Vous pouvez générer un schéma TypeScript ou un ensemble de schémas JSON depuis la CLI. Chaque sortie est propre à la version de Codex que vous avez exécutée ; les artefacts générés correspondent donc exactement à cette version :

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

Prise en main

  1. Démarrez le serveur avec codex app-server (transport stdio par défaut), codex app-server --listen ws://127.0.0.1:4500 (WebSocket TCP) ou codex app-server --listen unix:// (socket Unix par défaut).
  2. Connectez un client au moyen du transport sélectionné, puis envoyez initialize, suivi de la notification initialized.
  3. Démarrez un thread et un tour, puis continuez à lire les notifications dans le flux du transport actif.

Exemple (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" } });

Concepts fondamentaux

  • Thread : conversation entre un utilisateur et l’agent Codex. Les threads contiennent des tours.
  • Tour : requête unique d’un utilisateur et travail effectué ensuite par l’agent. Les tours contiennent des éléments et diffusent des mises à jour incrémentielles.
  • Élément : unité d’entrée ou de sortie (message utilisateur, message de l’agent, exécution de commande, modification de fichier, appel d’outil, etc.).

Utilisez les API de thread pour créer, répertorier ou archiver des conversations. Pilotez une conversation avec les API de tour et suivez sa progression grâce aux notifications de tour.

Vue d’ensemble du cycle de vie

  • Initialiser une fois par connexion : immédiatement après l’ouverture d’une connexion de transport, envoyez une requête initialize avec les métadonnées de votre client, puis émettez initialized. Le serveur rejette toute requête sur cette connexion avant cette négociation.
  • Démarrer (ou reprendre) un thread : appelez thread/start pour une nouvelle conversation, thread/resume pour poursuivre une conversation existante ou thread/fork pour créer une branche de l’historique avec un nouvel identifiant de thread.
  • Commencer un tour : appelez turn/start avec le threadId cible et l’entrée utilisateur. Les champs facultatifs remplacent le modèle, la personnalité, cwd, la politique de sandbox, etc.
  • Orienter un tour actif : appelez turn/steer pour ajouter une entrée utilisateur au tour actuellement en cours sans créer de nouveau tour.
  • Diffuser les événements : après turn/start, continuez à lire les notifications sur stdout : thread/archived, thread/unarchived, item/started, item/completed, item/agentMessage/delta, la progression des outils et d’autres mises à jour.
  • Terminer le tour : le serveur émet turn/completed avec l’état final lorsque le modèle a terminé ou après une annulation turn/interrupt.

Initialisation

Les clients doivent envoyer une seule requête initialize par connexion de transport avant d’appeler toute autre méthode sur cette connexion, puis en accuser réception avec une notification initialized. Les requêtes envoyées avant l’initialisation reçoivent une erreur Not initialized, et les appels répétés à initialize sur la même connexion renvoient Already initialized.

Le serveur renvoie la chaîne user-agent qu’il présentera aux services en amont, ainsi que les valeurs platformFamily et platformOs décrivant la cible d’exécution. Définissez clientInfo pour identifier votre intégration.

initialize.params.capabilities prend également en charge les capacités client suivantes :

  • optOutNotificationMethods - noms exacts des méthodes de notification à supprimer pour cette connexion. La correspondance est exacte (sans caractères génériques ni préfixes) ; les noms inconnus sont acceptés et ignorés.
  • requestAttestation - permet d’accepter la requête attestation/generate initiée par le serveur. Les hôtes de bureau qui fournissent une attestation en amont répondent avec une valeur { "token": "..." } opaque.
  • mcpServerOpenaiFormElicitation - autorise les serveurs MCP en aval à envoyer la variante étendue OpenAI de mcpServer/elicitation/request.

Important : utilisez clientInfo.name pour identifier votre client auprès de l’OpenAI Compliance Logs Platform. Si vous développez une nouvelle intégration Codex destinée à un usage en entreprise, veuillez contacter OpenAI afin qu’elle soit ajoutée à la liste des clients connus. Pour plus de contexte, consultez la référence sur les journaux Codex.

Exemple (tiré de l’extension Codex pour VS Code) :

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

Exemple avec désactivation de certaines notifications :

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

Activation de l’API expérimentale

Certaines méthodes et certains champs du serveur d’application sont intentionnellement conditionnés par la capacité experimentalApi.

  • Omettez capabilities (ou définissez experimentalApi sur false) pour rester sur la surface d’API stable ; le serveur rejettera alors les méthodes et champs expérimentaux.
  • Définissez capabilities.experimentalApi sur true pour activer les méthodes et champs expérimentaux.
{
  "method": "initialize",
  "id": 1,
  "params": {
    "clientInfo": {
      "name": "my_client",
      "title": "My Client",
      "version": "0.1.0"
    },
    "capabilities": {
      "experimentalApi": true
    }
  }
}

Si un client envoie une méthode ou un champ expérimental sans l’avoir activé, le serveur d’application le rejette avec :

<descriptor> requires experimentalApi capability

Vue d’ensemble de l’API

  • thread/start - crée un nouveau thread ; émet thread/started et vous abonne automatiquement aux événements de tour et d’élément de ce thread.
  • thread/resume - rouvre un thread existant à partir de son id afin que les appels turn/start ultérieurs y ajoutent du contenu.
  • thread/fork - crée un nouveau thread à partir d’un fork en copiant l’historique stocké. Transmettez lastTurnId pour copier l’historique jusqu’à ce tour et omettre les tours suivants, ou ephemeral: true pour créer un fork en mémoire. Émet thread/started pour le nouveau thread ; les threads renvoyés incluent forkedFromId lorsqu’il est disponible.
  • thread/read - lit un thread stocké à partir de son id sans le reprendre ; définissez includeTurns pour renvoyer l’historique complet des tours. Les objets thread renvoyés incluent le status d’exécution.
  • thread/list - parcourt par pages les journaux des threads stockés ; prend en charge la pagination par curseur ainsi que modelProviders, sourceKinds, archived, isPinned, cwd, useStateDbOnly, searchTerm et les filtres expérimentaux parentThreadId ou ancestorThreadId. Les objets thread renvoyés incluent le status d’exécution.
  • thread/turns/list - expérimental ; parcourt par pages l’historique des tours d’un thread stocké sans le reprendre. itemsView détermine si les éléments des tours sont omis, résumés ou chargés intégralement.
  • thread/items/list - expérimental ; parcourt par pages les éléments persistants d’un thread, avec la possibilité de limiter les résultats à un seul turnId. Le stockage de threads actif doit prendre en charge la pagination des éléments.
  • thread/loaded/list - répertorie les identifiants des threads actuellement chargés en mémoire.
  • thread/name/set - définit ou met à jour le nom visible par l’utilisateur d’un thread chargé ou d’un rollout persistant ; émet thread/name/updated.
  • thread/goal/set - définit l’objectif d’un thread ; émet thread/goal/updated.
  • thread/goal/get - lit l’objectif actuel d’un thread.
  • thread/goal/clear - efface l’objectif d’un thread ; émet thread/goal/cleared.
  • thread/metadata/update - met à jour les métadonnées des threads stockés adossées à SQLite, y compris les valeurs persistantes gitInfo et isPinned.
  • thread/archive - déplace le fichier journal d’un thread vers le répertoire d’archivage et tente d’archiver les journaux des threads descendants générés qui ne le sont pas encore ; renvoie {} en cas de réussite et émet thread/archived pour chaque thread archivé.
  • thread/delete - supprime définitivement un thread persistant actif ou archivé ainsi que tous les threads descendants générés ; renvoie {} en cas de réussite et émet thread/deleted pour chaque thread supprimé.
  • thread/unsubscribe - désabonne cette connexion des événements de tour et d’élément du thread. S’il s’agissait du dernier abonné, le serveur décharge le thread après un délai de grâce d’inactivité sans abonné et émet thread/closed.
  • thread/unarchive - restaure le rollout d’un thread archivé dans le répertoire des sessions actives ; renvoie le thread restauré et émet thread/unarchived.
  • thread/status/changed - notification émise lorsque le status d’exécution d’un thread chargé change.
  • thread/compact/start - déclenche la compaction de l’historique de conversation d’un thread ; renvoie immédiatement {} tandis que la progression est diffusée via les notifications turn/* et item/*.
  • thread/shellCommand - exécute une commande shell lancée par l’utilisateur sur un thread. Elle s’exécute hors du bac à sable avec un accès complet et n’hérite pas de la politique de bac à sable du thread.
  • thread/backgroundTerminals/clean - arrête tous les terminaux d’arrière-plan en cours d’exécution pour un thread (expérimental ; nécessite capabilities.experimentalApi).
  • thread/backgroundTerminals/list - répertorie les terminaux d’arrière-plan en cours d’exécution pour un thread chargé (expérimental ; nécessite capabilities.experimentalApi).
  • thread/backgroundTerminals/terminate - met fin à un terminal d’arrière-plan en cours d’exécution à partir du processId d’app-server (expérimental ; nécessite capabilities.experimentalApi).
  • thread/rollback - obsolète ; retire les N derniers tours du contexte en mémoire et conserve un marqueur de restauration ; renvoie le thread mis à jour.
  • turn/start - ajoute une entrée utilisateur ou une sortie d’outil autonome à un thread et démarre la génération de Codex ; répond avec le turn initial et diffuse les événements. Pour collaborationMode, settings.developer_instructions: null signifie « utiliser les instructions intégrées pour le mode sélectionné ».
  • thread/inject_items - ajoute des éléments bruts de Responses API à l’historique visible par le modèle d’un thread chargé sans démarrer de tour utilisateur.
  • turn/steer - ajoute une entrée utilisateur au tour actif en cours d’un thread ; renvoie le turnId accepté.
  • turn/interrupt - demande l’annulation d’un tour en cours ; la réussite correspond à {} et le tour se termine avec status: "interrupted".
  • review/start - lance le réviseur Codex pour un thread ; émet les éléments enteredReviewMode et exitedReviewMode.
  • command/exec - exécute une seule commande dans le bac à sable du serveur sans démarrer de thread ni de tour.
  • command/exec/write - écrit des octets stdin dans une session command/exec en cours d’exécution ou ferme stdin.
  • command/exec/resize - redimensionne une session command/exec en cours d’exécution adossée à un PTY.
  • command/exec/terminate - arrête une session command/exec en cours d’exécution.
  • command/exec/outputDelta (notification) - émise pour les fragments stdout/stderr encodés en base64 provenant d’une session command/exec diffusée en continu.
  • process/spawn - démarre une session de processus explicite hors du bac à sable de Codex (expérimental ; nécessite capabilities.experimentalApi).
  • process/writeStdin - écrit des octets stdin dans une session process/spawn en cours d’exécution ou ferme stdin (expérimental).
  • process/resizePty - redimensionne une session de processus en cours d’exécution adossée à un PTY (expérimental).
  • process/kill - met fin à une session de processus en cours d’exécution (expérimental).
  • process/outputDelta et process/exited (notification) - émises pour la sortie de processus diffusée en continu et l’état de sortie du processus (expérimental).
  • model/list - répertorie les modèles disponibles (définissez includeHidden: true pour inclure les entrées avec hidden: true), avec les options d’effort, le champ facultatif upgrade et inputModalities.
  • modelProvider/capabilities/read - lit les limites des capacités du fournisseur pour les combinaisons modèle/fournisseur.
  • experimentalFeature/list - répertorie les indicateurs de fonctionnalités avec les métadonnées de leur phase de cycle de vie et une pagination par curseur.
  • experimentalFeature/enablement/set - modifie les paramètres d’exécution en mémoire pour les clés de fonctionnalités prises en charge, telles que apps et plugins.
  • environment/info - expérimental ; se connecte à un environnement d’exécution configuré et renvoie son shell ainsi que son répertoire de travail par défaut.
  • permissionProfile/list - répertorie les profils d’autorisation bêta et indique si les exigences effectives les permettent, avec une pagination par curseur.
  • collaborationMode/list - répertorie les préréglages du mode de collaboration (expérimental, sans pagination).
  • skills/list - répertorie les skills pour une ou plusieurs valeurs cwd (prend en charge forceReload et le champ facultatif perCwdExtraUserRoots).
  • skills/extraRoots/set - remplace les racines supplémentaires au niveau du processus utilisées pour découvrir des skills autonomes, sans les conserver.
  • skills/changed (notification) - émise lorsque des fichiers de skill locaux surveillés changent.
  • hooks/list - répertorie les hooks de cycle de vie découverts pour une ou plusieurs valeurs cwd.
  • marketplace/add - ajoute une marketplace de plugins distante et la conserve dans la configuration des marketplaces de l’utilisateur.
  • marketplace/remove - supprime une marketplace configurée et, s’il existe, le répertoire racine de sa marketplace installée.
  • marketplace/upgrade - actualise une marketplace Git configurée, ou toutes les marketplaces Git configurées si vous omettez le nom de la marketplace.
  • plugin/list - en cours de développement ; répertorie les marketplaces de plugins découvertes et l’état des plugins, notamment les métadonnées des politiques d’installation et d’authentification, les erreurs de chargement des marketplaces, les identifiants des plugins mis en avant et les métadonnées des sources de plugins locales, Git, de registre de paquets ou distantes. Les résumés peuvent inclure les éléments distants version, locaux localVersion, des icônes structurées pour les thèmes clair et sombre ainsi que installPolicySource, qui peut prendre la valeur null, WORKSPACE_SETTING ou IMPLICIT_CANONICAL_APP pour les lignes distantes actuelles. N’appelez pas encore cette méthode depuis des clients en production.
  • plugin/read - en cours de développement ; lit un plugin à partir du chemin de sa marketplace, ou du nom de la marketplace distante et du nom du plugin, notamment les skills, apps et noms de serveurs MCP inclus, ainsi qu’un shareUrl de plugin distant lorsque le catalogue distant en fournit un. N’appelez pas encore cette méthode depuis des clients en production.
  • plugin/install - en cours de développement ; installe un plugin à partir du chemin d’une marketplace ou du nom d’une marketplace distante. N’appelez pas encore cette méthode depuis des clients en production.
  • plugin/uninstall - en cours de développement ; désinstalle un plugin installé. N’appelez pas encore cette méthode depuis des clients en production.
  • plugin/skill/read - lit à la demande le Markdown d’un skill de plugin distant à partir de la marketplace distante, de l’identifiant du plugin et du nom du skill.
  • app/installed - lit l’état d’exécution des apps installées, notamment l’état effectif d’activation et d’appel de chaque app.
  • app/list - répertorie les apps (connecteurs) disponibles avec pagination et métadonnées d’accessibilité et d’activation.
  • app/read - récupère les métadonnées et, éventuellement, des résumés d’outils destinés uniquement à l’affichage pour des identifiants d’app spécifiques.
  • skills/config/write - active ou désactive des skills à partir de leur chemin.
  • mcpServer/oauth/login - démarre une connexion OAuth pour un serveur MCP configuré ; renvoie une URL d’autorisation et émet mcpServer/oauthLogin/completed à la fin.
  • tool/requestUserInput - invite l’utilisateur à répondre à 1 à 3 questions courtes pour un appel d’outil (expérimental) ; les questions peuvent définir isOther pour une option de saisie libre.
  • mcpServer/elicitation/request (requête du serveur) - demande au client une saisie structurée dans un formulaire ou la confirmation d’un flux d’URL demandé par un serveur MCP.
  • item/permissions/requestApproval (requête du serveur) - demande au client d’accorder un sous-ensemble des autorisations réseau ou de système de fichiers requises par l’outil request_permissions intégré.
  • config/mcpServer/reload - recharge depuis le disque la configuration des serveurs MCP et place en file d’attente une actualisation pour les threads chargés.
  • mcpServerStatus/list - répertorie les serveurs, outils et ressources MCP ainsi que l’état de l’authentification (pagination par curseur et limite). Utilisez detail: "full" pour obtenir toutes les données ou detail: "toolsAndAuthOnly" pour omettre les ressources.
  • mcpServer/resource/read - lit une seule ressource MCP au moyen d’un serveur MCP initialisé.
  • mcpServer/tool/call - appelle un outil sur le serveur MCP configuré d’un thread.
  • mcpServer/startupStatus/updated (notification) - émise lorsque l’état de démarrage d’un serveur MCP configuré change pour un thread chargé.
  • windowsSandbox/setupStart - démarre la configuration du bac à sable Windows pour le mode elevated ou unelevated ; renvoie rapidement une réponse, puis émet ultérieurement windowsSandbox/setupCompleted.
  • feedback/upload - envoie un rapport de commentaires (classification, motif/journaux facultatifs et identifiant de conversation, ainsi que des pièces jointes extraLogFiles facultatives).
  • config/read - récupère la configuration effective sur le disque après résolution des différentes couches de configuration.
  • externalAgentConfig/detect - détecte les artefacts d’agents externes pouvant être migrés avec includeHome et, facultativement, cwds ; chaque élément détecté inclut cwd (null pour le répertoire personnel).
  • externalAgentConfig/import - applique les éléments de migration d’agents externes sélectionnés en transmettant explicitement migrationItems avec cwd (null pour le répertoire personnel). Les types d’éléments pris en charge comprennent la configuration, les skills, AGENTS.md, les plugins, la configuration des serveurs MCP, les sous-agents, les hooks, les commandes et les sessions ; les importations non vides émettent externalAgentConfig/import/progress et externalAgentConfig/import/completed au fil de l’avancement. Les importations de plugins et de sessions peuvent se terminer de manière asynchrone.
  • config/value/write - écrit une seule clé/valeur de configuration dans le fichier config.toml de l’utilisateur sur le disque.
  • config/batchWrite - applique de manière atomique des modifications de configuration au fichier config.toml de l’utilisateur sur le disque.
  • configRequirements/read - récupère les exigences depuis requirements.toml et/ou MDM, notamment la configuration gérée exacte, les listes d’autorisation, les featureRequirements épinglés et les exigences réseau (ou null si vous n’en avez configuré aucune).
  • fs/readFile, fs/writeFile, fs/createDirectory, fs/getMetadata, fs/readDirectory, fs/remove, fs/copy, fs/watch, fs/unwatch et fs/changed (notification) - agissent sur des chemins absolus du système de fichiers au moyen de l’API de système de fichiers app-server v2.

Les résumés de plugins incluent une union source. Les plugins locaux renvoient { "type": "local", "path": ... }, les entrées de marketplace reposant sur Git renvoient { "type": "git", "url": ..., "path": ..., "refName": ..., "sha": ... }, les entrées de registre de paquets renvoient { "type": "npm", "package": ..., "version": ..., "registry": ... } et les entrées de catalogue distant renvoient { "type": "remote" }. Pour les entrées de catalogue uniquement distantes, PluginMarketplaceEntry.path peut valoir null ; transmettez remoteMarketplaceName au lieu de marketplacePath lors de la lecture ou de l’installation de ces plugins.

Modèles

Répertorier les modèles (model/list)

Appelez model/list pour découvrir les modèles disponibles et leurs capacités avant d’afficher les sélecteurs de modèle ou de personnalité.

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

Chaque entrée de modèle peut inclure :

  • supportedReasoningEfforts - options d’effort prises en charge par le modèle.
  • defaultReasoningEffort - effort par défaut suggéré pour les clients.
  • upgrade - identifiant facultatif du modèle de mise à niveau recommandé pour les invites de migration dans les clients.
  • upgradeInfo - métadonnées de mise à niveau facultatives pour les invites de migration dans les clients.
  • hidden - indique si le modèle est masqué dans la liste du sélecteur par défaut.
  • inputModalities - types d’entrée pris en charge par le modèle (par exemple text, image).
  • supportsPersonality - indique si le modèle prend en charge les instructions propres à une personnalité, telles que /personality.
  • isDefault - indique si le modèle est celui recommandé par défaut.

Par défaut, model/list renvoie uniquement les modèles visibles dans le sélecteur. Définissez includeHidden: true si vous avez besoin de la liste complète et souhaitez effectuer le filtrage côté client avec hidden.

Lorsque inputModalities est absent (anciens catalogues de modèles), considérez-le comme ["text", "image"] pour assurer la rétrocompatibilité.

Répertorier les fonctionnalités expérimentales (experimentalFeature/list)

Utilisez ce point de terminaison pour découvrir les indicateurs de fonctionnalité avec leurs métadonnées et leur étape de cycle de vie :

{ "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 peut valoir beta, underDevelopment, stable, deprecated ou removed. Pour les indicateurs non bêta, displayName, description et announcement peuvent valoir null.

Inspecter un environnement d’exécution (expérimental)

Utilisez environment/info pour inspecter un environnement distant configuré avant d’y commencer le travail. La méthode nécessite 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 peut valoir null. Lorsqu’il est présent, il s’agit d’un URI file: canonique qui utilise la syntaxe de chemin native de l’environnement. Les identifiants d’environnement inconnus et les échecs de connexion ou de protocole renvoient des erreurs de requête.

Threads

  • thread/read lit un thread stocké sans s’y abonner ; définissez includeTurns pour inclure les tours.
  • thread/turns/list est expérimental et parcourt par pages l’historique des tours d’un thread stocké sans le reprendre. Utilisez itemsView pour choisir si les éléments des tours sont omis, résumés ou chargés intégralement.
  • thread/items/list est expérimental et parcourt par pages les éléments persistants d’un thread, avec la possibilité de les limiter à un seul tour.
  • thread/list prend en charge la pagination par curseur ainsi que les filtres modelProviders, sourceKinds, archived, isPinned, cwd, useStateDbOnly, searchTerm et les filtres expérimentaux parentThreadId ou ancestorThreadId.
  • thread/loaded/list renvoie les identifiants des threads actuellement en mémoire.
  • thread/archive déplace le journal JSONL persistant du thread vers le répertoire des archives et tente d’archiver les journaux des threads descendants générés qui ne le sont pas encore.
  • thread/delete supprime définitivement un thread persistant actif ou archivé ainsi que ses threads descendants générés.
  • thread/metadata/update modifie les métadonnées stockées du thread, notamment les champs persistants gitInfo et isPinned.
  • thread/unsubscribe désabonne la connexion actuelle d’un thread chargé et peut déclencher thread/closed après un délai de grâce sans activité.
  • thread/unarchive restaure le rollout d’un thread archivé dans le répertoire des sessions actives.
  • thread/compact/start déclenche la compaction et renvoie immédiatement {}.
  • thread/rollback est obsolète. Il retire les N derniers tours du contexte en mémoire et enregistre un marqueur de restauration dans le journal JSONL persistant du thread.
  • thread/inject_items ajoute des éléments bruts de la Responses API à l’historique visible par le modèle d’un thread chargé sans démarrer de tour utilisateur.

Démarrer ou reprendre un thread

Démarrez un nouveau thread lorsque vous avez besoin d’une nouvelle conversation Codex.

{ "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 est facultatif. Définissez-le lorsque vous souhaitez que le serveur d’application associe aux métriques du thread le nom de service de votre intégration.

thread/start, thread/resume et thread/fork renvoient instructionSources, un tableau de chemins de fichiers d’instructions chargés. Chaque chemin utilise la syntaxe absolue native de son environnement source, y compris pour les environnements distants.

Les clients expérimentaux peuvent définir historyMode sur thread/start avec la valeur "legacy" (par défaut) ou "paginated". La création de threads paginés n’est pas encore prise en charge et renvoie l’erreur JSON-RPC -32601. Le serveur d’application peut répertorier et lire les résumés des enregistrements paginés existants, mais les lectures de l’historique complet, la pagination des tours et la reprise échouent de manière sécurisée tant que l’historique paginé n’est pas pris en charge.

Les clients bêta qui activent capabilities.experimentalApi peuvent transmettre un identifiant de profil d’autorisation nommé dans permissions au lieu de l’ancien champ sandbox. N’envoyez pas permissions et sandbox ensemble. Utilisez permissionProfile/list avec le cwd du projet pour découvrir les profils disponibles et savoir si les exigences gérées autorisent chacun d’eux.

thread.sessionId identifie la racine de l’arborescence de sessions active actuelle. Les threads racines utilisent leur propre identifiant de thread comme identifiant de session ; les threads dérivés conservent l’identifiant de session de leur racine d’origine. Les clients doivent lire l’identifiant de session dans thread.sessionId plutôt que de le déduire de l’identifiant de thread.

Pour poursuivre une session stockée, appelez thread/resume avec le thread.id que vous avez enregistré auparavant. La structure de la réponse correspond à thread/start. Vous pouvez également transmettre les mêmes remplacements de configuration que ceux pris en charge par thread/start, comme 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 } } }

La reprise d’un thread ne met pas à jour thread.updatedAt (ni l’heure de modification du fichier de rollout) à elle seule. L’horodatage est mis à jour lorsque vous démarrez un tour.

Si vous marquez un serveur MCP activé comme required dans la configuration et que l’initialisation de ce serveur échoue, thread/start et thread/resume échouent au lieu de continuer sans lui.

dynamicTools dans thread/start est un champ expérimental (nécessite capabilities.experimentalApi = true). Codex conserve ces outils dynamiques dans les métadonnées de rollout du thread et les restaure lors de thread/resume si vous ne fournissez pas de nouveaux outils dynamiques.

Si vous reprenez un thread avec un modèle différent de celui enregistré dans le rollout, Codex émet un avertissement et applique une instruction ponctuelle de changement de modèle au tour suivant.

Gérer l’objectif d’un thread

Utilisez thread/goal/set, thread/goal/get et thread/goal/clear pour gérer le même état d’objectif persistant que celui présenté par /goal dans la 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
  }
} }

Les objectifs doivent être non vides et ne pas dépasser 4 000 caractères. Fournir un nouvel objectif remplace l’objectif et réinitialise le suivi de l’utilisation. Fournir l’objectif actuel non terminal, ou omettre objective, met à jour l’état ou le budget de jetons tout en préservant l’historique d’utilisation.

Pour créer une branche à partir d’une session stockée, appelez thread/fork avec le thread.id. Cela crée un nouvel identifiant de thread et émet une notification thread/started correspondante. Transmettez lastTurnId pour copier l’historique jusqu’à ce tour inclus et omettre les tours suivants :

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

Le serveur d’application rejette un lastTurnId en cours. Si vous omettez ce champ alors que le thread source est au milieu d’un tour, la branche enregistre un marqueur d’interruption au lieu de conserver un tour partiel non marqué.

Transmettez ephemeral: true pour créer une branche en mémoire sans l’ajouter aux listes de threads stockés :

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

Les branches éphémères de threads paginés nécessitent également excludeTurns: true. Ce champ est expérimental et nécessite capabilities.experimentalApi = true.

Lorsqu’un titre de thread visible par l’utilisateur a été défini, le serveur d’application renseigne thread.name dans les réponses thread/list, thread/read, thread/resume, thread/unarchive et thread/rollback. thread/start et thread/fork peuvent omettre name (ou renvoyer null) jusqu’à ce qu’un titre soit défini ultérieurement.

Lire un thread stocké (sans le reprendre)

Utilisez thread/read lorsque vous souhaitez obtenir les données d’un thread stocké sans le reprendre ni vous abonner à ses événements.

  • includeTurns - lorsqu’il vaut true, la réponse inclut les tours du thread ; lorsqu’il vaut false ou est omis, vous obtenez uniquement le résumé du thread.
  • Les objets thread renvoyés incluent le champ d’exécution status (notLoaded, idle, systemError ou active avec 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": [] } } }

Contrairement à thread/resume, thread/read ne charge pas le thread en mémoire et n’émet pas thread/started.

Répertorier les tours d’un thread

thread/turns/list est expérimental. Utilisez-le pour parcourir par pages l’historique des tours d’un thread stocké sans le reprendre. Par défaut, les résultats sont classés du plus récent au plus ancien afin que les clients puissent récupérer les tours plus anciens avec nextCursor. La réponse inclut également backwardsCursor ; transmettez-le comme cursor avec sortDirection: "asc" pour récupérer les tours plus récents que le premier élément de la page précédente.

itemsView contrôle la quantité de données des éléments de tour incluse dans la réponse :

  • notLoaded omet les éléments.
  • summary renvoie des données résumées sur les éléments et constitue la valeur par défaut lorsqu’il est omis.
  • full renvoie les données complètes des éléments.
{ "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 est également expérimental. Il parcourt par pages les éléments persistants sans reprendre le thread. Transmettez turnId pour limiter les résultats à un seul tour, ou omettez-le pour parcourir par pages les éléments de l’ensemble du thread. Le magasin de threads actif doit prendre en charge la pagination des éléments ; sinon, le serveur renvoie une erreur indiquant que la méthode n’est pas prise en charge.

Répertorier les threads (avec pagination et filtres)

thread/list vous permet d’afficher une interface d’historique. Par défaut, les résultats sont classés du plus récent au plus ancien selon createdAt. Les filtres s’appliquent avant la pagination. Transmettez n’importe quelle combinaison des champs suivants :

  • cursor - chaîne opaque issue d’une réponse précédente ; omettez-la pour la première page.
  • limit - le serveur utilise par défaut une taille de page raisonnable si ce champ n’est pas défini.
  • sortKey - created_at (par défaut), updated_at ou recency_at.
  • sortDirection - desc (par défaut) ou asc.
  • modelProviders - limite les résultats à des fournisseurs précis ; une valeur non définie, null ou un tableau vide inclut tous les fournisseurs.
  • sourceKinds - limite les résultats à des sources de threads précises. Lorsqu’il est omis ou vaut [], le serveur utilise par défaut uniquement les sources interactives : cli et vscode.
  • archived - lorsqu’il vaut true, répertorie uniquement les threads archivés. Lorsqu’il vaut false ou est omis, répertorie les threads non archivés (par défaut).
  • isPinned - lorsqu’il est fourni, renvoie uniquement les threads dont l’état d’épinglage persistant correspond. Omettez-le pour renvoyer les threads épinglés et non épinglés.
  • cwd - limite les résultats aux threads dont le répertoire de travail actuel de la session correspond exactement à ce chemin ou à l’un des chemins d’un tableau. Les chemins relatifs sont résolus à partir du répertoire de travail du processus du serveur d’application.
  • useStateDbOnly - lorsqu’il vaut true, renvoie les résultats de la base de données d’état sans analyser les journaux de threads JSONL pour réparer les métadonnées. Omettez-le ou transmettez false pour le comportement d’analyse et de réparation par défaut.
  • searchTerm - limite les résultats aux threads dont le titre extrait contient ce fragment de texte sensible à la casse.
  • parentThreadId - limite les résultats aux threads enfants directs du thread indiqué. Ce filtre est expérimental et nécessite capabilities.experimentalApi = true.
  • ancestorThreadId - limite les résultats aux descendants générés du thread indiqué, quelle que soit leur profondeur. Ce filtre est expérimental et nécessite capabilities.experimentalApi = true ; ne l’associez pas à parentThreadId.

sourceKinds accepte les valeurs suivantes :

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

Exemple :

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

Lorsque nextCursor vaut null, vous avez atteint la dernière page.

Mettre à jour les métadonnées stockées d’un thread

Utilisez thread/metadata/update pour modifier les métadonnées d’un thread stocké sans le reprendre. Définissez isPinned pour épingler ou désépingler le thread, ou mettez à jour gitInfo pour modifier les métadonnées Git persistantes. Les champs omis restent inchangés ; une valeur null explicite efface une valeur de métadonnée Git stockée.

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

Suivre les changements d’état d’un thread

thread/status/changed est émis chaque fois que l’état d’exécution d’un thread chargé change. La charge utile inclut threadId et le nouveau status.

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

Répertorier les threads chargés

thread/loaded/list renvoie les identifiants des threads actuellement chargés en mémoire.

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

Se désabonner d’un thread chargé

thread/unsubscribe supprime l’abonnement de la connexion actuelle à un thread. L’état de la réponse peut être :

  • unsubscribed lorsque la connexion était abonnée et ne l’est désormais plus.
  • notSubscribed lorsque la connexion n’était pas abonnée à ce thread.
  • notLoaded lorsque le thread n’est pas chargé.

S’il s’agissait du dernier abonné, le serveur conserve le thread chargé jusqu’à ce qu’il n’ait plus aucun abonné ni aucune activité pendant 30 minutes. À l’expiration du délai de grâce, le serveur d’application décharge le thread et émet une transition thread/status/changed vers notLoaded ainsi que thread/closed.

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

Si le thread expire ensuite :

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

Archiver un thread

Utilisez thread/archive pour déplacer le journal persistant du thread (stocké sous forme de fichier JSONL sur le disque) vers le répertoire des sessions archivées. L’archivage d’un thread tente également d’archiver les threads descendants générés qui ne le sont pas encore.

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

Les threads archivés n’apparaîtront pas dans les futurs appels à thread/list, sauf si vous transmettez archived: true. Le serveur émet une notification thread/archived pour chaque thread qu’il archive effectivement ; si un descendant généré ne peut pas être archivé, la requête peut tout de même réussir sans notification d’archivage pour ce descendant.

Supprimer un thread

Utilisez thread/delete pour supprimer définitivement un thread actif ou archivé persistant ainsi que les threads descendants qu’il a créés. Le serveur supprime les fichiers de rollout existants et les métadonnées associées avant de renvoyer un résultat positif ; les fichiers de rollout manquants sont considérés comme déjà supprimés. Les threads racines éphémères ne peuvent pas être supprimés.

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

Désarchiver un thread

Utilisez thread/unarchive pour replacer le rollout d’un thread archivé dans le répertoire des sessions actives.

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

Déclencher la compaction d’un thread

Utilisez thread/compact/start pour déclencher manuellement la compaction de l’historique d’un thread. La requête renvoie immédiatement {}.

App-server émet la progression sous forme de notifications turn/* et item/* standard sur le même threadId, notamment le cycle de vie d’un élément contextCompaction (item/started puis item/completed).

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

Exécuter une commande shell dans un thread

Utilisez thread/shellCommand pour les commandes shell initiées par l’utilisateur qui appartiennent à un thread. La requête renvoie immédiatement {} tandis que la progression est diffusée au moyen des notifications turn/* et item/* standard.

Cette API s’exécute hors du bac à sable avec un accès complet et n’hérite pas de la politique de bac à sable du thread. Les clients ne doivent l’exposer que pour les commandes explicitement initiées par l’utilisateur.

Si le thread comporte déjà un tour actif, la commande s’exécute comme action auxiliaire de ce tour et sa sortie mise en forme est injectée dans le flux de messages du tour. Si le thread est inactif, app-server lance un tour autonome pour la commande shell.

Définissez timeoutMs pour limiter la durée d’exécution en millisecondes. Si vous l’omettez ou transmettez null, la valeur par défaut d’une heure est utilisée. 0 demande une expiration immédiate du délai ; les valeurs négatives sont rejetées. Le délai d’expiration ne retarde pas l’accusé de réception RPC immédiat.

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

Nettoyer les terminaux en arrière-plan

Utilisez thread/backgroundTerminals/clean pour arrêter tous les terminaux en arrière-plan en cours d’exécution associés à un thread. Cette méthode est expérimentale et nécessite capabilities.experimentalApi = true.

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

Utilisez thread/backgroundTerminals/list pour examiner les terminaux en arrière-plan en cours d’exécution pour un thread chargé. La requête prend en charge la pagination standard cursor et limit, et la valeur processId renvoyée correspond à l’identifiant du processus app-server. Cette méthode est expérimentale et nécessite 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 } }

Utilisez thread/backgroundTerminals/terminate avec cette valeur processId pour arrêter un terminal en arrière-plan. Cette méthode est expérimentale et nécessite capabilities.experimentalApi = true :

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

Annuler les tours récents

thread/rollback est obsolète et sera supprimé. Il retire les dernières entrées numTurns du contexte en mémoire et conserve un marqueur d’annulation dans le journal de rollout. La valeur thread renvoyée comprend turns renseigné après l’annulation.

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

Tours

Le champ input accepte une liste d’éléments :

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

Vous pouvez remplacer les paramètres de configuration pour chaque tour (modèle, effort, personnalité, cwd, politique de bac à sable, résumé). Lorsqu’ils sont spécifiés, ces paramètres deviennent les valeurs par défaut des tours suivants du même thread. outputSchema s’applique uniquement au tour actuel. Pour sandboxPolicy.type = "externalSandbox", définissez networkAccess sur restricted ou enabled ; pour workspaceWrite, networkAccess reste une valeur booléenne.

Pour turn/start.collaborationMode, settings.developer_instructions: null signifie « utiliser les instructions intégrées du mode sélectionné » et non supprimer les instructions du mode.

Accès en lecture du bac à sable (ReadOnlyAccess)

sandboxPolicy prend en charge des contrôles explicites de l’accès en lecture :

  • readOnly : valeur access facultative ({ "type": "fullAccess" } par défaut, ou racines restreintes).
  • workspaceWrite : valeur readOnlyAccess facultative ({ "type": "fullAccess" } par défaut, ou racines restreintes).

Structure de l’accès en lecture restreint :

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

Sous macOS, includePlatformDefaults: true ajoute une politique Seatbelt prédéfinie propre à la plateforme pour les sessions à accès en lecture restreint. Cela améliore la compatibilité des outils sans autoriser largement l’intégralité de /System.

Exemples :

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

Démarrer un tour

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

Pour démarrer un tour avec la sortie d’un outil exécuté par votre client, transmettez toolOutput avec un name non vide, un namespace facultatif et une chaîne output ou un tableau d’éléments de contenu. Définissez input sur un tableau vide ; vous ne pouvez pas combiner toolOutput avec une entrée utilisateur non vide.

{
  "method": "turn/start",
  "id": 31,
  "params": {
    "threadId": "thr_123",
    "input": [],
    "toolOutput": {
      "name": "run_tests",
      "namespace": null,
      "output": "All 42 tests passed."
    }
  }
}

La sortie demeure une sortie d’outil dans la conversation et apparaît comme un élément functionCallOutput dans les notifications et l’historique persistant. Si un tour normal est déjà actif, Codex place la sortie en file d’attente pour ce tour.

Injecter des éléments dans un thread

Utilisez thread/inject_items pour ajouter des éléments Responses API préconstruits à l’historique du prompt d’un thread chargé sans démarrer de tour utilisateur. Ces éléments sont conservés dans le rollout et inclus dans les requêtes ultérieures adressées au modèle.

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

Orienter un tour actif

Utilisez turn/steer pour ajouter davantage d’entrées utilisateur au tour actif en cours.

  • Incluez expectedTurnId ; sa valeur doit correspondre à l’identifiant du tour actif.
  • La requête échoue si le thread ne comporte aucun tour actif.
  • turn/steer n’émet pas de nouvelle notification turn/started.
  • turn/steer n’accepte pas les remplacements au niveau du tour (model, cwd, sandboxPolicy ou 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" } }

Démarrer un tour (invoquer un skill)

Invoquez explicitement un skill en incluant $<skill-name> dans l’entrée textuelle et en ajoutant à ses côtés un élément d’entrée skill.

{ "method": "turn/start", "id": 33, "params": {
  "threadId": "thr_123",
  "input": [
    { "type": "text", "text": "$skill-creator Add a new skill for triaging flaky CI and include step-by-step usage." },
    { "type": "skill", "name": "skill-creator", "path": "/Users/me/.codex/skills/skill-creator/SKILL.md" }
  ]
} }
{ "id": 33, "result": { "turn": { "id": "turn_457", "status": "inProgress", "items": [], "error": null } } }

Interrompre un tour

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

En cas de réussite, le tour se termine avec status: "interrupted".

Revue

review/start exécute l’outil de revue de Codex pour un thread et diffuse les éléments de la revue. Les cibles comprennent :

  • uncommittedChanges
  • baseBranch (diff par rapport à une branche)
  • commit (revue d’un commit précis)
  • custom (instructions libres)

Utilisez delivery: "inline" (valeur par défaut) pour exécuter la revue sur le thread existant, ou delivery: "detached" pour créer un nouveau thread de revue par dérivation.

Exemple de requête/réponse :

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

Pour une revue détachée, utilisez "delivery": "detached". La réponse possède la même structure, mais reviewThreadId correspond à l’identifiant du nouveau thread de revue (différent de la valeur threadId d’origine). Le serveur émet également une notification thread/started pour ce nouveau thread avant de diffuser le tour de revue.

Codex diffuse la notification turn/started habituelle, suivie d’un élément item/started contenant un élément enteredReviewMode :

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

Lorsque l’outil de revue a terminé, le serveur émet item/started et item/completed contenant un élément exitedReviewMode avec le texte final de la revue :

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

Utilisez cette notification pour afficher la sortie de l’outil de revue dans votre client.

Exécution de processus

process/* est une API expérimentale de contrôle explicite des processus. Elle nécessite capabilities.experimentalApi = true et s’exécute hors du bac à sable de Codex. Utilisez-la uniquement si votre client expose intentionnellement un contrôle local des processus sans bac à sable.

Démarrez un processus avec process/spawn et fournissez un processHandle, puis utilisez ce handle pour les requêtes d’entrée standard, de redimensionnement et d’arrêt. La sortie est diffusée au moyen des notifications process/outputDelta et la fin de l’exécution au moyen de 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
} }

Utilisez process/writeStdin avec deltaBase64, closeStdin, ou les deux, pour envoyer des entrées. Utilisez process/resizePty pour les événements de redimensionnement du PTY et process/kill pour arrêter un processus en cours d’exécution.

Exécution de commandes

command/exec exécute une seule commande (tableau argv) dans le bac à sable du serveur sans créer de thread.

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

Utilisez sandboxPolicy.type = "externalSandbox" si vous placez déjà le processus du serveur dans un bac à sable et souhaitez que Codex n’applique pas son propre bac à sable. Pour le mode de bac à sable externe, définissez networkAccess sur restricted (valeur par défaut) ou enabled. Pour readOnly et workspaceWrite, utilisez la même structure facultative access / readOnlyAccess que celle présentée ci-dessus.

Remarques :

  • Le serveur rejette les tableaux command vides.
  • sandboxPolicy accepte la même structure que celle utilisée par turn/start (par exemple, dangerFullAccess, readOnly, workspaceWrite, externalSandbox).
  • Lorsqu’il est omis, timeoutMs utilise la valeur par défaut du serveur.
  • Définissez tty: true pour les sessions reposant sur un PTY, et utilisez processId si vous prévoyez d’envoyer ensuite command/exec/write, command/exec/resize ou command/exec/terminate.
  • Définissez streamStdoutStderr: true pour recevoir des notifications command/exec/outputDelta pendant l’exécution de la commande.

Lire les exigences d’administration (configRequirements/read)

Utilisez configRequirements/read pour examiner les exigences d’administration effectives chargées depuis requirements.toml et/ou 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.requirements vaut null lorsqu’aucune exigence n’est configurée. Consultez la documentation sur requirements.toml pour en savoir plus sur les clés et valeurs prises en charge.

Configuration du bac à sable Windows (windowsSandbox/setupStart)

Les clients Windows personnalisés peuvent déclencher la configuration du bac à sable de manière asynchrone au lieu de bloquer lors des vérifications de démarrage.

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

App-server lance la configuration en arrière-plan, puis émet ultérieurement une notification de fin :

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

Modes :

  • elevated - exécute le processus de configuration avec élévation de privilèges du bac à sable Windows.
  • unelevated - exécute l’ancien processus de configuration/vérification préalable.

Système de fichiers

Les API de système de fichiers v2 utilisent des chemins absolus. Utilisez fs/watch lorsqu’un client doit invalider l’état de l’interface utilisateur après la modification d’un fichier ou d’un répertoire.

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

La surveillance d’un fichier émet fs/changed pour le chemin de ce fichier, y compris pour les mises à jour effectuées au moyen d’opérations de remplacement ou de renommage.

Événements

Les notifications d’événements constituent le flux initié par le serveur pour les cycles de vie des threads, des tours et de leurs éléments. Après avoir démarré ou repris un thread, continuez à lire le flux de transport actif pour recevoir les notifications thread/started, thread/archived, thread/unarchived, thread/closed, thread/status/changed, turn/*, item/* et serverRequest/resolved.

Désactivation des notifications

Les clients peuvent supprimer certaines notifications pour chaque connexion en envoyant leurs noms de méthode exacts dans initialize.params.capabilities.optOutNotificationMethods.

  • Correspondance exacte uniquement : item/agentMessage/delta ne supprime que cette méthode.
  • Les noms de méthode inconnus sont ignorés.
  • Cela s’applique aux notifications thread/*, turn/*, item/* et aux notifications v2 associées actuelles.
  • Cela ne s’applique pas aux requêtes, aux réponses ni aux erreurs.

Événements de recherche approximative de fichiers (expérimental)

L’API de session de recherche approximative de fichiers émet des notifications pour chaque requête :

  • fuzzyFileSearch/sessionUpdated - { sessionId, query, files } avec les correspondances actuelles de la requête active.
  • fuzzyFileSearch/sessionCompleted - { sessionId } une fois l’indexation et la recherche de correspondances terminées pour cette requête.

Événements d’avertissement

  • configWarning - { summary, details?, path?, range? } pour les problèmes récupérables de configuration ou d’initialisation.
  • warning - { threadId?, message } pour les avertissements d’exécution non fatals.

Événements de configuration du bac à sable Windows

  • windowsSandbox/setupCompleted - { mode, success, error } émis après la fin d’une requête windowsSandbox/setupStart.

Événements de tour

  • turn/started - { turn } avec l’identifiant du tour, un champ items vide et status: "inProgress".
  • turn/completed - { turn }turn.status vaut completed, interrupted ou failed ; les échecs comportent { error: { message, codexErrorInfo?, additionalDetails? } }.
  • turn/diff/updated - { threadId, turnId, diff } avec le dernier diff unifié agrégé de toutes les modifications de fichiers du tour.
  • turn/plan/updated - { turnId, explanation?, plan } chaque fois que l’agent partage ou modifie son plan ; chaque entrée plan est un élément { step, status } dont la valeur status est pending, inProgress ou completed.
  • hook/started et hook/completed - { threadId, turnId?, run } au démarrage d’un hook de cycle de vie synchrone et lorsque le résumé de son exécution finale est disponible. Ces notifications ne sont pas émises pour les hooks asynchrones.
  • model/safetyBuffering/updated - { threadId, turnId, model, useCases, reasons, showBufferingUi, fasterModel } lorsqu’une réponse entre dans une phase transitoire de mise en mémoire tampon de sécurité.
  • model/rerouted - { threadId, turnId, fromModel, toModel, reason } lorsque le service achemine une requête vers un autre modèle.
  • model/verification - { threadId, turnId, verifications } lorsque le service exige une vérification supplémentaire du compte.
  • thread/tokenUsage/updated - mises à jour de l’utilisation pour le thread actif.

turn/diff/updated et turn/plan/updated comprennent actuellement des tableaux items vides, même lorsque des événements d’élément sont diffusés. Utilisez les notifications item/* comme source de vérité pour les éléments du tour.

Éléments

ThreadItem est l’union discriminée transmise dans les réponses des tours et les notifications item/*. Les types d’éléments courants comprennent :

  • userMessage - {id, content}content est une liste d’entrées utilisateur (text, image ou localImage).
  • functionCallOutput - {id, name, namespace, output} pour une sortie d’outil autonome fournie via turn/start.toolOutput. namespace peut être null.
  • agentMessage - {id, text, phase?} contenant la réponse cumulée de l’agent. Lorsqu’il est présent, phase utilise les valeurs de protocole de Responses API (commentary, final_answer).
  • plan - {id, text} contenant le texte du plan proposé en mode plan. Considérez le dernier élément plan de item/completed comme faisant autorité.
  • reasoning - {id, summary, content}summary contient les résumés de raisonnement diffusés en continu et content les blocs de raisonnement bruts.
  • commandExecution - {id, command, cwd, status, commandActions, aggregatedOutput?, exitCode?, durationMs?}.
  • fileChange - {id, changes, status} décrivant les modifications proposées ; changes répertorie {path, kind, diff}.
  • mcpToolCall - {id, server, tool, status, arguments, appContext?, pluginId?, result?, error?}. Pour les apps MCP approuvées, appContext peut inclure connectorId, linkId, resourceUri, appName, templateId et la valeur stable actionName du connecteur. Les anciens éléments persistants peuvent omettre les métadonnées plus récentes. Utilisez appContext.resourceUri à la place du champ de niveau supérieur mcpAppResourceUri, désormais obsolète.
  • dynamicToolCall - {id, tool, arguments, status, contentItems?, success?, durationMs?} pour les appels dynamiques d’outils exécutés par le client.
  • collabToolCall - {id, tool, status, senderThreadId, receiverThreadId?, newThreadId?, prompt?, agentStatus?}.
  • webSearch - {id, query, action?} pour les requêtes de recherche web émises par l’agent.
  • imageView - {id, path} émis lorsque l’agent appelle l’outil de visualisation d’images.
  • enteredReviewMode - {id, review} envoyé lorsque le réviseur démarre.
  • exitedReviewMode - {id, review} émis lorsque le réviseur termine son travail.
  • contextCompaction - {id} émis lorsque Codex compacte l’historique de la conversation.

Pour webSearch.action, l’action type peut être search (query?, queries?), openPage (url?) ou findInPage (url?, pattern?).

App-server rend obsolète l’ancienne notification thread/compacted ; utilisez plutôt l’élément contextCompaction.

Tous les éléments émettent deux événements de cycle de vie communs :

  • item/started - émet l’intégralité de item au début d’une nouvelle unité de travail ; la valeur item.id correspond à la valeur itemId utilisée par les deltas.
  • item/completed - envoie la valeur item finale une fois le travail terminé ; considérez-la comme l’état faisant autorité.

Deltas des éléments

  • item/agentMessage/delta - ajoute le texte diffusé au message de l’agent.
  • item/plan/delta - diffuse le texte du plan proposé. L’élément plan final peut ne pas correspondre exactement aux deltas concaténés.
  • item/reasoning/summaryTextDelta - diffuse des résumés de raisonnement lisibles ; summaryIndex est incrémenté à l’ouverture de chaque nouvelle section du résumé.
  • item/reasoning/summaryPartAdded - marque une limite entre les sections du résumé de raisonnement.
  • item/reasoning/textDelta - diffuse le texte de raisonnement brut (lorsque le modèle le prend en charge).
  • item/commandExecution/outputDelta - diffuse stdout/stderr pour une commande ; ajoutez les deltas dans l’ordre.
  • item/fileChange/outputDelta - notification de compatibilité obsolète pour l’ancienne sortie textuelle apply_patch. Les versions actuelles d’app-server ne l’émettent plus ; utilisez les éléments fileChange et turn/diff/updated à la place.

Erreurs

Si un tour échoue, le serveur émet un événement error avec { error: { message, codexErrorInfo?, additionalDetails? } }, puis termine le tour avec status: "failed". Lorsqu’un statut HTTP en amont est disponible, il apparaît dans codexErrorInfo.httpStatusCode.

Les valeurs codexErrorInfo courantes comprennent :

  • ContextWindowExceeded
  • UsageLimitExceeded
  • HttpConnectionFailed (erreurs 4xx/5xx en amont)
  • ResponseStreamConnectionFailed
  • ResponseStreamDisconnected
  • ResponseTooManyFailedAttempts
  • BadRequest, Unauthorized, SandboxError, InternalServerError, Other

Lorsqu’un statut HTTP en amont est disponible, le serveur le transmet dans httpStatusCode sur la variante codexErrorInfo concernée.

Approbations

Selon les paramètres Codex d’un utilisateur, l’exécution de commandes et les modifications de fichiers peuvent nécessiter une approbation. App-server envoie au client une requête JSON-RPC initiée par le serveur, et le client répond avec une charge utile de décision.

  • Décisions d’exécution de commandes : accept, acceptForSession, decline, cancel ou { "acceptWithExecpolicyAmendment": { "execpolicy_amendment": ["cmd", "..."] } }.

  • Décisions de modification de fichiers : accept, acceptForSession, decline, cancel.

  • Les requêtes comprennent threadId et turnId ; utilisez-les pour limiter l’état de l’interface utilisateur à la conversation active.

  • Le serveur reprend ou refuse le travail et termine l’élément avec item/completed.

Approbations d’exécution de commandes

Ordre des messages :

  1. item/started affiche l’élément commandExecution en attente avec command, cwd et d’autres champs.
  2. item/commandExecution/requestApproval comprend itemId, threadId, turnId, le champ facultatif reason, le champ facultatif command, le champ facultatif cwd, le champ facultatif commandActions, le champ facultatif proposedExecpolicyAmendment, le champ facultatif networkApprovalContext et le champ facultatif availableDecisions. Lorsque initialize.params.capabilities.experimentalApi = true, la charge utile peut également inclure le champ expérimental additionalPermissions décrivant l’accès au bac à sable demandé pour chaque commande. Tous les chemins de système de fichiers dans additionalPermissions sont absolus lors de la transmission.
  3. Le client répond avec l’une des décisions d’approbation d’exécution de commandes ci-dessus.
  4. serverRequest/resolved confirme que la requête en attente a reçu une réponse ou a été effacée.
  5. item/completed renvoie l’élément commandExecution final avec status: completed | failed | declined.

Lorsque networkApprovalContext est présent, l’invite concerne l’accès réseau géré (et non l’approbation générale d’une commande shell). Le schéma v2 actuel expose la cible host et protocol ; les clients doivent afficher une invite propre au réseau et ne pas supposer que command constitue un aperçu de commande shell compréhensible pour l’utilisateur.

Codex regroupe les invites d’approbation réseau simultanées par destination (host, protocole et port). App-server peut donc envoyer une seule invite qui débloque plusieurs requêtes en attente vers la même destination, tandis que des ports différents sur le même hôte sont traités séparément.

Approbations de modification de fichiers

Ordre des messages :

  1. item/started émet un élément fileChange avec les valeurs changes et status: "inProgress" proposées.
  2. item/fileChange/requestApproval comprend itemId, threadId, turnId, le champ facultatif reason et le champ facultatif grantRoot.
  3. Le client répond avec l’une des décisions d’approbation de modification de fichiers ci-dessus.
  4. serverRequest/resolved confirme que la requête en attente a reçu une réponse ou a été effacée.
  5. item/completed renvoie l’élément fileChange final avec status: completed | failed | declined.

tool/requestUserInput

Lorsque le client répond à item/tool/requestUserInput, app-server émet serverRequest/resolved avec { threadId, requestId }. Si la requête en attente est effacée au démarrage, à la fin ou à l’interruption du tour avant que le client ne réponde, le serveur émet la même notification pour ce nettoyage.

Les paramètres de la requête comprennent autoResolutionMs sous forme de délai d’expiration entier en millisecondes ou null. Lorsqu’il est présent, les clients hôtes peuvent résoudre automatiquement l’invite après cet intervalle si l’utilisateur ne répond pas.

Demandes d’autorisation

L’outil intégré request_permissions envoie item/permissions/requestApproval avec threadId, turnId, itemId, environmentId, cwd, la valeur facultative reason et les autorisations réseau ou de système de fichiers demandées. Répondez avec permissions en indiquant uniquement le sous-ensemble accordé. Définissez scope sur "session" pour conserver l’autorisation pour les tours suivants de la même session ; omettez-le ou utilisez "turn" pour une autorisation limitée au tour. Les autorisations qui n’ont pas été demandées sont ignorées.

Demandes de sollicitation du serveur MCP

Un serveur MCP peut interrompre un tour avec mcpServer/elicitation/request. La requête comprend threadId, une valeur facultative turnId, serverName et l’une des structures de requête suivantes :

  • mode: "form" ou mode: "openai/form", avec message et requestedSchema.
  • mode: "url", avec message, url et elicitationId.

Répondez avec action: "accept" et la valeur content demandée, ou avec action: "decline" ou "cancel" et content: null. App-server émet ensuite serverRequest/resolved. Pour recevoir la variante openai/form, activez-la avec initialize.params.capabilities.mcpServerOpenaiFormElicitation.

Appels d’outils dynamiques (expérimental)

dynamicTools sur thread/start et le flux de requête ou de réponse item/tool/call correspondant sont des API expérimentales.

Les noms d’outils dynamiques et d’espaces de noms doivent respecter les contraintes de nommage de Responses API. Évitez les noms d’espaces de noms réservés utilisés par les outils intégrés de Codex.

Lorsqu’un outil dynamique est invoqué pendant un tour, app-server émet :

  1. item/started avec item.type = "dynamicToolCall", status = "inProgress", ainsi que tool et arguments.
  2. item/tool/call sous forme de requête du serveur au client.
  3. La charge utile de réponse du client avec les éléments de contenu renvoyés.
  4. item/completed avec item.type = "dynamicToolCall", la valeur status finale et toute valeur contentItems ou success renvoyée.

Approbations d’appels d’outils MCP (apps)

Les appels d’outils d’une app (connecteur) peuvent également nécessiter une approbation. Lorsqu’un appel d’outil d’une app produit des effets secondaires, le serveur peut solliciter une approbation avec tool/requestUserInput et des options telles que Accepter, Refuser et Annuler. Les annotations d’outils destructifs déclenchent toujours une approbation, même si l’outil annonce également des indications de privilèges moindres. Si l’utilisateur refuse ou annule, l’élément mcpToolCall associé se termine par une erreur au lieu d’exécuter l’outil.

Skills

Invoquez un skill en incluant $<skill-name> dans l’entrée textuelle de l’utilisateur. Ajoutez un élément d’entrée skill (recommandé) afin que le serveur injecte les instructions complètes du skill au lieu de laisser le modèle résoudre son nom.

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

Si vous omettez l’élément skill, le modèle analysera tout de même le marqueur $<skill-name> et tentera de localiser le skill, ce qui peut augmenter la latence.

Exemple :

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

Utilisez skills/list pour récupérer les skills disponibles (éventuellement limités par cwds, avec forceReload). Vous pouvez également inclure perCwdExtraUserRoots afin d’analyser des chemins absolus supplémentaires comme portée user pour certaines valeurs cwd. App-server ignore les entrées dont la valeur cwd n’est pas présente dans cwds. skills/list peut réutiliser un résultat mis en cache pour chaque cwd ; définissez forceReload: true pour actualiser les données depuis le disque. Lorsqu’ils sont présents, le serveur lit interface et dependencies depuis 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": []
  }]
} }

Le serveur émet également des notifications skills/changed lorsque les fichiers locaux surveillés d’un skill changent. Considérez-les comme un signal d’invalidation et réexécutez skills/list avec vos paramètres actuels lorsque cela est nécessaire.

Pour activer ou désactiver un skill à partir de son chemin :

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

Apps (connecteurs)

Utilisez app/installed pour lire le dernier instantané validé de l’environnement d’exécution des apps installées. Chaque résultat comprend la valeur id de l’app, runtimeName (ou null), l’état effectif enabled et l’état callable. Une app peut être appelée uniquement lorsque sa configuration effective l’active et qu’au moins un outil visible par le modèle respecte les politiques de l’app et des outils.

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

Omettez threadId pour utiliser la configuration globale au lieu de celle d’un thread chargé. Définissez forceRefresh: true pour actualiser l’instantané de l’environnement d’exécution du connecteur avant de le lire. Lorsque la politique globale ou celle de l’espace de travail bloque l’accès à l’app, une app observée peut tout de même apparaître avec enabled et callable définis sur false.

Utilisez app/list pour récupérer les apps disponibles. Dans le CLI/TUI, /apps est le sélecteur présenté à l’utilisateur ; dans les clients personnalisés, appelez directement app/list. Chaque entrée comprend à la fois isAccessible (disponible pour l’utilisateur) et isEnabled (activée dans config.toml), afin que les clients puissent distinguer l’installation/l’accès de l’état d’activation local. Les entrées d’app peuvent également inclure les champs facultatifs branding, appMetadata et labels.

{ "method": "app/list", "id": 50, "params": {
  "cursor": null,
  "limit": 50,
  "threadId": "thread-1",
  "forceRefetch": false
} }
{ "id": 50, "result": {
  "data": [
    {
      "id": "demo-app",
      "name": "Demo App",
      "description": "Example connector for documentation.",
      "logoUrl": "https://example.com/demo-app.png",
      "logoUrlDark": null,
      "distributionChannel": null,
      "branding": null,
      "appMetadata": null,
      "labels": null,
      "installUrl": "https://chatgpt.com/apps/demo-app/demo-app",
      "isAccessible": true,
      "isEnabled": true
    }
  ],
  "nextCursor": null
} }

Si vous fournissez threadId, le contrôle d’accès aux fonctionnalités de l’app (features.apps) utilise l’instantané de configuration de ce thread. Lorsqu’il est omis, app-server utilise la dernière configuration globale.

app/list renvoie un résultat une fois les apps accessibles et celles du répertoire chargées. Définissez forceRefetch: true pour contourner les caches d’apps et récupérer des données à jour. Les entrées du cache ne sont remplacées que lorsque les actualisations réussissent.

Le serveur émet également des notifications app/list/updated chaque fois que le chargement de l’une des sources (apps accessibles ou apps du répertoire) se termine. Chaque notification comprend la dernière liste fusionnée des apps.

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

Utilisez app/read lorsque vous connaissez déjà les identifiants des apps et avez besoin de leurs métadonnées plutôt que de l’état de leur environnement d’exécution installé. Transmettez au maximum 100 valeurs appIds. Le serveur ne conserve que la première occurrence de chaque identifiant répété et préserve cet ordre dans apps et missingAppIds. Les apps inconnues ou inaccessibles sont renvoyées dans missingAppIds sans faire échouer l’ensemble de la requête.

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

Définissez includeTools: true pour demander des résumés publics des outils destinés uniquement à l’affichage. La réponse de métadonnées n’inclut pas l’état de l’environnement d’exécution de l’app installée et n’autorise pas un appel d’outil ; utilisez app/installed pour vérifier les états effectifs enabled et callable.

Invoquez une app en insérant $<app-slug> dans l’entrée textuelle et en ajoutant un élément d’entrée mention avec le chemin app://<id> (recommandé).

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

Exemples de RPC de configuration pour les paramètres d’apps

Utilisez config/read, config/value/write et config/batchWrite pour examiner ou mettre à jour les contrôles des apps dans config.toml.

Lisez la structure de configuration effective des apps (y compris _default et les remplacements propres à chaque outil) :

{ "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 définit l’outil de revue pour toutes les apps, sauf si une valeur propre à une app la remplace. Lorsque les deux sont omises, l’app hérite de la valeur de premier niveau approvals_reviewer. apps._default.default_tools_approval_mode définit le mode d’approbation de secours pour les outils qui ne comportent aucun remplacement propre à l’app ou à l’outil. Les exigences gérées en matière de mode d’approbation remplacent les paramètres du mode d’approbation des outils.

Mettez à jour un seul paramètre d’app :

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

Appliquez plusieurs modifications d’app de manière atomique :

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

Détecter et importer la configuration d’un agent externe

Utilisez externalAgentConfig/detect pour découvrir les artefacts d’agents externes qui peuvent être migrés, puis transmettez les entrées sélectionnées à externalAgentConfig/import.

Exemple de détection :

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

Exemple d’importation :

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

Le paramètre d’importation facultatif de premier niveau source indique le produit qui a généré les éléments de migration sélectionnés.

Le serveur émet externalAgentConfig/import/progress à mesure que les types d’éléments sont traités, et externalAgentConfig/import/completed une fois toutes les importations synchrones et en arrière-plan terminées. Ces notifications comprennent la même valeur importId que la réponse ainsi que itemTypeResults avec les valeurs successes et failures propres à chaque type. La notification de fin peut arriver immédiatement après la réponse ou une fois les importations distantes en arrière-plan terminées.

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

Lire les importations déjà terminées :

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

Les valeurs itemType prises en charge sont AGENTS_MD, CONFIG, SKILLS, PLUGINS, MCP_SERVER_CONFIG, SUBAGENTS, HOOKS, COMMANDS et SESSIONS. Pour les éléments PLUGINS, details.plugins répertorie chaque marketplaceName et la valeur pluginNames que Codex peut tenter de migrer. La détection ne renvoie que les éléments qui nécessitent encore une intervention. Par exemple, Codex ignore la migration AGENTS lorsque AGENTS.md existe déjà et n’est pas vide, et les importations de skills ne remplacent pas les répertoires de skills existants.

Lors de la détection de plugins depuis .claude/settings.json, Codex lit les sources de marketplaces configurées dans extraKnownMarketplaces. Si enabledPlugins contient des plugins provenant de claude-plugins-official mais que la source de la marketplace est absente, Codex déduit que anthropics/claude-plugins-official est la source.

Points de terminaison d’authentification

La surface JSON-RPC d’authentification et de compte expose des méthodes de requête/réponse ainsi que des notifications initiées par le serveur (sans id). Utilisez-les pour déterminer l’état d’authentification, démarrer ou annuler des connexions, se déconnecter, examiner les limites de débit de ChatGPT et informer les propriétaires d’un espace de travail lorsque les crédits ou les limites d’utilisation sont épuisés.

Modes d’authentification

Codex prend en charge les modes d’authentification suivants. account/updated.authMode indique le mode actif et comprend la valeur ChatGPT planType actuelle lorsqu’elle est disponible. account/read fournit également des informations sur le compte et l’abonnement.

  • API key (apikey) - l’appelant fournit une API key OpenAI avec type: "apiKey", et Codex la stocke pour les requêtes API.
  • Géré par ChatGPT (chatgpt) - Codex gère le flux OAuth de ChatGPT, conserve les jetons et les actualise automatiquement. Commencez avec type: "chatgpt" pour le flux par navigateur ou type: "chatgptDeviceCode" pour le flux par code d’appareil.
  • Jetons ChatGPT externes (chatgptAuthTokens) - mode expérimental destiné aux applications hôtes qui gèrent déjà le cycle de vie de l’authentification ChatGPT de l’utilisateur. L’application hôte fournit directement un accessToken, un chatgptAccountId et, facultativement, un chatgptPlanType, puis doit actualiser le jeton sur demande.
  • Amazon Bedrock - account/read signale les comptes Bedrock sous la forme type: "amazonBedrock" et indique si les identifiants proviennent d’une API key Bedrock gérée par Codex (credentialSource: "codexManaged") ou de la chaîne externe d’identifiants AWS (credentialSource: "awsManaged"). account/updated.authMode utilise bedrockApiKey pour les API keys Bedrock gérées par Codex.

Vue d’ensemble de l’API

  • account/read - récupère les informations actuelles du compte ; peut éventuellement actualiser les jetons.
  • account/login/start - démarre la connexion (apiKey, chatgpt, chatgptDeviceCode ou le mode expérimental chatgptAuthTokens).
  • account/login/completed (notification) - émise lorsqu’une tentative de connexion se termine (réussite ou erreur).
  • account/login/cancel - annule une connexion ChatGPT gérée en attente à l’aide de loginId.
  • account/logout - déconnecte l’utilisateur ; déclenche account/updated.
  • account/updated (notification) - émise chaque fois que le mode d’authentification change (authMode : apikey, chatgpt, chatgptAuthTokens, agentIdentity, personalAccessToken, bedrockApiKey ou null) et comprend planType lorsqu’il est disponible.
  • account/chatgptAuthTokens/refresh (requête du serveur) - demande de nouveaux jetons ChatGPT gérés en externe après une erreur d’autorisation.
  • account/rateLimits/read - récupère les limites de débit de ChatGPT.
  • account/rateLimits/updated (notification) - émise chaque fois que les limites de débit ChatGPT d’un utilisateur changent.
  • account/sendAddCreditsNudgeEmail - demande à ChatGPT d’envoyer un e-mail au propriétaire d’un espace de travail lorsque les crédits sont épuisés ou qu’une limite d’utilisation est atteinte.
  • account/rateLimitResetCredit/consume - utilise une réinitialisation de limite de débit acquise avec une valeur idempotencyKey fournie par l’appelant.
  • account/usage/read - récupère les résumés de l’activité des jetons du compte ChatGPT et les compartiments quotidiens.
  • account/workspaceMessages/read - récupère les messages actifs de l’espace de travail, y compris les titres de notification lorsqu’ils sont disponibles.
  • mcpServer/oauthLogin/completed (notification) - émise à la fin d’un flux mcpServer/oauth/login ; la charge utile comprend { name, threadId, success, error? }. threadId peut valoir null pour les flux OAuth limités à une app ou à un plugin.
  • mcpServer/startupStatus/updated (notification) - émise lorsque l’état de démarrage d’un serveur MCP configuré change ; la charge utile comprend { threadId, name, status, error, failureReason }. threadId vaut null pour un démarrage limité à une app. En cas d’échec du démarrage, failureReason: "reauthenticationRequired" signifie que les identifiants OAuth stockés ont expiré et n’ont pas pu être actualisés ; le client doit alors proposer de reconnecter le serveur.

1) Vérifier l’état d’authentification

Requête :

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

Exemples de réponses :

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

Remarques sur les champs :

  • refreshToken (valeur booléenne) : définissez true pour forcer l’actualisation d’un jeton en mode ChatGPT géré. En mode de jetons externes (chatgptAuthTokens), app-server ignore cet indicateur.
  • email vaut null lorsque le compte ChatGPT ne possède pas d’adresse e-mail.
  • requiresOpenaiAuth indique le fournisseur actif ; lorsque sa valeur est false, Codex peut s’exécuter sans identifiants OpenAI.
  • Amazon Bedrock renvoie credentialSource: "codexManaged" lorsqu’il utilise une API key Bedrock gérée par Codex. Il renvoie credentialSource: "awsManaged" pour le chemin externe des identifiants AWS. Cela indique la source d’identifiants sélectionnée, mais ne vérifie pas si la chaîne d’identifiants AWS peut résoudre des identifiants.

2) Se connecter avec une API key

  1. Envoyez :
   {
     "method": "account/login/start",
     "id": 2,
     "params": { "type": "apiKey", "apiKey": "sk-..." }
   }
  1. Résultat attendu :
   { "id": 2, "result": { "type": "apiKey" } }
  1. Notifications :
   {
     "method": "account/login/completed",
     "params": { "loginId": null, "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "apikey", "planType": null }
   }

3) Se connecter avec ChatGPT (flux par navigateur)

  1. Démarrez :
   {
     "method": "account/login/start",
     "id": 3,
     "params": {
       "type": "chatgpt",
       "useHostedLoginSuccessPage": true,
       "appBrand": "chatgpt"
     }
   }

Par défaut, un rappel de navigateur réussi redirige vers une page locale confirmant la réussite. Définissez useHostedLoginSuccessPage: true pour utiliser la page de réussite hébergée lorsque la configuration de l’organisation n’est pas requise. Lorsque la page de réussite hébergée est activée, appBrand peut valoir "codex" ou "chatgpt" ; les valeurs omises ou null utilisent par défaut "codex".

   {
     "id": 3,
     "result": {
       "type": "chatgpt",
       "loginId": "<uuid>",
       "authUrl": "https://chatgpt.com/...&redirect_uri=http%3A%2F%2Flocalhost%3A<port>%2Fauth%2Fcallback"
     }
   }
  1. Ouvrez authUrl dans un navigateur ; app-server héberge le rappel local.
  2. Attendez les notifications :
   {
     "method": "account/login/completed",
     "params": { "loginId": "<uuid>", "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "chatgpt", "planType": "plus" }
   }

3b) Se connecter avec ChatGPT (flux par code d’appareil)

Utilisez ce flux lorsque votre client gère la procédure de connexion ou lorsqu’un rappel de navigateur manque de fiabilité.

  1. Démarrez :
   {
     "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. Présentez verificationUrl et userCode à l’utilisateur ; l’interface gère l’expérience utilisateur.
  2. Attendez les notifications :
   {
     "method": "account/login/completed",
     "params": { "loginId": "<uuid>", "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "chatgpt", "planType": "plus" }
   }

3c) Se connecter avec des jetons ChatGPT gérés en externe (chatgptAuthTokens)

Utilisez ce mode expérimental uniquement lorsqu’une application hôte gère le cycle de vie de l’authentification ChatGPT de l’utilisateur et fournit directement les jetons. Les clients doivent définir capabilities.experimentalApi = true pendant initialize avant d’utiliser ce type de connexion.

  1. Envoyez :
   {
     "method": "account/login/start",
     "id": 7,
     "params": {
       "type": "chatgptAuthTokens",
       "accessToken": "<jwt>",
       "chatgptAccountId": "org-123",
       "chatgptPlanType": "business"
     }
   }
  1. Résultat attendu :
   { "id": 7, "result": { "type": "chatgptAuthTokens" } }
  1. Notifications :
   {
     "method": "account/login/completed",
     "params": { "loginId": null, "success": true, "error": null }
   }
   {
     "method": "account/updated",
     "params": { "authMode": "chatgptAuthTokens", "planType": "business" }
   }

Lorsque le serveur reçoit un 401 Unauthorized, il peut demander des jetons actualisés à l’application hôte :

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

Le serveur réessaie la requête d’origine après une réponse d’actualisation réussie. Les requêtes expirent après environ 10 secondes.

4) Annuler une connexion ChatGPT

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

5) Se déconnecter

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

6) Limites de débit (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 }
  }
} }

Remarques sur les champs :

  • rateLimits est la vue à compartiment unique assurant la rétrocompatibilité.
  • rateLimitsByLimitId (lorsqu’il est présent) est la vue multicompartiment indexée par la valeur mesurée limit_id (par exemple codex).
  • limitId est l’identifiant du compartiment mesuré.
  • limitName est un libellé facultatif destiné à l’utilisateur pour ce compartiment.
  • usedPercent correspond à l’utilisation actuelle dans la fenêtre de quota.
  • windowDurationMins correspond à la durée de la fenêtre de quota.
  • resetsAt est un horodatage Unix (en secondes) de la prochaine réinitialisation.
  • planType est inclus lorsque le serveur renvoie l’abonnement ChatGPT associé à un compartiment.
  • credits est inclus lorsque le serveur renvoie le détail des crédits restants de l’espace de travail.
  • rateLimitReachedType indique l’état de limite classifié par le serveur lorsqu’une limite a été atteinte.
  • rateLimitResetCredits contient le nombre de réinitialisations acquises disponibles lorsque le service le fournit ; sinon, sa valeur est null.
  • rateLimitResetCredits.credits vaut null lorsque seul le nombre est connu. Un tableau vide signifie que le service a récupéré les détails et n’a renvoyé aucun crédit disponible. Le service peut limiter le nombre de lignes de détail ; availableCount fait donc autorité.
  • Chaque ligne de détail comprend une valeur opaque id, resetType, status, grantedAt, expiresAt (qui peut valoir null), title (qui peut valoir null) et description (qui peut valoir null).
  • Récupérez account/rateLimits/read après avoir utilisé une réinitialisation.

7) Utilisation des jetons (ChatGPT)

Utilisez account/usage/read pour récupérer les champs récapitulatifs de l’activité des jetons ChatGPT et des compartiments quotidiens facultatifs.

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

Remarques sur les champs :

  • Les valeurs summary peuvent valoir null lorsque le service n’a pas renvoyé cette métrique.
  • dailyUsageBuckets peut valoir null ; lorsqu’il est présent, chaque compartiment comprend startDate et tokens.
  • Le point de terminaison nécessite une authentification reposant sur les services Codex. ChatGPT, les jetons ChatGPT externes, l’identité de l’agent et l’authentification par jeton d’accès personnel fonctionnent ; l’authentification uniquement par API key et l’authentification Bedrock ne fonctionnent pas.

8) Réinitialisations acquises des limites de débit (ChatGPT)

Utilisez account/rateLimitResetCredit/consume pour utiliser une réinitialisation acquise.

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

Remarques sur les champs :

  • idempotencyKey ne doit pas être vide. Utilisez un UUID pour chaque tentative logique d’utilisation et réutilisez la même valeur lorsque vous réessayez cette tentative.
  • creditId est facultatif. Lorsqu’il est fourni, il doit s’agir d’un identifiant opaque non vide provenant de account/rateLimits/read. Lorsqu’il est omis, le service sélectionne le prochain crédit disponible.
  • reset signifie qu’un crédit a été utilisé.
  • alreadyRedeemed signifie que la même utilisation a déjà été effectuée. Considérez cela comme une réussite idempotente et actualisez les limites du compte.
  • nothingToReset signifie qu’aucune fenêtre de limite de débit éligible ne peut être réinitialisée.
  • noCredit signifie que le compte ne dispose d’aucun crédit de réinitialisation acquis.
  • Récupérez account/rateLimits/read après avoir utilisé une réinitialisation au lieu de déduire les fenêtres mises à jour à partir de cette réponse.

9) Informer le propriétaire d’un espace de travail d’une limite

Utilisez account/sendAddCreditsNudgeEmail pour demander à ChatGPT d’envoyer un e-mail au propriétaire d’un espace de travail lorsque les crédits sont épuisés ou qu’une limite d’utilisation a été atteinte.

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

Utilisez creditType: "credits" lorsque les crédits de l’espace de travail sont épuisés, ou creditType: "usage_limit" lorsque la limite d’utilisation de l’espace de travail a été atteinte. Si le propriétaire a déjà été informé récemment, l’état de la réponse est cooldown_active.

10) Messages de l’espace de travail (ChatGPT)

Utilisez account/workspaceMessages/read pour récupérer les messages actifs de l’espace de travail actuel, y compris les titres de notification lorsqu’ils sont disponibles.

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