etheric labs docs

Technical explorations and explanations

View the Project on GitHub

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.

About the AWS Bedrock service

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

Defining a foundation model

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 problem

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

Steps to reproduce

**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

2 Create a user group

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:

Click “Create user group”

3 Configure permissions for the 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

4 Create a user and generate an access key

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:

Click “Next” and enter more user details:

Click “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:

Click “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”

5 Create a new virtual machine for a development environment

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

6 Set up the development environment

Install and configure the AWS CLI utility

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

Configure the AWS CLI utility

Start the aws executable with the configure option

[you@dev ~]$ aws configure

Confirm 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

7 Create a gateway specifying the Amazon foundation model and an agent

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

8 Use the run_agent.py script and receive an error from Anthropic

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.

Expected outcome

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

Actual outcome

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.

Logs from the Python agent script

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

9 Tear down the cloud resources used for the demonstration

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.

Delete your development environment as well.

Responsible disclosure timeline

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

Resolution

The documentation has been updated.

The problem can only affect applications that