Technical explorations and explanations
Complexity affects everyone.
Services that provide complex capabilities are simultaneously a cost and a benefit to the integrator. Customers rely on supplier information and guidance to mitigate the risks.
While the risks can be difficult to identify and even harder to observe, the effects can be quite tangible.
AWS describe Bedrock as
The platform for building generative AI applications and agents at production scale
emphasising that
Organizations choose Amazon Bedrock to deliver personalized experiences, automate complex workflows, and uncover actionable insights—all in a comprehensive platform that lets teams innovate fast without compromising on security.
A chart summarises the “core capabilities you need for building production AI in one platform”, prioritising guardrails & policy checks, with the whole product underscored with “built-in security”.
The AWS documentation is necessarily not simple, covering
In one area of Bedrock functionality, AWS Bedrock agents, the integrator is required to consider how AWS have implemented agent collaboration, retrieval augmented generation, memory retention, code interpretation, orchestration and execution, along with open source agentic protocols and frameworks.
Other AWS products and services are needed to implement solutions based on Bedrock
Specific implementations commonly include further AWS products and services
With each layer and subdivision, the complexity is compounded
Customers specify which foundation model an AWS Bedrock gateway will integrate with.
Gateways are created with Python code, and AWS provide an example of how to do this https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-quick-start.html
The provided code defines the model clearly:
# Model configuration - change if needed
model_id = "anthropic.claude-3-7-sonnet-20250219-v1:0"
It’s clear how to implement a gateway that uses a different model:
# Model configuration - change if needed
model_id = "amazon.titan-text-lite-v1"
**The current, updated documentation has corrected the problem. Customers using the provided script verbatim will not be affected.**
When the model_id is not set, an Anthropic model is chosen by default.
The use of a default Anthropic model is revealed when no use case details form has been submitted to Anthropic, as an error is generated.
No error is generated by Anthropic where a use case details form has been submitted.
**Reproduction depends on a line which has been corrected in the provided script.**
Assuming that you don’t already have use case details form with Anthropic, here’s how you can reproduce the issue for yourself.
Ensure that you are authenticating in one of the two regions recommended for Bedrock
US-East-1 was used for this demonstration
Authenticate at the regional AWS web console with root user credentials
Choose the Identity and access management dashboard
From the left navigation, in the access management section select User groups
Click Create group and enter new group details:
bedrock-usersAmazonBedrockFullAccessClick “Create user group”
Click “bedrock-users” Click “Permissions” Click “Add permissions” Click “Create inline policy” In the Policy editor section, select “JSON” and update the generated JSON in the editor with the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"bedrock-agentcore:*",
"cognito-idp:*",
"iam:*",
"lambda:*"
],
"Resource": [
"*"
]
}
]
}
Click “Next”
Enter a policy name: bedrock-gateway-demo
Click “Create policy”
Confirm that the user group provides two policies
Generate and record a password
sdfaFDHJ7844
From the left navigation, in the Access management section select “Users”
Click “Create user” and enter details for the new user:
bedrockYesYour strong passwordNoClick “Next” and enter more user details:
Add user to groupbedrock-usersClick “Next”
Click “Create user”
Click “Return to user list”
A warning about viewing the password is shown
Click “Continue”
At the Users list, click the bedrock user name
Click “Create access key” and enter your use case:
[x]Command Line Interface (CLI)YesClick “Next”
Click “Create access key”
Copy and record the access key value
Copy and record the secret access key value
Click “Done”
A warning about downloading the secret key is shown
Click “Continue”
Anything that lets you run Python and the AWS CLI utility will do.
I used Google Cloud Platform to create a new Compute Engine instance in Northern Virginia running CentOS, configured as follows:
| Configuration | Values |
| ————- | ——————————————————————————————————————————————————— |
| Instance | Name: bedrock
Region: us-east4 (Northern Virginia)
Zone: us-east4-a
Type: General purpose E2 e2-standard-4 (4 vCPU, 2 core, 16Gb memory) |
| OS | Operating system: CentOS
Version: CentOS Stream 10
Boot disk type: Balanced persistent disk
Size (Gb): 20 |
| Protection | Backups: No backups |
| Networking | Leave at defaults |
| Observability | Leave at defaults |
| Security | Manage access > Add manually generated SSH keys
Add item: Paste your public key |
| Advanced | Leave at defaults |
When the virtual machine is available, start a terminal session
Install unzip
[you@dev ~]$ sudo dnf -y install unzip
Create and activate a new Python virtual environment
[you@dev ~]$ python -m venv bedrock && source bedrock/bin/activate
Record the public key supplied by AWS for verification of the AWS CLI utility installer
[you@dev ~]$ cat << EOF > awscli-exe-linux-x86_64.zip.pub
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF2Cr7UBEADJZHcgusOJl7ENSyumXh85z0TRV0xJorM2B/JL0kHOyigQluUG
ZMLhENaG0bYatdrKP+3H91lvK050pXwnO/R7fB/FSTouki4ciIx5OuLlnJZIxSzx
PqGl0mkxImLNbGWoi6Lto0LYxqHN2iQtzlwTVmq9733zd3XfcXrZ3+LblHAgEt5G
TfNxEKJ8soPLyWmwDH6HWCnjZ/aIQRBTIQ05uVeEoYxSh6wOai7ss/KveoSNBbYz
gbdzoqI2Y8cgH2nbfgp3DSasaLZEdCSsIsK1u05CinE7k2qZ7KgKAUIcT/cR/grk
C6VwsnDU0OUCideXcQ8WeHutqvgZH1JgKDbznoIzeQHJD238GEu+eKhRHcz8/jeG
94zkcgJOz3KbZGYMiTh277Fvj9zzvZsbMBCedV1BTg3TqgvdX4bdkhf5cH+7NtWO
lrFj6UwAsGukBTAOxC0l/dnSmZhJ7Z1KmEWilro/gOrjtOxqRQutlIqG22TaqoPG
fYVN+en3Zwbt97kcgZDwqbuykNt64oZWc4XKCa3mprEGC3IbJTBFqglXmZ7l9ywG
EEUJYOlb2XrSuPWml39beWdKM8kzr1OjnlOm6+lpTRCBfo0wa9F8YZRhHPAkwKkX
XDeOGpWRj4ohOx0d2GWkyV5xyN14p2tQOCdOODmz80yUTgRpPVQUtOEhXQARAQAB
tCFBV1MgQ0xJIFRlYW0gPGF3cy1jbGlAYW1hem9uLmNvbT6JAlQEEwEIAD4CGwMF
CwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQT7Xbd/1cEYuAURraimMQrMRnJHXAUC
aGveYQUJDMpiLAAKCRCmMQrMRnJHXKBYD/9Ab0qQdGiO5hObchG8xh8Rpb4Mjyf6
0JrVo6m8GNjNj6BHkSc8fuTQJ/FaEhaQxj3pjZ3GXPrXjIIVChmICLlFuRXYzrXc
Pw0lniybypsZEVai5kO0tCNBCCFuMN9RsmmRG8mf7lC4FSTbUDmxG/QlYK+0IV/l
uJkzxWa+rySkdpm0JdqumjegNRgObdXHAQDWlubWQHWyZyIQ2B4U7AxqSpcdJp6I
S4Zds4wVLd1WE5pquYQ8vS2cNlDm4QNg8wTj58e3lKN47hXHMIb6CHxRnb947oJa
pg189LLPR5koh+EorNkA1wu5mAJtJvy5YMsppy2y/kIjp3lyY6AmPT1posgGk70Z
CmToEZ5rbd7ARExtlh76A0cabMDFlEHDIK8RNUOSRr7L64+KxOUegKBfQHb9dADY
qqiKqpCbKgvtWlds909Ms74JBgr2KwZCSY1HaOxnIr4CY43QRqAq5YHOay/mU+6w
hhmdF18vpyK0vfkvvGresWtSXbag7Hkt3XjaEw76BzxQH21EBDqU8WJVjHgU6ru+
DJTs+SxgJbaT3hb/vyjlw0lK+hFfhWKRwgOXH8vqducF95NRSUxtS4fpqxWVaw3Q
V2OWSjbne99A5EPEySzryFTKbMGwaTlAwMCwYevt4YT6eb7NmFhTx0Fis4TalUs+
j+c7Kg92pDx2uQ==
=OBAt
-----END PGP PUBLIC KEY BLOCK-----
EOF
Import the public key
[you@dev ~]$ gpg --import awscli-exe-linux-x86_64.zip.pub
Download the installer and installer signature files
[you@dev ~]$ curl --silent --remote-name "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"
[you@dev ~]$ curl --silent --remote-name "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip.sig"
Verify, decompress and run the installer
[you@dev ~]$ gpg --verify awscli-exe-linux-x86_64.zip.sig awscli-exe-linux-x86_64.zip
[you@dev ~]$ unzip -q awscli-exe-linux-x86_64.zip
[you@dev ~]$ sudo aws/install
Confirm the AWS CLI utility installation
[you@dev ~]$ aws --version
Expect to see version information
aws-cli/2.34.0 Python/3.13.11 Linux/6.12.0-201.el10.x86_64 exe/x86_64.centos.10
Start the aws executable with the configure option
[you@dev ~]$ aws configure
bedrock user access key value recorded earlierbedrock user secret access key value recorded earlierus-east-1jsonConfirm the AWS CLI utility configuration is correct by requesting a list of available foundation models
[you@dev ~]$ aws bedrock list-foundation-models
Expect to see a JSON representation of available foundation models
Following the instructions in the AWS Bedrock gateway workshop, a gateway is provisioned using a Python script
Install the requirements that the gateway provisioning script will need
[you@dev ~]$ pip install boto3 bedrock-agentcore-starter-toolkit strands-agents
Create the gateway provisioning script
[you@dev ~]$ cat << EOF > create_gateway.py
from bedrock_agentcore_starter_toolkit.operations.gateway.client import GatewayClient
import json
import logging
import time
region = 'us-east-1'
def createGateway():
print( 'Creating gateway' )
client = GatewayClient( region_name=region )
print( '- Creating an OAuth authorizer to provide a client identifier and secret' )
cognito_response = client.create_oauth_authorizer_with_cognito( "TestGateway" )
print( '- Creating a gateway with MCP support, OAuth authorisation and semantic search' )
gateway = client.create_mcp_gateway(
name=None,
role_arn=None,
authorizer_config=cognito_response["authorizer_config"],
enable_semantic_search=True
)
print( 'Fixing IAM permissions (30s)' )
client.fix_iam_permissions(gateway)
time.sleep(30)
print( '- Creating lambda target with get_weather and get_time tools, then register it as a target in the gateway' )
lambda_target = client.create_mcp_gateway_target(
gateway=gateway,
name=None,
target_type="lambda",
target_payload=None,
credentials=None
)
print( 'Dumping configuration file for agents to adopt' )
config = {
"gateway_url": gateway["gatewayUrl"],
"gateway_id": gateway["gatewayId"],
"region": region,
"client_info": cognito_response["client_info"]
}
with open( "/tmp/gateway_configuration.json", "w") as f:
json.dump(config, f, indent=2)
print( 'Wrote gateway configuration to /tmp/gateway_configuration.json' )
return config
if __name__ == "__main__":
createGateway()
EOF
Run the gateway provisioning script and expect it to take a while
[you@dev ~]$ python create_gateway.py
Confirm that the gateway provisioning script ran as expected by checking the generated gateway configuration file intended to be used by agents
[you@dev ~]$ cat /tmp/gateway_configuration.json
Create a Python script to provision an agent with access to the gateway, specifying that the agent will use the amazon.titan-text-lite-v1 foundation model
**The provided script has now been corrected.**
[you@dev ~]$ cat << EOF > run_agent.py
from strands import Agent
from strands.models import BedrockModel
from strands.tools.mcp.mcp_client import MCPClient
from mcp.client.streamable_http import streamablehttp_client
from bedrock_agentcore_starter_toolkit.operations.gateway.client import GatewayClient
import json
import sys
def create_streamable_http_transport(mcp_url: str, access_token: str):
return streamablehttp_client(mcp_url, headers={"Authorization": f"Bearer {access_token}"})
def get_full_tools_list(client):
"""Get all tools with pagination support"""
more_tools = True
tools = []
pagination_token = None
while more_tools:
tmp_tools = client.list_tools_sync(pagination_token=pagination_token)
tools.extend(tmp_tools)
if tmp_tools.pagination_token is None:
more_tools = False
else:
more_tools = True
pagination_token = tmp_tools.pagination_token
return tools
def run_agent():
# Load configuration
try:
with open("/tmp/gateway_configuration.json", "r") as f:
config = json.load(f)
except FileNotFoundError:
print("Error: gateway_config.json not found!")
print("Please run 'python setup_gateway.py' first to create the Gateway.")
sys.exit(1)
gateway_url = config["gateway_url"]
client_info = config["client_info"]
# Get access token for the agent
print("Getting access token...")
client = GatewayClient(region_name=config["region"])
access_token = client.get_access_token_for_cognito(client_info)
print("Access token obtained\n")
# Model configuration - change if needed
model_id = "amazon.titan-text-lite-v1"
print("Starting AgentCore Gateway Test Agent")
print(f"Gateway URL: {gateway_url}")
print(f"Model: {model_id}")
print("-" * 60)
# Setup Bedrock model
bedrockmodel = BedrockModel(
inference_profile_id=model_id,
streaming=True,
)
# Setup MCP client
mcp_client = MCPClient(lambda: create_streamable_http_transport(gateway_url, access_token))
with mcp_client:
# List available tools
tools = get_full_tools_list(mcp_client)
print(f"\nAvailable tools: {[tool.tool_name for tool in tools]}")
print("-" * 60)
# Create agent
agent = Agent(model=bedrockmodel, tools=tools)
# Interactive loop
print("\nInteractive Agent Ready!")
print("Try asking: 'What's the weather in Seattle?'")
print("Type 'exit', 'quit', or 'bye' to end.\n")
while True:
user_input = input("You: ")
if user_input.lower() in ["exit", "quit", "bye"]:
print("Goodbye!")
break
print("\nThinking...\n")
response = agent(user_input)
print(f"\nAgent: {response.message.get('content', response)}\n")
if __name__ == "__main__":
run_agent()
EOF
The provided script now corrects the variable name, replacing this line `inference_profile_id=model_id` with this `model_id=model_id`
[you@dev ~]$ cat << EOF > run_agent.py
from strands import Agent
from strands.models import BedrockModel
from strands.tools.mcp.mcp_client import MCPClient
from mcp.client.streamable_http import streamablehttp_client
from bedrock_agentcore_starter_toolkit.operations.gateway.client import GatewayClient
import json
import sys
def create_streamable_http_transport(mcp_url: str, access_token: str):
return streamablehttp_client(mcp_url, headers={"Authorization": f"Bearer {access_token}"})
def get_full_tools_list(client):
"""Get all tools with pagination support"""
more_tools = True
tools = []
pagination_token = None
while more_tools:
tmp_tools = client.list_tools_sync(pagination_token=pagination_token)
tools.extend(tmp_tools)
if tmp_tools.pagination_token is None:
more_tools = False
else:
more_tools = True
pagination_token = tmp_tools.pagination_token
return tools
def run_agent():
# Load configuration
try:
with open("/tmp/gateway_configuration.json", "r") as f:
config = json.load(f)
except FileNotFoundError:
print("Error: gateway_config.json not found!")
print("Please run 'python setup_gateway.py' first to create the Gateway.")
sys.exit(1)
gateway_url = config["gateway_url"]
client_info = config["client_info"]
# Get access token for the agent
print("Getting access token...")
client = GatewayClient(region_name=config["region"])
access_token = client.get_access_token_for_cognito(client_info)
print("Access token obtained\n")
# Model configuration - change if needed
model_id = "amazon.titan-text-lite-v1"
print("Starting AgentCore Gateway Test Agent")
print(f"Gateway URL: {gateway_url}")
print(f"Model: {model_id}")
print("-" * 60)
# Setup Bedrock model
bedrockmodel = BedrockModel(
model_id=model_id,
streaming=True,
)
# Setup MCP client
mcp_client = MCPClient(lambda: create_streamable_http_transport(gateway_url, access_token))
with mcp_client:
# List available tools
tools = get_full_tools_list(mcp_client)
print(f"\nAvailable tools: {[tool.tool_name for tool in tools]}")
print("-" * 60)
# Create agent
agent = Agent(model=bedrockmodel, tools=tools)
# Interactive loop
print("\nInteractive Agent Ready!")
print("Try asking: 'What's the weather in Seattle?'")
print("Type 'exit', 'quit', or 'bye' to end.\n")
while True:
user_input = input("You: ")
if user_input.lower() in ["exit", "quit", "bye"]:
print("Goodbye!")
break
print("\nThinking...\n")
response = agent(user_input)
print(f"\nAgent: {response.message.get('content', response)}\n")
if __name__ == "__main__":
run_agent()
EOF
Run the Python script to create and run the agent
[you@dev ~]$ python run_agent.py
When the agent is ready, ask it about the weather in Seattle.
The agent uses the amazon.titan-text-lite-v1 foundation model to respond to the prompt with data from the weather lambda function through the gateway
Strands-agents defines a default which is adopted when a value is not supplied by the implementer
https://github.com/strands-agents/sdk-python/blob/31f1e649320b71686eb86fb8ee61aaf534bab06b/src/strands/models/bedrock.py#L38
When no value is provided, Strands defaults to the us.anthropic.claude-sonnet-4-20250514-v1:0 foundation model and the attempt fails because a use case details form has not been submitted to Anthropic
Model use case details have not been submitted for this account. Fill out the Anthropic use case details form before using the model. If you have already filled out the form, try again in 15 minutes.
botocore.errorfactory.ResourceNotFoundException: An error occurred (ResourceNotFoundException) when calling the ConverseStream operation: Model use case details have not been submitted for this account. Fill out the Anthropic use case details form before using the model. If you have already filled out the form, try again in 15 minutes.
└ Bedrock region: us-east-1
└ Model id: us.anthropic.claude-sonnet-4-20250514-v1:0
You’ll need to delete the AWS Bedrock Agentcore gateway target, the AWS Bedrock Agentcore gateway, the AWS Cognito user pool, the AWS User bedrock and access key and then the AWS User group bedrock-users.
bedrock user namebedrock-users group namebedrock-users to confirm group deletionDelete your development environment as well.
All communication was conducted through the HackerOne platform for responsible disclosure
2025-11-20 Initial report to HackerOne
2025-11-25 HackerOne verify and escalate the report to AWS
2025-11-28 AWS acknowledge the report
2026-02-20 AWS updated the agent script in the documentation
2026-03-05 AWS helped to improve this write up
The documentation has been updated.
The problem can only affect applications that