Amazon Bedrock Agents are conversational AI applications that extend the capabilities of Large Language Models (LLMs) by enabling them to understand multi-step user requests and orchestrate actions across different systems. They act as intelligent intermediaries, breaking down complex tasks, reasoning about the required steps, maintaining conversation context, and using defined tools to interact with external services to fulfill user goals.
You can leverage Bedrock Agents extensively for AWS operations by integrating them with AWS services via Action Groups linked to tools like Lambda functions or APIs. This allows agents to perform automated resource management tasks, such as listing EC2 instances, enumerating S3 buckets, or creating new servers based on natural language commands. They can also retrieve operational information for troubleshooting or provide a simplified, conversational interface for users to interact with and manage AWS resources without needing deep technical expertise or direct console access.
An action group defines actions that the agent can help the user perform. For example, listing EC2 servers. You define the parameters and information that the agent must elicit from the user for each action in the action group to be carried out. You also decide how the agent handles the parameters and information it receives from the user and where it sends the information it elicits from the user. Knowledge bases can also be configured optionally.
This article will guide you through setting up a Bedrock Agent with Action Groups and then building a custom web application around it. We will create and integrate AWS Lambda functions that allow the agent to:
- List existing EC2 instances
- List existing S3 buckets
- Create a new EC2 instance with specified parameters
This demonstrates how you can leverage large language models (LLMs) orchestrated by Bedrock Agents to perform actions in your AWS account based on natural language commands, and then provide a user-friendly interface for those actions.
Prerequisites
To follow along with this tutorial, you will need:
- AWS Account: An active AWS account with necessary permissions to create and manage Bedrock Agents, IAM roles, Lambda functions, EC2 instances, and view S3 buckets
- Amazon Bedrock Access: Ensure Amazon Bedrock is enabled in your account and the AWS region you plan to use
- Bedrock Model Access: You need access to a supported model for Bedrock Agents, such as Anthropic Claude. Follow the steps in the Bedrock console under "Model access" to enable this
Step 1: Enable Bedrock Model Access
Under the Amazon Bedrock console, go to "Model access" (bottom left). Click "Modify access," select the Anthropic Claude Sonnet 3.5 models, and submit.
Note: If you are in India, your payment mode should be invoice-based, not card-based, to avoid errors about an invalid payment mode.
After a few minutes, you will get access, and these models will become active in your console.
Step 2: Create AWS Lambda Functions
We will create three Lambda functions. Each function performs a specific AWS task and returns the result in a format Bedrock Agents expect. Deploy these functions in the same AWS region where you configure your Bedrock Agent.
You can find the complete Python code for these functions in the following GitHub repository:
https://github.com/sauveerk/projects/tree/main/Code/Gen-AI-Bedrock-Agents
Lambda Function 1: List EC2 Instances
- This function,
action_group_ec2
, lists the IDs of all EC2 instances in the current region -
IAM Permissions Needed:
ec2:DescribeInstances
Lambda Function 2: List S3 Buckets
- This function,
action_group_s3
, lists the S3 buckets -
IAM Permissions Needed:
s3:ListBuckets
Lambda Function 3: Create EC2 Instance
- This function,
action_group_create_ec2
, creates an EC2 server. It takes the instance type and region as parameters -
IAM Permissions Needed:
ec2:RunInstances
,ec2:DescribeInstances
Step 3: Create Bedrock Agent and Action Groups
In the Bedrock console, navigate to "Agents" under "Builder Tools." Click "Create agent." Give your agent a name and a description (e.g., "AWS Resource Manager Agent").
After the agent is created, click on it and select "Edit" in the Agent Builder.
Select "Create and use a new service role" and define instructions for the agent. This prompt guides the agent's behavior. Something like:
You are an AI assistant that can help users manage their AWS resources. You can list EC2 instances, list S3 buckets, and create new EC2 instances.
Under the "Action Groups" section, click "Add." Give the action group a name (e.g., Ec2ManagementActions
). Provide a description (e.g., "Actions for managing EC2 resources"). Under "Action group invocation," select "Define with Function details."
Select "Quick create a new Lambda function." This will create a Lambda function and add a resource-based policy to it so that it can be invoked by the Bedrock agent. Provide the function name and description. No parameters are required for this function as it only lists EC2 instances.
You can select "Enable confirmation of action group function" here. The agent will ask for confirmation before proceeding with the invocation. It is disabled by default. Click save to create the action group.
Click on the action group again. You can see the newly created Lambda function. Click "View," which will take you to the Lambda console. Copy the code from the GitHub repo given above and paste it into the function, then deploy it.
Go to the Lambda function configuration, increase the timeout duration. Then, go to the "Permissions" section and add additional permissions to the role being used by the Lambda function. In this case, it is ec2:DescribeInstances
.
Now the Lambda function is ready. You can test it by giving a test event in the appropriate format:
{
"messageVersion": "1.0",
"function": "bedrock-agent-list-ec2",
"inputText": "",
"sessionId": "888900372248953",
"agent": {
"name": "agent-aws-resources",
"version": "DRAFT",
"id": "VGGUJUPSEC",
"alias": "TSTALIASID"
},
"actionGroup": "action_group_ec2",
"sessionAttributes": {},
"promptSessionAttributes": {}
}
Follow similar steps to add the other two action groups. For the EC2 create function, remember to add the parameters also.
Save the agent in the agent builder.
Step 4: Test the Bedrock Agent
Once your agent is created, you can test its ability to invoke your Lambda functions from the Bedrock console. On the agent details page, click the "Prepare" button. This compiles the agent configuration. Wait for the status to show "Prepared." Click the Prepare button after configuring the agent.
Stay on the agent details page and use the "Test" panel on the right. Because we enabled confirmation for these action groups, it will decide which action groups to use and then ask us for confirmation. Confirm these.
After invoking these two action groups and corresponding Lambda functions, the agent returns the response.
If you click on "Show trace," you can see the thought process and steps used by the agent. It shows two trace steps, which you can expand to see the details.
Let's take it one step further. Prompt to create an EC2 instance:
Create a t2.nano EC2 instance in ap-south-1 region.
In the AWS console, you can also see the same instance ID and IP address.
In the trace, we can see how the agent has identified the correct action group and invoked it.
As I had provided all required parameters in the prompt, it was able to directly invoke the third Lambda. Otherwise, it will ask for parameters. Let's try that by giving the prompt: "create an ec2 server."
Part 2 — Agentic AI Web App for End Users
The article above outlined how to create a powerful agent that can manage AWS resources using natural language. If we want to use this for regular use, for example by operations teams, we can create a web app around it with a nice web interface. This allows users to interact with the agent without needing to access the Bedrock console.
In this section, we will create a simple web app around our agent. The full app code is present here, and it can be cloned:
https://github.com/sauveerk/projects/tree/main/Code/WebApp-Bedrock-Agent
Step 1: Modify Action Group Behavior and Create Agent Alias
We had enabled the confirmation to test the behavior of our agent by selecting "Enable confirmation of action group function" for action groups that list S3 and EC2 servers. Let's disable this to simplify our web app code.
Go to the action group that lists EC2 servers. Check the "disabled" button and click save. Verify that this is also disabled for other action groups. Save the agent and prepare it.
To use the agent programmatically, we need to create an alias. On the agent page, under the "Alias" section, click "Create." Give it a name and keep the default choice — "Create a new version and associate it to this alias." Click on "Create alias."
Click on the newly created alias, and it will open the alias page. Use the "Test" button to verify that you are not being asked for confirmation.
Step 2: Python Program
This is the Python code using which we can invoke our model programmatically:
import boto3
import json
from botocore.exceptions import ClientError
from typing import Optional, Dict, Any
import uuid
def invoke_bedrock_agent(prompt: str) -> Optional[Dict[Any, Any]]:
"""
Invoke a Bedrock agent with the given prompt.
Args:
prompt (str): The prompt to send to the agent
Returns:
Optional[Dict]: The agent's response or None if an error occurs
"""
try:
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime')
except Exception as e:
print(f"Error creating Bedrock client: {str(e)}")
return None
if not prompt or not isinstance(prompt, str):
print("Error: Prompt must be a non-empty string")
return None
try:
session_id = str(uuid.uuid4())
response = bedrock_agent_runtime.invoke_agent(
agentId='<YOUR_AGENT_ID>',
agentAliasId='<YOUR_AGENT_ALIAS_ID>',
sessionId=session_id,
inputText=prompt
)
# Handle the event stream response
full_response = ""
for event in response['completion']:
if 'chunk' in event:
chunk_data = event['chunk']['bytes'].decode('utf-8')
full_response += chunk_data
# Parse the complete response if needed
if full_response:
try:
return json.loads(full_response)
except json.JSONDecodeError:
# If response is not JSON, return as plain text
return {"response": full_response}
else:
print("Error: Empty response from Bedrock Agent")
return None
except ClientError as e:
print(f"AWS API Error: {str(e)}")
return None
except Exception as e:
print(f"Unexpected error: {str(e)}")
return None
def main():
prompt = input("Enter your prompt: ")
response = invoke_bedrock_agent(prompt)
if response:
print("Agent Response:")
if isinstance(response, dict):
print(json.dumps(response, indent=2))
else:
print(response)
else:
print("Failed to get response from agent")
if __name__ == "__main__":
main()
Let's test the program. We can see that it responds correctly.
Step 3: Create Python Flask Web App
Use this project structure:
your_project_directory/
├── app.py
├── agent_invoke.py
└── templates/
└── index.html
This is the code for app.py
:
from flask import Flask, render_template, request
from agent_invoke import invoke_bedrock_agent
import json
app = Flask(__name__)
def extract_response_text(response):
try:
if isinstance(response, str):
response_dict = json.loads(response)
else:
response_dict = response
# Check for 'response' field in the dictionary
if 'response' in response_dict:
return response_dict['response']
# Check for 'completion' field as fallback
elif 'completion' in response_dict:
return response_dict['completion']
# Return the full response if no known fields are found
return str(response_dict)
except Exception as e:
return f"Error processing response: {str(e)}"
@app.route('/', methods=['GET', 'POST'])
def home():
response = None
if request.method == 'POST':
user_prompt = request.form.get('prompt')
if user_prompt:
raw_response = invoke_bedrock_agent(user_prompt)
response = extract_response_text(raw_response)
return render_template('index.html', response=response)
if __name__ == '__main__':
app.run(debug=True)
This is the code for index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bedrock Agent Interface</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.container {
display: flex;
flex-direction: column;
gap: 20px;
}
textarea {
width: 100%;
min-height: 100px;
padding: 10px;
margin: 10px 0;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.response-box {
border: 1px solid #ccc;
padding: 10px;
min-height: 100px;
white-space: pre-wrap;
}
</style>
</head>
<body>
<div class="container">
<h1>Bedrock Agent Interface</h1>
<form method="POST">
<label for="prompt">Enter your prompt:</label>
<textarea name="prompt" id="prompt" required>{{ request.form.get('prompt', '') }}</textarea>
<button type="submit">Submit</button>
</form>
{% if response %}
<div>
<h2>Agent Response:</h2>
<div class="response-box">{{ response }}</div>
</div>
{% endif %}
</div>
</body>
</html>
Step 4: Test the Web App
Go to the project directory and run the program using:
python app.py
This will start a local server. You can access the app on localhost:5000
.
Let's try the prompt "How many ec2 servers I have." Press submit. You can see the response on the web page.
Let's try another prompt: "Create an ec2 server of type t2.micro in ap-south-1 region."
We can see that the server has been created. Let's verify it in the AWS console.
If you check again, you will now have two servers.
Step 5: Clean Up
Remember to clean up the resources you created to avoid incurring unnecessary costs:
- Terminate any EC2 instances created during testing
- Delete the Bedrock Agent
Step 6: Additional Considerations
Prompt Quality: The quality of your prompt significantly impacts the agent's ability to correctly understand user intent and use the right tools. Be clear and specific.
Throttling: As there are service quotas applicable to the LLMs, you might face throttling errors. Check the service quota, wait, and retry.
User Interface: Creating custom web applications that leverage Bedrock Agents for AWS operations is a very compelling use case for many organizations. It enhances accessibility by enabling users who are not experts in the AWS console, CLI, or SDKs to perform pre-defined operational tasks. These can also assist technical teams and increase operational efficiency.
Customization vs. Amazon Q: Amazon Q in the console is a great starting point and provides general AWS assistance. AWS will keep integrating more functionality into Q in console and also Gen AI capabilities in other services. However, when you define action groups and knowledge bases for your agent that are unique to your organization, you can provide a tailored user experience and workflow integration. A custom web application built on Bedrock Agents allows you to create a highly specialized, integrated, and controlled operational tool tailored precisely to your organization's unique environment, processes, and user needs, going beyond the generic capabilities of a console-level assistant. It's about building your organization's intelligent assistant for its specific operational challenges.
This article demonstrates how to build intelligent AWS automation using Amazon Bedrock Agents with custom web interfaces.
Top comments (0)