---
slug: workers-ai-coding-models
title: Two id families, a 23x price gap: choosing a coding model on Cloudflare
canonical: https://miscsubjects.com/a/workers-ai-coding-models
---

Two model ids look almost the same and are not the same product.

`@cf/moonshotai/kimi-k2.7-code` runs on Cloudflare's GPUs: published per-token price, listed in the account's model catalogue over the API, billed as Workers AI against the same Neuron allowance as an image classifier.

`moonshotai/kimi-k3` runs on Moonshot's GPUs and Cloudflare resells it: no per-token price published anywhere in the documentation, absent from the account catalogue, billed through Unified Billing against prepaid credits.

The prefix is the whole difference. Get it wrong and the request either costs twenty times what was budgeted or returns a 402.

## Evidence status

**Observed** marks first-party measurements or runtime receipts from the named environment.
**Derived** marks arithmetic calculated from cited inputs. **Specified** marks vendor or standards
documentation. **Implemented** and **deployed** name code and live-state evidence, respectively.
**Reproduced** means the stated procedure was rerun. **Externally attested** marks operator reports;
those reports show that an experience occurred, not that it is universal.

## The prefix decides the bill, the discovery path and the request shape

| | Workers AI model | Catalogue (partner) model |
| --- | --- | --- |
| Id shape | `@cf/vendor/model` | `vendor/model` |
| Examples | `@cf/moonshotai/kimi-k2.7-code`, `@cf/zai-org/glm-5.2`, `@cf/zai-org/glm-4.7-flash` | `moonshotai/kimi-k3`, `xai/grok-4.5`, `minimax/m3` |
| Who runs the GPU | Cloudflare | The model vendor |
| Billing | Workers AI, Neurons, $0.011 per 1,000 Neurons, 10,000 Neurons free per day | Unified Billing, prepaid credits, 5% fee on credit purchase, provider rates passed through |
| Per-token price published? | Yes, on the pricing page and in the models API | No — the model page links to the dashboard |
| Listed by `GET /ai/models/search`? | Yes | No |
| Needs an authenticated gateway? | No | Yes — an unauthenticated gateway answers 402 |
| Free daily allowance applies? | Yes | No |
| Anthropic Messages endpoint | Refused by name | Sometimes accepted, shape not guaranteed |

Cloudflare states the split in one sentence: "Workers AI models (models prefixed with `@cf/`) routed through AI Gateway are not charged via Unified Billing." The credit mechanics, the 5% purchase fee and the authentication requirement are covered in [Cloudflare Unified Billing](/a/cloudflare-unified-billing).

## Every coding-relevant model Cloudflare hosts, priced from the account catalogue

The list below is the account's own catalogue, not the documentation. Fetch it:

```bash
ACCOUNT_ID=<ACCOUNT_ID>            # wrangler whoami
CF_API_TOKEN=<TOKEN>               # Workers AI: Read

curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai/models/search?per_page=500" \
  | jq -r '.result[] | select(.task.name=="Text Generation") |
      [.name,
       (.properties[]|select(.property_id=="context_window").value),
       ((.properties[]|select(.property_id=="function_calling").value) // "no")]
      | @tsv'
```

Read on 2026-07-26: 61 models in the catalogue, 26 of them Text Generation, and **13 in the whole catalogue advertise function calling**. Prices below are the `price` property returned by that same call, in US dollars per million tokens.

| Model id | Context | Tools | Vision | Input | Cached input | Output | What it is for |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `@cf/moonshotai/kimi-k2.7-code` | 262,144 | yes | yes | $0.95 | $0.19 | $4.00 | Main agent thread. The only hosted model with a large window and image input together. |
| `@cf/moonshotai/kimi-k2.6` | 262,144 | yes | yes | $0.95 | $0.16 | $4.00 | Previous Kimi. Same price, cheaper cache, no reason to pick it for new work. |
| `@cf/zai-org/glm-5.2` | 262,144 | yes | no | $1.40 | $0.26 | $4.40 | Second opinion from a different family. Most expensive hosted option. |
| `@cf/zai-org/glm-4.7-flash` | 131,072 | yes | no | $0.0605 | none | $0.40 | Background turns: titles, summaries, classification. 23x cheaper input than GLM-5.2. |
| `@cf/nvidia/nemotron-3-120b-a12b` | 256,000 | yes | no | $0.50 | none | $1.50 | Long context where output volume, not reasoning depth, dominates the bill. |
| `@cf/openai/gpt-oss-120b` | 128,000 | yes | no | $0.35 | none | $0.75 | Cheap tool calls, open licence. Window too small for a loaded agent. |
| `@cf/openai/gpt-oss-20b` | 128,000 | yes | no | $0.20 | none | $0.30 | Cheapest tool-caller with a six-figure window. |
| `@cf/google/gemma-4-26b-a4b-it` | 256,000 | yes | no | $0.10 | none | $0.30 | Large window, low price, no coding track record. |
| `@cf/qwen/qwen3-30b-a3b-fp8` | 32,768 | yes | no | $0.0509 | none | $0.335 | Cheapest tool-caller here. The window is the problem. |
| `@cf/qwen/qwen2.5-coder-32b-instruct` | 32,768 | **no** | no | $0.66 | none | $1.00 | Completion, not agency. Cannot call tools. |
| `@cf/deepseek-ai/deepseek-r1-distill-qwen-32b` | 80,000 | **no** | no | $0.497 | none | $4.881 | Cannot call tools, and the highest output price here. |

Two rows are traps. `qwen2.5-coder-32b-instruct` carries "coder" in the name and cannot call tools, so no agent can drive it. The DeepSeek distill is the same, at nine times the output price of GPT-OSS-120B. Cloudflare's [function calling](https://developers.cloudflare.com/workers-ai/features/function-calling/) page describes the capability; the catalogue is the only place that says which models have it.

## The catalogue models publish no price — the only way to learn it is to run one and read the log

`moonshotai/kimi-k3`, `xai/grok-4.5` and `minimax/m3` each have a documentation page. Each page has a Pricing row. Each Pricing row says the same thing: "View pricing in the Cloudflare dashboard".

The figures below are measured, not published: one identical request per model through the account's AI Gateway on 2026-07-26, cost read back from the gateway log rows.

| Model id | Context (docs) | Request formats (docs) | Published rate | Measured cost, this turn | Tokens in / out | Blended $/M |
| --- | --- | --- | --- | --- | --- | --- |
| `moonshotai/kimi-k3` | 1,048,576 | Chat Completions | none | $0.002283 | 126 / 127 | $9.02 |
| `xai/grok-4.5` | 500,000 | Chat Completions | none | $0.0010764 | 248 / 37 | $3.78 |
| `minimax/m3` | 1,000,000 | Chat Completions, Anthropic Messages | none | $0.00011934 | 217 / 68 | $0.42 |

A single observation cannot separate an input rate from an output rate — two unknowns, one equation. It does establish the order of magnitude: Kimi K3 costs roughly twenty times per token what MiniMax M3 costs for the same answer. Separating the two rates needs a second request with a deliberately different input-to-output ratio, then solving the pair.

## Three Cloudflare surfaces disagree about what GLM-4.7 Flash costs

Workers AI bills in Neurons and projects them into dollars. The projection is where the surfaces drift apart.

| Surface | GLM-4.7 Flash, per M input tokens |
| --- | --- |
| Pricing page, "Price in Tokens" column | $0.060 |
| Pricing page, "Price in Neurons" column | 5,500 neurons, which at $0.011 per 1,000 Neurons is $0.0605 |
| Models API `price` property | $0.0605 |
| AI Gateway log `cost` field | behaves as $0.060 |

The check that settles it: a direct Workers AI call returns a `neurons` figure in its usage block. An 18-input, 24-output turn returned `"neurons": 0.9726`, and 18 x 5,500/1e6 + 24 x 36,400/1e6 = 0.9726 exactly. Neurons are the real unit; the dollar columns are rounded projections. Meanwhile the gateway's `cost` field for a 46-input, 587-output turn came back as $0.00023756, which is 46 x $0.060 + 587 x $0.40 exactly, not 46 x $0.0605 + 587 x $0.40 = $0.000237583.

The gap is $0.000000023 on that turn. It matters because it means the log's dollar column is not authoritative to the last digit, which is worth knowing before building a chargeback report on it.

## The background slot is where a coding agent's money actually goes

A coding agent runs two model slots. The main slot answers the user. A second, smaller slot runs constantly and invisibly: naming the session, summarising the conversation when the window fills, classifying whether a command is safe. In Claude Code that slot is the environment variable `ANTHROPIC_DEFAULT_HAIKU_MODEL`. It fires whether or not anyone is watching, which is what makes a 23x input price difference compound.

Two turn shapes, priced through each model's published rate:

| Turn shape | GLM-4.7 Flash | Kimi K2.7 Code | GLM-5.2 |
| --- | --- | --- | --- |
| Measured short turn, 46 in / 587 out | $0.000238 | $0.002392 | $0.002647 |
| Conversation summary, 20,000 in / 500 out | $0.00141 | $0.02100 | $0.03020 |
| 2,000 summary turns in a month | **$2.82** | **$42.00** | **$60.40** |

The middle row written out: 20,000 x $0.0605/1,000,000 = $0.00121 input plus 500 x $0.40/1,000,000 = $0.0002 output, giving $0.00141. For GLM-5.2: 20,000 x $1.40/1,000,000 = $0.028 plus 500 x $4.40/1,000,000 = $0.0022, giving $0.0302. The 2,000-turn count is a stated assumption; the per-turn figures are not.

$57.58 a month, on turns no one reads. Point the background slot at `@cf/zai-org/glm-4.7-flash` and the main slot at whatever is worth paying for.

## How to call one

Both surfaces take a Cloudflare API token with `Workers AI: Read` and `Workers AI: Run`. Setting up the gateway itself: [How to create a Cloudflare AI Gateway](/a/cloudflare-ai-gateway-setup).

**Workers AI, OpenAI-compatible.** This is the shape almost every client expects.

```bash
curl -s -X POST \
  "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai/v1/chat/completions" \
  -H "Authorization: Bearer <TOKEN>" \
  -H "content-type: application/json" \
  -d '{"model":"@cf/zai-org/glm-4.7-flash","max_tokens":24,
       "messages":[{"role":"user","content":"What is 2+2? Answer with the number only."}]}'
```

The real response, 2026-07-26, trimmed to the fields that matter:

```json
{"model":"@cf/zai-org/glm-4.7-flash",
 "choices":[{"message":{"role":"assistant","content":null,
   "reasoning_content":"1.  **Analyze the user's request:** The user is asking for the sum of 2 and 2"},
   "finish_reason":"length"}],
 "usage":{"prompt_tokens":18,"completion_tokens":24,"total_tokens":42,"neurons":0.9726}}
```

`content` is `null`. That is not an error condition — see below.

To log, cache and rate-limit the call, add one header to the same request: `-H "cf-aig-gateway-id: <GATEWAY_ID>"`. Catalogue models use the identical path and body with the unprefixed id, for example `"model":"minimax/m3"`.

## The Anthropic endpoint refuses every `@cf/` model by name

Cloudflare exposes `POST /ai/v1/messages`. Sending a Workers AI model to it returns, verbatim:

```json
{"type":"error","error":{"type":"invalid_request_error",
 "message":"AiError: Anthropic Messages API is not supported for model \"@cf/moonshotai/kimi-k2.7-code\""}}
```

Catalogue models are accepted there, and the shape is not what the endpoint name promises. The documentation for `minimax/m3` lists its request formats as "Chat Completions, Anthropic Messages". Sent to `/ai/v1/messages` on 2026-07-26 it answered:

```json
{"id":"06b4c281ce76f4c5405e21e09af57dfa","model":"MiniMax-M3","object":"chat.completion",
 "choices":[{"message":{"role":"assistant","content":"",
   "reasoning_content":"The user simply said \"say OK\"..."},"finish_reason":"length"}],
 "usage":{"total_tokens":210,"prompt_tokens":178,"completion_tokens":32}}
```

`"object":"chat.completion"` and a `choices` array: an OpenAI body from an Anthropic-named endpoint. A client that parses `content` as an array of blocks throws on it. So a tool speaking only `POST /v1/messages` cannot reach any Workers AI model without a translator, and cannot trust the catalogue models' envelope either. That translator, with its source, is in [Claude Code on Kimi, GLM or Grok through your own Cloudflare account](/a/claude-code-on-cloudflare-ai-gateway).

## What breaks

**Reasoning models spend the output budget thinking and hand back nothing.** Kimi and GLM both emit a reasoning trace before the answer, charged as output and counted against `max_tokens`. The call above, capped at 24, returned `finish_reason: "length"`, `content: null`, and a bill for 24 output tokens. The same prompt at `max_tokens: 1024` returned `"4"` after 78 output tokens. A client reading only `content` sees an empty turn; one falling back to `reasoning_content` presents the scratchpad as the answer. Give the cap headroom.

**Constrained decoding turns that into a total failure.** Cloudflare's [JSON Mode](https://developers.cloudflare.com/workers-ai/features/json-mode/) accepts a `response_format` carrying a JSON Schema and forces the output to match it — which forbids the `<think>` preamble a reasoning model emits first. On the Workers AI binding, debuggingfuture root-caused an every-call failure to exactly this: "glm-4.7-flash answers correctly in the Cloudflare playground but failed **every** pr-review with `StructuredOutputInvalid: empty`." GLM-5.2 failed identically, which proved the decode path was at fault rather than the model, and led him to retract his own earlier "GLM is out" verdict.

Rerun on the REST path on 2026-07-26, the failure is a budget failure and it is escapable. `@cf/zai-org/glm-4.7-flash` with a two-field `json_schema` at `max_tokens: 256` returned `content: null` and 256 output tokens of reasoning. The identical request at `max_tokens: 2048` returned `{"score": 6, "why": "This code is syntactically correct and does exactly what it is supposed to do. However, it lacks context, documentation, and best practices."}` after 760 output tokens, 2,634 characters of which were discarded reasoning. Binding path and REST path do not behave the same way; the rule that covers both is to budget three to ten times the tokens the answer needs, or not to send guided JSON to a reasoning model at all.

**Corrupted output at real prompt sizes, on real traffic only.** Tenstorrent's serving stack produced garbage from Kimi K2.7 Code under an eight-thousand-token structured coding prompt: "People chatting on the console were seeing corrupted outputs. We did not observe something like this during the weekend nor with release workflow with limited samples." Short smoke tests do not test this model.

**Mid-stream failure on long agentic runs.** Faith-2002, on opencode 1.18.5, hitting Kimi K2.7 Code through a third-party host: `{"type":"error","sequence_number":1584,"code":"InternalServiceError","message":"The service encountered an unexpected internal error.","param":""}` — consistently, on complex tasks, 1,584 stream events in. Cheap tokens and reliable long runs are not the same purchase.

**Vision works or not depending on which client sends the image.** vilicvane found Kimi K2.7 Code reading images fine through one VS Code integration and rejecting them through another: "The original VSCode built-in Ollama seem to work vision of with Kimi K2.7 Code. However, when use with models provided by this extension, Kimi complains corrupted images." The catalogue's `vision: true` property is accurate; the payload shape the client builds decides whether it works.

**Announced availability is not granted entitlement.** aregtech cited GitHub's changelog announcing Kimi K2.7 for Copilot Pro, then screenshotted the CLI listing it: "The GitHub policy says that Kimi Code 2.7 (model `kimi-k2.7-code`) is available for Pro subscription. - In fact, it is listed in the `Blocked / Disabled` list." Check the catalogue call, not the announcement.

**OpenAI-compatible means Chat Completions, not everything OpenAI ships.** mrnoname set out to spend a Cloudflare Startups credit on Workers AI through Codex CLI: "Workers AI has an OpenAI-compatible API so I expected it to just work with Codex. Nope. The Responses API surface doesn't map". He wrote a proxy.

## Quality, honestly: one benchmark, one retraction, one zero

The most useful published comparison of Kimi K2.7 Code against Qwen coding models is useful mainly because its author threw his first version away. Amit Arora had published a five-model, six-task results matrix, then removed it: "The README's results section published a 5x6 matrix (Opus, Kimi, Devstral, MiniMax, Qwen Coder Next, Qwen 3.6 35B) whose per-model numbers are **not reproducible from artifacts in this repo** -- no `eval.json` files exist on disk for those models, and the figures differ materially from what the current judge produces. Publish only what we have actually measured."

What replaced it, scored by one judge (`codex exec`, `gpt-5.6-sol`, high effort), every model self-hosted on vLLM:

| Task | Kimi-K2.7-Code | Qwen3.6-35B | Qwen3-Coder-30B |
| --- | --: | --: | --: |
| remove-faiss | **75.25** | 59.25 | 49.0 |
| remove-efs | **71.25** | 63.0 | 45.0 |
| ssrf | **72.75** | 55.75 | 0.0 |
| migrate-secrets | **75.5** | 54.5 | 43.5 |
| keycloak-rds-iam | 0.0 | **48.75** | 33.25 |
| Mean of 5 | **58.95** | 56.25 | 34.15 |

The zero is the honest part. Kimi scored 0.0 on `keycloak-rds-iam`, a task Qwen3.6-35B leads, classified as a real failure rather than judging noise: it "hit the 60-turn cap with 2/4 artifacts". Qwen3-Coder-30B's zero on `ssrf` is the mirror image — it "spent every turn implementing instead of designing".

Two readings follow and they pull opposite ways. On the four tasks Kimi completed it is clearly ahead, a 73.69 mean. Across all five the margin is 58.95 to 56.25, which one blown task erases. A frontier-scale model that occasionally burns its whole turn budget and delivers half the artifacts is not strictly better than a small one that finishes.

The hardware asymmetry is stated too: "**Hardware:** Kimi-K2.7-Code (1.06T-param MoE) ran on **8x H200** (`p5en.48xlarge`); the three Qwen models (3B-active MoE) on a single **`g6e.12xlarge`** (4x L40S). All via vLLM." That is a comparison of weights, not of Cloudflare's serving of them.

On the other family the evidence is one operator changing his mind. December 2025, andai on GLM behind a coding CLI: "I had been using GLM in Claude code with Claude code router, because while you can just change the API endpoint, the web search function doesn't work, and neither does image recognition." He went back to first-party. June 2026, same person: "But it just works with Claude Code? They have a guide on their website." Between them prmph filed the other side: "For some reason I can't even get Claude Code (Running GLM 4.6) to do the simplest of tasks today without feeling like I want to tear my hair out, whereas it used to be pretty good before." Three reports, two verdicts, one direction of travel — and all three were true when written.

**The verdict.** Kimi K2.7 Code on the main thread: the only Cloudflare-hosted model with a 262,144-token window, tool calling and image input at once, leader in the only reproducible published comparison, 32% cheaper on input than GLM-5.2. GLM-4.7 Flash on the background slot. GLM-5.2 for the second opinion, not the first draft.

**What would change it.** A reproducible benchmark where Kimi's zero repeats on a second long-horizon task; a published `moonshotai/kimi-k3` rate under $2/M blended, which would make a 1M-token window affordable for the main thread; or a cached-input rate on GLM-4.7 Flash, which would make it viable for turns that repeat a large prefix.

## First-party measurement: the same coding prompt through six models

**Method.** One `POST /v1/messages` per model against the account's own Anthropic-shaped gateway route, `max_tokens: 1024`, no tools, no system prompt, single user message, sequential, one attempt each. Latency measured client-side around the `fetch`. Token counts from the response `usage` block. Cost read afterwards from the AI Gateway log rows for the same six requests, matched by timestamp and by the `model_asked` value in the request metadata. Run at 04:35:23–04:35:44 UTC on 2026-07-26.

The prompt, in full:

```
Write a Python function chunk(xs, n) that splits list xs into consecutive chunks
of length n, with a shorter final chunk if the list does not divide evenly.
Return only the code, no explanation.
```

| Requested alias | Resolved id | Latency | In | Out | Cached in | Gateway cost |
| --- | --- | --: | --: | --: | --: | --: |
| `claude-kimi-k2.7-code` | `@cf/moonshotai/kimi-k2.7-code` | 2,745 ms | 49 | 185 | 0 | $0.00078655 |
| `claude-glm-5.2` | `@cf/zai-org/glm-5.2` | 2,454 ms | 53 | 135 | 0 | $0.0006682 |
| `claude-glm-flash` | `@cf/zai-org/glm-4.7-flash` | 7,571 ms | 46 | 587 | 0 | $0.00023756 |
| `claude-kimi-k3` | `moonshotai/kimi-k3` | 6,663 ms | 126 | 127 | 0 | $0.002283 |
| `claude-grok-4.5` | `xai/grok-4.5` | 2,271 ms | 248 | 37 | 128 | $0.0010764 |
| `claude-minimax-m3` | `minimax/m3` | 1,809 ms | 217 | 68 | 114 | $0.00011934 |

**Every one of the six returned the same function.** Four wrote `xs[i:i+n]` and two wrote `xs[i:i + n]`:

```python
def chunk(xs, n):
    return [xs[i:i+n] for i in range(0, len(xs), n)]
```

**What it shows.** On a task with one obvious idiomatic answer, model choice changes nothing about the answer and a great deal about the cost. MiniMax M3 at $0.00011934 was 19 times cheaper than Kimi K3 at $0.002283 for a byte-identical result. The slowest turn came from the cheapest hosted model, GLM-4.7 Flash at 7,571 ms, because it spent 587 output tokens reasoning about a two-line function — 4.5 times the output of any other model here.

**What it does not show.** Nothing about multi-turn agentic work, tool calling, long contexts, or instruction adherence under pressure. One sample per model, one prompt, no repeats, so the latency figures carry no error bars and include whatever queueing each backend had that second. It is a floor check.

**Reconciliation.** The three Workers AI rows multiply out exactly against the published rates: 49 x $0.95 + 185 x $4.00 over a million is $0.00078655, the logged figure to the last digit; 53 x $1.40 + 135 x $4.40 is $0.0006682, likewise. A previously recorded row on this same account does *not* reconcile: a 149,187-input-token Kimi K2.7 Code turn billed $0.02852109, implying $0.191 per million — the cached rate, on a turn reporting 64 cached tokens. Published as unreconciled. The arithmetic holds at three-digit token counts and fails at six-digit ones, and the difference has not been explained.

## Choosing table

| Task | Pick | Why |
| --- | --- | --- |
| Main agent thread, tools, large repo | `@cf/moonshotai/kimi-k2.7-code` | 262,144 window, tools, vision, $0.19/M cached input, leader in the one reproducible comparison. |
| Session titles, summaries, safety classification | `@cf/zai-org/glm-4.7-flash` | $0.0605/M input against $1.40 for GLM-5.2. Same job, 23x less. |
| Second opinion on a design, different family | `@cf/zai-org/glm-5.2` | Independent weights. 47% more input, 10% more output. |
| Reading a screenshot or a diagram | `@cf/moonshotai/kimi-k2.7-code` | The only `@cf/` coding model with `vision: true`. |
| Context over 262,144 tokens | `moonshotai/kimi-k3` or `minimax/m3` | 1,048,576 and 1,000,000 tokens, both catalogue-billed and unpriced in the docs. |
| Cheapest possible tool call, small window fine | `@cf/openai/gpt-oss-20b` | $0.20/M in, $0.30/M out, 128,000 window, tools yes. |
| Bulk structured extraction with a JSON schema | `@cf/openai/gpt-oss-120b` | Guided JSON on a reasoning model burns the output budget. Budget generously. |
| Plain code completion, no agency | `@cf/qwen/qwen2.5-coder-32b-instruct` | Cheaper per output token than Kimi. Cannot drive a loop. |

## Symptom, cause, fix

| Symptom | Cause | Fix |
| --- | --- | --- |
| `"content": null`, `finish_reason: "length"`, tokens still billed | Reasoning trace consumed the whole `max_tokens` budget | Raise `max_tokens`. 1,024 is the floor for a one-line GLM-4.7 Flash answer. |
| `StructuredOutputInvalid: empty` on every guided-JSON call | `response_format` schema forbids the `<think>` preamble the model emits first | Drop `response_format` and parse JSON yourself, or give 3–10x the tokens the object needs. |
| `AiError: Anthropic Messages API is not supported for model "@cf/..."` | Workers AI models are excluded from `/ai/v1/messages` | Use `/ai/v1/chat/completions`, or put a translator in front. |
| Response has `"object":"chat.completion"` from `/ai/v1/messages` | A catalogue model returned its native OpenAI body through the Anthropic-named path | Detect the envelope shape at runtime; do not trust the endpoint name. |
| HTTP 402, "Gateway authentication is required to use unified billing" | A catalogue model routed through an unauthenticated gateway | Enable authentication on the gateway and send `cf-aig-authorization`. See [Cloudflare Unified Billing](/a/cloudflare-unified-billing). |
| `{"code":"InternalServiceError"}` mid-stream on a long run | Hosted-path instability on extended agentic sessions | Retry with backoff, resume from the last completed tool result. The stream is not atomic. |
| Garbled tokens in the answer at large prompt sizes | Serving-stack corruption that short samples do not surface | Test at the prompt size actually used. |
| "corrupted images" from a vision-capable model | Client built the image part in a shape the backend does not accept | Send OpenAI `image_url` parts on `/ai/v1/chat/completions`. Verify with a tiny known PNG. |
| Model is announced but the CLI lists it blocked | Announcement and entitlement are separate systems | Call `/ai/models/search` and treat its output as the truth. |
| The id 404s or silently resolves to another model | The public model name is not the Cloudflare id | Copy the id from the catalogue call. `@cf/moonshotai/kimi-k2.5` exists but is Deprecated. |
| Codex CLI or any Responses-API client cannot connect | Workers AI implements Chat Completions, not the Responses API | Use a Chat Completions client, or a translating proxy. |
| Cost report does not tie out to the published rate | The gateway `cost` field rounds, and large-context rows have not reconciled | Reconcile on token counts from `usage`, not the dollar column. |

## Rerun any of it

The alias-to-id mapping used in the six-model run is the `CATALOGUE` table in [the gateway translator source](https://github.com/redacted/claude-code-cloudflare-gateway). Every price and capability above comes from one call; every cost from another.

```bash
# The catalogue: prices, context windows, function_calling, vision
curl -s -H "Authorization: Bearer <TOKEN>" \
 "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai/models/search?per_page=500" | jq .

# What a turn actually cost, from the gateway log (needs AI Gateway: Read, not Workers AI)
curl -s -H "Authorization: Bearer <TOKEN>" \
 "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai-gateway/gateways/<GATEWAY_ID>/logs?per_page=10&order_by=created_at&order_by_direction=desc" \
 | jq -r '.result[] | [.model, .tokens_in, .tokens_out, .cost] | @tsv'
```
