Resources File Reference
The open-source AISIX gateway can load provider credentials, models, caller credentials, and runtime policies from a declarative resources.yaml file. This reference covers the file's YAML rules, cross-resource naming, environment interpolation, and every supported resource collection.
Set resources_file in the startup configuration to select the file. To create and load a working configuration, start with the Open-Source AISIX Gateway Quickstart. Use the CLI Reference to validate changes and Configuration Status to inspect the active or rejected configuration.
File Format
AISIX loads exactly one YAML document from one resources file. The filename is not fixed: resources.yaml is the convention used in these docs, but resources_file can point to any readable file path.
The setting accepts one path only. AISIX does not load a directory, resolve include or import directives, or combine multiple resource files. If you maintain the configuration as separate source fragments, assemble them into one YAML document before validating and loading it.
The document's top level is a mapping with a mandatory _format_version and up to ten resource collections:
_format_version: "1"
provider_keys:
- display_name: openai-prod
provider: openai
api_key: ${OPENAI_API_KEY}
models:
- display_name: gpt-4o
provider: openai
model_name: gpt-4o-2024-11-20
provider_key: openai-prod
api_keys:
- display_name: ci-bot
key_env: CI_BOT_KEY
allowed_models: ["gpt-4o"]
rate_limit_policies:
- name: cap-gpt4o
scope: model
scope_ref: gpt-4o
window: minute
max_requests: 300
| Collection | Purpose | Identity field |
|---|---|---|
provider_keys | Store upstream provider credentials and connection settings. | display_name |
models | Define caller-facing model aliases and dispatch behavior. | display_name |
api_keys | Authenticate callers and control their model, MCP tool, and A2A agent access. | display_name |
oidc_providers | Trust JWT issuers for caller authentication. | name |
claim_mappings | Resolve verified JWT claims to caller API keys. | name |
guardrails | Screen or transform request and response content. | name |
mcp_servers | Expose MCP servers or OpenAPI operations as tools. | name or display_name |
a2a_agents | Register upstream agents for A2A callers. | name or display_name |
cache_policies | Cache matching non-streaming model responses. | name |
observability_exporters | Export request telemetry to external systems. | name |
rate_limit_policies | Apply conditional or single-scope request and token limits. | name |
YAML Structure
_format_version must be exactly the string "1", quoted so YAML parses it as a string. A missing or unrecognized version is a load error, and an unquoted 1 gets a dedicated error asking you to quote it.
The gateway applies the following YAML constraints:
- The file must contain exactly one YAML document. Multiple documents separated by
---are a load error. - The top level and every nested mapping must use string keys.
- Each resource collection, when present, must be a sequence of mappings. An absent or
nullcollection loads as empty. - Unknown top-level collections and unknown fields within a resource are load errors.
- YAML anchors and aliases can reuse values. Merge keys (
<<) are not expanded and fail schema validation as unknown fields.
Identity and Derived IDs
Every entry's identity field must be a non-empty string that is unique within its collection; a duplicate is a load error naming both entries. For mcp_servers and a2a_agents, either name or display_name supplies the identity. An entry that carries both spellings is a load error, so use exactly one.
The file accepts no id field on any entry. Entry IDs are derived deterministically from <kind>/<identity> as a UUIDv5, so the same file always produces the same IDs across reloads and processes. References and rate-limit counters keyed by ID therefore survive a SIGHUP reload.
Name References
Entries select related resources by name. The loader checks each relationship as follows:
| Relationship | Name to use | Validation behavior |
|---|---|---|
| Model to provider credentials | Provider key display name | Must match a defined provider key. An unknown name is a load error that lists the available provider keys. A resources file cannot use provider_key_id instead. |
| Caller or virtual model to target model | Model display name | Must match a model defined in the file. Values containing * are glob patterns and are not checked for an exact match. |
| Rate limit to its subject | Model or caller key display name | For model and api_key scopes, the name resolves to the target. For other scopes, the value passes through unchanged. |
| Caller identity to JWT issuer | OIDC provider name | Remains a name rather than resolving to a derived ID. |
Environment Interpolation
${VAR} references resolve against the gateway process environment only when they appear in string scalars. The value is substituted into the parsed YAML tree, so an environment value can never inject YAML structure, and mapping keys are never interpolated.
This interpolation is for user-defined process variables. For AISIX-defined startup and connection variables, see Environment Variables.
- Partial interpolation is supported:
api_base: https://${UPSTREAM_HOST}/v1. - A variable that is unset or empty causes a load error that names the variable but never its value.
- Shell-style fallback and required-value expressions, such as
${VAR:-default}and${VAR:?message}, are not supported. $$produces a literal$; a bare$VARwithout braces passes through untouched; an unterminated${or empty${}is an error.- Non-string scalars, including integer, float, boolean, and
nullvalues, are never interpolated.
Loading, Errors, and Reload
The load pipeline is identical at boot, during a SIGHUP reload, and when run by aisix validate. The gateway reads the file, parses the YAML, interpolates ${VAR} references, converts each entry, resolves name references, validates schemas, and checks cross-references. Schema validation is the same for every configuration source.
Errors aggregate across the whole file and identify the offending entry and field, for example models[2] ("gpt-4o"). Loading is all-or-nothing: any error rejects the entire file.
At boot, a rejected file stops the gateway immediately. During a SIGHUP reload, the gateway keeps serving the last valid snapshot, logs the aggregated report, and exposes the rejected load through GET /status/config. The gateway does not watch the file for changes; reloads are explicit.
Provider Keys
A provider key stores an upstream credential together with the connection settings used for that provider. Models select the provider key by its display_name. Unknown fields are rejected at every nesting level.
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | yes | Entry identity, unique within provider_keys. Models reference the key by this name. |
api_key | string | conditional | The upstream provider's API key. Supply it as ${VAR}. secret is accepted as an alternative spelling; exactly one of the two must be present. Some provider credentials contain more than one field. For these providers, supply a JSON credential document through one environment variable. See the credential shapes for AWS Bedrock and Azure OpenAI with Entra ID. |
provider | string | no | Upstream provider identifier, such as openai or deepseek. An open string used for provider-specific dispatch. Default: empty. |
adapter | enum | no | Upstream protocol family used when no provider-specific dispatch applies: openai, anthropic, bedrock, vertex, or azure-openai. See Adapter Protocol Families. |
api_base | string | no | Override base URL for the upstream provider. Required in practice for private OpenAI-compatible endpoints. Supports partial interpolation, such as https://${UPSTREAM_HOST}/v1. |
strip_headers | array of strings | no | Inbound headers removed before passthrough forwarding. Default: authorization, cookie, set-cookie, x-api-key. Entries are trimmed, lowercased, and deduplicated. An explicit [] disables stripping; it does not fall back to the default. |
tls | object | no | TLS settings for this key's endpoint. When omitted, the key uses the deployment-wide upstream.tls settings. |
tls.ca_cert | string | no | PEM-encoded certificate authority certificates trusted as additional issuers for this endpoint. A bundle can contain several certificates. See TLS and mTLS. |
tls.verify | boolean | no | Whether to verify the upstream certificate. Default: true. Setting it to false accepts any certificate and is for test environments only. |
telemetry_tags | object | no | Attribution tags emitted with requests routed through this key. |
telemetry_tags.kind | enum | no | Attribution category: catalog or byo. |
telemetry_tags.featured | boolean | no | Whether the provider key is featured. Default: false. |
telemetry_tags.branded_provider | string | no | Branded provider slug for catalog entries. |
telemetry_tags.pk_label | string | no | Operator-defined provider-key label, such as production. |
telemetry_tags.byo_label | string | no | Operator-defined bring-your-own label, such as a team name. |
request | object | no | Request-shape overrides applied before dispatch. |
request.param_renames | map of string to string | no | Top-level request body keys named on the left are renamed to the key on the right before dispatch. |
request.param_constraints | object | no | Clamp bounds for temperature in chat completion bodies. |
request.param_constraints.temperature_min | number | no | Minimum accepted temperature. When omitted, no lower bound is applied. |
request.param_constraints.temperature_max | number | no | Maximum accepted temperature. When omitted, no upper bound is applied. |
request.default_headers | map of string to string | no | Headers added to the outbound request. Because the loader resolves ${...} from the environment first, write request-context references as $${...}; for example, $${request.api_key.team_id} loads as ${request.api_key.team_id} for per-request rendering. A header whose variables have no value is dropped rather than sent empty. These headers outrank a header relayed by forward_client_headers, but cannot replace a name the gateway sets itself. The gateway also drops reserved authentication, signing, session, and routing names. See Upstream Request Headers. |
request.forward_client_headers | array of strings | no | Inbound client headers relayed to the upstream, as exact names or single-* globs such as x-trace-*, matched case-insensitively. Empty (the default) forwards nothing. Authentication, transport, x-aisix-*, and x-stainless-* headers are never forwarded. See Upstream Request Headers. |
request.default_body_fields | map of string to JSON value | no | Top-level body fields added to the outbound request when the caller did not set them. |
response | object | no | Response-shape overrides applied by provider bridges that support them. |
response.stream_done_marker | enum | no | Whether the upstream SSE stream is expected to emit data: [DONE]: required, optional, or none. Omitted accepts either. |
response.content_list_to_string | boolean | no | When true, flattens a messages[*].content array of text blocks into a single string before dispatch. Default: false. |
response.reasoning_field | string | no | Path used to lift reasoning content from the provider response, such as delta.reasoning_content. |
response.error_envelope | string | no | Stored error-envelope preference kept for compatibility with control-plane configuration; the proxy does not currently apply it. |
The following example brings those settings together. It defines one OpenAI provider key and one private OpenAI-compatible endpoint. The private endpoint declares the openai adapter, builds its base URL from the environment, and trusts an additional certificate authority.
_format_version: "1"
provider_keys:
- display_name: openai-prod
provider: openai
api_key: ${OPENAI_API_KEY}
- display_name: internal-vllm
provider: internal-vllm
adapter: openai
api_base: https://${UPSTREAM_HOST}/v1
api_key: ${INTERNAL_LLM_KEY}
# Only needed when this endpoint's certificate is signed by a
# private or enterprise certificate authority.
tls:
ca_cert: |
-----BEGIN CERTIFICATE-----
MIIB...
-----END CERTIFICATE-----
Models
A model entry defines a caller-facing alias. Direct, embedding, routing, ensemble, and semantic aliases all appear in /v1/models; wildcard patterns do not (see Model Aliases). Every entry uses exactly one dispatch shape: direct, routing, ensemble, or semantic. Mixing shapes in one entry is a load error, and unknown fields are rejected at every nesting level.
The following fields for timeouts, retries, access, cost, and inline limits are shared across model shapes, but each is accepted only on the kinds where the gateway resolves it — the Applies to column lists them, and a field set on a kind that does not resolve it is rejected as a load error:
| Field | Type | Applies to | Description |
|---|---|---|---|
display_name | string | all | Entry identity, unique within models. The caller-facing alias. Required on every shape. |
timeout | integer (ms) | direct, embedding, routing, semantic | End-to-end deadline for non-streaming upstream calls. On a routing model or semantic router this is the group/router-level slot applied to every target that does not set its own; absent falls back through that slot, then the deployment-wide upstream.timeout_ms default (6000000 ms = 6000 s). 0 disables it. Not accepted on ensemble — its per-call deadline is ensemble.timeout_ms. |
stream_timeout | integer (ms) | direct, embedding, routing, semantic | Maximum gap between upstream streaming chunks. 0 or absent falls back to the group/router stream_timeout, then to timeout, then to the deployment defaults. Not accepted on ensemble. |
retries | integer | direct, embedding, semantic | Retry attempts against this model after a retryable upstream failure. On a semantic router this is the router-level slot. 0 disables same-target retries. A routing model does not take a top-level retries — its group slot is routing.retries (below); a routing target's own retries overrides that. Not accepted on ensemble. |
rate_limit | object | all | Per-model request, token, and concurrency limits, enforced on the entry the caller addressed. See below. |
allowed_cidrs | array of strings | all | Client IP allowlist in CIDR notation (IPv4 and IPv6). Empty or absent allows all clients. With a restriction configured, a missing or malformed source IP is denied. |
cost | object | direct, embedding | Per-token cost for budget tracking and least_cost ranking: input_per_1k and output_per_1k, both USD per 1,000 tokens and both required when the block is present. Set it on the direct/embedding models a group dispatches to, not on the group. |
Within rate_limit, each field is optional and unlimited when absent:
| Field | Limit |
|---|---|
rate_limit.rps | Requests per fixed 1-second window. |
rate_limit.rpm | Requests per fixed 60-second window. |
rate_limit.rph | Requests per fixed 3,600-second window. |
rate_limit.rpd | Requests per fixed 86,400-second window. |
rate_limit.tpm | Tokens per fixed 60-second window. |
rate_limit.tpd | Tokens per fixed 86,400-second window. |
rate_limit.concurrency | Maximum in-flight requests. This is a semaphore, not a window. |
Direct Models
The direct shape names one upstream model behind one provider key:
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | yes | Vendor identity such as openai or anthropic. Starts with a lowercase letter or digit; ., _, and - are allowed after the first character; 1–64 characters. |
model_name | string | yes | Upstream model identifier sent in provider requests, such as gpt-4o-2024-11-20. |
provider_key | string | yes* | Name of a provider_keys entry. Mutually exclusive with provider_key_id. In a resources file, use provider_key. |
embedding | object | no | Marks the model as embedding-capable: dimensions (required, vector dimensionality) and normalize (default true, whether the endpoint already returns L2-normalized vectors). The model can then serve /v1/embeddings and back a semantic router. |
background_model_check | object | no | Background health checks. See Health Checks. Sub-fields enabled, interval_seconds (min 5), timeout_seconds, prompt, max_tokens, and stale_after_seconds are required when the block is present; ignore_statuses (array of status codes) is optional. |
cooldown | object | no | Request-path cooldown after retryable upstream failures. See below. |
auto_prompt_caching | object | no | Automatic Anthropic prompt-cache marker injection. Supported only for direct models whose provider is anthropic. enabled is required when the object is present; ttl is 5m (default) or 1h. See Anthropic Prompt Caching. |
The optional cooldown object accepts these settings:
| Field | Default | Behavior |
|---|---|---|
cooldown.enabled | true | Enables request-path cooldown tracking. |
cooldown.default_seconds | 30 | Sets the cooldown TTL when no usable Retry-After header exists. |
cooldown.max_seconds | 600 | Caps a cooldown derived from Retry-After. |
cooldown.honor_retry_after | true | Uses a valid Retry-After value when available. |
cooldown.trigger_statuses | [401, 408, 429, 500, 502, 503, 504] | Status codes that trigger cooldown. Setting the field replaces the complete default list. |
cooldown.trigger_on_timeout | true | Triggers cooldown after an upstream timeout. |
cooldown.trigger_on_transport | true | Triggers cooldown after an upstream transport failure. |
Embedding settings, background model checks, cooldown, and automatic prompt caching are permitted only on direct models. Automatic prompt caching additionally requires the Anthropic provider.
Routing Models
A routing entry selects one target per request and dispatches through that target model's upstream configuration:
| Field | Type | Required | Description |
|---|---|---|---|
routing.targets | array | yes | Ordered target set, minimum one entry. targets[].model names a direct model; targets[].weight (default 1) applies to the weighted strategy; targets[].tags scopes the target to requests carrying matching routing tags, with the tag default reserved as the fallback marker. |
routing.strategy | enum | no | round_robin, weighted, failover (default), least_cost, least_latency, or least_busy. Positional strategies pick a starting target and walk forward on failure; metric strategies rank all targets best-first. |
routing.retries | integer | no | Default retry attempts on each target before failing over. A target model's retries overrides it. If neither is set, AISIX moves to the next eligible target without retrying and applies the deployment-wide default only to the last target. |
routing.max_fallbacks | integer | no | Maximum later targets attempted after the initial target fails. Default: all later targets. 0 disables failover. |
routing.retry_on_429 | boolean | no | Whether an upstream 429 participates in retries and failover. Default false. |
routing.fallback_on_statuses | array of integers | no | Additional 4xx status codes treated as retryable, for providers that use them for transient conditions, such as [408, 409]. 5xx codes are already retryable. |
routing.when_all_unavailable | enum | no | fail (default): return 503 when health and cooldown state rule out every target. try_anyway: attempt every target in declaration order regardless. |
routing.sticky | boolean | no | Deterministic weighted selection: hash the x-aisix-routing-key header (else the caller's API key) into the weight distribution, so the same key lands on the same target. Default false. |
See Multi-Target Routing and Failover for configuration, routing behavior, and a runnable failure test.
Ensemble Models
An ensemble entry fans each request out to every panel member concurrently, then has a judge model synthesize one answer:
| Field | Type | Required | Description |
|---|---|---|---|
ensemble.panel | array | yes | Panel members, minimum one. panel[].model names a direct model; optional panel[].temperature and panel[].seed override sampling per member; panel[].weight is accepted and currently ignored. |
ensemble.judge | object | yes | judge.model names the direct model that performs synthesis; optional judge.synthesis_prompt overrides the built-in synthesis prompt. |
ensemble.min_responses | integer | no | Minimum successful panel responses required before synthesis. Default: the smaller of 2 and the panel size. Clamped to the panel size, floored at 1. |
ensemble.timeout_ms | integer (ms) | no | Per-call deadline for each panel member and the judge call. 0 or absent disables it. |
See Ensemble Models for behavior and response shape.
Semantic Routers
A semantic entry embeds the latest user message, scores it against each route's example embeddings, and dispatches to the best route above the threshold. When no route clears the threshold, it dispatches to default.
| Field | Type | Required | Description |
|---|---|---|---|
semantic.embedding_model | string | yes | Name of an embedding-capable direct model (one carrying an embedding block). |
semantic.routes | array | yes | Routes, minimum one. Each route requires name (surfaced in the x-aisix-route response header), target (a direct model name), and examples (at least one example utterance; embedded and cached at apply time); optional description (documentation only) and threshold (overrides match.threshold for this route). |
semantic.default | string | yes | Direct model that receives requests matching no route. |
semantic.match | object | yes | Shared matching parameters: threshold (required, 0.0–1.0, higher is stricter), distance_metric (cosine, the only supported value), and aggregation (max, the only supported value; a route scores by its best-matching example). |
semantic.embedding_timeout_ms | integer (ms) | no | Deadline for the embedding call. 0 or absent disables it. |
semantic.on_embedding_failure | enum or object | no | What to do when the embedding call fails: default (route to the default model; this is the default behavior), fail (reject with 503), or { target: "<alias>" } (route to a specific model). |
See Semantic Routing for behavior and tuning.
The complete example below shows how the four model shapes relate. The three direct models are reusable targets; the remaining entries compose them into a weighted router, an ensemble, and a semantic router.
_format_version: "1"
provider_keys:
- display_name: openai-main
provider: openai
api_key: ${OPENAI_API_KEY}
models:
- display_name: gpt-4o
provider: openai
model_name: gpt-4o
provider_key: openai-main
timeout: 30000
rate_limit:
rpm: 100
tpm: 100000
cost:
input_per_1k: 0.0025
output_per_1k: 0.01
- display_name: gpt-4o-mini
provider: openai
model_name: gpt-4o-mini
provider_key: openai-main
- display_name: text-embed
provider: openai
model_name: text-embedding-3-small
provider_key: openai-main
embedding:
dimensions: 1536
- display_name: balanced
routing:
strategy: weighted
sticky: true
targets:
- model: gpt-4o
weight: 90
- model: gpt-4o-mini
weight: 10
retries: 1
retry_on_429: true
- display_name: council
ensemble:
panel:
- model: gpt-4o
- model: gpt-4o-mini
temperature: 0.2
judge:
model: gpt-4o
min_responses: 2
timeout_ms: 45000
- display_name: smart-router
semantic:
embedding_model: text-embed
routes:
- name: coding
target: gpt-4o
examples:
- "Write a Python function that parses CSV"
- "Debug this stack trace"
threshold: 0.8
default: gpt-4o-mini
match:
threshold: 0.75
on_embedding_failure: default
Caller API Keys
A caller API key entry authenticates the applications that call the gateway. The file never holds the plaintext key: supply it through key_env, or pre-hash it into key_hash.
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | yes | Entry identity, unique within api_keys. |
key_env | string | yes* | The name of an environment variable holding the plaintext caller key. Use a bare name such as MY_APP_KEY, not a ${VAR} reference. At load the value is hashed with SHA-256 and dropped; the plaintext never appears in the loaded document, errors, or logs. Mutually exclusive with key_hash; exactly one of the two is required. Do not start the variable name with AISIX_; that prefix is reserved for startup-configuration overrides. |
key_hash | string | yes* | Lowercase-hex SHA-256 hash of the plaintext key, passed through untouched. Two entries resolving to the same credential are a load error that names the entries, never the hashes. |
allowed_models | array of strings | yes | Models this key may use. Entries are single-* globs: "*" grants every model, "team-a/*" grants matching names, and an entry without * must match a model display_name defined in the same file. An empty array denies all models. |
rate_limit | object | no | Per-key limits with the same sub-fields as a model's rate_limit: rps, rpm, rph, rpd, tpm, tpd, concurrency. |
allowed_tools | array of strings | no | MCP tools this key may call, as <server>__<tool> names, matched as single-* globs: "github__*" grants every tool on one server. Omitted, null, or empty means no MCP tool access. |
mcp_rate_limits | object | no | Per-MCP-server request and concurrency limits for this key. Keys are registered MCP server names; see below. |
mcp_access | object | no | Policy-driven MCP access settings accepted for compatibility with AISIX Cloud configuration; see below. |
allowed_agents | array of strings | no | A2A agents this key may reach, by registered name, matched as single-* globs. Omitted, null, or empty means no A2A agent access. |
jwt_subject | string | no | External identity selected from a verified JWT. Set it together with jwt_provider; the pair must be unique within the file. |
jwt_provider | string | no | Name of the oidc_providers entry allowed to assert jwt_subject. Required when jwt_subject is set. |
expires_at | string | no | RFC 3339 timestamp after which the key stops authenticating with 401. Omitted means the key never expires. A malformed timestamp rejects the entry at load rather than silently never expiring. |
disabled | boolean | no | Administratively disable the key: requests are rejected with 401 until it is enabled again. Default false. |
team_id | string | no | Team attribution, matched verbatim by rate_limit_policies with scope: team. |
user_id | string | no | Owning member attribution, matched verbatim by member-scope policies. |
user_name | string | no | Readable owner name for telemetry labels only. |
MCP Tool Access and Limits
For a gateway configured through a resources file, grant MCP tool access with allowed_tools. Although mcp_access is accepted for compatibility with AISIX Cloud configuration, it cannot grant tools in a resources-file deployment because the file has no mcp_policies collection. Omit mcp_access.
Use mcp_rate_limits to give one caller key a separate limit for each registered MCP server. Each server entry supports the following fields:
| Field | Limit |
|---|---|
rps | Requests per second. |
rpm | Requests per minute. |
rph | Requests per hour. |
rpd | Requests per day. |
concurrency | Maximum in-flight tool calls. |
These limits apply to tools/call requests alongside the key's general rate_limit; initialization and tool-list requests are not counted.
This example gives one caller access to a model and every tool exposed by the github MCP server. The general rate_limit applies alongside the tool limits, while mcp_rate_limits.github adds a tighter limit for that server's tool calls.
_format_version: "1"
provider_keys:
- display_name: openai-main
provider: openai
api_key: ${OPENAI_API_KEY}
models:
- display_name: gpt-4o
provider: openai
model_name: gpt-4o
provider_key: openai-main
api_keys:
# MY_APP_KEY names an environment variable holding the plaintext
# caller key; it is hashed at load and never stored.
- display_name: my-app
key_env: MY_APP_KEY
allowed_models: ["gpt-4o"]
allowed_tools: ["github__*"]
rate_limit:
rpm: 60
concurrency: 5
mcp_rate_limits:
github:
rpm: 30
concurrency: 2
OIDC Providers
An OIDC provider entry defines an external issuer whose JWT tokens the gateway trusts for caller authentication. A verified identity maps to the caller API key whose jwt_provider and jwt_subject fields match the provider and token.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within oidc_providers. Caller API keys reference the provider by this name. |
issuer | string | yes | Expected JWT iss claim, compared exactly. Every enabled provider must have a distinct issuer. |
audiences | array of strings | yes | Accepted JWT aud values. The token must contain at least one configured value. The list must contain at least one entry. |
jwks_uri | string | no | JWKS endpoint used to fetch signing keys. When omitted, AISIX resolves it from <issuer>/.well-known/openid-configuration. |
identity_claim | string | no | Claim whose string value selects a caller API key's jwt_subject. Dots traverse nested objects. Default: sub. |
required_scopes | array of strings | no | Scopes that must all appear in the token's scope claim. The claim may be a space-delimited string or an array. Default: no required scopes. |
bound_claims | object | no | Additional claim requirements that must all pass. Dots in keys traverse nested claims. Each value is a string or a nonempty array; a string claim must equal an accepted value, and an array claim must contain one. |
leeway_secs | integer | no | Clock-skew allowance from 0 to 300 seconds for exp and nbf. Default: 0. |
enabled | boolean | no | Whether the provider participates in authentication. Default: true. |
The issuer and jwks_uri must not contain embedded credentials in user information or credential-like query parameters. AISIX accepts asymmetric JWT signing algorithms and rejects HMAC-signed tokens. See JWT Authentication for supported algorithms, request behavior, and key rotation.
The following configuration trusts the corp-keycloak issuer and maps the JWT subject agent-billing-01 to the billing-agent caller entry.
Every caller entry still requires key_env or key_hash, even when JWT authentication is enabled. Set BILLING_AGENT_KEY in the gateway process environment before loading this example. The empty allowed_models list denies model access; add model aliases when this identity should call model endpoints.
_format_version: "1"
oidc_providers:
- name: corp-keycloak
issuer: https://sso.example.com/realms/agents
audiences: ["aisix-gateway"]
required_scopes: ["ai.access"]
bound_claims:
department: ai-lab
api_keys:
- display_name: billing-agent
key_env: BILLING_AGENT_KEY
allowed_models: []
jwt_subject: agent-billing-01
jwt_provider: corp-keycloak
Claim Mappings
A claim mapping resolves the verified claims of a JWT to an existing caller API key when no key binds the token's subject directly. Enabled mappings for the matched provider are evaluated in priority order (lower first, ties broken by name); the first mapping whose conditions all hold selects the key, and a token matching no mapping is rejected. See JWT Claim Mappings for evaluation semantics.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within claim_mappings. Also the evaluation tie-break for equal priorities. |
jwt_provider | string | yes | Name of the oidc_providers entry whose tokens this mapping applies to. Must reference a provider defined in the file. |
priority | integer | no | Evaluation order among the provider's mappings; lower values are evaluated first. Default: 0. |
match | array of objects | yes | Claim conditions, all of which must hold. Each carries claim (dots traverse nested objects), op (exact for a string claim, contains for an array claim; non-string array items are ignored), and values (accepted alternatives). The list must contain at least one condition. |
resolve.api_key | string | see below | display_name of the caller API key matching requests run as. Resolved to the entry at load time. |
resolve.api_key_id | string | see below | Canonical form of the key reference, accepted when a document is authored against the canonical schema. Set exactly one of resolve.api_key / resolve.api_key_id. A configuration export emits resolve.api_key, converting the stored ID back to the key's name like every other reference. |
enabled | boolean | no | Whether the mapping participates in evaluation. Default: true. |
The referenced provider and API key must be defined in the same file; an unknown reference or an empty match list fails the load.
_format_version: "1"
oidc_providers:
- name: corp-keycloak
issuer: https://sso.example.com/realms/agents
audiences: ["aisix-gateway"]
api_keys:
- display_name: finance-policy-key
key_env: FINANCE_POLICY_KEY
allowed_models: []
claim_mappings:
- name: finance-dept
jwt_provider: corp-keycloak
priority: 100
match:
- claim: department
op: exact
values: ["finance"]
resolve:
api_key: finance-policy-key
Guardrails
A guardrail entry screens request or response content. The resources file has no attachment collection, so every enabled guardrail applies to every request. The kind field selects the provider, and that kind's configuration fields sit directly on the entry. There is no nested config object. Unknown fields for the selected kind are rejected.
These fields apply to every guardrail kind unless noted:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within guardrails. Surfaces in metric labels and error reasons. |
kind | enum | yes | Provider discriminator. See the kinds table below. |
enabled | boolean | no | false stages the rule without running it. Default true. |
hook_point | enum | no | Where the rule runs: input (request payload, before the upstream call), output (upstream response), or both (default). |
direction | string | no | Compatibility field for attachment-based configuration. It does not select where a resources-file guardrail runs; hook_point controls execution. Omit it from new resources files. |
enforcement_mode | string | no | block (default) applies the verdict; monitor records what would have happened without blocking or redacting. |
fail_open | boolean | no | For remote-API kinds, behavior when the guardrail provider is unreachable on the input hook: true (default) allows the request and records the bypass; false blocks with 422. |
output_fail_open | boolean | no | The same policy for the output hook, on the remote-API kinds only; keyword and pii reject it. Default: false. During a provider outage, the default holds model output rather than releasing unscanned content. |
mandatory | boolean | no | true makes guardrail evaluation errors fatal, overriding fail_open on the failure path. Default false. |
timeout_ms | integer | no | Per-call timeout for the remote-API kinds only. keyword, pii, and bedrock reject it; Bedrock uses latency_mode instead. Default: 5000. |
created_at | string | no | RFC 3339 timestamp. When present, guardrails evaluate oldest first; entries without it sort last. |
The selected kind determines which additional fields the entry accepts:
kind | Required fields | Notable options |
|---|---|---|
keyword | patterns: array of {kind: literal | regex, value} blocklist patterns, evaluated in-process. An empty list loads but matches nothing. | None |
pii | None | detectors (built-in detector list: email, china_mobile, china_id_card, bank_card, us_ssn, ip_address, api_key, jwt, private_key, each with optional per-detector action), custom_patterns (operator regexes with name and regex), default_action (mask default, or block). Masked spans become [<DETECTOR>_REDACTED]; matched values never appear in logs or errors. |
presidio | analyzer_url, anonymizer_url: base URLs of customer-run Presidio containers. | entities (Presidio entity types with optional per-entity action), default_action, operator (replace default, mask, hash, redact), language (default en), score_threshold. |
openai_moderation | api_key | model (default omni-moderation-latest), category_thresholds (per-category score map; empty defers to the provider's flagged decision), endpoint override. Detection-only; never rewrites content. |
lakera | api_key | project_id, endpoint override for regional or self-hosted deployments. |
azure_content_safety | endpoint, api_key | Azure Prompt Shield on the Cognitive Services endpoint. |
azure_content_safety_text_moderation | endpoint, api_key | categories (default all four of Hate, Sexual, SelfHarm, Violence), severity_threshold (default 2), severity_threshold_by_category, output_type, blocklist_names, halt_on_blocklist_hit, text_source (concatenate_user_content default, or concatenate_all_content), and streaming controls below. text_source affects the input hook only. |
aliyun_text_moderation | region, access_key_id, access_key_secret | endpoint override, risk_level_threshold (low, medium, high; default high), streaming controls below. |
aliyun_ai_guardrail | region, access_key_id, access_key_secret | endpoint override, service_level (pro default, or basic), streaming controls below. The selected service tier must be activated in Alibaba Cloud. |
bedrock | guardrail_id, guardrail_version, region, aws_credentials ({kind: static, access_key_id, secret_access_key}), latency_mode ({kind: serial} or {kind: timed, timeout_ms: 100–5000}) | None |
The Azure Text Moderation, Alibaba Cloud Content Moderation, and Alibaba Cloud AI Guardrails kinds support streamed-output controls:
| Field | Applies to | Behavior |
|---|---|---|
stream_processing_mode | The three streaming guardrail kinds | window incrementally releases a sliding window and is the default. buffer_full holds the complete response before release. |
window_size | The three streaming guardrail kinds | Sets the sliding-window size. |
window_overlap_size | The three streaming guardrail kinds | Sets the overlap between consecutive windows. |
max_buffer_bytes | PII, Lakera, Presidio, and the three streaming kinds in buffer_full mode | Maximum response bytes held for inspection. Default 262144. |
on_buffer_exceeded | The same buffering kinds | fail_closed rejects when the buffer limit is exceeded and is the default. fail_open releases the content. |
Provider credentials (api_key, access_key_secret, aws_credentials.secret_access_key) are secrets, so supply them as ${VAR}. See the guardrail guides for per-provider behavior.
The example combines a local input check with remote moderation. block-secrets rejects matching request text before an upstream call, while content-moderation uses the OpenAI Moderation API at the default both hook point for requests and responses.
_format_version: "1"
guardrails:
# In-process keyword blocklist on the request side only.
- name: block-secrets
kind: keyword
hook_point: input
patterns:
- kind: literal
value: internal-project-codename
- kind: regex
value: '\bAKIA[0-9A-Z]{16}\b'
# Remote moderation; blocks when a listed category reaches its threshold.
- name: content-moderation
kind: openai_moderation
api_key: ${OPENAI_API_KEY}
category_thresholds:
violence: 0.5
MCP Servers
An MCP server entry exposes tools to MCP clients as <name>__<tool>. It can connect to an upstream MCP server or generate tools from an inline OpenAPI document. In both cases, the gateway holds the upstream credential; it is never forwarded from or exposed to the calling client.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within mcp_servers, and the namespace prefix for the server's tools. Must not contain the reserved separator __. display_name is accepted as an alternative spelling; use one, not both. |
type | enum | no | mcp (default) connects to a real MCP server. openapi generates tools from an OpenAPI document and sends their calls as regular HTTP requests. |
url | string | yes | For type: mcp, the upstream MCP endpoint. For type: openapi, the REST API base URL used for generated tool calls. |
spec | object | yes* | Inline OpenAPI 3.x document, required for type: openapi and ignored for type: mcp. In a resources file, write the document as a nested YAML mapping. |
transport | enum | no | streamable_http, the only supported transport for type: mcp and the default. |
auth_type | enum | no | How the gateway authenticates upstream: none (default), bearer (secret sent as Authorization: Bearer), api_key (secret sent as an API key header), or oauth2 (client credentials grant; the token is cached until shortly before expiry). |
api_key_header | string | no | Header used when type: openapi and auth_type: api_key. Default x-api-key. A real MCP server always uses x-api-key for API key authentication. |
secret | string | no | The bearer token, API key, or OAuth client secret, per auth_type. Supply it as ${VAR}. |
client_id | string | no | OAuth client identifier. Used with auth_type: oauth2. |
token_url | string | no | OAuth token endpoint where client credentials are exchanged. Used with auth_type: oauth2. |
scopes | array of strings | no | OAuth scopes, joined with spaces into the token request. |
timeout_ms | integer | no | Deadline per upstream operation (session setup, tool listing, tool calls). Minimum 1. Default: 30,000 ms. |
enabled | boolean | no | false removes the server's tools from listings and calls. Default true. |
Caller access to tools is granted per key through api_keys[].allowed_tools. See the MCP Gateway Overview for the caller connection flow.
This entry exposes a remote MCP server as the github tool namespace and authenticates upstream with a bearer token from the environment:
_format_version: "1"
mcp_servers:
- name: github
type: mcp
url: https://api.example.com/mcp
auth_type: bearer
secret: ${GITHUB_MCP_TOKEN}
OpenAPI-Backed Servers
For type: openapi, supported HTTP operations become MCP tools. AISIX uses operationId as the tool name when present and otherwise derives a name from the HTTP method and path. The resources file accepts the document directly under spec; it does not accept the AISIX Cloud write fields spec_content or spec_url.
Here, the listItems operation becomes an MCP tool in the inventory namespace. Tool calls go to the configured REST API with the interpolated API key in X-Inventory-Key.
_format_version: "1"
mcp_servers:
- name: inventory
type: openapi
url: https://inventory.example.com/api
auth_type: api_key
api_key_header: X-Inventory-Key
secret: ${INVENTORY_API_KEY}
spec:
openapi: 3.0.0
info:
title: Inventory API
version: 1.0.0
paths:
/items:
get:
operationId: listItems
responses:
"200":
description: Items returned successfully
A2A Agents
An A2A agent entry registers an upstream agent that the gateway exposes to callers under /a2a/<name>, serving its agent card with URLs rewritten to the gateway. As with MCP servers, the upstream credential stays in the gateway.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within a2a_agents, and the caller-facing path segment. display_name is accepted as an alternative spelling; use one, not both. |
url | string | yes | The upstream agent's base URL. |
protocol_version | enum | no | A2A wire format: "1.0" (default) or "0.3". Quote the value so YAML keeps it a string. |
auth_type | enum | no | none (default), bearer, or api_key, with the same semantics as MCP servers. |
secret | string | no | The upstream credential, per auth_type. Supply it as ${VAR}. |
timeout_ms | integer | no | Deadline per upstream operation, including agent-card fetches. On a streaming method (message/stream, tasks/resubscribe) it bounds opening the stream, not its duration, so a long-running task is not cut off. Minimum 1. Default: 30,000 ms. |
enabled | boolean | no | false stops serving the agent. Default true. |
Caller access is granted per key through api_keys[].allowed_agents. See Set Up Agent Gateway for a complete caller connection flow.
This entry publishes an upstream agent at /a2a/invoice-processor and supplies its bearer token from the environment:
_format_version: "1"
a2a_agents:
- name: invoice-processor
url: https://agents.example.com/a2a
auth_type: bearer
secret: ${INVOICE_AGENT_TOKEN}
Cache Policies
A cache policy caches eligible non-streaming chat-completions responses for matching requests. Other endpoint families and streaming responses are not cached. The proxy uses the first enabled policy that matches each request. See Response Caching for key matching and verification.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within cache_policies. 1–120 characters. Surfaces in metric labels and cache headers. |
enabled | boolean | no | false stages the policy without applying it. Default true. |
backend | enum | no | memory (default) or redis. The redis backend requires the gateway's static cache.redis configuration; without it, matching requests are not cached. |
ttl_seconds | integer | no | Entry time-to-live, 1–604,800 seconds (7 days). Default 3600. |
applies_to | string | no | Eligibility selector: all (default), model:<alias> (requests targeting that model alias, compared before router fan-out), or api_key:<id> (requests authenticated by the caller API key with that resource ID). |
scope | enum | no | Sharing boundary for cached entries, applied to both matching layers: api_key (default — entries are private to the caller API key that stored them) or env (every caller in the environment shares the entries). |
purge_generation | integer | no | Server-managed invalidation counter, default 0. Increasing it invalidates every entry the policy stored under earlier values, across both matching layers and every gateway instance. |
semantic | object | no | Enables embedding-similarity matching on top of the exact layer. See the sub-table below. |
semantic fields:
| Field | Type | Required | Description |
|---|---|---|---|
embedding_model | string | yes | display_name of a model entry in this file that carries an embedding block. Its dimensions value fixes the vector size for the policy's entries. |
threshold | number | yes | Minimum cosine similarity, 0–1, for a stored entry to be served. Higher is stricter; below ~0.9 the wrong-answer risk rises sharply. |
max_entries | integer | no | Entry cap on the memory backend, 1–10,000, default 1000; oldest evicted first. Shared backends bound growth by TTL and ignore this. |
embedding_timeout_ms | integer | no | Per-call embedding deadline. On timeout the request proceeds upstream uncached. 0 or absent disables the dedicated deadline. |
Only requests whose messages are entirely text participate in similarity matching. On backend: redis, the semantic layer requires Redis 8+ (vector search) in single or sentinel mode; without it the policy serves exact matches only and logs a warning. See Semantic Caching.
applies_to values are matched at request time, not resolved at load. For api_key, the resources loader does not resolve a display_name; use the derived ID. A model alias that matches nothing simply never caches. The semantic.embedding_model reference, by contrast, must name an embedding model entry in the same file — a dangling name disables the semantic layer with a warning while exact caching continues.
An unrecognized applies_to prefix is treated as all. A mistyped prefix therefore broadens caching instead of disabling the policy.
The following complete example caches non-streaming responses for the gpt-4o alias in memory for 10 minutes:
_format_version: "1"
provider_keys:
- display_name: openai-prod
provider: openai
api_key: ${OPENAI_API_KEY}
models:
- display_name: gpt-4o
provider: openai
model_name: gpt-4o-2024-11-20
provider_key: openai-prod
cache_policies:
- name: gpt-4o-cache
backend: memory
ttl_seconds: 600
applies_to: "model:gpt-4o"
Observability Exporters
An observability exporter delivers request telemetry to an external system. The kind field selects the backend, and that kind's fields sit directly on the entry. Each kind is closed, so unknown fields are rejected, including any plaintext credential field.
Every exporter kind accepts these shared fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within observability_exporters. 1–120 characters. |
kind | enum | yes | otlp_http, aliyun_sls, datadog, or object_store. |
enabled | boolean | no | Disabled exporters stay configured but receive no telemetry. Default true. |
The selected kind then adds its backend-specific fields:
kind | Required fields | Optional fields |
|---|---|---|
otlp_http | endpoint: full OTLP/HTTP traces URL including the receiver path, such as https://api.honeycomb.io/v1/traces. Must be https:// except for loopback and test hosts. | headers (static headers per export request; put API keys in ${VAR} values), sample_rate (0.0–1.0; absent exports every request), content_mode, content_max_bytes. |
aliyun_sls | endpoint (regional *.aliyuncs.com host, no scheme), project, logstore, credential_ref | content_mode, content_max_bytes. |
datadog | site (a known Datadog site such as datadoghq.com or datadoghq.eu), service, credential_ref | ddsource (default aisix-ai-gateway), tags (rendered into ddtags), content_mode, content_max_bytes. |
object_store | provider (s3, gcs, or azure_blob), bucket, prefix | region (S3 signature scope), endpoint (S3-compatible override for MinIO, OSS, R2; https:// required except loopback and test hosts), compression (gzip default, or none), auth_mode, credential_ref. |
For otlp_http, aliyun_sls, and datadog, content_mode controls whether exported records omit prompt and response content (metadata_only, the default) or include it (full). content_max_bytes limits each captured content field in full mode to 1–1,048,576 bytes and defaults to 131,072. The object_store kind accepts neither field.
See Observability Exporters for delivery and content-capture behavior.
Remote credentials never live directly in an exporter resource. In the variable names below, <REF> is the exporter's credential_ref converted to uppercase with non-alphanumeric characters replaced by underscores—for example, datadog-prod becomes DATADOG_PROD.
| Exporter | Credential source |
|---|---|
| OTLP/HTTP | Put API keys in interpolated headers values. |
| Alibaba Cloud SLS | A credential reference named <REF> resolves SLS_CRED_<REF>_AK_ID and SLS_CRED_<REF>_AK_SECRET. |
| Datadog | A credential reference named <REF> resolves DD_CRED_<REF>_API_KEY. |
| Object store | A credential reference named <REF> resolves the applicable OBJSTORE_CRED_<REF>_* variables. For S3 and GCS, cloud_identity uses the host's attached identity instead and does not require a credential reference. |
The example compares all three credential-loading patterns: direct interpolation in an OTLP header, a named Datadog credential reference, and attached cloud identity for S3. The numbered notes below the YAML explain what the highlighted fields resolve to.
_format_version: "1"
observability_exporters:
- name: honeycomb-prod
kind: otlp_http
endpoint: https://api.honeycomb.io/v1/traces
headers:
x-honeycomb-team: ${HONEYCOMB_API_KEY}
sample_rate: 0.25
- name: datadog-prod
kind: datadog
site: datadoghq.com
credential_ref: datadog-prod
service: ai-gateway
tags: ["team:platform", "tier:prod"]
- name: s3-events
kind: object_store
provider: s3
bucket: acme-aisix-events
prefix: ai-gateway
region: us-east-1
auth_mode: cloud_identity
❶ Standard resource interpolation supplies the Honeycomb API key from HONEYCOMB_API_KEY.
❷ The datadog-prod reference resolves the API key from DD_CRED_DATADOG_PROD_API_KEY; the credential never appears in the resources file.
❸ cloud_identity uses the host's attached cloud identity instead of static keys. This mode supports S3 and GCS exporters.
Rate Limit Policies
A rate limit policy caps requests or tokens independently of the inline rate_limit blocks on models and caller API keys. Use the conditional form for policies that match several request attributes or split counters by dimension. Use the classic form for one subject and one fixed window. An entry must use exactly one form; mixing their fields is a load error. See Rate-Limit Policies for configuration paths and verification.
Conditional Form
Use the conditional form for new policies. It matches requests with a condition tree, can split counters by dimensions, and supports request, token, and concurrency limits.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Entry identity, unique within rate_limit_policies. Counters key on the derived ID, so they survive reloads. |
conditions | array | no | Condition nodes the request must satisfy; top-level nodes all apply (AND), and an empty or omitted list matches every request. Each node is either a condition (dimension, operator, optional negate, value) or a group (logic: and | or, optional negate, children). Nesting is capped at 3 levels and 16 conditions per policy. See the node fields below. |
group_by | array | no | Bucket-split dimensions, any subset of team, member, api_key, model, provider. Each distinct value combination counts in an independent bucket with the same limits; empty or omitted means one shared bucket. A matched request lacking one of these dimensions is not subject to the policy. |
limits | object | yes | At least one of rps, rpm, rph, rpd, tpm, tpd, concurrency (all minimum 1), with the same shape and semantics as the inline rate_limit blocks. |
action | enum | no | Over-limit behavior; only reject (HTTP 429, the default) exists today. |
schedules | array | no | Recurring suspension windows, identical to the classic form described below. |
A conditions node can be a condition or a group. A condition accepts these fields:
| Field | Type | Required | Description |
|---|---|---|---|
dimension | enum | yes | team, member, api_key, model, model_name, or provider. For api_key and model, values take the display_name of an entry defined in the same file. The name is resolved at load, and an unknown name is a load error. team/member values match the caller API key's team_id/user_id verbatim. model and model_name match the dispatched model and — on a request routed through a model group, semantic router, or ensemble — the addressed parent as well, so a group's name selects every request routed through it and a member's name selects that member whether called directly or through a group; negate excludes both. provider matches the dispatched model's provider ID. |
operator | enum | yes | ==, ~= (not equal), in, ~~ (regex), or ~* (case-insensitive regex): lua-resty-expr tokens. The regex operators apply to model_name and provider only; patterns are capped at 256 characters and must compile. |
negate | boolean | no | Inverts the condition by applying the lua-resty-expr ! prefix. The combination of negate and in reads "not in." A request that does not carry the dimension matches neither the condition nor its negation. |
value | string or array | yes | One string for the scalar operators; 1–64 strings for in. |
For nested Boolean logic, use a group node:
| Field | Type | Required | Description |
|---|---|---|---|
logic | enum | yes | and or or, which determines how children combine. |
negate | boolean | no | Inverts the group result (!AND / !OR). |
children | array | yes | Nested nodes (conditions or further groups), at least one. |
Classic Form
The classic form remains fully supported for policies that apply to one subject.
| Field | Type | Required | Description |
|---|---|---|---|
scope | enum | yes | The subject type: api_key, model, team (one shared bucket for the whole team), member, or team_member (the team's limit, but an independent counter per member). |
scope_ref | string | yes | The specific subject. For scope: api_key or scope: model, use the display_name of an entry defined in the same file. The name is resolved at load, and an unknown name is a load error. For team, member, and team_member, use a team or user ID matched verbatim against the caller API key's team_id or user_id. |
window | enum | yes | second, minute, hour, or day. |
max_requests | integer | no* | Requests allowed per window, minimum 1. At least one of max_requests and max_tokens is required. |
max_tokens | integer | no* | Tokens allowed per window, minimum 1. Token caps are enforced on minute and day windows; on second and hour windows the cap is accepted but not applied. Pair max_tokens with a minute or day window. See Manage Classic Single-Scope Policies. |
schedules | array | no | Recurring wall-clock windows during which the policy is suspended (not enforced). Enforcement resumes automatically when a window closes, on the same counters. See the entry fields below and Suspend a Policy on a Schedule. |
Each schedules entry selects its days either weekly (days_of_week) or by explicit dates (dates). Use exactly one of the two.
| Field | Type | Required | Description |
|---|---|---|---|
timezone | string | yes | IANA timezone the entry's wall-clock fields are interpreted in, for example Asia/Shanghai. |
days_of_week | array | no* | Weekly recurrence: any of mon, tue, wed, thu, fri, sat, sun. Mutually exclusive with dates. |
dates | array | no* | Explicit YYYY-MM-DD dates in timezone, for holidays and other irregular days. Mutually exclusive with days_of_week. |
start_time | string | yes | Window start, HH:MM wall clock, inclusive. |
end_time | string | yes | Window end, HH:MM wall clock, exclusive; 24:00 means end of day. An end before the start crosses midnight, and the window belongs to its start day. Equal times are rejected in AISIX Cloud and never match in the resources file. For example, days_of_week: [fri] with 22:00 to 09:00 covers Friday 22:00 through Saturday 09:00. |
This example sets a 300-request-per-minute limit in both forms. The conditional policy creates a separate counter for each team across the gpt-4 model family; the classic policy creates one counter for the gpt-4o model alias.
_format_version: "1"
provider_keys:
- display_name: openai-prod
provider: openai
api_key: ${OPENAI_API_KEY}
models:
- display_name: gpt-4o
provider: openai
model_name: gpt-4o-2024-11-20
provider_key: openai-prod
rate_limit_policies:
# Conditional form: the gpt-4 family shares one 300-RPM pool per team.
- name: gpt4-family-per-team
conditions:
- dimension: model_name
operator: "~~"
value: "^gpt-4"
group_by: [team]
limits:
rpm: 300
# Classic form (legacy): one subject per policy.
- name: cap-gpt4o
scope: model
scope_ref: gpt-4o
window: minute
max_requests: 300
max_tokens: 100000