5.3 Action Groups, OpenAPI Schemas & AWS Lambda Integration
Key Takeaways
- Action groups empower Amazon Bedrock Agents to execute real-world tasks and interact with external enterprise systems by mapping foundation model reasoning to concrete API operations.
- Action group interfaces are defined either via OpenAPI 3.0 specifications stored in Amazon S3 or through inline function definitions that specify parameter names, types, descriptions, and required constraints.
- Precise, semantically rich descriptions in OpenAPI operations and parameters are vital because foundation models inspect these descriptions directly to determine when and how to invoke tools.
- Amazon Bedrock invokes the backing AWS Lambda function using a standardized JSON event containing the agent metadata, actionGroup name, apiPath, httpMethod, parameters, requestBody, and session attributes.
- The backing Lambda function must return an actionResponse containing messageVersion 1.0, httpStatusCode, and stringified responseBody, secured by a resource-based policy granting bedrock.amazonaws.com invocation rights filtered by AWS:SourceArn.
5.3 Action Groups, OpenAPI Schemas & AWS Lambda Integration
While foundation models possess broad general knowledge, enterprise AI applications deliver value through operational capability—reading real-time data, initiating financial transactions, updating CRM pipelines, and invoking enterprise microservices. In Amazon Bedrock, Action Groups provide the mechanism that connects an agent's cognitive reasoning to executable business logic. This section explores how to author OpenAPI 3.0 schemas, structure AWS Lambda invocation and response payloads, manage client-side tool execution via Return Control, and enforce IAM least-privilege boundaries.
Action Groups Architecture
An Action Group defines a set of related business actions that an Amazon Bedrock Agent can perform. When an agent determines during its ReAct loop that external intervention is needed, it consults its registered Action Groups.
Each Action Group consists of three primary elements:
- Action Group Name and Description: High-level semantic context describing the scope of actions (e.g.,
CustomerBillingActionsfor invoice queries and payment processing). - Interface Definition: The API contract defining available operations, paths, HTTP methods, and parameter schemas. This is provided either as an OpenAPI 3.0 specification stored in Amazon S3 or as inline function definitions.
- Action Execution Target: The fulfillment mechanism. This is typically an AWS Lambda function that executes the business logic. Alternatively, developers can configure Return Control (
RETURN_CONTROL), which delegates tool execution directly to the client calling application.
Defining Action Group Schemas: OpenAPI 3.0 vs. Inline Functions
Developers have two architectural approaches for defining action group contracts:
1. OpenAPI 3.0 Specification (S3 or Inline Schema)
For complex RESTful architectures, existing enterprise services, or teams adhering to API-first design, developers define an OpenAPI 3.0 specification in JSON or YAML format and upload it to an Amazon S3 bucket (or provide it inline).
openapi: 3.0.0
info:
title: Corporate IT Support API
version: 1.0.0
description: Actions for checking device status and resetting enterprise credentials.
paths:
/devices/{deviceId}/status:
get:
summary: Check corporate device hardware and compliance status
description: Retrieves diagnostic telemetry, OS patch level, and encryption compliance for a corporate device.
operationId: getDeviceStatus
parameters:
- name: deviceId
in: path
required: true
description: The unique corporate hardware serial number (e.g., DEV-99421)
schema:
type: string
responses:
'200':
description: Device telemetry retrieved successfully
content:
application/json:
schema:
type: object
properties:
isCompliant:
type: boolean
lastCheckIn:
type: string
The Critical Role of Semantic Descriptions
In conventional REST development, OpenAPI description and summary fields are optional documentation for human developers. In Amazon Bedrock Agents, however, descriptions are executable prompt instructions. The foundation model inspects these descriptions during prompt orchestration to determine:
- Whether the tool is relevant to the user's intent.
- Which specific path and HTTP method to invoke.
- How to format and extract parameters from conversation history.
[!IMPORTANT] A parameter named
idwith no description will cause frequent agent tool-calling failures. Renaming or describing it asThe 8-digit alphanumeric employee badge ID (e.g., EMP12345)gives the foundation model the exact semantic guidance needed to bind arguments correctly.
2. Inline Function Definitions (Code-First / Simplified)
For lightweight tools or microservices where authoring a full OpenAPI 3.0 document introduces unnecessary overhead, Bedrock allows developers to define functions directly via the AWS Management Console or AWS SDK. Developers declare the function name, description, and an array of parameters with types (string, number, integer, boolean, array), descriptions, and a required flag.
AWS Lambda Integration: The Invocation Event Schema
When an agent selects a tool backed by an AWS Lambda function, Bedrock constructs a standardized JSON event payload and invokes the Lambda function synchronously. Understanding this event structure is essential for authoring robust Lambda handler logic.
{
"messageVersion": "1.0",
"agent": {
"name": "ITSupportAgent",
"id": "AGT10EXAMPLE",
"alias": "PROD",
"version": "2"
},
"inputText": "Can you check if device DEV-99421 is compliant?",
"sessionId": "sess-8834-user-9",
"actionGroup": "DeviceManagementActions",
"apiPath": "/devices/{deviceId}/status",
"httpMethod": "GET",
"parameters": [
{
"name": "deviceId",
"type": "string",
"value": "DEV-99421"
}
],
"requestBody": {
"content": {
"application/json": {
"properties": []
}
}
},
"sessionAttributes": {
"userRole": "Tier2Support",
"authenticatedUser": "alice@corp.internal"
},
"promptSessionAttributes": {
"temporaryCorrelationId": "corr-99214"
}
}
Key Event Fields
actionGroup: Identifies which action group triggered the execution.apiPath: The exact URI template from the OpenAPI schema (or the function name if using inline functions).httpMethod: The verb (GET,POST,PUT,DELETE).parameters: An array of parameter objects extracted from path, query, or header locations.requestBody: The parsed body payload conforming to the OpenAPI requestBody schema.sessionAttributes&promptSessionAttributes: Contextual state passed from the client or previous Lambda executions.
Constructing the Lambda Response Payload
The AWS Lambda function must return a strictly formatted JSON envelope. If the returned payload deviates from this structure, the Bedrock runtime treats the action execution as an unhandled error and enters fallback recovery.
{
"messageVersion": "1.0",
"response": {
"actionGroup": "DeviceManagementActions",
"apiPath": "/devices/{deviceId}/status",
"httpMethod": "GET",
"httpStatusCode": 200,
"responseBody": {
"application/json": {
"body": "{\"deviceId\": \"DEV-99421\", \"isCompliant\": true, \"osVersion\": \"macOS 15.1\", \"lastCheckIn\": \"2026-09-25T14:22:00Z\"}"
}
}
},
"sessionAttributes": {
"lastQueriedDevice": "DEV-99421"
}
}
[!CAUTION] Notice that the
bodyfield underresponseBody.application/jsonmust be a stringified JSON string (or plain text string), not a raw nested JSON dictionary. Returning a raw JSON object instead of a stringified payload will trigger a schema parsing exception in the Bedrock orchestration engine.
Python Lambda Implementation Example
import json
def lambda_handler(event, context):
action_group = event.get('actionGroup')
api_path = event.get('apiPath')
http_method = event.get('httpMethod')
parameters = {p['name']: p['value'] for p in event.get('parameters', [])}
response_data = {}
status_code = 200
if api_path == '/devices/{deviceId}/status' and http_method == 'GET':
device_id = parameters.get('deviceId')
# Business logic: query corporate asset management database
response_data = {
"deviceId": device_id,
"isCompliant": True,
"osVersion": "macOS 15.1",
"lastCheckIn": "2026-09-25T14:22:00Z"
}
else:
status_code = 404
response_data = {"error": "Unsupported operation"}
# Assemble the strict Bedrock Agent response envelope
return {
"messageVersion": "1.0",
"response": {
"actionGroup": action_group,
"apiPath": api_path,
"httpMethod": http_method,
"httpStatusCode": status_code,
"responseBody": {
"application/json": {
"body": json.dumps(response_data)
}
}
}
}
Client-Side Tool Execution: Return Control (RETURN_CONTROL)
In certain architectures, security policies or operational boundaries prevent AWS Lambda functions from directly executing actions. For example:
- The target system resides in an on-premises datacenter without VPC connectivity to AWS.
- The action requires interactive user confirmation in a client GUI (e.g., approving a high-value wire transfer or biometric verification).
- The tool needs client-side state (such as local device hardware access, camera, or browser DOM).
In these scenarios, developers configure the Action Group to use Return Control (customControl: RETURN_CONTROL). Instead of invoking Lambda, Bedrock emits a returnControl block in the InvokeAgent response stream containing the invocationId, actionGroup, apiPath, and parsed parameters. The client application executes the action locally and submits the result back to Bedrock in a subsequent InvokeAgent request using the invocationInputs block.
Security: IAM Resource-Based Policies on AWS Lambda
By default, AWS Lambda rejects invocation requests from external services. To allow Amazon Bedrock to invoke the backing Lambda function, developers must attach an IAM Resource-Based Policy to the Lambda function.
To adhere to least privilege, the policy must not only grant lambda:InvokeFunction to the bedrock.amazonaws.com service principal, but it must include an AWS:SourceArn condition matching the specific Bedrock Agent ARN.
{
"Version": "2012-10-17",
"Id": "BedrockAgentLambdaPolicy",
"Statement": [
{
"Sid": "AllowBedrockAgentInvocation",
"Effect": "Allow",
"Principal": {
"Service": "bedrock.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:ITSupportActionHandler",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:bedrock:us-east-1:123456789012:agent/AGT10EXAMPLE"
}
}
}
]
}
[!WARNING] Omitting the
AWS:SourceArncondition creates a confused deputy vulnerability, where any customer in the AWS region could potentially configure their Bedrock agent to invoke your Lambda function.
Action Group Architectural Patterns Comparison
| Pattern | Schema Mechanism | Fulfillment Location | Best Suited For |
|---|---|---|---|
| Standard Lambda with OpenAPI | OpenAPI 3.0 specification in S3 | AWS Lambda | Enterprise REST services, microservices, complex multi-parameter endpoints. |
| Inline Functions with Lambda | Console/SDK inline function declarations | AWS Lambda | Rapid prototyping, lightweight tools, operations with fewer than 5 parameters. |
Return Control (RETURN_CONTROL) | OpenAPI or Inline Functions | Client Application / Frontend | On-premises systems, human-in-the-loop approvals, client-side hardware interactions. |
Exam Scenarios & Common Architectural Traps
Real-World Exam Scenario
A developer creates an Action Group backed by a Lambda function. During testing via the Bedrock console, the agent formulates the correct thought and identifies the tool, but the execution terminates with the error: "DependencyFailedException: Amazon Bedrock could not invoke the Lambda function due to an access denied exception."
Diagnosis & Resolution: The Lambda function does not have a resource-based policy permitting bedrock.amazonaws.com to call lambda:InvokeFunction. The developer must execute aws lambda add-permission --function-name <name> --statement-id AllowBedrock --action lambda:InvokeFunction --principal bedrock.amazonaws.com --source-arn <agent-arn>.
Common Architectural Traps
- Trap 1: Returning Raw JSON Instead of Stringified Body: Returning
"responseBody": {"application/json": {"body": {"status": "ok"}}}triggers an invalid response format error. Thebodymust be a serialized string:json.dumps({"status": "ok"}). - Trap 2: Vague OpenAPI Parameter Descriptions: Authoring an OpenAPI spec where parameters lack descriptions forces the foundation model to guess the semantic meaning of variables, leading to hallucinations or incorrect tool invocation.
- Trap 3: Confusing Agent Execution Role with Lambda Resource Policy: The Agent Execution Role grants permissions for Bedrock to call services (identity-based policy). However, Lambda requires a resource-based policy on the Lambda function itself to permit cross-service invocation.
A developer writes an AWS Lambda function to serve as an action group target for an Amazon Bedrock Agent. When testing the agent, the tool invocation fails with an invalid response structure error. The developer inspects the Lambda return payload: { "status": 200, "data": {"balance": 450.00, "currency": "USD"} } What structural modification must the developer make to satisfy Amazon Bedrock Agent specifications?
An engineer deploys an Amazon Bedrock Agent with an action group backed by an AWS Lambda function in the us-east-1 region. When invoking the agent, the CloudWatch trace logs show that tool execution failed with an AccessDeniedException when attempting to invoke the Lambda function. Which configuration is required to resolve this authorization failure according to least privilege?
An organization is defining an OpenAPI 3.0 specification for an action group that allows an Amazon Bedrock Agent to manage corporate cloud infrastructure. During pilot testing, the agent frequently selects the wrong API operation or attempts to supply invalid data types for resource tags. What schema design best practice directly remedies this behavior?