Cloudflare Workers AI
Cloudflare Workers AI provides serverless inference for models hosted on Cloudflare's network. AISIX gives applications an OpenAI-compatible API for those models while keeping the Cloudflare token, caller access, rate limits, and usage accounting at the gateway.
Prerequisites
Before starting, prepare the following:
- One AISIX setup:
- For AISIX Cloud, an environment with an attached gateway and a write-scoped admin token. For On-Premises, follow the AISIX Cloud Quickstart. To request Hybrid Cloud access, contact API7.
- For the open-source AISIX gateway, prepare either a local AISIX installation or the Docker setup from the Open-Source AISIX Gateway Quickstart. Configure the gateway to load a declarative resources file.
- 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.
curlandjq.
Configure with AISIX Cloud
Export the AISIX Cloud connection details:
# AISIX_CP is the Admin API base URL; include /api and omit a trailing slash
# The local On-Premises quickstart uses http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
Create a provider key, model alias, and caller API key for the Workers AI-backed chat-completions route.
Cloudflare Workers AI is a community catalog provider. AISIX accepts cloudflare-workers-ai as the provider value and selects the openai adapter with bearer authentication. AISIX does not supply a curated base URL or provider-specific request and response rewrites, so you must configure the account-scoped api_base.
The dashboard labels this provider as a community entry whose wire format is unverified.
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 AISIX 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 Keys.
❸ 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.
Configure with the Open-Source AISIX Gateway
Export the upstream credential and choose the caller API key that applications will send to the gateway:
export CLOUDFLARE_API_TOKEN="YOUR_PROVIDER_API_KEY"
export CLOUDFLARE_ACCOUNT_ID="YOUR_CLOUDFLARE_ACCOUNT_ID"
export CALLER_API_KEY="YOUR_CALLER_API_KEY"
Create a complete declarative resources file for this provider:
_format_version: "1"
provider_keys:
- display_name: "cloudflare-workers-ai-prod"
provider: "cloudflare-workers-ai"
adapter: "openai"
api_key: ${CLOUDFLARE_API_TOKEN}
api_base: "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/v1"
models:
- display_name: "cloudflare-gptoss-prod"
provider: "cloudflare-workers-ai"
model_name: "@cf/openai/gpt-oss-120b"
provider_key: "cloudflare-workers-ai-prod"
api_keys:
- display_name: "cloudflare-caller"
key_env: CALLER_API_KEY
allowed_models:
- "cloudflare-gptoss-prod"
If AISIX is installed locally, validate the file before loading it:
aisix validate --resources resources.yaml
After validation, start the gateway with the referenced environment variables in its process environment. Reload an existing gateway only if those variables are already available to the process; otherwise, restart it with the updated environment.
If you use Docker, adapt the validation and startup commands in the Open-Source AISIX Gateway Quickstart. Mount this resources.yaml file and pass every environment variable it references with -e in both commands. After the resources load, prepare the shared verification request below:
export AISIX_API_KEY="$CALLER_API_KEY"
Verify the Provider Connection
Export the AISIX gateway origin:
# The local quickstarts use http://127.0.0.1:3000
export AISIX_PROXY="YOUR_AISIX_GATEWAY_ORIGIN"
Send a chat-completions request through the AISIX proxy:
curl -sS -X POST "$AISIX_PROXY/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 an AISIX-curated adapter mapping 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 such mapping, 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 through the Responses bridge over the chat adapter path rather than passed through verbatim. OpenAI-specific Responses fields without a chat equivalent are ignored. |
/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/* | Available through a configured passthrough route claiming this prefix with the account-scoped /ai/v1 root as its target_url; grant the route on the caller key's allowed_routes. Such a route reaches paths under /ai/v1, so Cloudflare's native /ai/run/@cf/... endpoint sits outside the root and is not reachable through it. |
Next Steps
You have now connected AISIX to Cloudflare Workers AI and verified the model alias. Continue with these guides:
- Model Aliases: configure routing, retry behavior, or cost metadata 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.