fern/03-reference/baml/clients/providers/aws-bedrock.mdx
The aws-bedrock provider supports all text-output models available via the Converse API.
client<llm> MyClient {
provider aws-bedrock
options {
model "anthropic.claude-3-sonnet-20240229-v1:0"
inference_configuration {
max_tokens 100
temperature 0.7
}
// Pass any other parameters that are model specific,
// like with claude thinking models.
additional_model_request_fields {
thinking {
type "enabled"
budget_tokens 1030
}
}
}
}
AWS Bedrock uses standard AWS authentication methods. We recommend using AWS profiles in development and AWS services' IAM roles in production, but all of the following are supported:
<Tabs> <Tab title="AWS Profile" language="ini">When developing locally, you can use the AWS CLI in combination with profiles to manage your credentials.
For example, if you run aws sso login with a default profile, BAML will automatically pick up those credentials:
[default]
sso_start_url = https://your-sso-start-url.awsapps.com/start
sso_region = us-west-2
sso_account_id = 123456789012
sso_role_name = YourSSORole
region = us-west-2
output = json
You can also choose a specific profile by setting the AWS_PROFILE environment variable.
In the BAML playground, you can set this by clicking the "API Keys" button in
the top right (you'll also need to set AWS_REGION to the same region as your
profile).
The BAML-generated clients will also respect AWS_PROFILE if it is set:
export AWS_PROFILE=staging-profile
Alternatively, you can also explicitly specify the profile directly in the BAML config itself (this will take precedence over the environment variable):
# First, login with SSO
aws sso login --profile staging-profile
# Then use the profile in your BAML config
client<llm> MyClient {
provider aws-bedrock
options {
profile "staging-profile"
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
In AWS Lambda, EC2, ECS, etc., BAML will automatically use the service's IAM role, by reading the relevant environment variables. To override this behavior, see the section on Explicit Credentials.```
client<llm> MyClient {
provider aws-bedrock
options {
region "us-east-1" // Only region is required
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
Best Practices:
The simplest way to authenticate. Set these environment variables:
export AWS_ACCESS_KEY_ID="your_key"
export AWS_SECRET_ACCESS_KEY="your_secret"
export AWS_REGION="us-east-1"
client<llm> MyClient {
provider aws-bedrock
options {
// No need to specify credentials - they'll be picked up from environment
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
You can specify credentials directly in your BAML configuration:
client<llm> MyClient {
provider aws-bedrock
options {
access_key_id env.AWS_ACCESS_KEY_ID
secret_access_key env.AWS_SECRET_ACCESS_KEY
region "us-east-1"
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
Important Notes:
session_tokenBAML follows a specific order when resolving AWS credentials:
Explicit BAML Configuration
client<llm> MyClient {
provider aws-bedrock
options {
access_key_id env.MY_ACCESS_KEY // Highest precedence
secret_access_key env.MY_SECRET_KEY
region "us-east-1"
}
}
Environment Variables
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN # Optional
AWS_REGION
AWS_PROFILE
AWS Configuration Files
# ~/.aws/credentials
[default]
aws_access_key_id = ...
aws_secret_access_key = ...
# ~/.aws/config
[default]
region = us-east-1
Instance Metadata (EC2/ECS only)
All or Nothing
client<llm> MyClient {
provider aws-bedrock
options {
access_key_id env.AWS_ACCESS_KEY_ID
// Error: secret_access_key is required when access_key_id is provided
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
Session Token Requirements
session_token, you must provide all three:
access_key_idsecret_access_keysession_tokenProfile Exclusivity
profile, you cannot specify other credentials:
client<llm> MyClient {
provider aws-bedrock
options {
profile "my-profile"
access_key_id env.AWS_ACCESS_KEY_ID // Error: Cannot mix profile with explicit credentials
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
Environment Variable Override
client<llm> MyClient {
provider aws-bedrock
options {
access_key_id "AKIAXXXXXXXX" // This will be used even if AWS_ACCESS_KEY_ID exists
secret_access_key env.AWS_SECRET_ACCESS_KEY
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
AWS Lambda/ECS/EC2
You can map your own environment variable names:
<Tabs> <Tab title="BAML" language="baml">client<llm> MyClient {
provider aws-bedrock
options {
access_key_id env.MY_CUSTOM_AWS_KEY_ID
secret_access_key env.MY_CUSTOM_AWS_SECRET
session_token env.MY_CUSTOM_AWS_SESSION // Optional
region env.MY_CUSTOM_AWS_REGION
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
# Your custom environment variables
export MY_CUSTOM_AWS_KEY_ID="your_key"
export MY_CUSTOM_AWS_SECRET="your_secret"
export MY_CUSTOM_AWS_REGION="us-east-1"
export MY_CUSTOM_AWS_SESSION="optional_session_token"
To use Bedrock from a different AWS account:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::SOURCE_ACCOUNT_ID:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "YOUR_EXTERNAL_ID"
}
}
}
]
}
# ~/.aws/config
[profile target-role]
role_arn = arn:aws:iam::TARGET_ACCOUNT_ID:role/ROLE_NAME
source_profile = default
region = us-east-1
client<llm> MyClient {
provider aws-bedrock
options {
profile "target-role"
model "anthropic.claude-3-sonnet-20240229-v1:0"
}
}
# Assume role and export credentials
aws sts assume-role \
--role-arn arn:aws:iam::TARGET_ACCOUNT_ID:role/ROLE_NAME \
--role-session-name "BamlSession" \
--external-id "YOUR_EXTERNAL_ID"
export AWS_ACCESS_KEY_ID="from-sts-output"
export AWS_SECRET_ACCESS_KEY="from-sts-output"
export AWS_SESSION_TOKEN="from-sts-output"
import { ClientRegistry } from '@baml/core';
import { STSClient, AssumeRoleCommand } from '@aws-sdk/client-sts';
const sts = new STSClient({ region: 'us-east-1' });
const response = await sts.send(new AssumeRoleCommand({
RoleArn: 'arn:aws:iam::TARGET_ACCOUNT_ID:role/ROLE_NAME',
RoleSessionName: 'BamlSession',
ExternalId: 'YOUR_EXTERNAL_ID'
}));
const registry = new ClientRegistry();
registry.addLlmClient('MyClient', 'aws-bedrock', {
accessKeyId: response.Credentials!.AccessKeyId,
secretAccessKey: response.Credentials!.SecretAccessKey,
sessionToken: response.Credentials!.SessionToken,
region: 'us-east-1'
});
The following IAM permissions are required for basic Bedrock access:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "arn:aws:bedrock:*:*:model/*"
}
]
}
Depending on your setup, you might need additional permissions:
<Tabs> <Tab title="Cross-Account Access" language="json"> See [Cross-Account Access](#cross-account-access) section for the required trust relationships and permissions. </Tab> <Tab title="VPC Endpoints" language="json"> If using VPC endpoints: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream" ], "Resource": "arn:aws:bedrock:*:*:model/*", "Condition": { "StringEquals": { "aws:SourceVpc": "vpc-xxxxxxxx" } } } ] } ``` </Tab> <Tab title="Resource-Based" language="json"> To restrict access to specific models: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream" ], "Resource": [ "arn:aws:bedrock:*:*:model/anthropic.claude-*", "arn:aws:bedrock:*:*:model/meta.llama2-*" ] } ] } ``` </Tab> </Tabs>optionsThese unique parameters (aka options) are modify the API request sent to the provider.
You can use this to modify the region, access_key_id, secret_access_key, and session_token sent to the provider.
b.request returns a fully signed SigV4 HTTPRequest pointing at the
Converse API.Authorization, X-Amz-Date, and (if needed) X-Amz-Security-Token.import { SignatureV4 } from "@aws-sdk/signature-v4"
import { defaultProvider } from "@aws-sdk/credential-provider-node"
import { HttpRequest } from "@aws-sdk/protocol-http"
import { b } from 'baml_client'
async function callBedrock() {
const req = await b.request.ExtractResume("John Doe | Software Engineer | BSc in CS")
const body = req.body.json() as any
const bodyString = JSON.stringify(body)
const url = new URL(req.url)
const region = (req.client_details.options?.region as string) ?? process.env.AWS_REGION ?? "us-east-1"
const signer = new SignatureV4({
service: "bedrock",
region,
credentials: defaultProvider(),
})
const unsigned = new HttpRequest({
protocol: url.protocol,
hostname: url.hostname,
path: url.pathname,
method: req.method,
headers: {
...req.headers,
host: url.host,
"content-type": "application/json",
},
body: bodyString,
})
const signed = await signer.sign(unsigned)
const res = await fetch(req.url, {
method: req.method,
headers: signed.headers as Record<string, string>,
body: bodyString,
})
if (!res.ok) {
throw new Error(`Bedrock request failed: ${res.status}`)
}
const payload = await res.json()
const message = payload.output.message.content.find((block: any) => block.text)?.text ?? ''
return b.parse.ExtractResume(message)
}
import json
import requests
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
import boto3
from baml_client import b
def call_bedrock():
req = b.request.ExtractResume("John Doe | Software Engineer | BSc in CS")
body = req.body.json()
body_bytes = json.dumps(body).encode("utf-8")
session = boto3.Session()
credentials = session.get_credentials().get_frozen_credentials()
region = req.client_details.options.get("region") or session.region_name or "us-east-1"
aws_request = AWSRequest(
method=req.method,
url=req.url,
data=body_bytes,
headers=dict(req.headers),
)
SigV4Auth(credentials, "bedrock", region).add_auth(aws_request)
response = requests.post(
req.url,
headers=dict(aws_request.headers.items()),
data=body_bytes,
)
response.raise_for_status()
payload = response.json()
message = payload["output"]["message"]["content"][0]["text"]
return b.parse.ExtractResume(message)
These are other options that are passed through to the provider, without modification by BAML. For example if the request has a temperature field, you can define it in the client here so every call has that set.
Consult the specific provider's documentation for more information.
<ParamField path="model (or model_id)" type="string" required> The model to use.| Model | Description |
|---|
anthropic.claude-opus-4-1-20250805-v1:0 - Most powerful codinganthropic.claude-sonnet-4-20250514-v1:0 - Best default, 1M context availableanthropic.claude-3-5-haiku-20241022-v1:0 - Fast and efficientmeta.llama4-maverick-17b-instruct-v1:0 - Latest Llama 4meta.llama3-3-70b-instruct-v1:0 - Enhanced Llama 3.3Run aws bedrock list-foundation-models | jq '.modelSummaries.[].modelId' to see available models.
Note: You must request model access before use. </ParamField>
<ParamField path="inference_configuration" type="object"> Model-specific inference parameters. See [AWS Bedrock documentation](https://docs.rs/aws-sdk-bedrockruntime/latest/aws_sdk_bedrockruntime/types/struct.InferenceConfiguration.html).client<llm> MyClient {
provider aws-bedrock
options {
inference_configuration {
max_tokens 1000
temperature 1.0
top_p 0.8
}
}
}