🧠 All Things AI
Intermediate

Python SDK (boto3)

boto3 is the AWS SDK for Python. It's the standard way to interact with Bedrock programmatically. This page covers the setup, auth pattern, and the most common Bedrock operations you'll use in production code.

Install

pip install boto3
# or for latest Bedrock features:
pip install "boto3>=1.34.0"

Authentication

boto3 uses the standard AWS credentials chain — it looks for credentials in this order:

  1. 1. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
  2. 2. AWS credentials file (~/.aws/credentials)
  3. 3. IAM role attached to the compute (EC2, Lambda, ECS task role, etc.)
  4. 4. AWS SSO / IAM Identity Center

In production on AWS, always use IAM roles (option 3) — no credentials in environment variables or config files. For local development, use aws configure to set up a credentials file, or use named profiles for multiple accounts.

Required IAM permissions

Your role needs bedrock:InvokeModel and/or bedrock:InvokeModelWithResponseStreamon the specific model ARNs you use. For Converse: bedrock:Converse andbedrock:ConverseStream. Scope to specific models via ARN conditions for least-privilege.

Standard Converse Pattern

import boto3

client = boto3.client("bedrock-runtime", region_name="us-east-1")

def call_model(user_message: str, system_prompt: str = "") -> str:
    messages = [{"role": "user", "content": [{"text": user_message}]}]
    kwargs = {
        "modelId": "anthropic.claude-sonnet-4-5",
        "messages": messages,
        "inferenceConfig": {"maxTokens": 1024, "temperature": 0.3},
    }
    if system_prompt:
        kwargs["system"] = [{"text": system_prompt}]

    response = client.converse(**kwargs)
    return response["output"]["message"]["content"][0]["text"]

result = call_model(
    user_message="Summarise the key risks in three bullet points.",
    system_prompt="You are a risk analyst. Be concise.",
)
print(result)

Streaming

def stream_response(user_message: str) -> None:
    response = client.converse_stream(
        modelId="anthropic.claude-sonnet-4-5",
        messages=[{"role": "user", "content": [{"text": user_message}]}],
        inferenceConfig={"maxTokens": 1024},
    )
    for event in response["stream"]:
        if "contentBlockDelta" in event:
            delta = event["contentBlockDelta"]["delta"]
            if "text" in delta:
                print(delta["text"], end="", flush=True)
    print()  # newline after stream ends

Tool Use (Function Calling)

tools = [
    {
        "toolSpec": {
            "name": "get_stock_price",
            "description": "Get the current stock price for a ticker symbol",
            "inputSchema": {
                "json": {
                    "type": "object",
                    "properties": {
                        "ticker": {"type": "string", "description": "Stock ticker, e.g. AMZN"}
                    },
                    "required": ["ticker"],
                }
            },
        }
    }
]

response = client.converse(
    modelId="anthropic.claude-sonnet-4-5",
    messages=[{"role": "user", "content": [{"text": "What is Amazon's stock price?"}]}],
    toolConfig={"tools": tools},
)

# If the model calls a tool:
if response["stopReason"] == "tool_use":
    tool_use_block = next(
        b for b in response["output"]["message"]["content"] if "toolUse" in b
    )
    tool_name = tool_use_block["toolUse"]["name"]
    tool_input = tool_use_block["toolUse"]["input"]
    print(f"Model wants to call: {tool_name}({tool_input})")

Multi-Turn Conversations

Bedrock does not store conversation history — you send the full history on every call. Maintain a messages list and append each turn:

history = []

def chat(user_input: str) -> str:
    history.append({"role": "user", "content": [{"text": user_input}]})
    response = client.converse(
        modelId="anthropic.claude-sonnet-4-5",
        messages=history,
        inferenceConfig={"maxTokens": 512},
    )
    assistant_msg = response["output"]["message"]
    history.append(assistant_msg)
    return assistant_msg["content"][0]["text"]

Checklist: Do You Understand This?

  • What is the recommended authentication method for boto3 on AWS compute?
  • What IAM permissions does your role need to call Converse?
  • Can you write a streaming Converse call that prints tokens as they arrive?
  • How do you handle multi-turn conversations when Bedrock doesn't store history?