|
| 1 | +--- |
| 2 | +title: Image Bridge |
| 3 | +description: Route image_generation hosted-tool calls to xAI Grok Imagine when using a non-OpenAI provider. |
| 4 | +--- |
| 5 | + |
| 6 | +## Overview |
| 7 | + |
| 8 | +When you route Codex through a non-OpenAI model (Claude, Gemini, Grok, etc.), the |
| 9 | +`image_generation` **hosted tool** normally doesn't work — it requires OpenAI's server-side |
| 10 | +execution environment. The Image Bridge detects these calls and transparently reroutes them to |
| 11 | +xAI Grok Imagine, so the model you're actually chatting with can still generate images. |
| 12 | + |
| 13 | +## Prerequisites |
| 14 | + |
| 15 | +- **Enable the bridge** by setting `images.bridgeEnabled: true` in your config (it is off by |
| 16 | + default to avoid unexpected xAI charges — see [Configuration](#configuration) below). |
| 17 | +- An `xai` provider entry with an **API key**. The bridge pins fulfillment to the registry xAI |
| 18 | + Images endpoint (`https://api.x.ai/v1`); any configured `baseUrl` override is ignored for image |
| 19 | + calls. OAuth / `ocx login xai` alone does **not** arm the bridge (the Grok CLI OAuth transport is |
| 20 | + chat-oriented and is not used for `/images/*`). |
| 21 | + |
| 22 | + ```json |
| 23 | + { |
| 24 | + "providers": { |
| 25 | + "xai": { "adapter": "openai-chat", "apiKey": "xai-…", "authMode": "key" } |
| 26 | + } |
| 27 | + } |
| 28 | + ``` |
| 29 | + |
| 30 | +- A non-OpenAI model selected as your active provider. (When the active provider is OpenAI, |
| 31 | + the native hosted tool is used directly and the bridge is bypassed.) |
| 32 | + |
| 33 | +## Configuration |
| 34 | + |
| 35 | +Image Bridge options live under `images` in `~/.opencodex/config.json`. Bridging is |
| 36 | +**opt-in** — you must set `bridgeEnabled: true` to enable paid xAI Grok Imagine generation: |
| 37 | + |
| 38 | +```json |
| 39 | +{ |
| 40 | + "images": { |
| 41 | + "bridgeEnabled": true, |
| 42 | + "bridgeModel": "grok-imagine-image-quality", |
| 43 | + "maxRounds": 3, |
| 44 | + "timeoutMs": 60000 |
| 45 | + } |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +| Option | Default | Description | |
| 50 | +| --- | --- | --- | |
| 51 | +| `bridgeEnabled` | `false` | Master switch. Set `true` to enable bridging. Off by default to avoid unexpected xAI charges. | |
| 52 | +| `bridgeModel` | `grok-imagine-image-quality` | The xAI image model id to send prompts to. | |
| 53 | +| `maxRounds` | `3` | Maximum image-generation loop iterations per turn. Floored to an integer and clamped to `[0, 10]`; non-finite values fall back to `3`. | |
| 54 | +| `timeoutMs` | `60000` | Per-call xAI deadline in milliseconds. Finite positive values are floored and passed to the xAI request. | |
| 55 | +| `artifactsKeepCount` | `200` | Maximum number of files retained under `artifacts/`. When exceeded, the oldest files are deleted after each fulfilled call. Set to `0` or a negative value to disable pruning. | |
| 56 | + |
| 57 | +## Artifact Retention |
| 58 | + |
| 59 | +Generated images are written to `~/.opencodex/artifacts/`. To prevent unbounded disk |
| 60 | +growth in long-running sessions, the directory is pruned automatically after each fulfilled |
| 61 | +image call (once the full batch for that call is on disk) — the oldest files (by modification |
| 62 | +time) are deleted when the count exceeds the configured maximum (default 200, configurable via |
| 63 | +`images.artifactsKeepCount`). Only paths that survive pruning are returned to the model. |
| 64 | + |
| 65 | +## How It Works |
| 66 | + |
| 67 | +The Image Bridge activates only on **Responses** turns that include the hosted |
| 68 | +`image_generation` tool in the `/v1/responses` tools array while a **non-OpenAI** |
| 69 | +model is selected. It does **not** intercept Codex's built-in `image_gen` tool, |
| 70 | +which POSTs directly to `/v1/images/generations` (or `/images/edits`) — that path |
| 71 | +is covered separately in [Codex Integration](/guides/codex-integration/#built-in-image-generation-image_gen). |
| 72 | + |
| 73 | +1. When a Responses request lists `image_generation` in `tools`, OpenCodex detects it |
| 74 | + during request preprocessing. |
| 75 | +2. The hosted tool is replaced with a **synthetic function tool** that the routed model can call |
| 76 | + normally — the model sees a callable tool rather than an opaque hosted tool it can't execute. |
| 77 | +3. When the model invokes that tool, OpenCodex intercepts the call and sends the prompt to xAI's |
| 78 | + image generation API. |
| 79 | +4. Generated images are saved to `~/.opencodex/artifacts/` and the **local file path** is returned |
| 80 | + to the model as the tool result. |
| 81 | +5. The model continues the conversation with knowledge of the generated image and its location. |
| 82 | + |
| 83 | +From the model's perspective nothing changed — it called a tool and got a result. From the user's |
| 84 | +perspective, image generation works with any routed provider instead of silently failing. |
| 85 | + |
| 86 | +## Limitations |
| 87 | + |
| 88 | +- **Only xAI Grok Imagine is supported.** DALL-E and other image providers may be added later. |
| 89 | +- **Web search takes priority** on adapters that support the web-search sidecar loop. If both web |
| 90 | + search and image generation are requested in the same turn, web-search runs and image |
| 91 | + generation is skipped. Cursor/`runTurn` adapters cannot use that sidecar today, so the image |
| 92 | + bridge may still run for those dual-tool turns. |
| 93 | +- **xAI costs apply.** Image generation via xAI requires an active xAI subscription or API credits. |
| 94 | +- **Streaming only.** The bridge works by intercepting the SSE response stream; requests with |
| 95 | + `stream: false` are rejected with a 400 error. |
0 commit comments