Claude Code on Amazon Bedrock
Claude Code can run in Bedrock mode (CLAUDE_CODE_USE_BEDROCK=1) against Corveil instead of AWS. Corveil serves Bedrock's own API under /v1/bedrock. It checks each request against your organization's catalog, the caller's key and your input guardrails. It then forwards the request to Amazon Bedrock unchanged, signed with your organization's AWS credential. AWS bills your AWS account for the tokens. Corveil writes a request log and a spend row for every model call, priced at Bedrock rates, and enforces your budgets.
Choosing a path
Claude Code can reach Corveil in two ways:
| Anthropic API (Claude Code) | Amazon Bedrock (this page) | |
|---|---|---|
| Claude Code setting | ANTHROPIC_BASE_URL | CLAUDE_CODE_USE_BEDROCK and ANTHROPIC_BEDROCK_BASE_URL |
| Who bills the tokens | Anthropic, on the organization's Anthropic key (Direct) or the person's own (Passthrough) | AWS, on the organization's AWS account |
| Model IDs | Anthropic model names | Bedrock inference profile IDs, such as us.anthropic.claude-opus-4-8 |
| Output guardrails | Applied | Logged only; output is not redacted |
Use Bedrock mode when the bill must stay on your AWS account: committed AWS spend, an AWS-only purchasing path, or engineers who already run Claude Code on Bedrock. Otherwise use the Anthropic API path. It needs no AWS setup, and Corveil can redact model output on it.
Prerequisites
An organization admin sets these up once.
- Bring-your-own AWS is on for the organization. It is off by default. Ask Corveil support to turn on
byo_bedrockfor your organization. Until it is on, AWS Bedrock is not offered as a provider. - An IAM user with the policy below. Corveil takes static IAM access keys. It does not assume a role, and it does not take a Bedrock API key as the organization's credential.
- The AWS account can use Anthropic's models. Anthropic requires a one-time use case form per AWS account: in the Amazon Bedrock console, open the model catalog, select an Anthropic model, and submit the form. See Anthropic's Bedrock guide.
- A Bedrock credential in Corveil. Under AI Gateway → Providers → Credentials, click Add credential, pick AWS Bedrock, and enter the access key ID, secret access key and region. Test checks that the keys are valid with AWS STS. It does not call Bedrock, so it doesn't prove the policy is attached.
- The inference profiles you want are enabled. Catalog discovery runs with your credential and adds a row for each Anthropic Claude cross-region inference profile your region lists, named by its profile ID (
us.anthropic.claude-opus-4-8,global.anthropic.claude-sonnet-4-6). Enable the ones your engineers will use under AI Gateway → Providers → Catalog. Claude Code only sees, and can only call, the profiles that are enabled there. - A virtual key per person. Each engineer gets a Corveil virtual key (
sk-citadel-…) under People & Access → API Keys. A key's Budget Limit and model allowlist apply to Bedrock calls too.
IAM policy
Attach this policy to the IAM user whose access keys you enter in Corveil. Replace:
<partition>withawsfor a commercial region, oraws-us-govfor GovCloud.<region>with the credential's region, such asus-east-1.<account-id>with the AWS account the keys belong to.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CatalogDiscovery",
"Effect": "Allow",
"Action": [
"bedrock:ListFoundationModels",
"bedrock:ListInferenceProfiles"
],
"Resource": "*"
},
{
"Sid": "InferenceProfiles",
"Effect": "Allow",
"Action": [
"bedrock:GetInferenceProfile"
],
"Resource": "arn:<partition>:bedrock:<region>:<account-id>:inference-profile/*"
},
{
"Sid": "Inference",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
"bedrock:CountTokens"
],
"Resource": [
"arn:<partition>:bedrock:*::foundation-model/*",
"arn:<partition>:bedrock:<region>:<account-id>:inference-profile/*"
]
}
]
}bedrock:ListInferenceProfilesis what adds the current Claude models to your catalog. Without it, only foundation models are listed.bedrock:InvokeModelWithResponseStreamserves every streamed turn.bedrock:CountTokensserves the exact counts in Claude Code's/context. Without it, Claude Code falls back to an estimate.- The foundation-model resource names every region (
*), because a cross-region profile can serve a request from any region in its geography.
Configure Claude Code
Set these in your shell, or in the env block of ~/.claude/settings.json:
export CLAUDE_CODE_USE_BEDROCK=1
export ANTHROPIC_BEDROCK_BASE_URL=https://corveil.io/v1/bedrock
export AWS_BEARER_TOKEN_BEDROCK=sk-citadel-your-key-here
export AWS_REGION=us-east-1
export ANTHROPIC_DEFAULT_OPUS_MODEL=us.anthropic.claude-opus-4-8
export ANTHROPIC_DEFAULT_SONNET_MODEL=us.anthropic.claude-sonnet-4-6
export ANTHROPIC_DEFAULT_HAIKU_MODEL=us.anthropic.claude-haiku-4-5-20251001-v1:0ANTHROPIC_BEDROCK_BASE_URLis your Corveil host followed by/v1/bedrock. On a self-hosted instance, replacecorveil.io.AWS_BEARER_TOKEN_BEDROCKholds your Corveil virtual key, not an AWS key. Claude Code sends it asAuthorization: Beareron every Bedrock call, and Corveil signs the call to AWS with the organization's credential. Your own AWS credentials andAWS_PROFILEare not used.AWS_REGION: use the region of the organization's Bedrock credential. Corveil always calls Bedrock in that region, whatever the client sets. Claude Code usesAWS_REGIONto pick its default profile prefix (us.,eu., …).- Model pins: the IDs must be inference profiles enabled in your catalog. See Pin enabled models.
Which credential variable
Use AWS_BEARER_TOKEN_BEDROCK, and leave CLAUDE_CODE_SKIP_BEDROCK_AUTH unset.
Anthropic's general gateway guide shows a different setup: CLAUDE_CODE_SKIP_BEDROCK_AUTH=1 with the gateway key in ANTHROPIC_AUTH_TOKEN, and AWS_BEARER_TOKEN_BEDROCK left unset. In Claude Code 2.1.295, that setup sends the key only on model calls. The inference-profile lookups and token-count calls go out with no credential, Corveil refuses them with a 401, and Claude Code falls back to its built-in model list and to estimated /context counts. Chat still works. With the key in AWS_BEARER_TOKEN_BEDROCK, every call carries it.
Don't combine the two. With CLAUDE_CODE_SKIP_BEDROCK_AUTH=1 set, Claude Code 2.1.295 sends the profile lookup with no credential even when AWS_BEARER_TOKEN_BEDROCK is set.
Pin enabled models
Pin each model tier to an inference profile your organization has enabled. Without pins, Claude Code uses its own defaults for Bedrock, which may not be enabled in your catalog.
To see the profiles your key can use, call Corveil's profile list:
curl -sS "$ANTHROPIC_BEDROCK_BASE_URL/inference-profiles" \
-H "Authorization: Bearer $AWS_BEARER_TOKEN_BEDROCK" \
| jq -r '.inferenceProfileSummaries[].inferenceProfileId'The list is the profiles enabled in Catalog that your key's model allowlist permits. Pin from it:
ANTHROPIC_DEFAULT_OPUS_MODELandANTHROPIC_DEFAULT_SONNET_MODELset theopusandsonnetaliases.ANTHROPIC_DEFAULT_HAIKU_MODELsets the model for background tasks, such as session titles. On Bedrock, Claude Code otherwise uses its default Sonnet model for them.- A profile must match the credential's region. A
us-east-1credential listsus.andglobal.profiles, noteu.ones.
In Claude Code, run /status. The Status tab should show Amazon Bedrock as the API provider and your Corveil URL as the Bedrock base URL. /model shows the model the session uses.
Verify
- Run the
curlabove. A list of profile IDs means the URL and the key work, a Bedrock credential is stored for the organization, and the listed profiles are enabled. Corveil answers this list from its catalog without calling AWS, so it doesn't prove the AWS keys or the IAM policy work. - Start
claudeand send a prompt that uses a tool, such as "list the files in this directory". A completed turn is what proves the organization's AWS keys and IAM policy work. - In Corveil, open Monitoring → Logs. Each turn is a row with provider
bedrockand endpoint/v1/bedrock/model/{modelId}/invoke-with-response-stream, with its tokens and cost. At startup Claude Code also sends a short request to each model it plans to use, to check it has access; those are rows with endpoint/v1/bedrock/model/{modelId}/invoke. - Run
/contextin Claude Code. Withbedrock:CountTokensgranted, the counts come from Bedrock. Token counting is not logged or billed.
Roll out to a fleet
Distribute the shared values through Claude Code managed settings, and leave each person's key to them. A shared key would put every engineer's spend on one key.
managed-settings.json goes in /Library/Application Support/ClaudeCode/ on macOS, /etc/claude-code/ on Linux and WSL, and C:\Program Files\ClaudeCode\ on Windows:
{
"env": {
"CLAUDE_CODE_USE_BEDROCK": "1",
"ANTHROPIC_BEDROCK_BASE_URL": "https://corveil.io/v1/bedrock",
"AWS_REGION": "us-east-1",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "us.anthropic.claude-opus-4-8",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "us.anthropic.claude-sonnet-4-6",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "us.anthropic.claude-haiku-4-5-20251001-v1:0"
}
}Each engineer then adds their own key to ~/.claude/settings.json:
{
"env": {
"AWS_BEARER_TOKEN_BEDROCK": "sk-citadel-your-key-here"
}
}Managed settings take precedence over user settings, so people can't override the base URL or the model pins in their own settings. Before you change a pin, enable the new profile in Catalog.
Limits
- Output is not redacted. Corveil forwards Bedrock's response unchanged. Input guardrails still block a request. A redacting guardrail that matches the input blocks it too, because Corveil does not rewrite the request. Output guardrails only log what they would have done.
- Claude Desktop is not covered. Desktop and Cowork stay on the Anthropic API through Claude Desktop (MDM) gateway mode.
- Stream length. Corveil ends a streamed turn after 10 minutes in total (
STREAM_MAX_DURATIONon a self-hosted instance). Corveil itself has no idle cut-off, because Bedrock sends no keep-alive frames. On corveil.io the load balancer closes a connection that is silent for 240 seconds, which is sooner than Claude Code's own 5-minute stall timeout. A non-streamed call is limited to 10 minutes. - No model ARNs. Corveil refuses ARNs, including application inference profiles, with a 400. Use inference profile IDs, including in
modelOverrides. - No Mantle.
CLAUDE_CODE_USE_MANTLEis not supported through Corveil. - Request size. A request body over 10 MB is refused.
- Service tiers. Corveil passes
X-Amzn-Bedrock-*headers through, soANTHROPIC_BEDROCK_SERVICE_TIERreaches Bedrock. Corveil's price for a call doesn't depend on the tier.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
401 from Corveil | AWS_BEARER_TOKEN_BEDROCK is unset or doesn't hold a valid Corveil key | Put a valid sk-citadel-… key in AWS_BEARER_TOKEN_BEDROCK. |
Chat works, but /context counts are estimates, and claude --debug logs Failed to list Bedrock inference profiles, falling back to hardcoded models | CLAUDE_CODE_SKIP_BEDROCK_AUTH=1 is set, so those calls carry no key | Unset it, and keep the key in AWS_BEARER_TOKEN_BEDROCK. See Which credential variable. |
400 ValidationException: this organization has no bedrock provider credential configured | The organization has no Bedrock credential. For a model call, Monitoring → Logs records it with error type provider_not_configured; profile-list and token-count refusals are not logged. | Add one under AI Gateway → Providers → Credentials. |
404 ResourceNotFoundException: model not available through this gateway | Corveil's catalog has no row for that ID, such as a typo or an Anthropic model name instead of a Bedrock ID | Pin an ID from the profile list. |
403 AccessDeniedException: model not enabled for your organization, or not allowed for this API key | The profile is disabled in Catalog, or the key's model allowlist excludes it | Enable it in Catalog, or change the key's allowlist. |
403 AccessDeniedException from AWS | The IAM policy is missing an action, or the AWS account hasn't submitted Anthropic's use case form | Attach the policy and submit the form. |
429 | A key, user, team or organization budget is used up, or a rate limit applies | Raise the budget, or wait for the period to reset. |
/status shows no Bedrock base URL, and AWS rejects the key | ANTHROPIC_BEDROCK_BASE_URL didn't reach Claude Code, so it called AWS directly | Set it where Claude Code reads it, and restart Claude Code. |