Rapid Development of Agents for Amazon Bedrock Using AWS Lambda Web Adapter

Rapid Development of Agents for Amazon Bedrock Using AWS Lambda Web Adapter

Hello everyone. This is my first post. I work as a system integrator in Japan. My work involves system architecture using services like Bedrock and serverless. I plan to continue posting here regularly, so please stay tuned. Thank you.

💡Original Japanese Version is here.
https://qiita.com/moritalous/items/f828c5d7d2d116884f9a

There is a feature called Agents for Amazon Bedrock that allows you to build agents on Amazon Bedrock. This feature is built on Lambda, but requires the following:

A Lambda function containing the business logic for the actions the agent will execute
An OpenAPI schema containing the API description, structure, and parameters

Additionally, since the event JSON is in a dedicated format, you need to be mindful of what kind of events will arrive while developing.

AWS’s AWS Lambda Web Adapter now supports Agents for Amazon Bedrock, so we’ll introduce how to use it.

What is AWS Lambda Web Adapter?

It’s a tool for running web applications on AWS Lambda.

With AWS Lambda Web Adaptor, developers can build web apps (HTTP APIs) using their familiar frameworks (Express.js, Next.js, Flask, SpringBoot, ASP.NET, Laravel, etc., anything that uses HTTP 1.1/1.0) and run them on AWS Lambda. You can also run the same Docker image on AWS Lambda, Amazon EC2, AWS Fargate, and your local computer.

https://github.com/awslabs/aws-lambda-web-adapter

Here’s an image showing the configuration (from the official site):

Until now, only HTTP events from API Gateway or ALB were supported, but Non-HTTP Events have now been supported! 🎉🎉🎉

Here’s an image for Non-HTTP events:

Non-HTTP events such as SNS or SQS can now be received. The event type is automatically identified, with HTTP events forwarded to their respective path, and Non-HTTP events forwarded to /events (which can be changed).

For Agents for Amazon Bedrock, the following JSON will be sent to /events. If the JSON received at /events can be parsed and routed to the desired path, it will work as intended.

Reference: Lambda input event from Amazon Bedrock

{
“messageVersion”: “1.0”,
“agent”: {
“name”: “string”,
“id”: “string”,
“alias”: “string”,
“version”: “string”
},
“inputText”: “string”,
“sessionId”: “string”,
“actionGroup”: “string”,
“apiPath”: “string”,
“httpMethod”: “string”,
“parameters”: [
{
“name”: “string”,
“type”: “string”,
“value”: “string”
},

],
“requestBody”: {
“content”: {
“<content_type>”: {
“properties”: [
{
“name”: “string”,
“type”: “string”,
“value”: “string”
},

]
}
}
},
“sessionAttributes”: {
“string”: “string”,
},
“promptSessionAttributes”: {
“string”: “string”
}
}

The routing process is common, so I’ve published a library using FastAPI’s Middleware mechanism.

With this library, you can develop APIs with FastAPI without worrying about /events.

https://github.com/moritalous/lwa-fastapi-middleware-bedrock-agent

💡Note
I requested support for Agents for Amazon Bedrock for Lambda Web Adapter, which led to its implementation. I was also asked to create a sample and a general library.
I hope support Agents for Amazon Bedrock #317
It was a very valuable experience.

Sample App Explanation

Here’s a sample app using this configuration:

https://github.com/moritalous/lwa-fastapi-middleware-bedrock-agent/tree/main/example/bedrock-agent-fastapi

Directory structure

bedrock-agent-fastapi
├── README.md
├── app
│ ├── Dockerfile
│ ├── __init__.py
│ ├── main.py
│ └── requirements.txt
├── events
│ ├── s3_bucket_count.json
│ ├── s3_object.json
│ └── s3_object_count.json
└── template.yaml

Libraries used

Main Python application libraries used:

FastAPI

lwa-fastapi-middleware-bedrock-agent (FastAPI Middleware for “Agents for Amazon Bedrock”)

Integrating Lambda Web Adapter

The deployment type for Lambda is containers. In the Dockerfile’s second line, we copy the contents of Lambda Web Adapter. This single line is the minimum required to use Lambda Web Adapter.

FROM public.ecr.aws/docker/library/python:3.12.0-slim
COPY –from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.1 /lambda-adapter /opt/extensions/lambda-adapter
ENV PORT=8000 AWS_LWA_READINESS_CHECK_PROTOCOL=tcp
WORKDIR /var/task
COPY requirements.txt ./
RUN python -m pip install -r requirements.txt
COPY *.py ./
CMD exec uvicorn –port=$PORT main:app

FastAPI API Development

The program code is only in main.py. Except for specifying the Middleware, it’s the same as a general FastAPI application.

This sample includes the following APIs:

Path
Method
Description

/s3_bucket_count
GET
Returns the number of S3 buckets

/s3_object_count
GET
Returns the number of objects in the specified S3 bucket

/s3_object
GET
Returns the last modified date of the specified S3 bucket and object key

import datetime
import logging

import boto3
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

from bedrock_agent.middleware import BedrockAgentMiddleware

app = FastAPI(
description=This agent allows you to query the S3 information in your AWS account.,
)
app.openapi_version = 3.0.2
app.add_middleware(BedrockAgentMiddleware)

middleware_logger = logging.getLogger(bedrockagent-middleware)
middleware_logger.setLevel(level=logging.DEBUG)

s3 = boto3.resource(s3)

class S3BucketCountResponse(BaseModel):
count: int = Field(description=the number of S3 buckets)

@app.get(/s3_bucket_count)
async def get_s3_bucket_count() -> S3BucketCountResponse:
“””
This method returns the number of S3 buckets in your AWS account.

Return:
S3BucketCountResponse: A json object containing the number of S3 buckets in your AWS account.
“””

count = len(list(s3.buckets.all()))

return S3BucketCountResponse(count=count)

class S3ObjectCountResponse(BaseModel):
count: int = Field(description=the number of S3 objects)

@app.get(/s3_object_count)
async def get_s3_object_count(
bucket_name: str = Query(description=Bucket name),
) -> S3ObjectCountResponse:
“””
This method returns the number of S3 objects in your specified bucket.

Return:
S3ObjectCountResponse: A json object containing the number of S3 objects in your specified bucket.
“””

count = len(list(s3.Bucket(bucket_name).objects.all()))
return S3ObjectCountResponse(count=count)

class S3GetObjectRequest(BaseModel):
bucket_name: str = Field(description=Bucket name)
object_key: str = Field(description=Object key)

class S3GetObjectResponse(BaseModel):
last_modified: datetime.datetime = Field(description=the last modified date)

@app.post(/s3_object)
async def get_s3_object(request: S3GetObjectRequest):
“””
This method returns the last modified date of S3 object.

Return:
S3GetObjectResponse: A json object containing the last modified date of S3 objects.
“””

object = s3.Object(request.bucket_name, request.object_key)
last_modified = object.get()[LastModified]
return S3GetObjectResponse(last_modified=last_modified)

The Middleware specification is in this part. This single specification routes events received at /events appropriately.

from bedrock_agent.middleware import BedrockAgentMiddleware

app.add_middleware(BedrockAgentMiddleware)

Running FastAPI Locally

Install library

pip install fastapi uvicorn pydantic==1.10.13 lwa-fastapi-middleware-bedrock-agent boto3

Since it’s a FastAPI app, you can run it as is.

uvicorn main:app –reload

(console log)

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [4999] using StatReload
INFO: Started server process [5001]
INFO: Waiting for application startup.
INFO: pass_through_path: /events
INFO: Application startup complete.

Accessing http://127.0.0.1:8000/docs will display the OpenAPI documentation via Swagger UI.

You can proceed with agent development as FastAPI APIs.

Generating OpenAPI Schema

The OpenAPI schema can be output using FastAPI’s functionality. This output can be used as-is for Agents for Amazon Bedrock.

(Run in the app directory)

python -c “import main;import json; print(json.dumps(main.app.openapi()))” > openapi.json

Build and Deploy

Since it’s a SAM project, you can build and deploy using standard commands.

sam build

sam deploy –guided

Local Testing

You can also test locally with the sam local invoke command.

sam local invoke –event events/s3_bucket_count.json

Creating Agents for Amazon Bedrock

With the Lambda and OpenAPI schema ready, you can create the agent using the management console.

Summary

Thank you for reading until the end. Since you can focus solely on API definition for agent development, please make use of it.

Leave a Reply

Your email address will not be published. Required fields are marked *