Bedrock
The gateway speaks Bedrock natively and does the SigV4 signing itself.
| Property | Value |
|---|---|
| Provider id | bedrock |
| Gateway speaks | Bedrock Runtime (Converse API), region-derived host |
| Credential | AWS workload role, or static access key + secret; plus region |
| Signing | Gateway signs SigV4 itself |
| Client base URL | OPENAI_BASE_URL (or ANTHROPIC_BASE_URL for Claude) → :8787 |
First, enable model access in the AWS console under Bedrock → Model access, in the region you plan to use; Anthropic models need a one-time use-case form. Nothing below works until that is granted.
Attach this policy to the role your gateway workload already runs as, and there is no credential to store or rotate.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BedrockInvoke",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
"bedrock:Converse",
"bedrock:ConverseStream",
"bedrock:ListFoundationModels",
"bedrock:ListInferenceProfiles"
],
"Resource": "*"
},
{
"Sid": "BedrockUseCaseAttestation",
"Effect": "Allow",
"Action": [
"bedrock:GetUseCaseForModelAccess",
"bedrock:PutUseCaseForModelAccess",
"aws-marketplace:ViewSubscriptions",
"aws-marketplace:Subscribe"
],
"Resource": "*"
}
]
}
The two List actions let the gateway resolve a model id its built-in table does not hold,
which includes every undated id such as claude-opus-5. To scope Resource, name both the
foundation-model and inference-profile ARNs, because Claude 4 and newer are profile-only in
most regions:
"Resource": [
"arn:aws:bedrock:*::foundation-model/anthropic.*",
"arn:aws:bedrock:*:<account-id>:inference-profile/*anthropic*"
]
With no explicit key pair configured, the gateway uses the standard AWS credential chain: an ECS/Fargate task role (not the task execution role), an EC2 instance profile, an EKS service-account role (IRSA), or standard AWS environment/shared-config credentials. Role credentials are short-lived and never stored by Anyray, and IAM evaluates at call time, so a running gateway can invoke Bedrock within seconds of the attach, no redeploy.
On the CloudFormation deployment, attach it to the stack's TaskRole as a managed
policy, never inline: the template reconciles inline policies on every stack update and can
remove one you added by hand (role mechanics).
A gateway with no AWS workload identity, or a Bedrock account different from the gateway's,
uses a static key pair instead:
static keys and cross-account access.
Console → Providers → add bedrock: the region you enabled model access in (for
example us-east-1), and either both key fields or neither. Blank key fields select the
workload role, so blank is the configuration and not a missing step; an explicit pair takes
precedence over the role, and one field without the other is rejected. Session token is
optional, for explicitly configured temporary keys.
export OPENAI_BASE_URL=http://<gateway>:8787/v1
# Claude on Bedrock via Anthropic SDKs:
export ANTHROPIC_BASE_URL=http://<gateway>:8787
# requests carry: x-anyray-provider: bedrock
To make Bedrock the default for every request that pins no provider of its own, set Console →
Routing to mode single, target bedrock.
Send one request and look for it in the console.
curl http://<gateway>:8787/v1/chat/completions \
-H "Authorization: Bearer <your-anyray-key>" \
-H "x-anyray-provider: bedrock" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4-5-20250929","messages":[{"role":"user","content":"reply with the word ok"}]}'
Console → Traces should show the call with provider bedrock, the model id, token
counts, and a cost. A success with no row means the client is not going through the gateway.
Console → Cockpit splits one developer's requests by provider.
How developers enrol
Bedrock is an org-account lane: the credential lives on the gateway, and developers reach it with their personal gateway key; there is no per-developer AWS credential to distribute.
curl -fsSL https://app.anyray.ai/i/tnt_… | sh -s -- --org
Pass --org explicitly even though the org account is the fallback: with no flag, a
developer signed into a personal Claude plan bills that plan instead of your AWS account,
silently. --subscription is the wrong flag here; it forwards a Claude or ChatGPT seat token
to Anthropic or OpenAI, which never reaches Bedrock. To assign the lane per user and team
instead, or when only some developers should route to Bedrock:
mixing both lanes.
Model ids
Clients send canonical Anthropic ids and the gateway converts them
(claude-sonnet-4-5-20250929 → us.anthropic.claude-sonnet-4-5-20250929-v1:0): first a
built-in table of dated ids, then live discovery through the List actions, and otherwise
the id is forwarded exactly as written, so a native Bedrock id always works.
List actionsclaude-opus-5, claude-sonnet-5, and claude-fable-5 are in no built-in table and resolve
only through discovery, so for them the List actions are required, not optional.
From v1.10.269 an undated id for a dated-only family resolves to the newest published
snapshot (claude-sonnet-4-5 → claude-sonnet-4-5-20250929-v1:0); on earlier releases send
the dated id or set a model alias, which pins an exact id
ahead of all resolution. The full resolution order, the region-prefix rules, and per-region
Claude 5 availability: Bedrock reference.
Network access
The gateway reaches two AWS hostnames on port 443:
| Host | Used for |
|---|---|
bedrock-runtime.<region>.amazonaws.com | Every inference call. Required. |
bedrock.<region>.amazonaws.com | Model-id discovery, the List actions. Optional. |
An egress allowlist naming only bedrock-runtime leaves inference working while discovery
quietly fails, so include both. The CloudFormation stack needs no networking change; private
subnets and VPC endpoints: Bedrock reference.
CLAUDE_CODE_USE_BEDROCK bypasses the gatewayWith CLAUDE_CODE_USE_BEDROCK (or CLAUDE_CODE_USE_VERTEX) set, Claude Code signs requests
straight to the cloud provider and ignores ANTHROPIC_BASE_URL: everything looks healthy and
no request reaches Anyray, so there is no attribution, no spend data, and no savings. Connect
disables the switch at apply time (pinning it empty in the user settings env block, which
outranks a shell export); restart Claude Code afterwards and the gateway serves Bedrock. The
exception is an IT-managed managed-settings.json, which outranks user scope: there Connect
warns instead, and the admin who deploys that file must remove the switch. See
troubleshooting.
Troubleshooting
| What you see | Cause and fix |
|---|---|
AWS credentials were not found (500) | No key pair configured and no role reachable from the workload. Attach the policy to the role the gateway runs as (on ECS, the task role, not the execution role), or fill in the access-key pair. |
AWS access key ID and secret access key must be configured together (400) | Only one of the two fields is set. Set both, or clear both to fall back to the role. |
AccessDeniedException | Model access is not granted for that model in that region, or the policy omits the inference-profile ARN. |
ValidationException on the model id | An id that needed discovery without the List actions granted, an undated id for a dated-only family on a gateway older than v1.10.269, or a region with no profile for that model. Grant the List actions, or pin the exact Bedrock id with a model alias. |
ResourceNotFoundException asking for the use-case form | Bedrock evaluates the attestation per principal. Submit the form as the IAM user or role that is calling (how). |
| Requests succeed, nothing in the console | The client is signing to AWS directly. Unset CLAUDE_CODE_USE_BEDROCK and restart it. |
| Bedrock worked, then stopped after a stack update | An inline policy on a CloudFormation-managed role was reconciled away. Re-add it as a managed-policy attachment. |