generative-ai-cdk-constructs

Amazon Bedrock Agents

Amazon Bedrock Agents allow generative AI applications to automate complex, multistep tasks by seamlessly integrating with your company’s systems, APIs, and data sources.

Table of Contents

Agent Properties

Name Type Required Description
name string No The name of the agent. Defaults to a name generated by CDK
instruction string Yes The instruction used by the agent that determines how it will perform his task. Must have a minimum of 40 characters
foundationModel IInvokable Yes The foundation model used for orchestration by the agent
existingRole iam.IRole No The existing IAM Role for the agent to use. Must have a trust policy allowing Bedrock service to assume the role. Defaults to a new created role
shouldPrepareAgent boolean No Specifies whether to automatically update the DRAFT version of the agent after making changes. Defaults to false
idleSessionTTL Duration No How long sessions should be kept open for the agent. Session expires if no conversation occurs during this time. Defaults to 1 hour
kmsKey kms.IKey No The KMS key of the agent if custom encryption is configured. Defaults to AWS managed key
description string No A description of the agent. Defaults to no description
knowledgeBases IKnowledgeBase[] No The KnowledgeBases associated with the agent
actionGroups AgentActionGroup[] No The Action Groups associated with the agent
guardrail IGuardrail No The guardrail that will be associated with the agent
promptOverrideConfiguration PromptOverrideConfiguration No Overrides some prompt templates in different parts of an agent sequence configuration
userInputEnabled boolean No Select whether the agent can prompt additional information from the user when it lacks enough information. Defaults to false
codeInterpreterEnabled boolean No Select whether the agent can generate, run, and troubleshoot code when trying to complete a task. Defaults to false
forceDelete boolean No Whether to delete the resource even if it’s in use. Defaults to true
memory Memory No The type and configuration of the memory to maintain context across multiple sessions
agentCollaboration AgentCollaboratorType No The collaboration type for the agent. Defaults to DISABLED
agentCollaborators AgentCollaborator[] No Collaborators that this agent will work with
customOrchestration CustomOrchestration No Details of custom orchestration for the agent
orchestrationType OrchestrationType No The type of orchestration to use for the agent. Defaults to STANDARD

Create an Agent

The following example creates an Agent with a simple instruction and default prompts that consults a Knowledge Base.

TypeScript

const agent = new bedrock.Agent(this, 'Agent', {
  foundationModel: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_HAIKU_V1_0,
  instruction: 'You are a helpful and friendly agent that answers questions about literature.',
});

agent.addKnowledgeBase(kb);

Python

agent = bedrock.Agent(
    self,
    "Agent",
    foundation_model=bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_HAIKU_V1_0,
    instruction="You are a helpful and friendly agent that answers questions about insurance claims.",
)

agent.add_knowledge_base(kb)

You can also use system defined inference profiles to enable cross region inference requests for supported models. For instance:

TypeScript

const cris = bedrock.CrossRegionInferenceProfile.fromConfig({
  geoRegion: bedrock.CrossRegionInferenceProfileRegion.US,
  model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V1_0,
});

const agent = new bedrock.Agent(this, 'Agent', {
  foundationModel: cris,
  instruction: 'You are a helpful and friendly agent that answers questions about agriculture.',
});

Python

cris = bedrock.CrossRegionInferenceProfile.from_config(
  geo_region= bedrock.CrossRegionInferenceProfileRegion.US,
  model= bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V1_0
)

agent = bedrock.Agent(
    self,
    "Agent",
    foundation_model=cris,
    instruction="You are a helpful and friendly agent that answers questions about agriculture.",
)

For more information on cross region inference, please refer to Inference profiles.

Preparing an Agent

The Agent constructs take an optional parameter shouldPrepareAgent to indicate that the Agent should be prepared after any updates to an agent, Knowledge Base association, or action group. This may increase the time to create and update those resources. By default, this value is false .

Creating an agent alias will not prepare the agent, so if you create an alias using the AgentAlias resource then you should set shouldPrepareAgent to true.

Prompt Overriding

Bedrock Agents allows you to customize the prompts and LLM configuration for its different steps. You can disable steps or create a new prompt template. Prompt templates can be inserted from plain text files.

TypeScript

import { readFileSync } from 'fs';

const file = readFileSync(prompt_path, 'utf-8');

const agent = new bedrock.Agent(this, 'Agent', {
      foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
      instruction: 'You are a helpful and friendly agent that answers questions about literature.',
      userInputEnabled: true,
      codeInterpreterEnabled: false,
      shouldPrepareAgent:true,
      promptOverrideConfiguration: bedrock.PromptOverrideConfiguration.fromSteps(
        [
          {
            stepType: bedrock.AgentStepType.PRE_PROCESSING,
            stepEnabled: true,
            customPromptTemplate: file,
            inferenceConfig: {
              temperature: 0.0,
              topP: 1,
              topK: 250,
              maximumLength: 1,
              stopSequences: ["\n\nHuman:"],
            },
            foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1
          }
        ]
      )
    });

Python

orchestration = open('prompts/orchestration.txt', encoding="utf-8").read()
agent = bedrock.Agent(self, "Agent",
            foundation_model=bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_V2_1,
            instruction="You are a helpful and friendly agent that answers questions about insurance claims.",
            user_input_enabled=True,
            code_interpreter_enabled=False,
            should_prepare_agent=True,
            prompt_override_configuration= bedrock.PromptOverrideConfiguration.from_steps(
                steps=[
                    bedrock.PromptStepConfiguration(
                        step_type=bedrock.AgentStepType.PRE_PROCESSING,
                        step_enabled= True,
                        custom_prompt_template= file,
                        inference_config=bedrock.InferenceConfiguration(
                            temperature=0.0,
                            top_k=250,
                            top_p=1,
                            maximum_length=1,
                            stop_sequences=['\n\nHuman:'],
                        ),
                        foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1
                    ),
                ]
            ),
        )

Action Groups

An action group defines functions your agent can call. The functions are Lambda functions. The action group uses an OpenAPI schema to tell the agent what your functions do and how to call them.

Action Group Properties

Name Type Required Description
name string Yes The name of the action group
description string No A description of the action group
apiSchema ApiSchema No The API Schema
executor ActionGroupExecutor No The action group executor
enabled boolean No Specifies whether the action group is available for the agent to invoke or not when sending an InvokeAgent request. Defaults to true
forceDelete boolean No Specifies whether to delete the resource even if it’s in use. Defaults to false
functionSchema CfnAgent.FunctionSchemaProperty No Defines functions that each define parameters that the agent needs to invoke from the user
parentActionGroupSignature ParentActionGroupSignature No The AWS Defined signature for enabling certain capabilities in your agent. When specified, description, apiSchema, and actionGroupExecutor must be blank

TypeScript

const actionGroupFunction = new lambda_python.PythonFunction(this, 'ActionGroupFunction', {
  runtime: lambda.Runtime.PYTHON_3_12,
  entry: path.join(__dirname, '../lambda/action-group'),
});

const actionGroup = new AgentActionGroup({
  name: 'query-library',
  description: 'Use these functions to get information about the books in the library.',
  executor: bedrock.ActionGroupExecutor.fromlambdaFunction(actionGroupFunction),
  enabled: true,
  apiSchema: bedrock.ApiSchema.fromLocalAsset(path.join(__dirname, 'action-group.yaml')),
});

agent.addActionGroup(actionGroup);

Python


action_group_function = PythonFunction(
            self,
            "LambdaFunction",
            runtime=Runtime.PYTHON_3_12,
            entry="./lambda",
            index="app.py",
            handler="lambda_handler",
)

actionGroup = bedrock.AgentActionGroup(
    name="query-library",
    description="Use these functions to get information about the books in the library.",
    executor= bedrock.ActionGroupExecutor.fromlambda_function(action_group_function),
    enabled=True,
    api_schema=bedrock.ApiSchema.from_local_asset("action-group.yaml"))

agent.add_action_group(actionGroup)

Memory Configuration

Agents can maintain context across multiple sessions and recall past interactions using memory. This feature is useful for creating a more coherent conversational experience.

Memory Options

You can configure memory for an agent using the memory property in the AgentProps interface. The memory configuration allows you to specify the type of memory and its properties.

TypeScript

import { Agent, Memory, SessionSummaryMemoryProps } from 'src/cdk-lib/bedrock/agents';

const agent = new Agent(this, 'MyAgent', {
  name: 'MyAgent',
  instruction: 'Your instruction here',
  foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
  memory: Memory.sessionSummary({
    maxRecentSessions: 10, // Keep the last 10 session summaries
    memoryDurationDays: 20, // Retain summaries for 20 days
  }),
});

Python

from src.cdk_lib.bedrock.agents import Agent, Memory, BedrockFoundationModel

agent = Agent(self, 'MyAgent',
    name='MyAgent',
    instruction='Your instruction here',
    foundation_model=BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
    memory=Memory.session_summary(
        max_recent_sessions=10,  # Keep the last 10 session summaries
        memory_duration_days=20,  # Retain summaries for 20 days
    ),
)

Memory Properties

Memory Types

Currently, the following memory type is supported:

Agent Collaboration

Agent Collaboration enables multiple Bedrock Agents to work together on complex tasks. This feature allows agents to specialize in different areas and collaborate to provide more comprehensive responses to user queries.

Collaboration Types

You can configure collaboration for an agent using the agentCollaboration and agentCollaborators properties in the AgentProps interface.

TypeScript

import { Agent, AgentCollaboratorType, RelayConversationHistoryType } from '@cdklabs/generative-ai-cdk-constructs';

// Create a specialized agent for customer support
const customerSupportAgent = new Agent(this, 'CustomerSupportAgent', {
  name: 'CustomerSupportAgent',
  instruction: 'You specialize in answering customer support questions about our products.',
  foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
});

// Create an agent alias for the specialized agent
const customerSupportAlias = new AgentAlias(this, 'CustomerSupportAlias', {
  agent: customerSupportAgent,
  aliasName: 'production',
});

// Create a main agent that can collaborate with the specialized agent
const mainAgent = new Agent(this, 'MainAgent', {
  name: 'MainAgent',
  instruction: 'You are a helpful assistant that can answer general questions and route specialized customer support questions to the customer support agent.',
  foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
  agentCollaboration: AgentCollaboratorType.SUPERVISOR,
  agentCollaborators: [
    new bedrock.AgentCollaborator({
      agentAlias: customerSupportAlias,
      collaborationInstruction: 'Route customer support questions to this agent.',
      collaboratorName: 'CustomerSupport',
      relayConversationHistory: true,
    }),
  ],
});

Python

from cdklabs.generative_ai_cdk_constructs import (
    bedrock, 
    AgentCollaboratorType, 
    RelayConversationHistoryType
)

# Create a specialized agent for customer support
customer_support_agent = bedrock.Agent(self, 'CustomerSupportAgent',
    name='CustomerSupportAgent',
    instruction='You specialize in answering customer support questions about our products.',
    foundation_model=bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
)

# Create an agent alias for the specialized agent
customer_support_alias = bedrock.AgentAlias(self, 'CustomerSupportAlias', 
    agent=customer_support_agent,
    alias_name='production',
)

# Create a main agent that can collaborate with the specialized agent
main_agent = bedrock.Agent(self, 'MainAgent',
    name='MainAgent',
    instruction='You are a helpful assistant that can answer general questions and route specialized customer support questions to the customer support agent.',
    foundation_model=bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
    agent_collaboration=AgentCollaboratorType.SUPERVISOR,
    agent_collaborators=[
      bedrock.AgentCollaborator(
        agent_alias= customer_support_alias,
        collaboration_instruction= 'Route customer support questions to this agent.',
        collaborator_name= 'CustomerSupport',
        relay_conversation_history= true,
      )
    ],
)

For more information on agent collaboration, refer to the AWS Bedrock documentation.

Custom Orchestration

Custom Orchestration allows you to override the default agent orchestration flow with your own Lambda function. This enables more control over how the agent processes user inputs, handles knowledge base queries, and invokes action groups.

Orchestration Types

You can configure the orchestration type using the orchestrationType and customOrchestration properties in the AgentProps interface.

TypeScript

import { Agent, OrchestrationType, OrchestrationExecutor } from '@cdklabs/generative-ai-cdk-constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';

// Create a Lambda function for custom orchestration
const orchestrationFunction = new lambda.Function(this, 'OrchestrationFunction', {
  runtime: lambda.Runtime.PYTHON_3_10,
  handler: 'index.handler',
  code: lambda.Code.fromAsset(path.join(__dirname, 'lambda/orchestration')),
});

// Create an agent with custom orchestration
const agent = new Agent(this, 'CustomOrchestrationAgent', {
  name: 'CustomOrchestrationAgent',
  instruction: 'You are a helpful assistant with custom orchestration logic.',
  foundationModel: bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
  orchestrationType: OrchestrationType.CUSTOM_ORCHESTRATION,
  customOrchestration: {
    executor: OrchestrationExecutor.fromlambdaFunction(orchestrationFunction),
  },
});

Python

from cdklabs.generative_ai_cdk_constructs import (
    bedrock, 
    OrchestrationType, 
    OrchestrationExecutor
)
import aws_cdk.aws_lambda as lambda_
import os

# Create a Lambda function for custom orchestration
orchestration_function = lambda_.Function(self, 'OrchestrationFunction',
    runtime=lambda_.Runtime.PYTHON_3_10,
    handler='index.handler',
    code=lambda_.Code.from_asset(os.path.join(os.path.dirname(__file__), 'lambda/orchestration')),
)

# Create an agent with custom orchestration
agent = bedrock.Agent(self, 'CustomOrchestrationAgent',
    name='CustomOrchestrationAgent',
    instruction='You are a helpful assistant with custom orchestration logic.',
    foundation_model=bedrock.BedrockFoundationModel.AMAZON_NOVA_LITE_V1,
    orchestration_type=OrchestrationType.CUSTOM_ORCHESTRATION,
    custom_orchestration=bedrock.CustomOrchestration(
      executor= OrchestrationExecutor.fromlambda_function(orchestration_function),
    )
)

The custom orchestration Lambda function receives events from Bedrock with the user’s input and context, and it can control the flow of the conversation by deciding when to query knowledge bases, invoke action groups, or respond directly to the user.

For more information on custom orchestration, refer to the AWS Bedrock documentation.

Agent Alias

After you have sufficiently iterated on your working draft and are satisfied with the behavior of your agent, you can set it up for deployment and integration into your application by creating aliases of your agent.

To deploy your agent, you need to create an alias. During alias creation, Amazon Bedrock automatically creates a version of your agent. The alias points to this newly created version. You can point the alias to a previously created version if necessary. You then configure your application to make API calls to that alias.

By default, the Agent resource does not create any aliases, and you can use the ‘DRAFT’ version.

TypeScript

const agentAlias2 = new bedrock.AgentAlias(this, 'myalias2', {
  aliasName: 'myalias',
  agent: agent,
  agentVersion: '1', // optional
  description: 'mytest'
});

Python

agent_alias_2 = bedrock.AgentAlias(self, 'myalias2',
    alias_name='myalias',
    agent=agent,
    agent_version='1', # optional
    description='mytest'
)

Permissions and Methods

Agent Methods

Method Description
addKnowledgeBase(knowledgeBase) Adds a knowledge base to the agent
addGuardrail(guardrail) Adds a guardrail to the agent
addActionGroup(actionGroup) Adds an action group to the agent
addAgentCollaborator(agentCollaborator) Adds an agent collaborator to the agent
addActionGroups(...actionGroups) Adds multiple action groups to the agent

Agent Alias Methods

Method Description
grant(grantee, ...actions) Grants the given principal identity permissions to perform actions on this agent alias
grantInvoke(grantee) Grants the given identity permissions to invoke the agent alias
grantGet(grantee) Grants the given identity permissions to get the agent alias
onCloudTrailEvent(id, options?) Defines an EventBridge rule that triggers when something happens to this agent alias

Agent Collaborator Methods

Method Description
grant(grantee) Grants the given identity permissions to collaborate with the agent

Import Methods

TypeScript

// Import an existing agent by ARN
const importedAgent = bedrock.Agent.fromAgentAttrs(this, 'ImportedAgent', {
  agentArn: 'arn:aws:bedrock:region:account:agent/agent-id',
  roleArn: 'arn:aws:iam::account:role/role-name',
  kmsKeyArn: 'arn:aws:kms:region:account:key/key-id', // optional
  lastUpdated: '2023-01-01T00:00:00Z', // optional
  agentVersion: '1', // optional, defaults to 'DRAFT'
});

Python

# Import an existing agent by ARN
imported_agent = bedrock.Agent.from_agent_attrs(
    self, 
    'ImportedAgent',
    agent_arn='arn:aws:bedrock:region:account:agent/agent-id',
    role_arn='arn:aws:iam::account:role/role-name',
    kms_key_arn='arn:aws:kms:region:account:key/key-id',  # optional
    last_updated='2023-01-01T00:00:00Z',  # optional
    agent_version='1'  # optional, defaults to 'DRAFT'
)