Build Dynamic AI Workflows with Lambda and Bedrock Prompt Flow

Introduction

Amazon Bedrock Flows enables you to build and orchestrate AI workflows using a visual builder, seamlessly integrating with Amazon Bedrock services like foundational models, knowledge bases, and prompt management. It also connects with other AWS services, such as AWS Lambda and Amazon S3.

This article shows you how to integrate AWS Lambda with Amazon Bedrock Prompt Flow to create an intelligent data retrieval and processing system. This solution helps you automate data processing and generate user-friendly summaries, improving efficiency and user experience. You will learn how to create a serverless solution that:

  1. Retrieves data from Amazon DynamoDB using the Lambda function
  2. Processes the retrieved data using Bedrock Prompt Flow
  3. Generates user-friendly summaries of access request details

Architecture Diagram

The following diagram illustrates the solution architecture:

AWS Cloud

The solution works as follows.

  1. The user sends a request with input parameters to Bedrock Prompt Flow.
  2. Bedrock Prompt Flow invokes the Lambda function with the request parameters.
  3. The lambda function queries DynamoDB using the provided Request ID to fetch record details.
  4. Lambda returns the DynamoDB response to Bedrock prompt flow.
  5. Bedrock prompt flow generates a user-friendly summary and returns it to the user.

Note: The condition node checks the Lambda response. If no data is found, it sends the response directly to the output. Otherwise, the data is sent to the prompt node for summarization.

Flow design

The following diagram shows the components and their interactions in the prompt flow:

AWS Flow Diagram

Prerequisites

  1. AWS Account with these permissions:
    1. Amazon Bedrock: Create/manage flows and access foundation models
    2. IAM: Create/manage policies and roles
    3. AWS Lambda: Create/manage functions
    4. Amazon DynamoDB: Create/manage tables
  2. Install or update to the latest version of the AWS CLI (version 2.x or later).
  3. Get credentials to grant programmatic access.

Implementation Steps


1. Create a DynamoDB Table

Create a table to store access request details.

  1. Open Command Prompt.
  2. Create a DynamoDB table using the CLI command:
    aws dynamodb create-table ^
        --table-name SharePointAccessRequests ^
        --attribute-definitions AttributeName=RequestId,AttributeType=S ^
        --key-schema AttributeName=RequestId,KeyType=HASH ^
        --billing-mode PAY_PER_REQUEST ^
        --table-class STANDARD
  3. Add sample items using the CLI command:
    aws dynamodb put-item ^
        --table-name SharePointAccessRequests  ^
        --item ^
            "{\"RequestId\": {\"S\": \"REQ27022025001\"}, \"Approver\": {\"S\": \"[email protected]\"},\"Requester\": {\"S\": \"[email protected]\"},\"SiteURL\": {\"S\": \"https://xxxx.sharepoint.com/sites/projectx\"},\"Status\": {\"S\": \"In Progress\"},\"BusinessJustification\": {\"S\": \"I am part of Project X team and need to collaborate with the team and project documents so kindly provide access to the SharePoint site\"}, \"Comments\": {\"S\": \"Work in progress\"}, \"CreatedDate\": {\"S\": \"2025-02-27 10:10:10\"}, \"ModifiedDate\": {\"S\": \"2025-02-27 11:10:10\"}}"
    
    aws dynamodb put-item ^
        --table-name SharePointAccessRequests  ^
        --item ^
            "{\"RequestId\": {\"S\": \"REQ27022025002\"}, \"Approver\": {\"S\": \"[email protected]\"},\"Requester\": {\"S\": \"[email protected]\"},\"SiteURL\": {\"S\": \"https://xxxx.sharepoint.com/sites/projecty\"},\"Status\": {\"S\": \"In Progress\"},\"BusinessJustification\": {\"S\": \"I am part of Project Y team and need to collaborate with the team and project documents so kindly provide access to the SharePoint site\"}, \"Comments\": {\"S\": \"Work in progress\"}, \"CreatedDate\": {\"S\": \"2025-02-27 10:10:10\"}, \"ModifiedDate\": {\"S\": \"2025-02-27 11:10:10\"}}"
    

2. Create a Lambda Execution Role

Create an IAM role that grants Lambda permission to access other AWS services.

  1. Create a JSON file with the following content and save it as trust-policy.json.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": "lambda.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }
  2. Open Command Prompt. Navigate to your JSON file location using the 'cd' command.
  3. Create Lambda execution role using CLI command:
    aws iam create-role ^
      --role-name AWSLambdaRetrieveRequestByIdServiceRole ^
      --assume-role-policy-document file://trust-policy.json

3. Create a Permission Policy for Lambda Function

Create a permission policy to allow Amazon CloudWatch log creation, log writing, and DynamoDB table read/write access.

  1. Create a JSON file with the following content and save it as lambda-function-policy.json. Replace the <region> and <account-id> with the actual values.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "logs:CreateLogGroup",
                "Resource": "arn:aws:logs:<region>:<account-id>:*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                ],
                "Resource": [
                    "arn:aws:logs:<region>:<account-id>:log-group:/aws/lambda/retrieve-request-by-id:*"
                ]
            },
            {
                "Effect": "Allow",
                "Action": [
                    "dynamodb:DescribeTable",
                    "dynamodb:GetItem"
                ],
                "Resource": "arn:aws:dynamodb:<region>:<account-id>:table/SharePointAccessRequests"
            },
            {
                "Effect": "Allow",
                "Action": "dynamodb:ListTables",
                "Resource": "*"
            }
        ]
    }
  2. Open Command Prompt. Navigate to your JSON file location using the 'cd' command.
  3. Create a permission policy using the CLI command:
    aws iam create-policy ^
      --policy-name AWSLambdaRetrieveRequestByIdServicePolicy ^
      --policy-document file://lambda-function-policy.json

4. Attach the permission policy to the Lambda Execution Role

Attach the created policy to enable Lambda to access CloudWatch and DynamoDB.

  1. Open Command Prompt.
  2. Attach the policy to the execution role using the CLI command: Replace <account-id> with the actual value.
    aws iam attach-role-policy ^
      --role-name AWSLambdaRetrieveRequestByIdServiceRole ^
      --policy-arn arn:aws:iam::<account-id>:policy/AWSLambdaRetrieveRequestByIdServicePolicy

5. Create the Lambda function

Create the Lambda function to retrieve the request details from the DynamoDB table based on the Request ID.

  1. Create a Python file (.py extension) and add the following code. Save it as lambda_function.py.
    import json
    import boto3
    import os
    from botocore.exceptions import ClientError
    
    # Initialize a session using Amazon DynamoDB
    dynamodb = boto3.resource('dynamodb')
    
    def lambda_handler(event, context):
        # Fetch environment variables
        table_name = os.environ['DYNAMODB_TABLE_NAME']    
    
        # Extract RequestId from the event 
        request_id = event.get('node', {}).get('inputs', [{}])[0].get('value', {}).get('requestId', None)
        if not request_id:
            return {
                'statusCode': 400,
                'body': json.dumps('RequestId is missing in the input')
            }
    
        # Reference to the DynamoDB table
        table = dynamodb.Table(table_name)
    
        try:
            # Get the item based on RequestId
            response = table.get_item(
                Key={
                    'RequestId': request_id  
                }
            )
    
            # Check if the item exists in the table
            if 'Item' in response:
                return {
                    'statusCode': 200,
                    'body': json.dumps(response['Item'])  # Return the item data as JSON
                }
            else:
                return {
                    'statusCode': 404,
                    'body': json.dumps(f"No item found with RequestId: {request_id}")
                }
    
        except ClientError as e:
            return {
                'statusCode': 500,
                'body': json.dumps(f"An error occurred: {e.response['Error']['Message']}")
            }
    
  2. Zip the Python file and name it as function.zip.
  3. Open Command Prompt. Navigate to your function.zip file location using the 'cd' command.
  4. Create Lambda function using CLI command: Replace <account-id> with actual value.
    aws lambda create-function ^
        --function-name retrieve-request-by-id ^
        --runtime python3.13 ^
        --handler lambda_function.lambda_handler ^
        --zip-file fileb://function.zip ^
        --role arn:aws:iam::<account-id>:role/AWSLambdaRetrieveRequestByIdServiceRole ^
        --environment Variables={DYNAMODB_TABLE_NAME="SharePointAccessRequests"} ^
        --timeout 180

6. Create a Bedrock Service Role

Create an IAM role that allows Amazon Bedrock to access other AWS services.

  1. Create a JSON file with the following content and save it as trust-policy.json. Replace the <region> and <account-id> with the actual values.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": "bedrock.amazonaws.com"
                },
                "Action": "sts:AssumeRole",
                "Condition": {
                    "StringEquals": {
                        "aws:SourceAccount": "<account-id>"
                    },
                    "ArnLike": {
                        "aws:SourceArn": "arn:aws:bedrock:<region>:<account-id>:flow/*"
                    }
                }
            }
        ]
    }
  2. Open Command Prompt. Navigate to your JSON file location using the 'cd' command.
  3. Create service role using CLI command:
    aws iam create-role ^
      --role-name AmazonBedrockFlowInvokeLambdaServiceRole ^
      --assume-role-policy-document file://trust-policy.json

7. Create the permission policy for the Bedrock Service Role

Create a permission policy to allow Amazon Bedrock to invoke the model and Lambda function.

  1. Create a JSON file with the following content and save it as flow-permission-policy.json. Replace the <region> and <account-id> with the actual values.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "InvokeModel",
                "Effect": "Allow",
                "Action": "bedrock:InvokeModel",
                "Resource": [
                    "arn:aws:bedrock:<region>::foundation-model/anthropic.claude-3-5-sonnet-20240620-v1:0"
                ]
            },
            {
                "Sid": "GetFlow",
                "Effect": "Allow",
                "Action": [
                    "bedrock:GetFlow"
                ],
                "Resource": [
                    "arn:aws:bedrock:<region>:<account-id>:flow/*"
                ]
            },
            {
                "Sid": "InvokeLambda",
                "Effect": "Allow",
                "Action": "lambda:InvokeFunction",
                "Resource": "arn:aws:lambda:<region>:<account-id>:function:retrieve-request-by-id:*"
            }
        ]
    }
  2. Open Command Prompt. Navigate to your JSON file location using the 'cd' command.
  3. Create a permission policy using the CLI command:
    aws iam create-policy ^
      --policy-name AmazonBedrockFlowInvokeLambdaServicePolicy ^
      --policy-document file://flow-permission-policy.json

8. Attach the permission policy to the Bedrock Service Role

Attach the created policy to enable Bedrock to invoke the model and Lambda function.

  1. Open Command Prompt.
  2. Attach the policy to the service role using the CLI command: Replace <account-id> with the actual value.
    aws iam attach-role-policy ^
      --role-name AmazonBedrockFlowInvokeLambdaServiceRole ^
      --policy-arn arn:aws:iam::<account-id>:policy/AmazonBedrockFlowInvokeLambdaServicePolicy

9. Create a prompt flow

Create and configure the prompt flow to handle request processing and response formatting.

  1. Create a JSON file with the following content and save it as flow-definition.json. Refer to this Create Flow request syntax documentation to prepare the flow definition. Note: Alternatively, you can use the Amazon Bedrock console to create the flow based on your requirements in the visual builder. Once you've created the flow, you can use the get-flow CLI command to retrieve the flow definition. Replace the <region> and <account-id> with the actual values for Lambda ARN.
    {
        "connections": [
            {
                "configuration": {
                    "data": {
                        "sourceOutput": "document",
                        "targetInput": "codeHookInput"
                    }
                },
                "name": "FlowInputNodeFlowInputNode0ToLambdaFunctionNode_RetrieveRequestByIdLambdaFunctionNode0",
                "source": "FlowInputNode",
                "target": "LambdaFunctionNode_RetrieveRequestById",
                "type": "Data"
            },
            {
                "configuration": {
                    "data": {
                        "sourceOutput": "modelCompletion",
                        "targetInput": "document"
                    }
                },
                "name": "Prompt_SummarizeResultPromptsNode0ToFlowOutputNode_ItemsExistsFlowOutputNode0",
                "source": "Prompt_SummarizeResult",
                "target": "FlowOutputNode_ItemsExists",
                "type": "Data"
            },
            {
                "configuration": {
                    "data": {
                        "sourceOutput": "functionResponse",
                        "targetInput": "statusCode"
                    }
                },
                "name": "LambdaFunctionNode_RetrieveRequestByIdLambdaFunctionNode0ToConditionNode_CheckStatusCodeConditionNode0",
                "source": "LambdaFunctionNode_RetrieveRequestById",
                "target": "ConditionNode_CheckStatusCode",
                "type": "Data"
            },
            {
                "configuration": {
                    "conditional": {
                        "condition": "Condition"
                    }
                },
                "name": "ConditionNode_CheckStatusCodeConditionNodeHandle0ToFlowOutputNode_NoItemFoundFlowOutputNode_NoItemFoundHeaderHandle",
                "source": "ConditionNode_CheckStatusCode",
                "target": "FlowOutputNode_NoItemFound",
                "type": "Conditional"
            },
            {
                "configuration": {
                    "data": {
                        "sourceOutput": "functionResponse",
                        "targetInput": "document"
                    }
                },
                "name": "LambdaFunctionNode_RetrieveRequestByIdLambdaFunctionNode0ToFlowOutputNode_NoItemFoundFlowOutputNode0",
                "source": "LambdaFunctionNode_RetrieveRequestById",
                "target": "FlowOutputNode_NoItemFound",
                "type": "Data"
            },
            {
                "configuration": {
                    "conditional": {
                        "condition": "default"
                    }
                },
                "name": "ConditionNode_CheckStatusCodeConditionNodeHandleDefaultConditionNode_CheckStatusCodeToPrompt_SummarizeResultPrompt_SummarizeResultHeaderHandle",
                "source": "ConditionNode_CheckStatusCode",
                "target": "Prompt_SummarizeResult",
                "type": "Conditional"
            },
            {
                "configuration": {
                    "data": {
                        "sourceOutput": "functionResponse",
                        "targetInput": "functionResponse"
                    }
                },
                "name": "LambdaFunctionNode_RetrieveRequestByIdLambdaFunctionNode0ToPrompt_SummarizeResultPromptsNode0",
                "source": "LambdaFunctionNode_RetrieveRequestById",
                "target": "Prompt_SummarizeResult",
                "type": "Data"
            }
        ],
        "nodes": [
            {
                "configuration": {
                    "input": {}
                },
                "name": "FlowInputNode",
                "outputs": [
                    {
                        "name": "document",
                        "type": "Object"
                    }
                ],
                "type": "Input"
            },
            {
                "configuration": {
                    "output": {}
                },
                "inputs": [
                    {
                        "expression": "$.data",
                        "name": "document",
                        "type": "String"
                    }
                ],
                "name": "FlowOutputNode_ItemsExists",
                "type": "Output"
            },
            {
                "configuration": {
                    "lambdaFunction": {
                        "lambdaArn": "arn:aws:lambda:<region>:<account-id:function:retrieve-request-by-id:$LATEST"
                    }
                },
                "inputs": [
                    {
                        "expression": "$.data.event",
                        "name": "codeHookInput",
                        "type": "Object"
                    }
                ],
                "name": "LambdaFunctionNode_RetrieveRequestById",
                "outputs": [
                    {
                        "name": "functionResponse",
                        "type": "Object"
                    }
                ],
                "type": "LambdaFunction"
            },
            {
                "configuration": {
                    "prompt": {
                        "sourceConfiguration": {
                            "inline": {
                                "additionalModelRequestFields": {
                                    "top_k": 250.0
                                },
                                "inferenceConfiguration": {
                                    "text": {
                                        "maxTokens": 2000,
                                        "stopSequences": [],
                                        "temperature": 1.0,
                                        "topP": 0.9990000128746033
                                    }
                                },
                                "modelId": "anthropic.claude-3-5-sonnet-20240620-v1:0",
                                "templateConfiguration": {
                                    "text": {
                                        "inputVariables": [
                                            {
                                                "name": "functionResponse"
                                            }
                                        ],
                                        "text": "You are an assistant that summarizes request details for users. Please take the following JSON response, which contains details about a SharePoint site access request, and format it in a user-friendly summary.\n\nJSON Data:\n{{functionResponse}}\n\nYour task:\n1. Summarize the SharePoint site access request by extracting the key details such as:\n   - Request Title\n   - Request ID\n   - Requester's Name and Email\n   - Approver's Name and Email\n   - Status of the request\n   - Comments provided by the requester\n   - Business Justification\n   - Site URL\n   - Created Date and Modified Date\n\n2. Provide the summary in a well-structured format with a human-friendly tone.\n\nYour output should look like this:\n\nSummary:\nRequest Title: [Title]\nRequest ID: [RequestId]\nRequester: [Requester Name] ([Requester Email])\nApprover: [Approver Name] ([Approver Email])\nStatus: [Status]\nComments: [Comments]\nBusiness Justification: [Business Justification]\nSite URL: [Site URL]\nCreated Date: [Created Date]\nModified Date: [Modified Date]\n\nDon't include any other text.\n"
                                    }
                                },
                                "templateType": "TEXT"
                            }
                        }
                    }
                },
                "inputs": [
                    {
                        "expression": "$.data",
                        "name": "functionResponse",
                        "type": "Object"
                    }
                ],
                "name": "Prompt_SummarizeResult",
                "outputs": [
                    {
                        "name": "modelCompletion",
                        "type": "String"
                    }
                ],
                "type": "Prompt"
            },
            {
                "configuration": {
                    "condition": {
                        "conditions": [
                            {
                                "expression": "(statusCode == 404)",
                                "name": "Condition"
                            },
                            {
                                "name": "default"
                            }
                        ]
                    }
                },
                "inputs": [
                    {
                        "expression": "$.data.statusCode",
                        "name": "statusCode",
                        "type": "Number"
                    }
                ],
                "name": "ConditionNode_CheckStatusCode",
                "type": "Condition"
            },
            {
                "configuration": {
                    "output": {}
                },
                "inputs": [
                    {
                        "expression": "$.data.body",
                        "name": "document",
                        "type": "String"
                    }
                ],
                "name": "FlowOutputNode_NoItemFound",
                "type": "Output"
            }
        ]
    }
  2. Open Command Prompt. Navigate to your JSON file location using the 'cd' command.
  3. Create a new flow using the CLI command: Replace <account-id> with the actual value and note down the flow ID.
    aws bedrock-agent create-flow ^
      --name "RetriveRequestDetailsFlow" ^
      --description "Flow to retrieve the SharePoint access request details" ^
      --execution-role-arn "arn:aws:iam::<account-id>:role/AmazonBedrockFlowInvokeLambdaServiceRole" ^
      --definition file://flow-definition.json
  4. Prepare the DRAFT version of a flow using the CLI command: Replace <flow-id> with the actual value.
    aws bedrock-agent prepare-flow --flow-identifier <flow-id>
  5. Create a version of the flow using the CLI command: Replace <flow-id> with the actual value.
    aws bedrock-agent create-flow-version --flow-identifier <flow-id>
  6. Create an alias of a flow using the CLI command: Replace <flow-id> with the actual value.
    aws bedrock-agent create-flow-alias ^
        --flow-identifier <flow-id> ^
        --name dev ^
        --routing-configuration flowVersion="1"

10. Validate the flow

Test the flow to ensure proper integration and response formatting.

  1. Navigate to the Amazon Bedrock service in the AWS Console.
  2. In the left-hand navigation pane, under the Builder Tools section, choose Flows and select the newly created flow.
  3. Choose Edit in the flow builder.
  4. In the Test flow section, enter the following prompt to view the response and the trace.

Conclusion

In this article, you learned how to build an intelligent data retrieval and processing system by integrating AWS Lambda with Amazon Bedrock. The solution can serve as a foundation for various use cases, such as:

  • Processing Customer Service Requests
  • Creating Intelligent Data Workflows
  • Automating Document Processing

Next Steps

To extend this solution, consider:

  • Creating custom prompt templates
  • Integrating with other AWS services

Additional Resources

Up Next
    Ebook Download
    View all
    Learn
    View all