ReqLLM.Providers.AmazonBedrock (ReqLLM v1.0.0)

View Source

AWS Bedrock provider implementation using the Provider behavior.

Supports AWS Bedrock's unified API for accessing multiple AI models including:

  • Anthropic Claude models (fully implemented)
  • Meta Llama models (fully implemented)
  • Mistral AI models (fully implemented)
  • Amazon Nova models (extensible)
  • Cohere models (extensible)
  • And more as AWS adds them

Authentication

Bedrock supports two authentication methods:

API Keys (Simplest - Introduced July 2025)

AWS Bedrock API keys provide simplified authentication with Bearer tokens:

# Option 1: Environment variable (recommended)
export AWS_BEARER_TOKEN_BEDROCK=your-api-key
export AWS_REGION=us-east-1

# Option 2: Pass directly in options
ReqLLM.generate_text(
  "bedrock:anthropic.claude-3-sonnet-20240229-v1:0",
  "Hello",
  api_key: "your-api-key",
  region: "us-east-1"
)

Note: API keys cannot be used with InvokeModelWithBidirectionalStream, Agents, or Data Automation operations. Short-term keys (up to 12 hours) are recommended for production. Long-term keys are for exploration only.

IAM Credentials (AWS Signature V4)

Traditional AWS authentication using access keys:

# Option 1: Environment variables
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1

# Option 2: Pass directly in options
ReqLLM.generate_text(
  "bedrock:anthropic.claude-3-sonnet-20240229-v1:0",
  "Hello",
  access_key_id: "AKIA...",
  secret_access_key: "...",
  region: "us-east-1"
)

# Option 3: Use ReqLLM.Keys (with composite key)
ReqLLM.put_key(:aws_bedrock, %{
  access_key_id: "AKIA...",
  secret_access_key: "...",
  region: "us-east-1"
})

Known Limitations

AWS Signature V4 Expiry with Long-Running Requests

AWS Signature V4 (used for all AWS API requests) has a hardcoded 5-minute expiry time. This creates a fundamental limitation for requests that take longer than 5 minutes to complete:

  • AWS validates the signature when responding, not when receiving the request
  • If a request takes >5 minutes to complete, AWS will reject it with a 403 "Signature expired" error
  • This affects slow models with large outputs (e.g., Claude Opus 4/4.1 with max token limits)
  • The 5-minute limit cannot be extended or configured - it's part of the AWS SigV4 spec
  • No workaround exists without implementing request re-signing during long-running requests

From AWS IAM documentation:

In most cases, a request must reach AWS within five minutes of the time stamp in the request.

Impact: Tests or production code using slow models with high token limits may intermittently fail with signature expiry errors. Consider using shorter timeouts or faster model variants for time-critical applications.

Examples

# Simple text generation with Claude on Bedrock
model = ReqLLM.Model.from("bedrock:anthropic.claude-3-sonnet-20240229-v1:0")
{:ok, response} = ReqLLM.generate_text(model, "Hello!")

# Streaming
{:ok, response} = ReqLLM.stream_text(model, "Tell me a story")
response
|> ReqLLM.StreamResponse.tokens()
|> Stream.each(&IO.write/1)
|> Stream.run()

# Tool calling (for models that support it)
tools = [%ReqLLM.Tool{name: "get_weather", ...}]
{:ok, response} = ReqLLM.generate_text(model, "What's the weather?", tools: tools)

Extending for New Models

To add support for a new model family:

  1. Add the model family to @model_families
  2. Implement format functions in the corresponding module (e.g., ReqLLM.Providers.Bedrock.Meta)
  3. The functions needed are:
    • format_request/3 - Convert ReqLLM context to provider format
    • parse_response/2 - Convert provider response to ReqLLM format
    • parse_stream_chunk/2 - Handle streaming responses

Summary

Functions

Default implementation of attach/3.

Default implementation of attach_stream/4.

Default implementation of decode_response/1.

Default implementation of decode_stream_event/2.

Default implementation of encode_body/1.

Default implementation of extract_usage/2.

Default implementation of prepare_request/4.

Default implementation of translate_options/3.

Functions

attach(request, model_input, user_opts)

Default implementation of attach/3.

Sets up Bearer token authentication and standard pipeline steps.

attach_stream(model, context, opts, finch_name)

Default implementation of attach_stream/4.

Builds complete streaming requests using OpenAI-compatible format.

decode_response(request_response)

Default implementation of decode_response/1.

Handles success/error responses with standard ReqLLM.Response creation.

decode_stream_event(event, model)

Default implementation of decode_stream_event/2.

Decodes SSE events using OpenAI-compatible format.

default_base_url()

default_env_key()

Callback implementation for ReqLLM.Provider.default_env_key/0.

default_provider_opts()

encode_body(request)

Default implementation of encode_body/1.

Encodes request body using OpenAI-compatible format for chat and embedding operations.

extract_usage(body, model)

Default implementation of extract_usage/2.

Extracts usage data from standard usage field in response body.

metadata()

pre_validate_options(operation, model, opts)

prepare_request(operation, model_spec, input, opts)

Default implementation of prepare_request/4.

Handles :chat, :object, and :embedding operations using OpenAI-compatible patterns.

provider_extended_generation_schema()

provider_id()

provider_schema()

supported_provider_options()

translate_options(operation, model, opts)

Default implementation of translate_options/3.

Pass-through implementation that returns options unchanged.

wrap_response(already_wrapped)