Skip to content

Commit 93f0891

Browse files
committed
docs: update Bedrock Agent Function documentation with new features and examples
1 parent 3fec468 commit 93f0891

2 files changed

Lines changed: 189 additions & 78 deletions

File tree

docs/core/event_handler/bedrock_agent_function.md

Lines changed: 187 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,24 @@ flowchart LR
1818
Bedrock[LLM] <-- uses --> Agent
1919
You[User input] --> Agent
2020
Agent[Bedrock Agent] <-- tool use --> Lambda
21-
2221
subgraph Agent[Bedrock Agent]
2322
ToolDescriptions[Tool Definitions]
2423
end
25-
2624
subgraph Lambda[Lambda Function]
2725
direction TB
2826
Parsing[Parameter Parsing] --> Routing
2927
Routing --> Code[Your code]
3028
Code --> ResponseBuilding[Response Building]
3129
end
32-
3330
style You stroke:#0F0,stroke-width:2px
3431
```
3532

3633
## Features
3734

38-
- **Simple Tool Registration**: Register functions with descriptive names that Bedrock Agents can invoke
39-
- **Automatic Parameter Handling**: Parameters are automatically extracted from Bedrock Agent requests and converted to the appropriate types
40-
- **Lambda Context Access**: Easy access to Lambda context for logging and AWS Lambda features
41-
- **Dependency Injection Support**: Seamless integration with .NET's dependency injection system
42-
- **AOT Compatibility**: Fully compatible with .NET 8 AOT compilation through source generation
35+
* Easily expose tools for your Large Language Model (LLM) agents
36+
* Automatic routing based on tool name and function details
37+
* Graceful error handling and response formatting
38+
* Fully compatible with .NET 8 AOT compilation through source generation
4339

4440
## Terminology
4541

@@ -66,75 +62,210 @@ dotnet add package AWS.Lambda.Powertools.EventHandler.Resolvers.BedrockAgentFunc
6662

6763
You must create an Amazon Bedrock Agent with at least one action group. Each action group can contain up to 5 tools, which in turn need to match the ones defined in your Lambda function. Bedrock must have permission to invoke your Lambda function.
6864

69-
??? note "Click to see example IaC templates"
70-
71-
TODO: add cdk
72-
65+
??? note "Click to see example SAM template"
66+
```yaml
67+
AWSTemplateFormatVersion: '2010-09-09'
68+
Transform: AWS::Serverless-2016-10-31
69+
70+
Globals:
71+
Function:
72+
Timeout: 30
73+
MemorySize: 256
74+
Runtime: dotnet8
75+
76+
Resources:
77+
HelloWorldFunction:
78+
Type: AWS::Serverless::Function
79+
Properties:
80+
Handler: FunctionHandler
81+
CodeUri: hello_world
82+
83+
AirlineAgentRole:
84+
Type: AWS::IAM::Role
85+
Properties:
86+
RoleName: !Sub '${AWS::StackName}-AirlineAgentRole'
87+
Description: 'Role for Bedrock Airline agent'
88+
AssumeRolePolicyDocument:
89+
Version: '2012-10-17'
90+
Statement:
91+
- Effect: Allow
92+
Principal:
93+
Service: bedrock.amazonaws.com
94+
Action: sts:AssumeRole
95+
Policies:
96+
- PolicyName: bedrock
97+
PolicyDocument:
98+
Version: '2012-10-17'
99+
Statement:
100+
- Effect: Allow
101+
Action: 'bedrock:*'
102+
Resource:
103+
- !Sub 'arn:aws:bedrock:us-*::foundation-model/*'
104+
- !Sub 'arn:aws:bedrock:us-*:*:inference-profile/*'
105+
106+
BedrockAgentInvokePermission:
107+
Type: AWS::Lambda::Permission
108+
Properties:
109+
FunctionName: !Ref HelloWorldFunction
110+
Action: lambda:InvokeFunction
111+
Principal: bedrock.amazonaws.com
112+
SourceAccount: !Ref 'AWS::AccountId'
113+
SourceArn: !Sub 'arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:agent/${AirlineAgent}'
114+
115+
# Bedrock Agent
116+
AirlineAgent:
117+
Type: AWS::Bedrock::Agent
118+
Properties:
119+
AgentName: AirlineAgent
120+
Description: 'A simple Airline agent'
121+
FoundationModel: !Sub 'arn:aws:bedrock:us-west-2:${AWS::AccountId}:inference-profile/us.amazon.nova-pro-v1:0'
122+
Instruction: |
123+
You are an airport traffic control agent. You will be given a city name and you will return the airport code for that city.
124+
AgentResourceRoleArn: !GetAtt AirlineAgentRole.Arn
125+
AutoPrepare: true
126+
ActionGroups:
127+
- ActionGroupName: AirlineActionGroup
128+
ActionGroupExecutor:
129+
Lambda: !GetAtt AirlineAgentFunction.Arn
130+
FunctionSchema:
131+
Functions:
132+
- Name: getAirportCodeForCity
133+
Description: 'Get the airport code for a given city'
134+
Parameters:
135+
city:
136+
Type: string
137+
Description: 'The name of the city to get the airport code for'
138+
Required: true
139+
```
73140

74141
## Basic Usage
75142

76143
To create an agent, use the `BedrockAgentFunctionResolver` to register your tools and handle the requests. The resolver will automatically parse the request, route it to the appropriate function, and return a well-formed response that includes the tool's output and any existing session attributes.
77144

78-
```csharp
79-
using Amazon.BedrockAgentRuntime.Model;
80-
using Amazon.Lambda.Core;
81-
using AWS.Lambda.Powertools.EventHandler;
145+
=== "Executable asembly"
82146

83-
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
147+
```csharp
148+
using Amazon.Lambda.Core;
149+
using Amazon.Lambda.RuntimeSupport;
150+
using AWS.Lambda.Powertools.EventHandler.Resolvers;
151+
using AWS.Lambda.Powertools.EventHandler.Resolvers.BedrockAgentFunction.Models;
84152

85-
namespace MyLambdaFunction
86-
{
87-
public class Function
153+
var resolver = new BedrockAgentFunctionResolver();
154+
155+
resolver
156+
.Tool("GetWeather", (string city) => $"The weather in {city} is sunny")
157+
.Tool("CalculateSum", (int a, int b) => $"The sum of {a} and {b} is {a + b}")
158+
.Tool("GetCurrentTime", () => $"The current time is {DateTime.Now}");
159+
160+
// The function handler that will be called for each Lambda event
161+
var handler = async (BedrockFunctionRequest input, ILambdaContext context) =>
88162
{
89-
private readonly BedrockAgentFunctionResolver _resolver;
90-
91-
public Function()
163+
return await resolver.ResolveAsync(input, context);
164+
};
165+
166+
// Build the Lambda runtime client passing in the handler to call for each
167+
// event and the JSON serializer to use for translating Lambda JSON documents
168+
// to .NET types.
169+
await LambdaBootstrapBuilder.Create(handler, new DefaultLambdaJsonSerializer())
170+
.Build()
171+
.RunAsync();
172+
```
173+
174+
=== "Class Library"
175+
176+
```csharp
177+
using AWS.Lambda.Powertools.EventHandler.Resolvers;
178+
using AWS.Lambda.Powertools.EventHandler.Resolvers.BedrockAgentFunction.Models;
179+
using Amazon.Lambda.Core;
180+
181+
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
182+
183+
namespace MyLambdaFunction
184+
{
185+
public class Function
92186
{
93-
_resolver = new BedrockAgentFunctionResolver();
187+
private readonly BedrockAgentFunctionResolver _resolver;
94188
95-
// Register simple tool functions
96-
_resolver
97-
.Tool("GetWeather", (string city) => $"The weather in {city} is sunny")
98-
.Tool("CalculateSum", (int a, int b) => $"The sum of {a} and {b} is {a + b}")
99-
.Tool("GetCurrentTime", () => $"The current time is {DateTime.Now}");
100-
}
101-
102-
// Lambda handler function
103-
public ActionGroupInvocationOutput FunctionHandler(
104-
ActionGroupInvocationInput input, ILambdaContext context)
105-
{
106-
return _resolver.Resolve(input, context);
189+
public Function()
190+
{
191+
_resolver = new BedrockAgentFunctionResolver();
192+
193+
// Register simple tool functions
194+
_resolver
195+
.Tool("GetWeather", (string city) => $"The weather in {city} is sunny")
196+
.Tool("CalculateSum", (int a, int b) => $"The sum of {a} and {b} is {a + b}")
197+
.Tool("GetCurrentTime", () => $"The current time is {DateTime.Now}");
198+
}
199+
200+
// Lambda handler function
201+
public BedrockFunctionResponse FunctionHandler(
202+
BedrockFunctionRequest input, ILambdaContext context)
203+
{
204+
return _resolver.Resolve(input, context);
205+
}
107206
}
108207
}
109-
}
110-
```
111-
208+
```
112209
When the Bedrock Agent invokes your Lambda function with a request to use the "GetWeather" tool and a parameter for "city", the resolver automatically extracts the parameter, passes it to your function, and formats the response.
113210

211+
## How It Works with Amazon Bedrock Agents
212+
213+
1. When a user interacts with a Bedrock Agent, the agent identifies when it needs to call an action to fulfill the user's request.
214+
2. The agent determines which function to call and what parameters are needed.
215+
3. Bedrock sends a request to your Lambda function with the function name and parameters.
216+
4. The BedrockAgentFunctionResolver automatically:
217+
- Finds the registered handler for the requested function
218+
- Extracts and converts parameters to the correct types
219+
- Invokes your handler with the parameters
220+
- Formats the response in the way Bedrock Agents expect
221+
5. The agent receives the response and uses it to continue the conversation with the user
222+
114223
## Advanced Usage
115224

116-
### Functions with Descriptions
225+
### Custom type serialization
117226

118-
Add descriptive information to your tool functions:
227+
You can have your own custom types as arguments to the tool function. The library will automatically handle serialization and deserialization of these types. In this case, you need to ensure that your custom type is serializable to JSON, if serialization fails, the object will be null.
119228

120-
```csharp
121-
_resolver.Tool(
122-
"CheckInventory",
123-
"Checks if a product is available in inventory",
124-
(string productId, bool checkWarehouse) =>
229+
```csharp hl_lines="4"
230+
resolver.Tool(
231+
name: "PriceCalculator",
232+
description: "Calculate total price with tax",
233+
handler: (MyCustomType myCustomType) =>
125234
{
126-
return checkWarehouse
127-
? $"Product {productId} has 15 units in warehouse"
128-
: $"Product {productId} has 5 units in store";
129-
});
235+
var withTax = myCustomType.Price * 1.2m;
236+
return $"Total price with tax: {withTax.ToString("F2", CultureInfo.InvariantCulture)}";
237+
}
238+
);
239+
```
240+
241+
### Custom type serialization native AOT
242+
243+
For native AOT compilation, you can use JsonSerializerContext and pass it to `BedrockAgentFunctionResolver`. This allows the library to generate the necessary serialization code at compile time, ensuring compatibility with AOT.
244+
245+
```csharp hl_lines="1 5 12-15"
246+
var resolver = new BedrockAgentFunctionResolver(MycustomSerializationContext.Default);
247+
resolver.Tool(
248+
name: "PriceCalculator",
249+
description: "Calculate total price with tax",
250+
handler: (MyCustomType myCustomType) =>
251+
{
252+
var withTax = myCustomType.Price * 1.2m;
253+
return $"Total price with tax: {withTax.ToString("F2", CultureInfo.InvariantCulture)}";
254+
}
255+
);
256+
257+
[JsonSerializable(typeof(MyCustomType))]
258+
public partial class MycustomSerializationContext : JsonSerializerContext
259+
{
260+
}
130261
```
131262

132263
### Accessing Lambda Context
133264

134265
You can access to the original Lambda event or context for additional information. These are passed to the handler function as optional arguments.
135266

136267
```csharp
137-
_resolver.Tool(
268+
resolver.Tool(
138269
"LogRequest",
139270
"Logs request information and returns confirmation",
140271
(string requestId, ILambdaContext context) =>
@@ -177,6 +308,7 @@ resolver.Tool("CustomFailure", () =>
177308
};
178309
});
179310
```
311+
180312
### Setting session attributes
181313

182314
When Bedrock Agents invoke your Lambda function, it can pass session attributes that you can use to store information across multiple interactions with the user. You can access these attributes in your handler function and modify them as needed.
@@ -254,7 +386,7 @@ Access the raw Bedrock Agent request:
254386
_resolver.Tool(
255387
"ProcessRawRequest",
256388
"Processes the raw Bedrock Agent request",
257-
(ActionGroupInvocationInput input) =>
389+
(BedrockFunctionRequest input) =>
258390
{
259391
var functionName = input.Function;
260392
var parameterCount = input.Parameters.Count;
@@ -288,30 +420,6 @@ resolver.Tool(
288420
});
289421
```
290422

291-
## How It Works with Amazon Bedrock Agents
292-
293-
1. When a user interacts with a Bedrock Agent, the agent identifies when it needs to call an action to fulfill the user's request.
294-
2. The agent determines which function to call and what parameters are needed.
295-
3. Bedrock sends a request to your Lambda function with the function name and parameters.
296-
4. The BedrockAgentFunctionResolver automatically:
297-
- Finds the registered handler for the requested function
298-
- Extracts and converts parameters to the correct types
299-
- Invokes your handler with the parameters
300-
- Formats the response in the way Bedrock Agents expect
301-
5. The agent receives the response and uses it to continue the conversation with the user
302-
303-
## Supported Parameter Types
304-
305-
- `string`
306-
- `int`
307-
- `number`
308-
- `bool`
309-
- `enum` types
310-
- `ILambdaContext` (for accessing Lambda context)
311-
- `ActionGroupInvocationInput` (for accessing raw request)
312-
- Any service registered in dependency injection
313-
314-
315423
## Using Attributes to Define Tools
316424

317425
You can define Bedrock Agent functions using attributes instead of explicit registration. This approach provides a clean, declarative way to organize your tools into classes:
@@ -361,6 +469,9 @@ var resolver = serviceProvider.GetRequiredService<BedrockAgentFunctionResolver>(
361469

362470
## Complete Example with Dependency Injection
363471

472+
You can find examples in the [Powertools for AWS Lambda (.NET) GitHub repository](https://github.com/aws-powertools/powertools-lambda-dotnet/tree/develop/examples/Event%20Handler/BedrockAgentFunction).
473+
474+
364475
```csharp
365476
using Amazon.BedrockAgentRuntime.Model;
366477
using Amazon.Lambda.Core;

examples/Event Handler/BedrockAgentFunction/infra/lib/bedrockagents-stack.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Duration,
88
} from 'aws-cdk-lib';
99
import type { Construct } from 'constructs';
10-
import { Runtime, Function, Code, Architecture } from 'aws-cdk-lib/aws-lambda';
10+
import { Runtime, Function as LambdaFunction, Code, Architecture } from 'aws-cdk-lib/aws-lambda';
1111
import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
1212
import { CfnAgent } from 'aws-cdk-lib/aws-bedrock';
1313
import {
@@ -29,7 +29,7 @@ export class BedrockAgentsStack extends Stack {
2929
retention: RetentionDays.ONE_DAY,
3030
});
3131

32-
const fn = new Function(this, 'MyFunction', {
32+
const fn = new LambdaFunction(this, 'MyFunction', {
3333
functionName: fnName,
3434
logGroup,
3535
timeout: Duration.minutes(3),

0 commit comments

Comments
 (0)