Skip to main content

AWS Bedrock Integration Guide (for repos with similar structure)

This guide shows what to change when moving from an OpenAI-style service to AWS Bedrock in a repo structured like:

  • asr_app/core/security.py
  • asr_app/services/openai_assessment_service.py

1) Environment and settings changes

.env additions

AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AWS_REGION=ap-south-1
BEDROCK_MODEL_ID=anthropic.claude-3-haiku-20240307-v1:0
# Optional only if your org uses bearer-token based gateway
AWS_BEARER_TOKEN_BEDROCK=your_bearer_token
BEDROCK_RUNTIME_ENDPOINT=https://bedrock-runtime.ap-south-1.amazonaws.com

asr_app/core/security.py additions

class Settings(BaseSettings):
...
AWS_ACCESS_KEY_ID: str
AWS_SECRET_ACCESS_KEY: str
AWS_REGION: str
AWS_BEARER_TOKEN_BEDROCK: str
BEDROCK_RUNTIME_ENDPOINT: Optional[str] = None
BEDROCK_MODEL_ID: Optional[str] = None

If you want IAM-only auth (recommended), make bearer token optional:

AWS_BEARER_TOKEN_BEDROCK: Optional[str] = None

2) Service-layer changes

Use Bedrock runtime endpoint and model id:

import os
import requests

AWS_REGION = os.getenv("AWS_REGION", "ap-south-1")
MODEL_ID = os.getenv("BEDROCK_MODEL_ID", "anthropic.claude-3-haiku-20240307-v1:0")
BEARER_TOKEN = os.getenv("AWS_BEARER_TOKEN_BEDROCK")

BEDROCK_ENDPOINT = (
f"https://bedrock-runtime.{AWS_REGION}.amazonaws.com/model/{MODEL_ID}/invoke"
)

Claude Messages request body for Bedrock:

body = {
"anthropic_version": "bedrock-2023-05-31",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": full_prompt}],
}
],
"max_tokens": 600,
"temperature": 0.7,
}

API call (your current bearer-token style):

headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {BEARER_TOKEN}",
}

response = requests.post(
BEDROCK_ENDPOINT,
headers=headers,
json=body,
timeout=30,
)
response.raise_for_status()
response_body = response.json()
content = response_body["content"][0]["text"]

If this is a standard AWS setup, prefer boto3 instead of raw requests + bearer token:

import boto3
import json
import os

AWS_REGION = os.getenv("AWS_REGION", "ap-south-1")
MODEL_ID = os.getenv("BEDROCK_MODEL_ID", "anthropic.claude-3-haiku-20240307-v1:0")

client = boto3.client("bedrock-runtime", region_name=AWS_REGION)

payload = {
"anthropic_version": "bedrock-2023-05-31",
"messages": [{"role": "user", "content": [{"type": "text", "text": full_prompt}]}],
"max_tokens": 600,
"temperature": 0.7,
}

resp = client.invoke_model(
modelId=MODEL_ID,
body=json.dumps(payload),
contentType="application/json",
accept="application/json",
)

result = json.loads(resp["body"].read())
content = result["content"][0]["text"]

4) OpenAI-to-Bedrock mapping checklist

  • Replace OpenAI client initialization with Bedrock runtime setup.
  • Replace OpenAI message schema with Bedrock Claude schema (anthropic_version + messages).
  • Replace OpenAI response parsing with Bedrock parsing (result["content"][0]["text"]).
  • Add Bedrock env vars to .env and settings model.
  • Verify timeout and error handling (requests.exceptions.RequestException or botocore.exceptions.ClientError).
  • Keep existing business prompt logic unchanged to reduce regression risk.

5) Drop-in function template

def generate_practice_content_by_bedrock(level: str, language: str, wrong_words: list) -> str:
try:
# 1) validate level and build prompt
# 2) call Bedrock
# 3) parse response content[0].text
# 4) clean output and return
return cleaned_text
except Exception as e:
return f"Error: {e}"

6) Validation steps after migration

  1. Run one request for each level: word, sentence, paragraph, story.
  2. Run with and without wrong_words.
  3. Confirm output parsing is stable and no extra metadata leaks to users.
  4. Confirm env loading works in local, staging, and production.
  5. Confirm the selected model is enabled in your AWS account/region.