Back to Baml

aws-bedrock

fern/03-reference/baml/clients/providers/aws-bedrock.mdx

0.226.218.4 KB
Original Source

The aws-bedrock provider supports all text-output models available via the Converse API.

Quick Start

baml
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
      }
    }
  }
}

Authentication

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:

ini
[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:

bash
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):

bash
# 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"
  }
}
</Tab> <Tab title="AWS Services (Lambda/ECS/EC2)" language="baml">

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.```

baml
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:

  • Use execution roles in Lambda
  • Use task roles in ECS
  • Use instance profiles in EC2
  • Never hardcode credentials in AWS environments
  • See IAM Permissions section for required permissions
</Tab> <Tab title="Environment Variables" language="bash">

The simplest way to authenticate. Set these environment variables:

bash
export AWS_ACCESS_KEY_ID="your_key"
export AWS_SECRET_ACCESS_KEY="your_secret"
export AWS_REGION="us-east-1"
baml
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"
  }
}
</Tab> <Tab title="Explicit Credentials" language="baml">

You can specify credentials directly in your BAML configuration:

baml
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:

  • Explicit credentials take precedence over environment variables
  • If specifying any credential, you must provide all required ones
  • For temporary credentials, include session_token
  • Not recommended for production AWS environments (use IAM roles instead)
</Tab> </Tabs>

Credential Resolution

BAML follows a specific order when resolving AWS credentials:

  1. Explicit BAML Configuration

    baml
    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"
      }
    }
    
  2. Environment Variables

    bash
    AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY
    AWS_SESSION_TOKEN    # Optional
    AWS_REGION
    AWS_PROFILE
    
  3. AWS Configuration Files

    ini
    # ~/.aws/credentials
    [default]
    aws_access_key_id = ...
    aws_secret_access_key = ...
    
    # ~/.aws/config
    [default]
    region = us-east-1
    
  4. Instance Metadata (EC2/ECS only)

    • IAM Role credentials
    • Instance profile credentials

Important Rules

  1. All or Nothing

    • If you provide any credential explicitly, you must provide all required credentials
    • This won't work:
      baml
      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"
        }
      }
      
  2. Session Token Requirements

    • When using session_token, you must provide all three:
      • access_key_id
      • secret_access_key
      • session_token
  3. Profile Exclusivity

    • When using profile, you cannot specify other credentials:
      baml
      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"
        }
      }
      
  4. Environment Variable Override

    • Explicit values in BAML always override environment variables:
      baml
      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"
        }
      }
      
  5. AWS Lambda/ECS/EC2

    • In AWS services, credentials are automatically provided by the runtime
    • Explicitly provided credentials will override the automatic ones
    • Best practice: Don't specify credentials in AWS environments, use IAM roles instead

Using Custom Environment Variables

You can map your own environment variable names:

<Tabs> <Tab title="BAML" language="baml">
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"
  }
}
</Tab> <Tab title="Environment" language="bash">
bash
# 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"
</Tab> </Tabs>

Cross-Account Access

To use Bedrock from a different AWS account:

  1. Set up the target account role (where Bedrock is):
json
{
  "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"
        }
      }
    }
  ]
}
  1. Configure the source account (where your application runs):
<Tabs> <Tab title="AWS Profile" language="ini">
ini
# ~/.aws/config
[profile target-role]
role_arn = arn:aws:iam::TARGET_ACCOUNT_ID:role/ROLE_NAME
source_profile = default
region = us-east-1
baml
client<llm> MyClient {
  provider aws-bedrock
  options {
    profile "target-role"
    model "anthropic.claude-3-sonnet-20240229-v1:0"
  }
}
</Tab> <Tab title="Environment Variables" language="bash">
bash
# 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"
</Tab> <Tab title="ClientRegistry" language="typescript">
typescript
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'
});
</Tab> </Tabs>

IAM Permissions

Basic Permissions

The following IAM permissions are required for basic Bedrock access:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "arn:aws:bedrock:*:*:model/*"
    }
  ]
}

Additional Permissions

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>

Best Practices

  • Follow the principle of least privilege
  • Use resource-based policies when possible
  • Consider using AWS Organizations SCPs for enterprise-wide controls
  • Regularly audit IAM permissions using AWS IAM Access Analyzer

Configuration Options

BAML-specific request options

These 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.

<ParamField path="region" type="string"> The AWS region to use. **Default: `AWS_REGION` environment variable** </ParamField> <ParamField path="access_key_id" type="string"> AWS access key ID. **Default: `AWS_ACCESS_KEY_ID` environment variable** </ParamField> <ParamField path="secret_access_key" type="string"> AWS secret access key. **Default: `AWS_SECRET_ACCESS_KEY` environment variable** </ParamField> <ParamField path="session_token" type="string"> Temporary session token. Required if using temporary credentials. **Default: `AWS_SESSION_TOKEN` environment variable** </ParamField> <ParamField path="profile" type="string"> AWS profile name from credentials file. **Default: `AWS_PROFILE` environment variable** </ParamField> <ParamField path="endpoint_url" type="string"> AWS endpoint URL. Useful for using a VPC endpoint. </ParamField> <Markdown src="/snippets/role-selection.mdx" /> <Markdown src="/snippets/allowed-role-metadata-basic.mdx" /> <Markdown src="/snippets/supports-streaming.mdx" /> <Markdown src="/snippets/finish-reason.mdx" />

Modular API

  • b.request returns a fully signed SigV4 HTTPRequest pointing at the Converse API.
  • Forward the request as-is. Do not mutate the headers; they already include Authorization, X-Amz-Date, and (if needed) X-Amz-Security-Token.
  • Send the request immediately after building it. The signature is computed at request time, so rebuilding gives you a fresh signature.
  • Streaming modular calls are not yet supported for Bedrock.
typescript
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)
}
python
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)
<Markdown src="/snippets/media-url-handler.mdx" /> <Note> AWS Bedrock converts most media to base64 by default (`send_base64` for images, audio, and PDFs). Consider using S3 presigned URLs with `send_url` mode for large files to avoid base64 overhead. </Note>

Provider request parameters

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.
ModelDescription

Anthropic Claude (Latest Generation)

  • anthropic.claude-opus-4-1-20250805-v1:0 - Most powerful coding
  • anthropic.claude-sonnet-4-20250514-v1:0 - Best default, 1M context available
  • anthropic.claude-3-5-haiku-20241022-v1:0 - Fast and efficient

Meta Llama (Latest Generation)

  • meta.llama4-maverick-17b-instruct-v1:0 - Latest Llama 4
  • meta.llama3-3-70b-instruct-v1:0 - Enhanced Llama 3.3

Run 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).
baml
client<llm> MyClient {
  provider aws-bedrock
  options {
    inference_configuration {
      max_tokens 1000
      temperature 1.0
      top_p 0.8
    }
  }
}
</ParamField>

Troubleshooting

Common Errors

<Accordion title="AccessDeniedException"> ```json { "Error": "AccessDeniedException", "Message": "User is not authorized to perform: bedrock:InvokeModel" } ``` **Solution:** - Check IAM permissions - Verify execution role permissions in Lambda/ECS - Ensure credentials have Bedrock access </Accordion> <Accordion title="UnrecognizedClientException"> ```json { "Error": "UnrecognizedClientException", "Message": "The security token included in the request is invalid" } ``` **Solution:** - Verify credentials are set correctly - Check if session token is required and provided - Ensure credentials haven't expired </Accordion> <Accordion title="ValidationException (Region)"> ```json { "Error": "ValidationException", "Message": "Model is not supported in this Region" } ``` **Solution:** - Check model availability in your region - Request model access if needed - Consider using a different region </Accordion> <Accordion title="ValidationException (Model Access)"> ```json { "Error": "ValidationException", "Message": "Account is not authorized to use model" } ``` **Solution:** - Request model access through AWS Console - Wait for approval (1-2 business days) - Verify model ID is correct </Accordion>

Environment-Specific Setup

<Accordion title="Lambda"> - Set appropriate memory and timeout - Configure execution role with Bedrock permissions - Consider VPC endpoints for private subnets </Accordion> <Accordion title="ECS/EC2"> - Use task roles (ECS) or instance profiles (EC2) - Configure VPC endpoints if needed - Check security group outbound rules </Accordion> <Accordion title="Local Development"> - Set AWS credentials in environment or config files - Use `AWS_PROFILE` to manage multiple profiles - Run `aws configure list` to verify configuration </Accordion>