RFC: Amazon Bedrock agents with action groups using Function details #6081
-
SummaryThe Powertools for AWS Lambda (Python) currently provides an event handler for Bedrock Agents, allowing users to build AI-driven applications with OpenAPI schemas. However, since adding support for it Bedrock has added support for function calling rather than structured API definitions. This proposal introduces BedrockAgentFunctionsResolver, a new Event Handler resolver designed to seamlessly build Bedrock Agents functions within AWS Lambda. This new resolver simplifies function-based interactions, allowing users to build modular AI assistants and task automation systems with optimized effort. Use CaseDevelopers often need to build AI-powered applications that can dynamically invoke functions based on user input or AI model reasoning. Examples include:
How it is todayLambda handler def get_current_time():
...
def greet_user(name):
...
def simple_calculator(a, b, operation):
...
def lambda_handler(event, context):
agent = event['agent']
actionGroup = event['actionGroup']
function = event['function']
parameters = event.get('parameters', [])
# Execute the appropriate function based on the 'function' parameter
if function == 'get_current_time':
result = get_current_time()
elif function == 'greet_user':
name = parameters[0]['value'] if parameters else "User"
result = greet_user(name)
elif function == 'simple_calculator':
if len(parameters) >= 3:
a = float(parameters[0]['value'])
b = float(parameters[1]['value'])
operation = parameters[2]['value']
result = simple_calculator(a, b, operation)
else:
result = "Error: Insufficient parameters for simple_calculator"
else:
result = f"Unknown function: {function}"
responseBody = {
"TEXT": {
"body": str(result)
}
}
action_response = {
'actionGroup': actionGroup,
'function': function,
'functionResponse': {
'responseBody': responseBody
}
}
function_response = {'response': action_response, 'messageVersion': event['messageVersion']}
print("Response: {}".format(function_response))
return function_response Action group - function details agent_functions = [
{
'name': 'get_current_time',
'description': 'Retrieve the current UTC time.',
'parameters': {}
},
{
'name': 'greet_user',
'description': 'Greet the user by name.',
'parameters': {
"name": {
"description": "The name of the user to greet.",
"required": True,
"type": "string"
}
}
},
{
'name': 'simple_calculator',
'description': 'Perform basic math operations (add, subtract, multiply, divide).',
'parameters': {
"a": {
"description": "The first number.",
"required": True,
"type": "number"
},
"b": {
"description": "The second number.",
"required": True,
"type": "number"
},
"operation": {
"description": "The operation to perform: add, subtract, multiply, divide.",
"required": True,
"type": "string"
}
}
}
] Lambda payloadExample Input {
"messageVersion": "1.0",
"agent": {
"alias": "PROD",
"name": "hr-assistant-function-def",
"version": "1",
"id": "1234abcd-56ef-78gh-90ij-klmn12345678"
},
"sessionId": "87654321-abcd-efgh-ijkl-mnop12345678",
"sessionAttributes": {
"employeeId": "EMP123",
"department": "Engineering"
},
"promptSessionAttributes": {
"lastInteraction": "2024-02-01T15:30:00Z",
"requestType": "vacation"
},
"inputText": "I want to request vacation from March 15 to March 20",
"actionGroup": "VacationsActionGroup",
"function": "submitVacationRequest",
"parameters": [{
"employeeId": "EMP123",
"startDate": "2024-03-15",
"endDate": "2024-03-20",
"vacationType": "annual"
}]
}
Example output {
"response":{
"actionGroup":"SmarterAgentActionGroup",
"function":"submitVacationRequest",
"functionResponse":{
"responseBody":{
"TEXT":{
"body":"Your vacation was scheduled!"
}
}
}
},
"messageVersion":"1.0"
}
ProposalBedrockAgentFunctionsResolver from aws_lambda_powertools.event_handler import BedrockAgentFunctionsResolver
from aws_lambda_powertools.utilities.typing import LambdaContext
app = BedrockAgentFunctionResolver()
@app.function(description="Gets the current UTC time")
def get_current_time():
...
@app.function(description="Greets the user using name")
def greet_user(name):
@app.function(description="Add two numbers")
def simple_calculator(a, b, operation):
...
def lambda_handler(event: dict, context: LambdaContext) → dict:
return app.resolve(event, context) Similar to OpenAPI implementation, Functions can return the Action Groups: __name__ == "__main__":
print(app.get_agent_functions_schema()) Proposed Implementation Details Function Registration
Invocation Handling
Error Handling & Logging
Alternatives Considered
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 8 replies
-
Hi @anafalcao - thank you so much for posting this! I'm going to take some time on Monday to go through it more in details and leave a comment, but from a first read it's looking already good! |
Beta Was this translation helpful? Give feedback.
-
Hello @anafalcao! Thank you so much for working on your first public RFC, this is an incredible achievement! 🚀. I have a few questions and I'll break them down to make it easier to follow and answer. Resolver decoratorLet's take this code as example: @app.function(description="Greets the user using name")
def greet_user(name):
... If I understand correctly, this 1 - The experience is not deterministic, I mean, someone looks at this code and tries to understand what it is doing. After reading the documentation and maybe the implementation, they will find that we are mapping the value of the Why don't we keep the same experience as other resolvers? I think make sense we discuss a little bit more if Functions can return the Action GroupsCan you elaborate a little bit more on what you expect from this experience? Are we proposing to reverse engineer and create the payload? __name__ == "__main__":
print(app.get_agent_functions_schema()) Again, thank you so much for working on this. It will be a great feature for our customers. |
Beta Was this translation helpful? Give feedback.
I like this idea @dreamorosi !
I believe we went through all the details, and now have a path forward.
Thank you all for the amazing suggestions and feedbacks!