---
title: Amazon Bedrock Agents
description: Core utility
status: new
---

Create [Amazon Bedrock Agents](https://docs.aws.amazon.com/bedrock/latest/userguide/agents.html#agents-how){target="_blank"} using event handlers with two different action groups approaches:

* OpenAPI schema
* Function details

<center>
```mermaid
--8<-- "docs/core/event_handler/bedrock_agents.mermaid"
```
</center>

## Key features

* Minimal boilerplate to build Amazon Bedrock Agents
* Support for both OpenAPI-based and Function-based actions
* Automatic generation of [OpenAPI schemas](https://www.openapis.org/){target="_blank"} from your business logic code
* Built-in data validation for requests and responses
* Similar experience to authoring [REST and HTTP APIs](api_gateway.md){target="_blank"}

## Terminology

**Data validation** automatically validates the user input and the response of your AWS Lambda function against a set of constraints defined by you.

**Event handler** is a Powertools for AWS feature that processes an event, runs data parsing and validation, routes the request to a specific function, and returns a response to the caller in the proper format.

**[OpenAPI schema](https://www.openapis.org/){target="_blank"}** is an industry standard JSON-serialized string that represents the structure and parameters of your API.

**Function details** consist of a list of parameters, defined by their name, [data type](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_ParameterDetail.html), and whether they are required. The agent uses these configurations to determine what information it needs to elicit from the user.

**Action group** is a collection of two resources where you define the actions that the agent should carry out when invoking your Lambda function.

**Large Language Models (LLM)** are very large deep learning models that are pre-trained on vast amounts of data, capable of extracting meanings from a sequence of text and understanding the relationship between words and phrases on it.

**Amazon Bedrock Agent** is an Amazon Bedrock feature to build and deploy conversational agents that can interact with your customers using Large Language Models (LLM) and AWS Lambda functions.

!!! tip "All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples)"

## Choose your Action Group

An action group defines actions that the agent can help the user perform. You can define action groups as OpenAPI-based or Function-based.

| Aspect               | OpenAPI-based Actions                                           | Function-based Actions                                          |
|----------------------|------------------------------------------------------------------|----------------------------------------------------------------|
| Definition Style      | `@app.get("/path", description="")`<br>`@app.post("/path", description="")` | `@app.tool(name="")`                               |
| Parameter Handling    | Path, query, and body parameters                                 | Function parameters                                           |
| Use Case              | REST-like APIs, complex request/response structures              | Direct function calls, simpler input                          |
| Response object       | Via `BedrockResponse`                                            | Via `BedrockFunctionResponse`                                 |
| Best For              | - Complex APIs with multiple endpoints<br>- When OpenAPI spec is required<br>- Integration with existing REST APIs | - Simple function-based actions<br>- Direct LLM-to-function mapping |

## Getting started

### Install

!!! info "This is unnecessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../../index.md#lambda-layer){target="_blank"}."

If you define the action group setting up an **OpenAPI schema**, you need to add `pydantic` as a dependency in your preferred tool _e.g., requirements.txt, pyproject.toml_. At this time, we only support Pydantic V2.

### Your first Agent

To create an agent, use the `BedrockAgentResolver` or the `BedrockAgentFunctionResolver` to annotate your actions.
This is similar to the way [all the other Event Handler](api_gateway.md) resolvers work.

The resolvers used by Amazon Bedrock Agents are compatible with all Powertools for AWS Lambda [features](../../index.md#features){target="blank"}.
For reference, we use [Logger](../logger.md) and [Tracer](../tracer.md) in this example.

**OpenAPI-based actions**

=== "Lambda handler"

    ```python hl_lines="4 9 12 21"
    --8<-- "examples/event_handler_bedrock_agents/src/getting_started.py"
    ```

	1. `description` is a **required** field that should contain a human readable description of your action.
	2. We take care of **parsing**, **validating**, **routing** and **responding** to the request.

=== "OpenAPI schema"

	Powertools for AWS Lambda [generates this automatically](#generating-openapi-schemas) from the Lambda handler.

	```json
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_schema.json"
	```

=== "Input payload"

	```json hl_lines="4 6 13"
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started.json"
	```

=== "Output payload"

	```json hl_lines="10"
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_output.json"
	```

**Function-based actions**
=== "Lambda handler"

    ```python hl_lines="4 9 12 21"
    --8<-- "examples/event_handler_bedrock_agents/src/getting_started_functions.py"
    ```

	1. `name` and `description` are optional here.
	2. We take care of **parsing**, **validating**, **routing** and **responding** to the request.

=== "Input payload"

	```json hl_lines="9 12"
	--8<-- "examples/event_handler_bedrock_agents/src/input_getting_started_func.json"
	```

=== "Output payload"

	```json hl_lines="9"
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_output_func.json"
	```

### Accessing custom request fields

The event sent by Amazon Bedrock Agents into your Lambda function contains a [number of extra event fields](#request_fields_table), exposed in the `app.current_event` field.

???+ note "Why is this useful?"
	You can for instance identify new conversations (`session_id`) or store and analyze entire conversations (`input_text`).

=== "Accessing request fields"

	In this example, we [append correlation data](../logger.md#appending-additional-keys) to all generated logs.
 	This can be used to aggregate logs by `session_id` and observe the entire conversation between a user and the Agent.

	```python hl_lines="13-16"
	--8<-- "examples/event_handler_bedrock_agents/src/accessing_request_fields.py"
	```

<a id="request_fields_table"></a>

The input event fields available depend on your Agent's configuration (OpenAPI-based or Function-based):

| Name | Type | Description | OpenAPI | Function |
|------|------|-------------|----------|-----------|
| message_version | str | The version of the message format. Amazon Bedrock only supports version 1.0. | ✅ | ✅ |
| agent | BedrockAgentInfo | Contains information about the name, ID, alias, and version of the agent. | ✅ | ✅ |
| input_text | str | The user input for the conversation turn. | ✅ | ✅ |
| session_id | str | The unique identifier of the agent session. | ✅ | ✅ |
| action_group | str | The name of the action group. | ✅ | ✅ |
| api_path | str | The path to the API operation, as defined in the OpenAPI schema. | ✅ | ❌ |
| http_method | str | The method of the API operation, as defined in the OpenAPI schema. | ✅ | ❌ |
| function | str | The name of the function being called. | ❌ | ✅ |
| parameters | List[Parameter] | Contains parameters with name, type, and value properties. | ✅ | ✅ |
| request_body | BedrockAgentRequestBody | Contains the request body and its properties. | ✅ | ❌ |
| session_attributes | Dict[str, str] | Contains session attributes and their values. | ✅ | ✅ |
| prompt_session_attributes | Dict[str, str] | Contains prompt attributes and their values. | ✅ | ✅ |

## OpenAPI-based actions

### Generating OpenAPI schemas

Use the `get_openapi_json_schema` function provided by the resolver to produce a JSON-serialized string that represents your OpenAPI schema.
You can print this string or save it to a file. You'll use the file later when creating the Agent.

You'll need to regenerate the OpenAPI schema and update your Agent everytime your API changes.

=== "app.py"

    ```python hl_lines="24 25"
    --8<-- "examples/event_handler_bedrock_agents/src/generating_openapi_schema.py"
    ```

	1. This ensures that it's only executed when running the file directly, and not when running on the Lambda runtime.
    2. You can use [additional options](#customizing-api-operations) to customize the OpenAPI schema.

=== "OpenAPI schema"

    ```json hl_lines="13 16 24"
    --8<-- "examples/event_handler_bedrock_agents/src/generating_openapi_schema.json"
    ```

To get the OpenAPI schema, run the Python script from your terminal.
The script will generate the schema directly to standard output, which you can redirect to a file.

```sh
python3 app.py > schema.json
```

### Crafting effective OpenAPI schemas

Working with Amazon Bedrock Agents will introduce [non-deterministic behaviour to your system](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-how.html#agents-rt){target="_blank"}.

???+ note "Why is that?"
	Amazon Bedrock uses LLMs to understand and respond to user input.
	These models are trained on vast amounts of data and are capable of extracting meanings from a sequence of text and understanding the relationship between words and phrases on it.
	However, this means that the same input can result in different outputs, depending on the characteristics of the LLM being used.

The OpenAPI schema provides context and semantics to the Agent that will support the decision process for invoking our Lambda function.
Sparse or ambiguous schemas can result in unexpected outcomes.

We recommend enriching your OpenAPI schema with as many details as possible to help the Agent understand your functions, and make correct invocations.
To achieve that, keep the following suggestions in mind:

* Always describe your function behaviour using the `description` field in your annotations
* When refactoring, update your description field to match the function outcomes
* Use distinct `description` for each function to have clear separation of semantics

### Validating input and output

You can define the expected format for incoming data and responses by using type annotations.
Define constraints using standard Python types, [dataclasses](https://docs.python.org/3/library/dataclasses.html) or [Pydantic models](https://docs.pydantic.dev/latest/concepts/models/).
Pydantic is a popular library for data validation using Python type annotations.

The examples below uses [Pydantic's EmailStr](https://docs.pydantic.dev/2.0/usage/types/string_types/#emailstr){target="_blank"} to validate the email address passed to the `schedule_meeting` function.
The function then returns a boolean indicating if the meeting was successfully scheduled.

=== "Lambda handler"

	```python hl_lines="1 2 6 16-18"
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_with_validation.py"
	```

	1. No need to add the `enable_validation` parameter, as it's enabled by default.
	2. Describe each input using human-readable descriptions
	3. Add the typing annotations to your parameters and return types, and let the event handler take care of the rest

=== "OpenAPI schema"

	```json
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_with_validation_schema.json"
	```

=== "Input payload"

	```json hl_lines="6-13 20"
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_with_validation.json"
	```

=== "Output payload"

	```json hl_lines="10"
	--8<-- "examples/event_handler_bedrock_agents/src/getting_started_with_validation_output.json"
	```

#### When validation fails

If the request validation fails, your event handler will not be called, and an error message is returned to Bedrock.
Similarly, if the response fails validation, your handler will abort the response.

???+ info "What does this mean for my Agent?"
	The event handler will always return a response according to the schema (OpenAPI) or type hints (Function-based).
	A validation failure in OpenAPI-based actions results in a [422 response](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422).
	For both approaches, how Amazon Bedrock interprets that failure is non-deterministic, since it depends on the characteristics of the LLM being used.

=== "OpenAPI-based Input payload"

	```json hl_lines="11"
	--8<-- "examples/event_handler_bedrock_agents/src/validation_failure_input.json"
	```

=== "OpenAPI-based Output payload"

	```json hl_lines="10"
	--8<-- "examples/event_handler_bedrock_agents/src/validation_failure_output.json"
	```

<center>
```mermaid
--8<-- "docs/core/event_handler/bedrock_agents_validation_sequence_diagram.mermaid"
```
</center>

### Video walkthrough

To create an Agent for Amazon Bedrock, refer to the [official documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-create.html) provided by AWS.

The following video demonstrates the end-to-end process:

<center>
<iframe width="720" height="405" src="https://www.youtube-nocookie.com/embed/NWoC5FTSt7s?si=AG2qpLJbxCkyiLma&amp;controls=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</center>

During the creation process, you should use the schema [previously generated](#generating-openapi-schemas) when prompted for an OpenAPI specification.

### Advanced

#### Additional metadata

To enrich the view that Amazon Bedrock Agents has of your Lambda functions,
use a combination of [Pydantic Models](https://docs.pydantic.dev/latest/concepts/models/){target="_blank"} and [OpenAPI](https://www.openapis.org/){target="_blank"} type annotations to add constraints to your APIs parameters.

???+ info "When is this useful?"
	Adding constraints to your function parameters can help you to enforce data validation and improve the understanding of your APIs by Amazon Bedrock.

#### Customizing OpenAPI parameters

--8<-- "docs/core/event_handler/_openapi_customization_parameters.md"

To implement these customizations, include extra constraints when defining your parameters:

```python hl_lines="19" title="customizing_api_parameters.py" title="Customizing API parameters"
--8<-- "examples/event_handler_bedrock_agents/src/customizing_bedrock_api_parameters.py"
```

1. Title should not be larger than 200 characters and [strict mode](https://docs.pydantic.dev/latest/concepts/strict_mode/){target="_blank"} is activated

#### Customizing API operations

--8<-- "docs/core/event_handler/_openapi_customization_operations.md"

To implement these customizations, include extra parameters when defining your routes:

```python hl_lines="13-22" title="customizing_api_operations.py" title="Customzing API operations"
--8<-- "examples/event_handler_bedrock_agents/src/customizing_bedrock_api_operations.py"
```

#### Enabling user confirmation

You can enable user confirmation with Bedrock Agents to have your application ask for explicit user approval before invoking an action.

```python hl_lines="14" title="enabling_user_confirmation.py" title="Enabling user confirmation"
--8<-- "examples/event_handler_bedrock_agents/src/enabling_user_confirmation.py"
```

1. Add an openapi extension

#### OpenAPI-based Responses

???+ info "Note"
	The default response only includes the essential fields to keep the payload size minimal, as AWS Lambda has a maximum response size of 25 KB.

You can use `BedrockResponse` class to add additional fields as needed, such as [session attributes, prompt session attributes, and knowledge base configurations](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html#agents-lambda-response){target="_blank"}.

???+ tip "Content Type Behavior"
	Amazon Bedrock Agents only support TEXT content type in the responseBody. All response bodies are automatically serialized as JSON strings regardless of the `content_type` parameter you provide. The `content_type` parameter exists for API consistency but does not affect the actual format sent to Bedrock Agents.
	Learn more: [AWS Bedrock Lambda Integration](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html){target="_blank"}

```python title="working_with_bedrockresponse.py" title="Customzing your Bedrock Response" hl_lines="5 16"
--8<-- "examples/event_handler_bedrock_agents/src/working_with_bedrockresponse.py"
```

#### Bedrock requests under the hood

Powertools handle the request from the Agent, parse, validate, and route it to the correct method in your code. The response is then validated and formatted back to the Agent.

<center>
```mermaid
--8<-- "docs/core/event_handler/bedrock_agents_getting_started.mermaid"
```
</center>

### Testing your code

Test your routes by passing an [Agent for Amazon Bedrock proxy event](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html#agents-lambda-input) request:

=== "assert_bedrock_agent_response.py"

	```python hl_lines="22-24 28"
	--8<-- "examples/event_handler_bedrock_agents/src/assert_bedrock_agent_response.py"
	```

=== "assert_bedrock_agent_response_module.py"

	```python hl_lines="14-17"
	--8<-- "examples/event_handler_bedrock_agents/src/assert_bedrock_agent_response_module.py"
	```

## Function-based Actions

The `BedrockAgentFunctionResolver` streamlines agent function development through three core capabilities:

* **Register Functions**: Use the `@app.tool()` decorator to expose your functions to Bedrock Agents

| Field | Required | Description |
|-------|----------|-------------|
| name | No | Custom name for your function. Uses the actual function name if omitted. |
| description | No | Explain what your function does to guide the agent's usage. |

* **Process Parameters**: Automatically maps input parameters from the agent to your function arguments
* **Format Responses**: Transforms your function outputs into properly structured Bedrock Agent responses

### Function-based Responses

???+ info "Note"
	The default response only includes the essential fields to keep the payload size minimal, as AWS Lambda has a maximum response size of 25 KB.

You can use `BedrockFunctionResponse` class to customize your response [with additional fields](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html#agents-lambda-response){target="_blank"}. This class allows you to:

* Return a response body
* Set session and prompt session attributes
* Set knowledge bases configurations
* Control the response state ("FAILURE" or "REPROMPT")

```python title="working_with_bedrockresponse.py" title="Customzing your Bedrock Function Response" hl_lines="1 4 7"
--8<-- "examples/event_handler_bedrock_agents/src/working_bedrock_functions_response.py"
```

<!-- markdownlint-disable MD043 -->
