Cloudflare Workers AI
Connect AISIX AI Gateway to Cloudflare Workers AI so applications can call Cloudflare-hosted open-weight models through the gateway's OpenAI-compatible API. AISIX keeps the Cloudflare API token on the gateway side. It authorizes model access with caller API keys and allowlists, and applies the same rate-limit and usage-accounting controls as other model aliases.
Cloudflare Workers AI is a community catalog provider. AISIX accepts cloudflare-workers-ai as a provider value because the ID is in the public model catalog, and assigns the openai adapter with HTTP bearer authentication. The dashboard labels the provider as a community entry whose wire format is unverified. AISIX registers no curated base URL, request rewrite, or response rewrite for it, so this page covers what you supply instead — starting with an api_base that no shared default can replace.
Prerequisites
The following examples configure the upstream through the AISIX Cloud Admin API. Before configuring the upstream, prepare the following:
- Access to AISIX Cloud with an environment, an attached gateway, and a write-scoped admin token. For On-Premises, follow the AISIX Cloud Quickstart. To request Hybrid Cloud access, contact API7.
- A Cloudflare account ID and a Workers AI API token. In the Cloudflare dashboard, open the Workers AI page and select Use REST API to create the token and copy the account ID, as described in Get started with the REST API.
Export the connection details used by every request below:
# Replace with your values
export AISIX_CP="http://localhost:8080/api"
export AISIX_TOKEN="aisix_pat_YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
Configure the Cloudflare Workers AI Upstream
Create a provider key, model alias, and caller API key for the Workers AI-backed chat-completions route.
Create a Provider Key
Create the provider key that stores the Cloudflare credential and the account-scoped API root:
# Replace with your values
export CLOUDFLARE_API_TOKEN="YOUR_PROVIDER_API_KEY"
export CLOUDFLARE_ACCOUNT_ID="YOUR_CLOUDFLARE_ACCOUNT_ID"
PROVIDER_KEY_ID=$(curl -sS -X POST "$AISIX_CP/provider_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "cloudflare-workers-ai-prod",
"provider": "cloudflare-workers-ai",
"api_key": "'"${CLOUDFLARE_API_TOKEN}"'",
"api_base": "https://api.cloudflare.com/client/v4/accounts/'"${CLOUDFLARE_ACCOUNT_ID}"'/ai/v1",
"allowed_environments": ["'"${ENV_ID}"'"]
}' | jq -r '.provider_key.id')
echo "$PROVIDER_KEY_ID"
❶ provider is cloudflare-workers-ai, the catalog ID. The Cloud Admin API derives the adapter from the catalog provider; the adapter field is only accepted on BYO provider keys, so do not set it here.
❷ api_key stores the Workers AI API token. Cloudflare authenticates the REST API with an Authorization: Bearer header, which is what the openai adapter already sends. The value follows the credential-handling behavior in Provider Credentials.
❸ api_base is the account-scoped root https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai/v1. Cloudflare documents the full OpenAI-compatible endpoint as https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1/chat/completions in OpenAI compatible API endpoints. AISIX appends the endpoint path such as /chat/completions to api_base, so the value must stop at /ai/v1. If you paste the full endpoint URL by mistake, AISIX strips the recognized suffix and the trailing slash, but the shorter root is the value to store.
Always set api_base on a Cloudflare Workers AI provider key.
For a community catalog provider, AISIX falls back to the base URL published in the public model catalog when you omit api_base. For Cloudflare Workers AI, that published value is https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/v1 — a template, not a resolved URL, because every Cloudflare account has its own endpoint. AISIX performs no placeholder substitution, and the fallback value is stored as written rather than re-validated. The create request still succeeds. The stored root then keeps the literal ${CLOUDFLARE_ACCOUNT_ID} text in place of an account ID, and the first request fails at the upstream. There is no shared default that could work for this provider.
The command captures the returned provider key ID in PROVIDER_KEY_ID.
Create a Model
Workers AI model IDs always begin with @cf/, followed by the publisher and the model name: @cf/<publisher>/<model>. Carry the entire string into model_name, including the @cf/ prefix and any precision or variant suffix such as -fp8-fast. Dropping the prefix, or reusing a bare ID that another host publishes for the same weights, produces an upstream model error.
The following IDs are current in the Cloudflare model catalog:
| Cloudflare model ID | Notes |
|---|---|
@cf/openai/gpt-oss-120b | Open-weight reasoning model with a selectable reasoning effort. |
@cf/meta/llama-3.3-70b-instruct-fp8-fast | Llama 3.3 70B quantized to fp8 for faster inference. |
@cf/qwen/qwen3-30b-a3b-fp8 | Qwen3 instruction model for multilingual chat, reasoning, and tool use. |
Check the Workers AI model catalog for the current list before you create an alias. Confirm that the model you pick is a text-generation model rather than an embedding, image, or speech model.
Create the model alias callers will send in requests:
MODEL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/models" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "cloudflare-gptoss-prod",
"model_name": "@cf/openai/gpt-oss-120b",
"provider_key_id": "'"${PROVIDER_KEY_ID}"'"
}' | jq -r '.model.id')
echo "$MODEL_ID"
❶ display_name is the alias callers send in model.
❷ model_name is the full Workers AI model ID, for example @cf/openai/gpt-oss-120b.
❸ provider_key_id attaches the alias to the Cloudflare Workers AI provider key.
To attach cost metadata for budget accounting and usage reports, see Model Aliases.
Create a Caller API Key
Create the caller API key that can access the model alias. The plaintext key is server-generated and returned once in the create response, so capture it now:
AISIX_API_KEY=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/api_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "cloudflare-caller",
"allowed_models": ["'"${MODEL_ID}"'"]
}' | jq -r '.plaintext')
echo "$AISIX_API_KEY"
The allowed_models value must reference the model ID captured in the previous step. After the write, the configuration projects to attached gateways automatically.
Verify the Provider Connection
Send a chat-completions request through the AISIX proxy:
curl -sS -X POST "http://127.0.0.1:3000/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "cloudflare-gptoss-prod",
"messages": [
{
"role": "user",
"content": "Say hello from Cloudflare Workers AI."
}
]
}'
The gateway returns an OpenAI-compatible response that echoes the caller-facing alias cloudflare-gptoss-prod.
If the request fails, work through the three causes in order:
- An upstream authentication failure points at the
api_keyvalue or at a token that lacks Workers AI permissions. - An upstream route or account error points at
api_base. Confirm that the account ID segment is a real account ID and that the value ends at/ai/v1. - An upstream model error points at
model_name. Confirm that the ID still carries the@cf/prefix.
Supply What the Community Catalog Does Not
Providers with a curated AISIX catalog entry ship request and response adjustments alongside the adapter. A caller-facing parameter that the upstream spells differently is renamed before it leaves the gateway. Cloudflare Workers AI has no curated entry, so no parameter rename and no reasoning-field mapping are registered for it. AISIX sends the caller's chat-completions body to the /ai/v1 root with the field names the caller used, and reads the reply as standard OpenAI chat-completions JSON.
That default is correct as long as the Cloudflare surface matches the OpenAI shape. When it does not, configure the difference explicitly on the provider key rather than reshaping every client:
{
"request": {
"param_renames": {
"max_completion_tokens": "max_tokens"
}
},
"response": {
"reasoning_field": "delta.reasoning"
}
}
request.param_renamesrenames a top-level parameter on the way out. Use it when a Workers AI model rejects the name your clients already send. If a request carries both names, AISIX uses the value from the original caller-facing name.response.reasoning_fieldmaps reasoning from a nonstandard streamingdeltapath onto the canonicaldelta.reasoning_contentfield. Use it when a model streams its reasoning somewhere other thanreasoning_content.
An override applies to every model that references the provider key, so validate it against a non-production alias first. See Provider-Specific Overrides for the full field catalog.
AISIX does not strip top-level parameters it does not model natively. A parameter that Cloudflare supports and AISIX has no typed field for still reaches the upstream unchanged. A rename is therefore needed only when the parameter name differs, not when the parameter is simply unfamiliar to the gateway.
Control Reasoning Effort
The @cf/openai/gpt-oss-120b model exposes a reasoning-effort control that accepts low, medium, and high. Because unrecognized top-level parameters pass through, send it at the top level of the chat-completions body:
{
"model": "cloudflare-gptoss-prod",
"messages": [
{
"role": "user",
"content": "Plan a three-step migration."
}
],
"reasoning_effort": "low"
}
Reasoning support is per model on Workers AI, and several models expose no reasoning control at all. Confirm the parameter on the model page for the specific model before you send it, because a model that does not accept the parameter can reject the request.
Endpoint Coverage
Cloudflare Workers AI serves text generation and text embeddings over its OpenAI-compatible root, so only part of the AISIX proxy surface applies to a Workers AI-backed alias.
| Route | Behavior with a Cloudflare Workers AI alias |
|---|---|
/v1/chat/completions | Supported, including stream: true. |
/v1/embeddings | Supported. Cloudflare implements OpenAI-compatible embeddings under the same /ai/v1 root, so create a second alias on the same provider key whose model_name is an embedding model such as @cf/baai/bge-m3. See Embeddings. |
/v1/responses | Supported. Non-OpenAI providers are bridged through the chat adapter path rather than passed through verbatim. |
/v1/messages | Supported for Anthropic-shaped callers through translation. Token counting at /v1/messages/count_tokens requires an Anthropic-backed model. |
/v1/images/generations | Rejected. The route accepts only models whose provider is openai. |
/v1/rerank | Rejected. The route accepts only the openai, cohere, and jina provider values. |
/v1/videos | Returns a not-implemented error. The route dispatches on a fixed provider set that does not include cloudflare-workers-ai. |
/passthrough/cloudflare-workers-ai/* | Supported, and rooted at api_base. The tunnel reaches paths under /ai/v1, so Cloudflare's native /ai/run/@cf/... endpoint sits outside the root and is not reachable through this provider key. See Provider Passthrough. |
Next Steps
You have now connected AISIX to Cloudflare Workers AI and verified the model alias. Continue with these guides:
- Model Aliases: add routing, cost metadata, and rate limits for this alias.
- Routing and Failover: fail over between Cloudflare Workers AI and a second provider.
- Provider-Specific Overrides: adapt request and response shapes when an upstream API differs from its adapter.
- Provider Compatibility: review supported proxy endpoints and provider-specific boundaries.