Last updated 2026-05-17
AWS Bedrock Provider
The bedrock provider talks to AWS Bedrock's
bedrock-runtime endpoint, with full SigV4 request
signing and per-model-family body translation. Chat is exposed via
Provider;
embeddings via
Embedder
(Titan and Cohere on Bedrock). TTS and STT are not supported on
Bedrock.
Import path
import ( "github.com/elloloop/llmrouter" "github.com/elloloop/llmrouter/providers/bedrock")Construction
Bedrock uses AWS SigV4 — there is no API key. The provider takes
an aws.Config and a region:
import ( "github.com/aws/aws-sdk-go-v2/config" "github.com/elloloop/llmrouter/providers/bedrock")
awsCfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))if err != nil { log.Fatal(err)}
p, err := bedrock.New( bedrock.WithAWSConfig(awsCfg), bedrock.WithRegion("us-east-1"),)Credentials are resolved by the AWS SDK chain (env vars, shared credentials file, EC2/ECS/EKS metadata, SSO). The library never sees raw credentials.
Model routing and body translation
Bedrock hosts many vendor families on one runtime, each with its
own request body. The provider inspects
ChatRequest.Model and routes to the right body
translator:
| Model prefix | Family | Body shape |
|---|---|---|
anthropic.claude-* | Claude | Anthropic /v1/messages |
meta.llama* | Llama | Meta chat templating |
amazon.titan-* | Titan | Amazon inputText |
amazon.nova-* | Nova | Amazon Converse |
mistral.* | Mistral | Mistral chat |
cohere.command-* | Cohere | Cohere /v1/chat |
The response stream is translated back to OpenAI-shaped
Chunks in every case.
Chat example (Claude on Bedrock)
stream, err := p.CompletionStream(ctx, llmrouter.ChatRequest{ Model: "anthropic.claude-3-5-sonnet-20241022-v2:0", Messages: []llmrouter.Message{ llmrouter.TextMessage("system", "You are concise."), llmrouter.TextMessage("user", "What's interesting about SigV4?"), }, MaxTokens: 256,})if err != nil { log.Fatal(err)}
for chunk := range stream.Chunks() { for _, c := range chunk.Choices { fmt.Print(c.Delta.Content) }}if err := stream.Err(); err != nil { log.Fatal(err)}Embeddings (Titan, Cohere)
Bedrock exposes two embedding families. The library routes
EmbedRequest.Model the same way as chat:
amazon.titan-embed-text-v2:0— 1024 dims, Amazon Titan.amazon.titan-embed-text-v1— 1536 dims, legacy.cohere.embed-english-v3— 1024 dims, Cohere on Bedrock.cohere.embed-multilingual-v3— 1024 dims.
resp, err := p.Embed(ctx, llmrouter.EmbedRequest{ Model: "amazon.titan-embed-text-v2:0", Inputs: []string{"What is SigV4?"}, TaskType: "RETRIEVAL_DOCUMENT", // mapped to Cohere input_type when applicable})Error handling
Non-2xx responses surface as
*llmrouter.ErrUpstream
with Provider == "bedrock". Common cases:
403— IAM principal lacksbedrock:InvokeModel*for the model ARN.400— model not enabled in the region (request access in the Bedrock console).429— service quota exhausted; either request a quota increase or use Provisioned Throughput.
Caveats
- No TTS, no STT. Bedrock has Polly (TTS) and
Transcribe (STT) as separate AWS services;
llmrouterdoes not wrap them. Use the AWS SDKs directly or ElevenLabs / Cartesia / Deepgram. - Region matters. Model availability varies by
region;
us-east-1has the broadest catalogue. - Cross-region inference profiles. Some newer
models (Claude 3.5 Sonnet v2) are accessed via
us.anthropic.claude-3-5-sonnet-20241022-v2:0profile IDs. Pass them as-is.
See also
- Anthropic provider — direct API, often faster.
- Byte passthrough — per-family bodies via
Raw.