Amazon Bedrock Provider
The Amazon Bedrock provider enables integration with foundation models through AWS Bedrock’s Converse API. It supports both synchronous and streaming message completion with full tool calling capabilities. Bedrock provides access to models from multiple providers (Anthropic, Meta, Mistral, Amazon) through a unified AWS-managed interface with enterprise features like VPC endpoints, CloudWatch logging, and model customization.
The provider handles AWS SigV4 request signing, the Bedrock Converse API format, and streaming via event-stream encoding. Authentication uses AWS credentials rather than API keys, supporting both permanent and temporary (STS) credentials.
BedrockProvider Struct
The provider is defined in src/client/providers/bedrock/mod.rs:
pub struct BedrockCredentials {
pub access_key_id: String,
pub secret_access_key: String,
pub session_token: Option<String>,
}
pub struct BedrockProvider {
credentials: BedrockCredentials,
region: String,
model: String,
}
impl BedrockProvider {
pub fn new(credentials: BedrockCredentials, region: String, model: String) -> Self {
Self { credentials, region, model }
}
pub fn model(&self) -> &str {
&self.model
}
pub fn region(&self) -> &str {
&self.region
}
}
API Configuration
The Bedrock provider uses the Converse API:
| Setting | Value |
|---|---|
| Base URL | https://bedrock-runtime.{region}.amazonaws.com |
| Converse | /model/{model}/converse |
| Stream | /model/{model}/converse-stream |
| Auth | AWS SigV4 |
The model ID is URL-encoded in the path (e.g., colons become %3A).
LLMSessionConfig Builder
Create a Bedrock session configuration using the bedrock() builder method:
use agent_air::controller::LLMSessionConfig;
let config = LLMSessionConfig::bedrock(
"AKIA...", // AWS Access Key ID
"secret...", // AWS Secret Access Key
"us-east-1", // AWS Region
"anthropic.claude-3-sonnet-20240229-v1:0" // Model ID
);
The bedrock() method sets these defaults:
| Option | Default Value |
|---|---|
| max_tokens | 4096 |
| streaming | true |
| context_limit | 200,000 |
| compaction | Threshold (default) |
Builder Methods
Customize the configuration using builder methods:
let config = LLMSessionConfig::bedrock(
access_key_id,
secret_access_key,
"us-east-1",
"anthropic.claude-3-sonnet-20240229-v1:0"
)
.with_bedrock_session_token(session_token) // For temporary credentials
.with_max_tokens(4096)
.with_system_prompt("You are a helpful assistant.")
.with_temperature(0.7)
.with_streaming(true)
.with_context_limit(200_000);
Available methods:
| Method | Description |
|---|---|
with_bedrock_session_token(impl Into<String>) | Set session token for temp credentials |
with_max_tokens(u32) | Set maximum response tokens |
with_system_prompt(impl Into<String>) | Set the system prompt |
with_temperature(f32) | Set sampling temperature |
with_streaming(bool) | Enable or disable streaming |
with_context_limit(i32) | Set context window size |
with_threshold_compaction(config) | Configure compaction |
without_compaction() | Disable compaction |
AWS Credentials
Permanent Credentials
Use IAM user credentials directly:
let config = LLMSessionConfig::bedrock(
std::env::var("AWS_ACCESS_KEY_ID").unwrap(),
std::env::var("AWS_SECRET_ACCESS_KEY").unwrap(),
"us-east-1",
"anthropic.claude-3-sonnet-20240229-v1:0"
);
Temporary Credentials (STS)
For assumed roles or temporary credentials, include the session token:
let config = LLMSessionConfig::bedrock(
access_key_id,
secret_access_key,
"us-east-1",
"anthropic.claude-3-sonnet-20240229-v1:0"
)
.with_bedrock_session_token(session_token);
BedrockCredentials Struct
For direct provider usage:
use agent_air::client::providers::bedrock::BedrockCredentials;
// Permanent credentials
let creds = BedrockCredentials::new(access_key_id, secret_access_key);
// Temporary credentials
let creds = BedrockCredentials::with_session_token(
access_key_id,
secret_access_key,
session_token
);
Required IAM Permissions
The IAM user or role needs these permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "arn:aws:bedrock:*::foundation-model/*"
}
]
}
For specific models only:
{
"Resource": [
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0",
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0"
]
}
Streaming Support
The Bedrock provider fully supports streaming via the Converse Stream API. Unlike standard SSE, Bedrock uses AWS event-stream encoding:
pub enum StreamEvent {
MessageStart { message_id: String, model: String },
TextDelta(String),
ToolUse { id: String, name: String, input: Value },
MessageStop,
Error(String),
}
The provider handles the binary event-stream parsing automatically.
Request Format (Converse API)
Bedrock uses the Converse API format which differs from direct provider APIs:
{
"messages": [
{
"role": "user",
"content": [{"text": "Hello"}]
}
],
"system": [
{"text": "You are a helpful assistant."}
],
"inferenceConfig": {
"maxTokens": 4096,
"temperature": 0.7,
"topP": 0.9
}
}
Role Mapping
| Generic Role | Bedrock Role |
|---|---|
| User | user |
| Assistant | assistant |
| System | system array (separate field) |
Content Types
Bedrock content uses specific object structures:
| Content Type | Format |
|---|---|
| Text | {"text": "..."} |
| Tool Use | {"toolUse": {"toolUseId": "...", "name": "...", "input": {...}}} |
| Tool Result | {"toolResult": {"toolUseId": "...", "content": [{"text": "..."}], "status": "success"}} |
Tool Use Format
Tools are sent in the Bedrock toolConfig format:
{
"toolConfig": {
"tools": [{
"toolSpec": {
"name": "get_weather",
"description": "Get weather for a location",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}
}],
"toolChoice": {"auto": {}}
}
}
Tool choice options:
| Choice | Format |
|---|---|
| Auto | {"auto": {}} |
| Any | {"any": {}} |
| Specific | {"tool": {"name": "tool_name"}} |
Environment Variables
Configure Bedrock via environment variables:
| Variable | Description | Default |
|---|---|---|
AWS_ACCESS_KEY_ID | AWS access key (required) | None |
AWS_SECRET_ACCESS_KEY | AWS secret key (required) | None |
AWS_SESSION_TOKEN | Session token (optional) | None |
AWS_REGION | AWS region | us-east-1 |
BEDROCK_MODEL | Model identifier | None |
Available Models
Common Bedrock model identifiers:
| Model | ID | Context |
|---|---|---|
| Claude 3 Sonnet | anthropic.claude-3-sonnet-20240229-v1:0 | 200K |
| Claude 3 Haiku | anthropic.claude-3-haiku-20240307-v1:0 | 200K |
| Claude 3 Opus | anthropic.claude-3-opus-20240229-v1:0 | 200K |
| Claude 3.5 Sonnet | anthropic.claude-3-5-sonnet-20240620-v1:0 | 200K |
| Llama 3 70B | meta.llama3-70b-instruct-v1:0 | 8K |
| Llama 3 8B | meta.llama3-8b-instruct-v1:0 | 8K |
| Mistral Large | mistral.mistral-large-2402-v1:0 | 32K |
Note: Model availability varies by region. Check AWS documentation for current availability.
YAML Configuration
Configure in your agent’s config file:
providers:
- provider: bedrock
bedrock_access_key_id: AKIA...
bedrock_secret_access_key: secret...
bedrock_region: us-east-1
model: anthropic.claude-3-sonnet-20240229-v1:0
system_prompt: "You are a helpful coding assistant."
default_provider: bedrock
Complete Example
use agent_air::AgentAir;
use agent_air::controller::LLMSessionConfig;
struct MyConfig;
impl AgentConfig for MyConfig {
fn config_path(&self) -> &str { ".myagent/config.yaml" }
fn default_system_prompt(&self) -> &str { "You are helpful." }
fn log_prefix(&self) -> &str { "myagent" }
fn name(&self) -> &str { "MyAgent" }
}
fn main() -> std::io::Result<()> {
let mut agent = AgentAir::new(&MyConfig)?;
// Configuration is loaded automatically from:
// 1. ~/.myagent/config.yaml (if exists)
// 2. AWS_* environment variables (fallback)
agent.run()
}
Programmatic Configuration
For direct configuration without files:
use agent_air::controller::{LLMSessionConfig, LLMController};
let config = LLMSessionConfig::bedrock(
std::env::var("AWS_ACCESS_KEY_ID").expect("Access key required"),
std::env::var("AWS_SECRET_ACCESS_KEY").expect("Secret key required"),
"us-east-1",
"anthropic.claude-3-sonnet-20240229-v1:0"
)
.with_system_prompt("You are a helpful assistant.")
.with_max_tokens(4096)
.with_streaming(true);
// Create session with this config
let controller = LLMController::new(None);
let session_id = controller.create_session(config).await?;
Error Handling
Bedrock API errors are converted to LlmError:
pub struct LlmError {
pub error_code: String,
pub error_message: String,
}
Common error codes:
| Error Code | Description |
|---|---|
ValidationException | Invalid request parameters |
AccessDeniedException | IAM permissions issue |
ThrottlingException | Rate limit exceeded |
ModelNotReadyException | Model not available in region |
ServiceUnavailableException | Temporary service issue |
Regions and Availability
Bedrock is available in these AWS regions (as of 2024):
| Region | Code | Notes |
|---|---|---|
| US East (N. Virginia) | us-east-1 | Most models |
| US West (Oregon) | us-west-2 | Most models |
| Europe (Frankfurt) | eu-central-1 | Limited |
| Europe (Paris) | eu-west-3 | Limited |
| Asia Pacific (Tokyo) | ap-northeast-1 | Limited |
| Asia Pacific (Sydney) | ap-southeast-2 | Limited |
Check AWS documentation for current model availability per region.
Comparison with Direct Anthropic API
| Feature | Bedrock | Direct Anthropic |
|---|---|---|
| Authentication | AWS SigV4 | API Key |
| API Format | Converse API | Messages API |
| VPC Support | Yes (PrivateLink) | No |
| Logging | CloudWatch | Custom |
| Billing | AWS consolidated | Separate |
| Rate Limits | Per-account | Per-API key |
| Model Access | Request required | Instant |
