--- title: Codex CLI Integration url: https://blog.guigpap.com/fr/workflows/codex-cli-integration/ url_md: https://blog.guigpap.com/fr/workflows/codex-cli-integration.md category: automation date: '2026-05-19' maturite: production techno: - n8n - telegram - claude application: - automation - operations --- # Codex CLI Integration > Famille de workflows N8N qui supervisent l'authentification Codex CLI, relancent le device-code et streament la progression vers Telegram ## 1. Quoi ? — Définition et contexte La **Codex CLI Integration** est une famille de quatre workflows N8N qui industrialisent l'usage du CLI Codex d'OpenAI au sein de la stack `ai-stack/cli-ollama`. Codex est devenu le provider par défaut de CLI Ollama (commit `195d432`) : sans automatisation autour de son authentification et de son streaming, le tooling AI casserait silencieusement à la première expiration de session OAuth. > **Note - Pourquoi une famille de workflows ?** > > Codex CLI s'authentifie via OAuth device-code. La session se rafraîchit en lisant `~/.codex/auth.json`, mais expire après plusieurs jours d'inactivité. Une seule expiration silencieuse coupe tous les agents Telegram, l'IA Router, les sub-workflows d'approbation et la chaîne MCP. La famille existe pour détecter, relancer, confirmer et streamer Codex de bout en bout. ### Périmètre | Workflow | ID | Nodes | Trigger | Rôle | |----------|----|-------|---------|------| | **Codex Auth Watchdog** | `PaBIkK76OPcHQr53` | 5 | Schedule (6h) | Surveille la fraîcheur de `auth.json` et alerte via Notification Hub | | **Codex Reauth Flow** | `sLAIrqJDGRUE6Jmj` | 5 | Execute Workflow | Démarre une session device-auth et envoie URL + code via Telegram | | **Codex Reauth Callback Actions** | `xpHr32uMtdEE0M3Q` | 8 | Execute Workflow | Traite les boutons `[Done]` / `[Cancel]` après réauth | | **Codex Progress Handler** | `w8r9JcpArIElZxRe` | 11 | Webhook `/codex-progress` | Buffer le streaming Codex et édite le message Telegram | ### Endpoints CLI Ollama consommés | Endpoint | Méthode | Consommé par | |----------|---------|--------------| | `/api/codex/auth/status` | GET | Auth Watchdog | | `/api/codex/reauth` | POST | Reauth Flow | | `/api/codex/reauth/{id}/status` | GET | Callback Actions ([Done]) | | `/api/codex/reauth/{id}` | DELETE | Callback Actions ([Cancel]) | | `/webhook/codex-progress` (N8N) | POST | Codex provider (streaming) | ### Architecture visuelle ```mermaid flowchart TD subgraph Watch["Codex Auth Watchdog · 5 nodes"] direction TB Sched["Schedule 6h"] Fetch["Get Codex Auth Status"] Eval["Evaluate Auth Health"] IfAlert["IF Should Alert"] Hub["Call Notification Hub"] end subgraph Reauth["Codex Reauth Flow · 5 nodes"] direction TB RTrig["Execute Workflow Trigger"] Start["Start Reauth Session"] Fmt["Format Reauth Message"] Send["Send Reauth Prompt"] Done["Return Reauth Started"] end subgraph CB["Codex Reauth Callback Actions · 8 nodes"] direction TB CTrig["Execute Workflow Trigger"] Ack["Answer Callback"] SwAct["Switch Action"] CheckS["Check Reauth Status"] Cancel["Cancel Reauth Session"] Edit["Edit Original Message"] end subgraph Prog["Codex Progress Handler · 11 nodes"] direction TB PHook["Webhook /codex-progress"] Parse["Parse Body"] Buf["DT Get Buffer"] Decide["Code Decide"] EditMsg["Edit Message"] NewMsg["Send New Message"] Upd["DT Update Buffer"] end CLI["cli-ollama
FastAPI · /api/codex/*"] TG["Telegram bot
chat utilisateur"] Watch --> Hub --> TG Watch -.->|HTTP GET /auth/status| CLI Reauth -->|HTTP POST /reauth| CLI Reauth --> TG TG -->|callback Done / Cancel| CB CB -->|HTTP GET /reauth/id/status| CLI CB -->|HTTP DELETE /reauth/id| CLI CB --> TG CLI -->|POST /webhook/codex-progress| Prog Prog --> TG ``` --- ## 2. Pourquoi ? — Enjeux et motivations ### Problèmes résolus | Problème | Sans la famille | Avec la famille | |----------|-----------------|------------------| | **Expiration silencieuse** | Toutes les requêtes AI échouent sans signal | Watchdog alerte à J-2 et J-0 de l'expiration | | **Réauth manuelle SSH** | Connexion VPS + `docker exec` + copier-coller du code | Bouton Telegram + device-code envoyé en push | | **Spawn hors conteneur** | Codex CLI lancé sur l'hôte écrit dans le mauvais `~/.codex` | Spawn in-container, écrit dans `/home/cli/.codex/auth.json` | | **Erreurs typées floues** | « subprocess failed » non actionnable | Erreur `auth_expired` détectée côté CLI Ollama | | **Streaming Codex perdu** | Long run = silence radio Telegram pendant 30s+ | Edit-in-place du message via buffer DT | | **Annulation impossible** | Session device-auth zombie en cas d'abandon | `[Cancel]` tue le subprocess via `DELETE /reauth/{id}` | ### Pourquoi un Watchdog et pas une alerte à la première erreur ? Découvrir l'expiration au moment d'un appel utilisateur dégrade l'UX : le message Telegram retourne une erreur cryptique et l'utilisateur doit ouvrir la documentation. Le Watchdog tourne toutes les 6 heures et anticipe : | Seuil | Sévérité | Action | |-------|----------|--------| | `auth.json` absent | `critical` | Alerte immédiate avec commande `codex login --device-auth` | | `age > 8 jours` | `critical` | Re-auth fortement recommandée | | `age > 6 jours` | `warning` | Surveillance, re-auth proche | | `last_refresh` illisible | `warning` | Fichier corrompu à inspecter | Les seuils 6/8 jours offrent une fenêtre confortable (~48h) entre la première alerte et la vraie panne. ### Pourquoi extraire le Callback Handler du Reauth Flow ? Le Reauth Flow envoie le message Telegram, mais le callback `[Done]` / `[Cancel]` est asynchrone : l'utilisateur peut cliquer 10 minutes plus tard. Le séparer en sub-workflow dédié (8 nodes) suit la même logique que `NH Callback Handler` (#276) : routage précoce via le Telegram Orchestrator, bypass de la dedup, pas d'état partagé. ### Évolutions récentes | Commit | Apport | |--------|--------| | `edfcf79` | Erreur typée `auth_expired` côté CLI Ollama (détection au lieu de subprocess error) | | `9771a97` | Spawn device-auth in-container + détection `auth missing` | | `ba0f7ae` | Bump n8n-exports avec corrections de reauth | | `32c3282` | Webhook streaming `/webhook/codex-progress` côté provider | | `7ee7dbd` | Chat Codex edit-in-place + streaming temps réel Telegram | --- ## 3. Comment ? — Mise en œuvre technique ### Composants | Workflow | ID | Nodes | Rôle | |----------|----|-------|------| | Codex Auth Watchdog | `PaBIkK76OPcHQr53` | 5 | Cron 6h, check `/api/codex/auth/status`, alerte Hub | | Codex Reauth Flow | `sLAIrqJDGRUE6Jmj` | 5 | Spawn device-auth, push Telegram avec URL + code | | Codex Reauth Callback Actions | `xpHr32uMtdEE0M3Q` | 8 | Switch sur callback, confirme ou annule la session | | Codex Progress Handler | `w8r9JcpArIElZxRe` | 11 | Buffer DT + edit-in-place du message Telegram | ### Codex Auth Watchdog (5 nodes) Chaîne linéaire : `Schedule 6h` → `Get Codex Auth Status` (HTTP GET) → `Evaluate Auth Health` (Code) → `IF Should Alert` → `Call Notification Hub` (Execute Workflow). Le node `Evaluate Auth Health` applique deux seuils : ```javascript var WARNING_AGE = 6 * 86400; // 6 jours var CRITICAL_AGE = 8 * 86400; // 8 jours if (!s.exists) { severity = 'critical'; title = 'Codex auth manquante'; } else if (age > CRITICAL_AGE) { severity = 'critical'; } else if (age > WARNING_AGE) { severity = 'warning'; } ``` L'appel au [Notification Hub](/fr/workflows/notification-hub/) délègue ensuite la dédup, les quiet hours et le routage Telegram. Le watchdog ne se préoccupe que de l'évaluation, jamais du transport. > **Tip - Schedule trigger à 6 heures** > > Un cron toutes les 6h offre 4 contrôles par jour. Cumulé avec le seuil à 6 jours, l'utilisateur reçoit au moins 8 alertes `warning` avant que `auth.json` n'atteigne 8 jours et bascule en `critical` — laissant ~48h de marge pour ouvrir un terminal. ### Codex Reauth Flow (5 nodes) Déclenché par Execute Workflow (depuis un agent conversationnel ou un alias `/codex-reauth`). Le node `Start Reauth Session` fait un `POST http://cli-ollama:11434/api/codex/reauth` : ```json { "reauth_id": "rau_xxx", "device_url": "https://auth.openai.com/device", "user_code": "ABCD-EFGH", "host_command": "docker exec -it cli-ollama codex login --device-auth", "ttl_seconds": 600 } ``` Le node `Format Reauth Message` construit un message Telegram avec inline keyboard `[Ouvrir l'URL]` `[Done]` `[Cancel]`. `Send Reauth Prompt` envoie le message, `Return Reauth Started` retourne le `reauth_id` au workflow appelant pour qu'il puisse corréler le callback ultérieur. ### Codex Reauth Callback Actions (8 nodes) Routé depuis le Telegram Orchestrator quand `callback_data` commence par `codex_reauth_`. Chaîne : 1. `Execute Workflow Trigger` — reçoit `chatId`, `messageId`, `callbackData`, `reauthId`. 2. `Answer Callback` — ferme le spinner Telegram immédiatement. 3. `Switch Action` — `done` vs `cancel`. 4. Branche `done` → `Check Reauth Status` (GET `/api/codex/reauth/{id}/status`) → `Format Done Result`. 5. Branche `cancel` → `Cancel Reauth Session` (DELETE `/api/codex/reauth/{id}`) → `Format Cancel Result`. 6. Convergence sur `Edit Original Message` (Telegram edit) qui remplace le prompt par le résultat. > **Caution - Idempotence du Cancel** > > Le `DELETE /api/codex/reauth/{id}` tue le subprocess Codex CLI. Si l'utilisateur clique `[Done]` après avoir cliqué `[Cancel]`, le `GET /status` retournera `404 reauth_session_not_found`. Le node `Format Done Result` doit gérer ce cas pour ne pas re-throw. ### Codex Progress Handler (11 nodes) Quand le provider Codex (`cli-ollama/app/services/providers/codex.py`) émet un événement de progression, il fait un `POST` vers `http://n8n:5678/webhook/codex-progress` avec : ```json { "chatId": "5883063462", "messageId": 12345, "sessionId": "tg_xxx", "progressText": "Reading 3 files...", "isFinal": false } ``` Chaîne du handler : 1. `Webhook Trigger` (path `codex-progress`). 2. `Parse Body` — extrait `chatId`, `messageId`, `progressText`. 3. `DT Get Buffer` — Data Table indexée par `messageId` (état de l'édition). 4. `IF Buffer Exists` — première progression ou suite ? 5. `Code Decide` — décide entre `edit` (append au buffer), `split` (nouveau message si > limite Telegram) ou `skip`. 6. `IF Should Edit` / `IF Need Split` — routage selon la décision. 7. `Edit Message` (Telegram) ou `Send New Message`. 8. `Prep DT Update` + `DT Update Buffer` — persiste le nouvel état pour la prochaine progression. Le buffer évite l'enchaînement d'éditions Telegram bloquant (rate-limit) et permet l'effet « live » sans saturer l'API. ### Sécurité | Surface | Protection | |---------|------------| | `/api/codex/*` | Endpoint interne du réseau `ai-internal`, non exposé via Caddy | | `/webhook/codex-progress` | Webhook N8N interne, bloqué par Caddy depuis l'extérieur | | Spawn `codex login --device-auth` | Exécuté dans le conteneur `cli-ollama` avec `~/.codex` isolé du host | | Session reauth TTL | 600 secondes — au-delà le subprocess est tué automatiquement | --- ## 4. Et si ? — Perspectives et limites ### Limites actuelles | Limite | Impact | Mitigation | |--------|--------|------------| | **Watchdog mono-instance** | Une seule installation Codex surveillée | Suffisant pour un usage solo VPS | | **Pas de re-auth automatique** | L'utilisateur doit toujours cliquer | Sécurité OAuth : le device-code exige une interaction humaine | | **Buffer DT non sharded** | Une seule conversation Codex active recommandée | Pour multi-utilisateur, partitionner par `chatId + messageId` | | **Pas de métrique Prometheus** | Pas de dashboard Grafana sur la santé Codex | TODO : exporter `codex_auth_age_seconds` depuis CLI Ollama | | **Cancel best-effort** | Si le subprocess est déjà bloqué sur stdin, le SIGTERM peut prendre quelques secondes | TTL 600s garantit la libération | ### Scénarios d'évolution **Si plusieurs providers à surveiller** : - Généraliser le Watchdog en `AI Auth Watchdog` paramétré (`provider=codex|gemini|claude`) - Endpoints unifiés `/api/auth/status?provider=...` - Un cron unique pour tous les providers **Si besoin de pré-auth proactif** : - Tâche cron à J-1 qui démarre déjà la session device-auth et envoie le code en avance - L'utilisateur prépare la re-auth sans urgence **Si volume de progressions explose** : - Throttle côté provider (1 update toutes les 2s minimum) - Aggrégation Redis (clé `progress:{messageId}`) puis flush périodique - Sortie alternative `ntfy` pour les longs runs en arrière-plan **Si multi-utilisateur** : - Data Table `codex_sessions` indexée par `chatId` - Chaque utilisateur a son propre `auth.json` (impossible avec le CLI actuel) - Workaround : un compte Codex partagé + traçabilité par session_id Redis --- ## Pages liées ### Infrastructure - [N8N en mode Queue](/fr/infrastructure/n8n-queue-mode/) — Backend qui exécute la famille - [Notify Stack](/fr/infrastructure/notify-stack/) — DIUN et ntfy en aval du Watchdog ### Workflows - [Notification Hub](/fr/workflows/notification-hub/) — Cible des alertes du Watchdog - [Telegram Orchestrator](/fr/workflows/telegram-orchestrator/) — Route les callbacks `codex_reauth_*` - [Système conversationnel](/fr/workflows/systeme-conversationnel/) — Consommateur principal du provider Codex - [Question Hub](/fr/workflows/question-hub/) — Modèle d'interaction Telegram asynchrone ### Référence - [Glossaire](/fr/reference/glossary/) — Device-code, Webhook, Buffer ## Metadonnees agent - Cet article est issu du blog GuiGPaP Lab. - Contexte global du blog: https://blog.guigpap.com/llms.txt - Contact auteur: https://odoo.guigpap.com/mon-cv - Licence: CC-BY-SA 4.0