Search

↑↓ to move↵ to openesc to closetop 6 documentation results

Book a demoTry TokenTriage

In development · Explore the product preview. Join the launch list or book a walkthrough.

Browse docs

Amazon Bedrock

A region, two or three AWS variables, and the pricing rule that turns one model into three different rates depending where you called it.

How-to guideLast updated

On this page

Bedrock is the family where the region is not a detail. It selects the endpoint host, it is the scope every request is signed against, and it changes the price: in the committed snapshot the same Claude model bills $0.80 per million input tokens in the United States and $0.25 in Europe. A gateway that treats region as cosmetic will hand you a confident wrong figure.

You need a region, an access key pair, and the Bedrock model id in the form AWS publishes it (anthropic.claude-3-5-haiku-20241022-v1:0, not claude-3-5-haiku).

The config

upstreams:
  bedrock:
    provider: bedrock
    base_url: https://bedrock-runtime.us-east-1.amazonaws.com
    region: us-east-1                       # signing scope and price selector
    auth:
      access_key_id_env: AWS_ACCESS_KEY_ID
      secret_access_key_env: AWS_SECRET_ACCESS_KEY
      session_token_env: AWS_SESSION_TOKEN  # optional; temporary credentials

tiers:
  - name: cheap
    upstream: bedrock
    model: anthropic.claude-3-5-haiku-20241022-v1:0

Every one of those *_env fields holds a variable name. Three variables, none of them in the file.

region: has its own field rather than living under params:. Writing it as a param is turned away with params.region: use the dedicated region: field, not params. Leave it out entirely and validation stops you:

$ tokentriage validate --config tokentriage.yaml
Error: configuration is invalid: upstreams["bedrock"].region: provider "bedrock" requires a region (aws_sigv4 signing scope / region-qualified pricing / a {region} URL template)

The upstream name inside the quotes is yours; the rest of the sentence is the binary’s, and it is worth grepping for. One thing is tidied above: the command prints that message twice, because it returns the error and then prints it again on the way out.

Using a Bedrock API key instead of signing

Set api_key_env alone, with no auth: block, and the key is presented as a bearer token rather than signing the request. region: is still required, because it still selects the price.

upstreams:
  bedrock:
    provider: bedrock
    base_url: https://bedrock-runtime.us-east-1.amazonaws.com
    region: us-east-1
    api_key_env: AWS_BEARER_TOKEN_BEDROCK

How the region reaches the price

Two different values come out of the one you wrote. The raw region signs the request, because SigV4 needs us-east-1. A shorter region class looks up the price, because the catalog keys its region-qualified rates by continent.

Your region: Class used for pricing
us-* us
eu-* eu
ap-* apac
anything else none, and the row is region_unknown

That last row is the one to plan around. A Bedrock upstream in ca-central-1, sa-east-1 or me-south-1 signs correctly and gets its answer, and any model whose rates are region-qualified comes back with no dollar rather than a neighbouring region’s.

The rule that produces a missing number instead of a wrong one

Each region class is a separate key in the price file, and you can read one back without sending a request:

$ tokentriage prices show bedrock/eu.anthropic.claude-3-5-haiku-20241022-v1:0
model:      bedrock/eu.anthropic.claude-3-5-haiku-20241022-v1:0
resolved:   bedrock/eu.anthropic.claude-3-5-haiku-20241022-v1:0
provider:   bedrock
snapshot:   litellm@2026-07-14#179affb
source:     litellm  fetched 2026-07-14  generator pricegen v2
upstream_sha256: 179affb29103fed8b02a83e22e93209c2c65a393cbf9dd785dbaec0f8748d6f7

RATE         USD / TOKEN          USD / 1M TOKENS
input        2.5e-07              $0.2500
output       1.25e-06             $1.2500
cache_read   2.5e-08              $0.0250
cache_write  3.125e-07            $0.3125
reasoning    (fallback = output)  $1.2500

Swap eu. for us. and the input rate is $0.80 with output at $4.00. The snapshot id and digest in that header are the build’s, not your account’s, and the same command on your machine prints the same figures while you run the same build.

The third class is where it gets interesting. There is no apac. key for this model:

$ tokentriage prices show bedrock/apac.anthropic.claude-3-5-haiku-20241022-v1:0
Error: prices: model "bedrock/apac.anthropic.claude-3-5-haiku-20241022-v1:0" not found in snapshot litellm@2026-07-14#179affb

A region-neutral key for that model does exist, at bedrock/anthropic.claude-3-5-haiku-20241022-v1:0. It is not used.

Models whose catalog entry is region-neutral throughout are unaffected: amazon.titan-text-lite-v1 prices at $0.30 per million input in every class, because the file holds no region-qualified key for it to defeat the neutral one.

Two Bedrock descriptors

bedrock and bedrock_converse speak the identical Converse wire and share the driver. They differ only in which price bucket they bind, and the buckets do not overlap: bedrock/ carries 267 priced keys and bedrock_converse/ carries 138, and no model key appears in both. Those are counts of rows in the vendored litellm@2026-07-14#179affb price file rather than claims about what either descriptor can reach.

Amazon’s own Nova models are the case that catches people. They are keyed under bedrock_converse/ and not under bedrock/, in all four forms:

$ tokentriage prices show bedrock_converse/us.amazon.nova-lite-v1:0
model:      bedrock_converse/us.amazon.nova-lite-v1:0
resolved:   bedrock_converse/us.amazon.nova-lite-v1:0
provider:   bedrock_converse
snapshot:   litellm@2026-07-14#179affb
source:     litellm  fetched 2026-07-14  generator pricegen v2
upstream_sha256: 179affb29103fed8b02a83e22e93209c2c65a393cbf9dd785dbaec0f8748d6f7

RATE         USD / TOKEN          USD / 1M TOKENS
input        6e-08                $0.0600
output       2.4e-07              $0.2400
cache_read   (fallback = input)   $0.0600
cache_write  (fallback = input)   $0.0600
reasoning    (fallback = output)  $0.2400

So: use bedrock unless your models resolve under the separate bedrock_converse/ bucket. If a model comes back model_unknown on one, try the other before concluding it is unsupported. Nova carries us., eu. and apac. keys as well as a neutral one, so the rule above applies to it in full.

Reaching Bedrock from an SDK you already have

On the translation axis, two client formats come in and four upstream dialects go out. An OpenAI-format or an Anthropic-format client reaches a bedrock upstream, streaming and not, and the same two formats also reach openai, anthropic and gemini upstreams. A Bedrock-format client reaches only a Bedrock upstream, because bedrock is a translation target rather than an inbound client format.

That asymmetry is a decision with a reason, and the reason is evidence rather than difficulty: no population of Bedrock-SDK clients pointed at a third-party gateway has been observed, and switching on a direction nobody has verified would leave an unowned surface behind rather than a feature. It behaves like a decision too. A Bedrock-format request is not rejected: the translator returns a named error, and the request is then served byte-faithfully on its own dialect, a Bedrock client reaching a Bedrock upstream, which loses nothing at all.

The full grid is drawn once, on the dialect matrix, rather than redrawn here. What a translated row records about fields that could not cross is on translation loss, and the streaming half of it is on streaming translation.

Prefixes that look missing and are not

Two catalog prefixes in this family sit outside the covered list, and neither one is a driver gap. bedrock_mantle holds 10 synthetic or future model ids on Bedrock. amazon_nova holds 4 shorthand ids such as nova-lite-v1, which is not the Bedrock model id you send: that is amazon.nova-lite-v1:0, and it prices under bedrock_converse/ as shown above.

Both belong to the published gap partition’s alias-or-sub-namespace class, whose own column heading in the generated table reads “Why it’s not a driver gap”. Binding either would be a pricing-bucket descriptor, pure data on the same pattern bedrock_converse follows, with no new wire code. The condition for doing it is an operator who uses that sub-namespace, which is a condition and not a date or a queue position. The coverage page carries the whole partition.

What is verified, and what is not

aws_sigv4 is the scheme these two descriptors declare, and they are the only two of the 95 built-in provider descriptors TokenTriage ships that declare it. Seven of the 95 carry no gated cell at all and neither of these two is among them: each declares one endpoint, chat, and the generated matrix gates both of those cells at its strongest evidence level, a row-stamp. The matrix names the gate per cell, so you can run one. Here they are TestBedrockCostGoldenRegionPriced and TestBedrockConverseDescriptor.

Three sibling tests in the same file carry the rest of this page. TestBedrockSigV4Wire asserts the AWS4-HMAC-SHA256 header and that the signature covers the forwarded body bytes. TestBedrockStreamFidelity asserts the binary event stream reaches the client byte-for-byte as the upstream sent it. TestBedrockCostUnpricedRegionUnknown asserts that a row from an unmapped region carries no dollar and no borrowed key. Every one of them runs against a mock, not against AWS, and no claim here is a claim about your account’s negotiated rates.

bedrock declares chat and nothing else. Bedrock’s embedding and image surfaces are not wired, so those calls are forwarded and ledgered without a cost figure.

What can go wrong

Symptom Cause Fix
requires a region no region: field add it; params.region is turned away with its own message
credentials_file_env: not valid for the "aws_sigv4" scheme Google-style credentials block use the AWS pair, or api_key_env alone
every request gets a signing error wrong region for the host, or a stale session token region must match the host; refresh temporary credentials
region_unknown on every row your region is outside us-, eu- and ap- expected; the rate does not exist for that class
model_unknown with a correct-looking model the short model name, or the wrong Bedrock bucket use the full AWS id; try bedrock_converse