Skip to main content

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.

caution

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 IDNotes
@cf/openai/gpt-oss-120bOpen-weight reasoning model with a selectable reasoning effort.
@cf/meta/llama-3.3-70b-instruct-fp8-fastLlama 3.3 70B quantized to fp8 for faster inference.
@cf/qwen/qwen3-30b-a3b-fp8Qwen3 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:

  1. An upstream authentication failure points at the api_key value or at a token that lacks Workers AI permissions.
  2. 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.
  3. 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_renames renames 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_field maps reasoning from a nonstandard streaming delta path onto the canonical delta.reasoning_content field. Use it when a model streams its reasoning somewhere other than reasoning_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.

RouteBehavior with a Cloudflare Workers AI alias
/v1/chat/completionsSupported, including stream: true.
/v1/embeddingsSupported. 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/responsesSupported. Non-OpenAI providers are bridged through the chat adapter path rather than passed through verbatim.
/v1/messagesSupported for Anthropic-shaped callers through translation. Token counting at /v1/messages/count_tokens requires an Anthropic-backed model.
/v1/images/generationsRejected. The route accepts only models whose provider is openai.
/v1/rerankRejected. The route accepts only the openai, cohere, and jina provider values.
/v1/videosReturns 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: