Introduction
In this tutorial, you'll learn how to create and deploy a stateful agent using Amazon Bedrock's new Stateful Runtime Environment. This technology enables persistent orchestration and memory for multi-step AI workflows, allowing agents to maintain context across interactions. We'll build a simple customer service agent that can remember conversation history and provide personalized responses.
Prerequisites
- Amazon Web Services (AWS) account with appropriate permissions
- AWS CLI installed and configured
- Python 3.8 or higher
- Boto3 library installed (
pip install boto3) - Basic understanding of AWS Bedrock and AI agents
Step 1: Set Up Your AWS Environment
1.1 Create Required IAM Role
First, we need to create an IAM role that grants Bedrock access to execute our agent. This role will have the necessary permissions to interact with Bedrock and other AWS services.
aws iam create-role \
--role-name BedrockAgentRole \
--assume-role-policy-document file://trust-policy.json
The trust policy allows Bedrock to assume this role. You'll need to create a file called trust-policy.json with the following content:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "bedrock.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
1.2 Attach Required Policies
Next, attach the necessary policies to your role to allow Bedrock to execute agents:
aws iam attach-role-policy \
--role-name BedrockAgentRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSBedrockExecutionRoleForAgents
Step 2: Create Your Stateful Agent
2.1 Define Agent Configuration
We'll create a basic agent configuration that includes state management capabilities:
import boto3
import json
bedrock_agent = boto3.client('bedrock-agent')
agent_config = {
"agentName": "CustomerServiceAgent",
"agentResourceRoleArn": "arn:aws:iam::YOUR_ACCOUNT:role/BedrockAgentRole",
"autoPrepare": True,
"idleSessionTTLInSeconds": 3600,
"description": "Stateful customer service agent with memory",
"statefulRuntime": True,
"guardrailConfiguration": {
"guardrailId": "YOUR_GUARDRAIL_ID",
"guardrailVersion": "DRAFT"
}
}
response = bedrock_agent.create_agent(**agent_config)
print(json.dumps(response, indent=2, default=str))
The key parameter here is statefulRuntime: True, which enables the persistent memory capabilities for your agent.
2.2 Create Agent Prompt
Define the agent's behavior and personality through a prompt template:
prompt_template = {
"name": "CustomerServicePrompt",
"content": "You are a helpful customer service agent. Remember previous conversations and provide personalized responses. Current conversation context: {context}"
}
response = bedrock_agent.create_prompt(
agentId=response['agent']['agentId'],
promptTemplate=prompt_template
)
Step 3: Implement State Management
3.1 Create Knowledge Base
Set up a knowledge base to store customer information and service history:
knowledge_base_config = {
"name": "CustomerKnowledgeBase",
"description": "Stores customer information and service history",
"roleArn": "arn:aws:iam::YOUR_ACCOUNT:role/BedrockAgentRole",
"vectorStore": {
"pinecone": {
"serverless": True,
"region": "us-east-1"
}
}
}
response = bedrock_agent.create_knowledge_base(**knowledge_base_config)
print(json.dumps(response, indent=2, default=str))
This knowledge base will help maintain state by storing conversation history and customer preferences.
3.2 Implement Conversation Memory
Create a simple memory management system for your agent:
def store_conversation_state(agent_id, session_id, conversation_history):
# Store conversation state in DynamoDB or similar
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('AgentConversationMemory')
table.put_item(
Item={
'agentId': agent_id,
'sessionId': session_id,
'conversationHistory': conversation_history,
'lastUpdated': datetime.utcnow().isoformat()
}
)
def retrieve_conversation_state(agent_id, session_id):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('AgentConversationMemory')
response = table.get_item(
Key={
'agentId': agent_id,
'sessionId': session_id
}
)
return response.get('Item', {}).get('conversationHistory', [])
Step 4: Deploy and Test Your Agent
4.1 Prepare Agent for Deployment
Before deployment, we need to prepare the agent with all necessary components:
prepare_response = bedrock_agent.prepare_agent(
agentId=response['agent']['agentId']
)
print(json.dumps(prepare_response, indent=2, default=str))
This step ensures all components are ready for execution and that the stateful runtime environment is properly configured.
4.2 Test Agent Interaction
Test your stateful agent with a sample conversation:
def test_agent_interaction(agent_id, session_id, user_input):
# Send user input to agent
response = bedrock_agent.invoke_agent(
agentId=agent_id,
agentAliasId='DRAFT',
sessionId=session_id,
inputText=user_input
)
# Process the response
if 'output' in response:
print(f"Agent Response: {response['output']['text']}")
# Update conversation state
conversation_history = retrieve_conversation_state(agent_id, session_id)
conversation_history.append({
'user': user_input,
'agent': response['output']['text'],
'timestamp': datetime.utcnow().isoformat()
})
store_conversation_state(agent_id, session_id, conversation_history)
return response
# Test with sample interaction
session_id = 'session-12345'
test_agent_interaction(response['agent']['agentId'], session_id, "Hello, I need help with my order")
This demonstrates how the agent maintains state between interactions, remembering previous conversation context.
Step 5: Monitor and Optimize
5.1 Set Up Monitoring
Implement monitoring to track agent performance and state management:
import boto3
import time
def monitor_agent_performance(agent_id):
cloudwatch = boto3.client('cloudwatch')
# Get agent metrics
response = cloudwatch.get_metric_statistics(
Namespace='AWS/Bedrock',
MetricName='AgentInvocations',
StartTime=datetime.utcnow() - timedelta(hours=1),
EndTime=datetime.utcnow(),
Period=300,
Statistics=['Sum', 'Average'],
Dimensions=[{
'Name': 'AgentId',
'Value': agent_id
}]
)
return response
5.2 Optimize State Management
Optimize your state management to prevent memory bloat:
def optimize_conversation_memory(conversation_history, max_length=10):
# Keep only the most recent interactions
if len(conversation_history) > max_length:
return conversation_history[-max_length:]
return conversation_history
This optimization ensures your agent doesn't consume excessive memory while maintaining useful context.
Summary
In this tutorial, you've learned how to create a stateful agent using Amazon Bedrock's new runtime environment. You've set up the required IAM permissions, configured agent state management, and implemented conversation memory. The key advantages of this approach include persistent context across interactions, secure execution, and the ability to maintain long-term conversation state. This foundation allows you to build sophisticated multi-step AI workflows that can remember and respond to user needs across multiple interactions.
Remember to monitor your agent's performance and optimize state management as your agent scales to ensure optimal performance and cost efficiency.



