Codex CLI Integration
1. What? — Definition and context
Section titled “1. What? — Definition and context”Codex CLI Integration is a family of four N8N workflows that industrialises usage of OpenAI’s Codex CLI inside the ai-stack/cli-ollama stack. Codex became the default provider for CLI Ollama (commit 195d432): without automation around its authentication and streaming, the AI tooling would break silently on the first OAuth session expiration.
| Workflow | ID | Nodes | Trigger | Role |
|---|---|---|---|---|
| Codex Auth Watchdog | PaBIkK76OPcHQr53 | 5 | Schedule (6h) | Watches auth.json freshness and alerts via Notification Hub |
| Codex Reauth Flow | sLAIrqJDGRUE6Jmj | 5 | Execute Workflow | Starts a device-auth session and sends URL + code to Telegram |
| Codex Reauth Callback Actions | xpHr32uMtdEE0M3Q | 8 | Execute Workflow | Handles [Done] / [Cancel] callbacks after reauth |
| Codex Progress Handler | w8r9JcpArIElZxRe | 11 | Webhook /codex-progress | Buffers Codex streaming and edits the Telegram message |
CLI Ollama endpoints consumed
Section titled “CLI Ollama endpoints consumed”| Endpoint | Method | Consumer |
|---|---|---|
/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) |
Visual architecture
Section titled “Visual architecture”2. Why? — Stakes and motivations
Section titled “2. Why? — Stakes and motivations”Problems solved
Section titled “Problems solved”| Problem | Without the family | With the family |
|---|---|---|
| Silent expiration | Every AI request fails with no signal | Watchdog alerts on D-2 and D-0 before expiry |
| Manual SSH reauth | VPS connection + docker exec + copy-paste the code | Telegram button + device-code pushed automatically |
| Out-of-container spawn | Codex CLI launched on the host writes to the wrong ~/.codex | In-container spawn writes to /home/cli/.codex/auth.json |
| Vague typed errors | ”subprocess failed” non-actionable | Typed auth_expired error detected in CLI Ollama |
| Lost Codex streaming | Long run = Telegram radio silence for 30s+ | Edit-in-place via DT buffer |
| No way to cancel | Zombie device-auth session if abandoned | [Cancel] kills the subprocess via DELETE /reauth/{id} |
Why a Watchdog instead of alerting on first error?
Section titled “Why a Watchdog instead of alerting on first error?”Discovering expiration at the moment of a user call degrades UX: the Telegram message returns a cryptic error and the user must dig into documentation. The Watchdog runs every 6 hours and anticipates:
| Threshold | Severity | Action |
|---|---|---|
auth.json missing | critical | Immediate alert with codex login --device-auth command |
age > 8 days | critical | Reauth strongly recommended |
age > 6 days | warning | Monitor, reauth soon |
Unreadable last_refresh | warning | Corrupted file to inspect |
The 6/8 day thresholds provide a comfortable ~48h window between first alert and actual failure.
Why extract the Callback Handler from the Reauth Flow?
Section titled “Why extract the Callback Handler from the Reauth Flow?”Reauth Flow sends the Telegram message, but the [Done] / [Cancel] callback is asynchronous: the user may click 10 minutes later. Splitting it into a dedicated sub-workflow (8 nodes) follows the same logic as NH Callback Handler (#276): early routing through the Telegram Orchestrator, dedup bypass, no shared state.
Recent evolutions
Section titled “Recent evolutions”| Commit | Improvement |
|---|---|
edfcf79 | Typed auth_expired error in CLI Ollama (detection instead of subprocess error) |
9771a97 | In-container device-auth spawn + auth missing detection |
ba0f7ae | Bump n8n-exports with reauth fixes |
32c3282 | Streaming webhook /webhook/codex-progress on the provider side |
7ee7dbd | Codex chat edit-in-place + real-time Telegram streaming |
3. How? — Technical implementation
Section titled “3. How? — Technical implementation”Components
Section titled “Components”| Workflow | ID | Nodes | Role |
|---|---|---|---|
| Codex Auth Watchdog | PaBIkK76OPcHQr53 | 5 | 6h cron, check /api/codex/auth/status, alert Hub |
| Codex Reauth Flow | sLAIrqJDGRUE6Jmj | 5 | Spawn device-auth, push Telegram with URL + code |
| Codex Reauth Callback Actions | xpHr32uMtdEE0M3Q | 8 | Switch on callback, confirm or cancel the session |
| Codex Progress Handler | w8r9JcpArIElZxRe | 11 | DT buffer + edit-in-place of the Telegram message |
Codex Auth Watchdog (5 nodes)
Section titled “Codex Auth Watchdog (5 nodes)”Linear chain: Schedule 6h → Get Codex Auth Status (HTTP GET) → Evaluate Auth Health (Code) → IF Should Alert → Call Notification Hub (Execute Workflow).
The Evaluate Auth Health node applies two thresholds:
var WARNING_AGE = 6 * 86400; // 6 daysvar CRITICAL_AGE = 8 * 86400; // 8 days
if (!s.exists) { severity = 'critical'; title = 'Codex auth missing';} else if (age > CRITICAL_AGE) { severity = 'critical';} else if (age > WARNING_AGE) { severity = 'warning';}The call to the Notification Hub then delegates dedup, quiet hours and Telegram routing. The watchdog only cares about evaluation, never about transport.
Codex Reauth Flow (5 nodes)
Section titled “Codex Reauth Flow (5 nodes)”Triggered via Execute Workflow (from a conversational agent or a /codex-reauth command). The Start Reauth Session node sends a POST http://cli-ollama:11434/api/codex/reauth:
{ "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}The Format Reauth Message node builds a Telegram message with the inline keyboard [Open URL] [Done] [Cancel]. Send Reauth Prompt sends the message, Return Reauth Started returns the reauth_id to the calling workflow so it can correlate the upcoming callback.
Codex Reauth Callback Actions (8 nodes)
Section titled “Codex Reauth Callback Actions (8 nodes)”Routed from the Telegram Orchestrator whenever callback_data starts with codex_reauth_. Chain:
Execute Workflow Trigger— receiveschatId,messageId,callbackData,reauthId.Answer Callback— closes the Telegram spinner immediately.Switch Action—donevscancel.donebranch →Check Reauth Status(GET/api/codex/reauth/{id}/status) →Format Done Result.cancelbranch →Cancel Reauth Session(DELETE/api/codex/reauth/{id}) →Format Cancel Result.- Both converge on
Edit Original Message(Telegram edit) which replaces the prompt with the result.
Codex Progress Handler (11 nodes)
Section titled “Codex Progress Handler (11 nodes)”When the Codex provider (cli-ollama/app/services/providers/codex.py) emits a progress event, it POSTs to http://n8n:5678/webhook/codex-progress with:
{ "chatId": "5883063462", "messageId": 12345, "sessionId": "tg_xxx", "progressText": "Reading 3 files...", "isFinal": false}Handler chain:
Webhook Trigger(pathcodex-progress).Parse Body— extractschatId,messageId,progressText.DT Get Buffer— Data Table keyed bymessageId(edit state).IF Buffer Exists— first progress event or continuation?Code Decide— decides betweenedit(append to buffer),split(new message if Telegram limit exceeded) orskip.IF Should Edit/IF Need Split— routing by decision.Edit Message(Telegram) orSend New Message.Prep DT Update+DT Update Buffer— persists the new state for the next progress event.
The buffer avoids back-to-back Telegram edits hitting rate limits and produces a “live” effect without saturating the API.
Security
Section titled “Security”| Surface | Protection |
|---|---|
/api/codex/* | Internal endpoint on the ai-internal network, not exposed through Caddy |
/webhook/codex-progress | Internal N8N webhook, blocked by Caddy from outside |
codex login --device-auth spawn | Run inside the cli-ollama container with ~/.codex isolated from host |
| Reauth session TTL | 600 seconds — beyond that the subprocess is killed automatically |
4. What if? — Outlook and limits
Section titled “4. What if? — Outlook and limits”Current limits
Section titled “Current limits”| Limit | Impact | Mitigation |
|---|---|---|
| Single-instance watchdog | Only one Codex install supervised | Sufficient for solo VPS usage |
| No automatic reauth | User still has to click | OAuth security: device-code mandates a human |
| Non-sharded DT buffer | Single active Codex conversation recommended | For multi-user, partition by chatId + messageId |
| No Prometheus metric | No Grafana dashboard on Codex health | TODO: export codex_auth_age_seconds from CLI Ollama |
| Best-effort cancel | If the subprocess is blocked on stdin, SIGTERM may take seconds | The 600s TTL guarantees eventual release |
Evolution scenarios
Section titled “Evolution scenarios”If multiple providers must be supervised:
- Generalise the Watchdog into
AI Auth Watchdogwith aprovider=codex|gemini|claudeparameter - Unified endpoints
/api/auth/status?provider=... - A single cron for every provider
If proactive pre-auth is wanted:
- A D-1 cron task that starts the device-auth session early and pushes the code in advance
- The user prepares the reauth without pressure
If the progress volume explodes:
- Throttle at the provider (at most one update every 2s)
- Redis aggregation (key
progress:{messageId}) then periodic flush - Alternate
ntfyoutput for long background runs
If multi-user:
- A
codex_sessionsData Table keyed bychatId - Each user gets their own
auth.json(not possible with the current CLI) - Workaround: a shared Codex account + session_id traceability in Redis
Related pages
Section titled “Related pages”Infrastructure
Section titled “Infrastructure”- N8N in queue mode — Backend that runs the family
- Notify Stack — DIUN and ntfy downstream of the Watchdog
Workflows
Section titled “Workflows”- Notification Hub — Target of watchdog alerts
- Telegram Orchestrator — Routes
codex_reauth_*callbacks - Conversational system — Main consumer of the Codex provider
- Question Hub — Asynchronous Telegram interaction pattern
Reference
Section titled “Reference”- Glossary — Device-code, Webhook, Buffer