Follow Discord
Sweep 03 Oct 2026 · 20:28Z Build v2.1.289 510 read Stable v2.1.285 Latest v2.1.289 Next v2.1.289 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Claude apps gateway configuration changedclaude-apps-gateway-config

Nearest release: v2.1.286, published 3 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 30 Sep 2026 20:43 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 30 Sep 2026 21:07 UTC.

Upstream edited
Recorded here
Lines+85added
Lines−4removed
From line 156 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits39to this page, all time

##### Bedrock in another AWS account ##### Per-developer AWS cost attribution

The whole hunk

from line 156, old and new numbered
/
lines
from line 156
156156 
157157`upstreams` is an ordered list. The gateway forwards inference to the first upstream that resolves the requested model.
158158 
159On `5xx`, `429`, `401`, `403`, `404`, or timeout the gateway fails over to the next upstream; other `4xx` doesn't, because those errors are attributable to the request rather than the upstream. A `401` or `403` means the gateway's own credential failed against that upstream. A `404` means that upstream doesn't serve the requested model, so a later upstream in the list still can.
159On `5xx`, `429`, `401`, `403`, `404`, or timeout the gateway fails over to the next upstream; other `4xx` doesn't, because those errors are attributable to the request rather than the upstream. A `401` or `403` means the credential the gateway used against that upstream failed. A `404` means that upstream doesn't serve the requested model, so a later upstream in the list still can.
160160 
161161If you set `forward_user_identity: true` on an upstream, a `429` it returns to a request that carried the developer's email doesn't fail over. See [how a per-user limit denial reaches the developer](#per-user-identity-headers-for-a-proxy-you-run).
162162 
from line 301
301301 The gateway doesn't support guardrail input tags. It adds no guard content tags to prompts, so a guardrail filter that Amazon Bedrock applies only to tagged input doesn't run on traffic through the gateway. For which filters depend on input tags, see [input tags](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-tagging.html) in the Amazon Bedrock documentation.
302302</Warning>
303303 
304Also grant the gateway's AWS principal `bedrock:ApplyGuardrail` on the guardrail.
304Also grant `bedrock:ApplyGuardrail` on the guardrail to the principal that signs this upstream's requests: the gateway's AWS principal, or with [`assume_role`](#bedrock-in-another-aws-account) the role named in `role_arn`.
305305 
306306Set `guardrail` on every `bedrock` upstream or on none. The gateway refuses to start on a mix, because [failover](#multiple-upstreams) could otherwise send a request to a Bedrock upstream that has no guardrail.
307307 
from line 309
309309 
310310When a `/v1/messages` request whose body carries an `amazon-bedrock-*` field, such as `amazon-bedrock-guardrailConfig`, reaches a Bedrock upstream that has `guardrail` set, the gateway answers 400 instead of forwarding it.
311311 
312<a id="bedrock-in-another-aws-account" />
313 
314##### Bedrock in another AWS account
315 
316Set `assume_role` on a Bedrock upstream and the gateway uses its own AWS identity only to call `sts:AssumeRole` on a role you name, which can be in a different AWS account from the gateway. Every Bedrock request from that upstream is signed with the one-hour credentials STS returns, so no long-lived access key crosses accounts.
317 
318Requires a gateway running Claude Code v2.1.281 or later. An earlier gateway refuses to start when it finds the key.
319 
320```yaml theme={null}
321upstreams:
322 - name: bedrock-isolated
323 provider: bedrock
324 region: us-east-1
325 auth: {} # the gateway's own role: it only calls STS
326 assume_role:
327 role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
328 # external_id: ${BEDROCK_ROLE_EXTERNAL_ID} # when the role's trust policy requires one
329```
330 
331The `assume_role` block takes three keys:
332 
333| Key | Meaning |
334| - | - |
335| `role_arn` | The IAM role the gateway assumes, as an `arn:aws:iam::` or `arn:aws-us-gov:iam::` ARN. Give it the [Bedrock permissions](#amazon-bedrock) this upstream needs, `bedrock:CountTokens` included, plus `bedrock:ApplyGuardrail` when the upstream sets `guardrail`. |
336| `external_id` | Optional. Sent as the external ID on every `sts:AssumeRole` call. Set it when the role's trust policy requires one, and quote it if it's all digits. |
337| `session_name` | Optional. `email` or `sub` gives each developer their own session: see [Per-developer AWS cost attribution](#per-developer-aws-cost-attribution). Unset, every request uses one session named `claude-apps-gateway`. |
338 
339The role's trust policy names the gateway's own principal, such as its IRSA or ECS task role. That principal needs `sts:AssumeRole` on the role and no Bedrock permission of its own. Drop the `Condition` if you set no `external_id`.
340 
341```json theme={null}
342{
343 "Version": "2012-10-17",
344 "Statement": [{
345 "Effect": "Allow",
346 "Principal": { "AWS": "arn:aws:iam::111111111111:role/claude-gateway" },
347 "Action": "sts:AssumeRole",
348 "Condition": { "StringEquals": { "sts:ExternalId": "your-external-id" } }
349 }]
350}
351```
352 
353* If STS refuses or is unreachable, the gateway doesn't send the request with the upstream's own credentials. It logs the STS error with what to check, then tries the next upstream you listed. [Upstream error messages](#upstream-error-messages) covers what the client receives when no upstream succeeds. A later upstream without `assume_role` would serve the request with its own credentials, so list one only if that is what you want.
354* The gateway calls the regional STS endpoint `sts.<region>.amazonaws.com`, which its network must reach. For the FIPS endpoint, set `AWS_USE_FIPS_ENDPOINT=true` in the gateway's environment rather than `use_fips_endpoint` in an AWS config file.
355* `assume_role` applies to `provider: bedrock` only and needs SigV4 source credentials: the gateway refuses to start when it's set beside `aws_bearer_token`.
356* Every developer the gateway admits can use this upstream; [`managed`](#managed) governs which developers may use which models. To keep a model served through the role from also being served from another account, give it a custom id whose `upstream_model` map has only this upstream's name. For such an id the gateway skips every other upstream, so neither the request nor the token count for an aborted request can fail over to another account. Built-in model names are still tried on every upstream in order, this one included, and a request that reaches it is signed with the same role, so list this upstream last unless its account should also serve them.
357 
358This example gives one model a custom id that only the isolated upstream serves:
359 
360```yaml theme={null}
361models:
362 - id: claude-opus-restricted # a custom id, not a built-in model name
363 upstream_model:
364 bedrock-isolated: us.anthropic.claude-opus-4-8 # the only upstream that serves it
365```
366 
367<a id="per-developer-aws-cost-attribution" />
368 
369##### Per-developer AWS cost attribution
370 
371By default the gateway signs every Bedrock request with one credential, so AWS sees all developers' requests under a single IAM principal. Add `session_name: email` to [`assume_role`](#bedrock-in-another-aws-account) and the gateway calls `sts:AssumeRole` once per developer per hour, with the session name set to that developer's email, and signs their requests with the returned credentials, so each developer's requests reach AWS under their own assumed-role session. The role can be in the gateway's own account.
372 
373Requires a gateway running Claude Code v2.1.281 or later. [Cost attribution on AWS](/docs/en/claude-apps-gateway-on-aws#cost-attribution) covers the IAM role and where AWS billing shows the sessions.
374 
375```yaml theme={null}
376upstreams:
377 - provider: bedrock
378 region: us-east-1
379 auth: {} # the gateway's own role: it only calls STS
380 assume_role:
381 role_arn: arn:aws:iam::123456789012:role/claude-gateway-bedrock-user
382 session_name: email # or sub
383```
384 
385`session_name` selects which verified claim becomes the AWS `RoleSessionName`: `email` or `sub`. The gateway writes any character other than ASCII letters, digits, and `_+,.@-` as `=XX` hex per UTF-8 byte, and shortens a result longer than 64 characters to a prefix plus a hash, so each developer's session name stays valid and unique. A request from a developer whose token lacks the claim isn't sent through this upstream, and the operator log says to switch to `sub` or set [`oidc.email_claim`](#oidc).
386 
387An active developer costs one STS call per hour per gateway replica, and concurrent first requests share one call.
388 
389The gateway also makes one call of its own on this role: the token count for a request the client abandoned, so that [spend limits](/docs/en/claude-apps-gateway-spend-limits) stay accurate. That count and its [one-token fallback request](#amazon-bedrock) are signed by the shared `claude-apps-gateway` session, so AWS attributes the fallback to `claude-apps-gateway` rather than to the developer.
390 
391For strict per-developer attribution, set `assume_role` with `session_name` on every Bedrock upstream you list. An upstream without it signs the requests it serves with its own credentials.
392 
312393#### Claude Platform on AWS
313394 
314395Claude Platform on AWS serves the first-party Anthropic API on AWS infrastructure at `aws-external-anthropic.<region>.api.aws`. It uses first-party model IDs, honors `anthropic-beta` headers as sent, and serves `count_tokens`, so none of the Bedrock-specific translation applies. The `anthropicAws` provider requires Claude Code v2.1.198 or later; earlier gateway releases reject it at boot.
from line 552
471552 provider: bedrock
472553 region: us-west-2
473554 auth: {}
474 # Different account: a separate Bedrock allotment via assumed-role creds.
555 # Different account: a separate Bedrock allotment via static keys.
475556 - name: bedrock-acct2
476557 provider: bedrock
477558 region: us-east-1
from line 579
498579| Lever | How |
499580| - | - |
500581| Different regions | One Amazon Bedrock upstream per region, each with its own `region:`. With [`auto_include_builtin_models: true`](#models) the cross-region inference profiles route automatically; for region-pinned deployments use a `models:` block. |
501| Different accounts | One Amazon Bedrock upstream per account, each with its own credentials in `auth:`. The default chain (`auth: {}`) uses the pod's identity; for a second account, set explicit credentials or a bearer token. |
582| Different accounts | One Amazon Bedrock upstream per account. The default chain (`auth: {}`) uses the pod's identity; for a second account, add [`assume_role`](#bedrock-in-another-aws-account) to reach it with short-lived credentials, or set explicit credentials or a bearer token in `auth:`. |
502583| Provisioned throughput | Map the model to the provisioned-throughput ARN in `models:` for that upstream's name. Other upstreams keep the on-demand ID, so PT capacity is exhausted before failing over. |
503584| VPC / FIPS endpoints | Set `base_url:` on the upstream to your VPC endpoint or FIPS endpoint URL |
504585| Model-scoped routing | Only a custom model `id`, one that isn't a built-in Claude model, skips the upstreams absent from its `upstream_model:` map. The gateway tries built-in models on every upstream in order and uses the provider's default ID where the map has no entry, so for built-in models the map changes which ID an upstream receives rather than whether it is tried; an upstream that rejects the ID follows the same [failover rules](#upstreams) as any other upstream error. |
Feedback