Repository: awslabs/generative-ai-cdk-constructs (ts)

Issue:
bedrock: add method to Agent to manage when prepare agent gets run
### Describe the feature

When an Agent, Knowledge Base, or Action Group is created or updated, the agent needs to be prepared by calling the PrepareAgent API. There is already a custom resource to call PrepareAgent, but it is only available within the Agent resource. It is preferable to only call PrepareAgent once after all updates are made.

I would like to be able to add dependencies and optionally a changeId to the PrepareAgent custom resource from outside of the Agent resource.

### Use Case

While developing Agent Action Groups, I see that there needs to be a public way to add a dependency to Prepare Agent. Agent Action Groups depend on an Agent, but the Agent needs to be prepared after creating or updating the Agent Action Group.

### Proposed Solution

An internal method on Agent called `_addPrepareAgentDependency` can be called to add a resource and optionally a changeId so CloudFormation knows to update PrepareAgent when the resource is updated.

```ts
/**
 * Register a dependency for prepareAgent.
 *
 * @param resource - The resource that will be registered as a dependency.
 * @param changeId - The changeId of the resource that will be registered as a dependency.
 *
 * @internal This is an internal core function and should not be called directly.
 */
public _addPrepareAgentDependency(resource: cdk.IResource, changeId?: string) {
  this.prepareAgent.node.addDependency(resource);
  if (changeId) {
    this.changeIds.push(changeId);
  }
}
```

Usage:
```ts
props.agent._addPrepareAgentDependency(agentActionGroup, agentActionGroup.getAttString('changeId'));
```

### Other Information

_No response_

### Acknowledgements

- [X] I may be able to implement this feature request
- [ ] This feature might incur a breaking change

Pull request:
feat(bedrock): method to add deps to PrepareAgent
Fixes #229 

This change makes `changeIds` and `prepareAgent` private fields of agent and adds a public, but internal method named `_addPrepareAgentDependency` to resources created after the Agent, such as an upcoming Action Group, can be dependencies of the PrepareAgent custom resource.

Changes
* Moves the PrepareAgent custom resource to earlier in the file so the Agent and KB Associations can use  the method.
* Use the new method to make the agent and KB association custom resources dependencies of prepareAgent.
* Make prepareAgent a dependency of any aliases.
* Use cdk.Lazy to evaluate changeIds at the end of synth.

---
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.


Patch:
diff --git a/apidocs/classes/bedrock.Agent.md b/apidocs/classes/bedrock.Agent.md
index 907473b..027c785 100644
--- a/apidocs/classes/bedrock.Agent.md
+++ b/apidocs/classes/bedrock.Agent.md
@@ -30,12 +30,15 @@ Deploy a Bedrock Agent.
 - [aliasId](bedrock.Agent.md#aliasid)
 - [aliasName](bedrock.Agent.md#aliasname)
 - [cdkTagManager](bedrock.Agent.md#cdktagmanager)
+- [changeIds](bedrock.Agent.md#changeids)
 - [name](bedrock.Agent.md#name)
 - [node](bedrock.Agent.md#node)
+- [prepareAgent](bedrock.Agent.md#prepareagent)
 - [role](bedrock.Agent.md#role)
 
 ### Methods
 
+- [\_addPrepareAgentDependency](bedrock.Agent.md#_addprepareagentdependency)
 - [addAlias](bedrock.Agent.md#addalias)
 - [toString](bedrock.Agent.md#tostring)
 - [isConstruct](bedrock.Agent.md#isconstruct)
@@ -116,6 +119,14 @@ cdk.ITaggableV2.cdkTagManager
 
 ___
 
+### changeIds
+
+• `Private` **changeIds**: `string`[] = `[]`
+
+A list of values to indicate if PrepareAgent or an Alias needs to be updated.
+
+___
+
 ### name
 
 • `Readonly` **name**: `string`
@@ -136,6 +147,16 @@ Construct.node
 
 ___
 
+### prepareAgent
+
+• `Private` **prepareAgent**: `CustomResource`
+
+The prepareAgent custom resource.
+
+Add other resources as dependencies to ensure Prepare Agent is called after they are updated.
+
+___
+
 ### role
 
 • `Readonly` **role**: `Role`
@@ -144,6 +165,25 @@ The IAM role for the agent.
 
 ## Methods
 
+### \_addPrepareAgentDependency
+
+▸ **_addPrepareAgentDependency**(`resource`, `changeId?`): `void`
+
+Register a dependency for prepareAgent.
+
+#### Parameters
+
+| Name | Type | Description |
+| :------ | :------ | :------ |
+| `resource` | `IResource` | The resource that will be registered as a dependency. |
+| `changeId?` | `string` | The changeId of the resource that will be registered as a dependency. This is an internal core function and should not be called directly. |
+
+#### Returns
+
+`void`
+
+___
+
 ### addAlias
 
 ▸ **addAlias**(`props`): [`AgentAlias`](bedrock.AgentAlias.md)
diff --git a/lambda/aws-qa-appsync-opensearch/question_answering/src/llms/text_generation_llm_selector.py b/lambda/aws-qa-appsync-opensearch/question_answering/src/llms/text_generation_llm_selector.py
index b3c781d..f15f125 100644
--- a/lambda/aws-qa-appsync-opensearch/question_answering/src/llms/text_generation_llm_selector.py
+++ b/lambda/aws-qa-appsync-opensearch/question_answering/src/llms/text_generation_llm_selector.py
@@ -11,7 +11,7 @@
 # and limitations under the License.
 #
 from langchain.llms.bedrock import Bedrock
-from langchain.embeddings import BedrockEmbeddings
+from langchain_community.embeddings import BedrockEmbeddings
 import os
 import boto3
 from .helper import get_credentials
diff --git a/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/chain.py b/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/chain.py
index a1a0862..59d7400 100644
--- a/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/chain.py
+++ b/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/chain.py
@@ -13,11 +13,11 @@
 #
 from .helper import load_vector_db_opensearch, send_job_status, JobStatus
 from .s3inmemoryloader import S3FileLoaderInMemory
-from langchain import PromptTemplate
+from langchain.prompts import PromptTemplate
 from langchain.callbacks.base import BaseCallbackHandler
 from langchain.schema import LLMResult
 from llms import get_llm, get_max_tokens
-from langchain import LLMChain
+from langchain.chains import LLMChain
 
 import boto3
 import os
diff --git a/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/helper.py b/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/helper.py
index 56607b4..d59f294 100644
--- a/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/helper.py
+++ b/lambda/aws-qa-appsync-opensearch/question_answering/src/qa_agent/helper.py
@@ -10,7 +10,7 @@
 # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
 # and limitations under the License.
 #
-from langchain.vectorstores import OpenSearchVectorSearch
+from langchain_community.vectorstores import OpenSearchVectorSearch
 from opensearchpy import RequestsHttpConnection
 from llms import get_embeddings_llm
 import requests
diff --git a/lambda/aws-qa-appsync-opensearch/question_answering/src/requirements.txt b/lambda/aws-qa-appsync-opensearch/question_answering/src/requirements.txt
index 44528d2..9122af5 100644
--- a/lambda/aws-qa-appsync-opensearch/question_answering/src/requirements.txt
+++ b/lambda/aws-qa-appsync-opensearch/question_answering/src/requirements.txt
@@ -3,11 +3,12 @@ aws-xray-sdk
 fastjsonschema
 typing-extensions
 aiohttp
-boto3>=1.28.69
-botocore>=1.31.69
+boto3>=1.34.29
+botocore>=1.34.29
 requests==2.31.0
 requests-aws4auth==1.2.3
-opensearch-py==2.3.1
+opensearch-py==2.4.2
 numpy
-langchain==0.0.329
+langchain==0.1.4
+langchain-community==0.0.16
 opensearch-py
\ No newline at end of file
diff --git a/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/helpers/opensearch_helper.py b/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/helpers/opensearch_helper.py
index d922559..e1bc7d4 100644
--- a/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/helpers/opensearch_helper.py
+++ b/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/helpers/opensearch_helper.py
@@ -11,8 +11,8 @@
 # and limitations under the License.
 #
 from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
-from langchain.vectorstores import OpenSearchVectorSearch
-from langchain.embeddings import BedrockEmbeddings
+from langchain_community.vectorstores import OpenSearchVectorSearch
+from langchain_community.embeddings import BedrockEmbeddings
 from typing import Tuple
 import boto3, os
 from aws_lambda_powertools import Logger, Tracer, Metrics
diff --git a/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/lambda.py b/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/lambda.py
index bf65795..13c88f4 100644
--- a/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/lambda.py
+++ b/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/lambda.py
@@ -20,10 +20,10 @@ import tempfile
 from helpers.credentials_helper import get_credentials
 from helpers.opensearch_helper import check_if_index_exists, process_shard
 from helpers.update_ingestion_status import updateIngestionJobStatus
-from langchain.embeddings import BedrockEmbeddings
+from langchain_community.embeddings import BedrockEmbeddings
 from helpers.s3inmemoryloader import S3TxtFileLoaderInMemory
 from opensearchpy import OpenSearch, RequestsHttpConnection
-from langchain.vectorstores import OpenSearchVectorSearch
+from langchain_community.vectorstores import OpenSearchVectorSearch
 from langchain.text_splitter import RecursiveCharacterTextSplitter
 import multiprocessing as mp
 from functools import partial
diff --git a/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/requirements.txt b/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/requirements.txt
index 1b49d3b..c92de96 100644
--- a/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/requirements.txt
+++ b/lambda/aws-rag-appsync-stepfn-opensearch/embeddings_job/src/requirements.txt
@@ -2,11 +2,12 @@ aws-lambda-powertools
 aws-xray-sdk
 fastjsonschema
 typing-extensions
-boto3>=1.28.61
-botocore>=1.31.61
+boto3>=1.34.29
+botocore>=1.34.29
 requests==2.31.0
 requests-aws4auth==1.2.3
-langchain==0.0.329
-opensearch-py==2.3.1
+langchain==0.1.4
+langchain-community==0.0.16
+opensearch-py==2.4.2
 sagemaker
 numpy
diff --git a/lambda/aws-rag-appsync-stepfn-opensearch/s3_file_transformer/src/requirements.txt b/lambda/aws-rag-appsync-stepfn-opensearch/s3_file_transformer/src/requirements.txt
index 677e97f..da45013 100644
--- a/lambda/aws-rag-appsync-stepfn-opensearch/s3_file_transformer/src/requirements.txt
+++ b/lambda/aws-rag-appsync-stepfn-opensearch/s3_file_transformer/src/requirements.txt
@@ -4,5 +4,5 @@ fastjsonschema
 typing-extensions
 boto3
 requests
-langchain==0.0.329
+langchain==0.1.4
 pypdf2
diff --git a/lambda/aws-summarization-appsync-stepfn/document_reader/requirements.txt b/lambda/aws-summarization-appsync-stepfn/document_reader/requirements.txt
index fe83dec..ec963e8 100644
--- a/lambda/aws-summarization-appsync-stepfn/document_reader/requirements.txt
+++ b/lambda/aws-summarization-appsync-stepfn/document_reader/requirements.txt
@@ -1,6 +1,6 @@
 redis
 pypdf2
-langchain==0.0.329
+langchain==0.1.4
 urllib3<2
 aws-xray-sdk
 aws-lambda-powertools
diff --git a/lambda/aws-summarization-appsync-stepfn/summary_generator/lambda.py b/lambda/aws-summarization-appsync-stepfn/summary_generator/lambda.py
index b094736..a3d632c 100644
--- a/lambda/aws-summarization-appsync-stepfn/summary_generator/lambda.py
+++ b/lambda/aws-summarization-appsync-stepfn/summary_generator/lambda.py
@@ -15,7 +15,7 @@ import base64
 
 from langchain.llms.bedrock import Bedrock
 from update_summary_status import updateSummaryJobStatus
-from langchain import PromptTemplate
+from langchain.prompts import PromptTemplate
 # external files
 from langchain.docstore.document import Document
 from langchain.chains.summarize import load_summarize_chain
diff --git a/lambda/aws-summarization-appsync-stepfn/summary_generator/requirements.txt b/lambda/aws-summarization-appsync-stepfn/summary_generator/requirements.txt
index 90d84f3..fd8ba65 100644
--- a/lambda/aws-summarization-appsync-stepfn/summary_generator/requirements.txt
+++ b/lambda/aws-summarization-appsync-stepfn/summary_generator/requirements.txt
@@ -1,9 +1,9 @@
 redis
-boto3>=1.28.61
-botocore>=1.31.61
+boto3>=1.34.29
+botocore>=1.34.29
 requests==2.31.0
 requests-aws4auth==1.2.3
-langchain==0.0.329
+langchain==0.1.4
 nltk==3.8.1
 urllib3<2
 aws-lambda-powertools
diff --git a/layers/langchain-common-deps/requirements.txt b/layers/langchain-common-deps/requirements.txt
index 29d6133..a7be025 100644
--- a/layers/langchain-common-deps/requirements.txt
+++ b/layers/langchain-common-deps/requirements.txt
@@ -1,7 +1,7 @@
-boto3>=1.34.6
-botocore>=1.34.6
+boto3>=1.34.29
+botocore>=1.34.29
 requests==2.31.0
 requests-aws4auth==1.2.3
-langchain==0.0.351
+langchain==0.1.4
 opensearch-py==2.4.2
-openai==1.6.0
+openai==1.10.0
diff --git a/layers/langchain-common-layer/python/genai_core/adapters/base/base.py b/layers/langchain-common-layer/python/genai_core/adapters/base/base.py
index 4285b53..94ac550 100644
--- a/layers/langchain-common-layer/python/genai_core/adapters/base/base.py
+++ b/layers/langchain-common-layer/python/genai_core/adapters/base/base.py
@@ -12,7 +12,7 @@
 #
 import os
 from enum import Enum
-from langchain import LLMChain
+from langchain.chains import LLMChain
 from langchain.callbacks.base import BaseCallbackHandler
 from langchain.chains import ConversationalRetrievalChain, ConversationChain
 from langchain.memory import ConversationBufferMemory
diff --git a/package.json b/package.json
index 8af855a..43cfc59 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
   },
   "devDependencies": {
     "@commitlint/config-conventional": "^18.6.0",
-    "@mrgrain/jsii-struct-builder": "^0.7.10",
+    "@mrgrain/jsii-struct-builder": "^0.7.11",
     "@types/jest": "^29.5.11",
     "@types/node": "^18",
     "@typescript-eslint/eslint-plugin": "^6",
@@ -74,7 +74,7 @@
     "constructs": "^10.3.0"
   },
   "dependencies": {
-    "cdk-nag": "^2.28.23"
+    "cdk-nag": "^2.28.24"
   },
   "keywords": [
     "aws-cdk",
diff --git a/src/cdk-lib/bedrock/agent.ts b/src/cdk-lib/bedrock/agent.ts
index b215d41..fd75e9d 100644
--- a/src/cdk-lib/bedrock/agent.ts
+++ b/src/cdk-lib/bedrock/agent.ts
@@ -291,6 +291,18 @@ export class Agent extends Construct implements cdk.ITaggableV2 {
    */
   public readonly cdkTagManager =
     new cdk.TagManager(cdk.TagType.MAP, 'Custom::Bedrock-Agent');
+  /**
+   * A list of values to indicate if PrepareAgent or an Alias needs to be updated.
+   * @private
+   */
+  private changeIds: string[] = [];
+  /**
+   * The prepareAgent custom resource.
+   *
+   * Add other resources as dependencies to ensure Prepare Agent is called after they are updated.
+   * @private
+   */
+  private prepareAgent: cdk.CustomResource;
 
   constructor(scope: Construct, id: string, props: AgentProps) {
     super(scope, id);
@@ -422,9 +434,17 @@ export class Agent extends Construct implements cdk.ITaggableV2 {
       true,
     );
 
-    const changeIds: string[] = [agent.getAttString('changeId')];
+    this.prepareAgent = new cdk.CustomResource(this, 'PrepareAgent', {
+      serviceToken: crProvider.serviceToken,
+      resourceType: 'Custom::Bedrock-PrepareAgent',
+      properties: {
+        agentId: this.agentId,
+        changeIds: cdk.Lazy.list({ produce: () => this.changeIds }),
+      },
+    });
+
+    this._addPrepareAgentDependency(agent, agent.getAttString('changeId'));
 
-    const kbAssociations: string[] = [];
     if (props.knowledgeBases && props.knowledgeBases.length > 0) {
       const kbAssocCRPolicy = new iam.Policy(this, 'KBAssocCRPolicy', {
         roles: [crProvider.role],
@@ -483,24 +503,14 @@ export class Agent extends Construct implements cdk.ITaggableV2 {
         );
         kbAssoc.node.addDependency(kbAssocCRPolicy);
         kbAssoc.node.addDependency(crProvider);
-        kbAssociations.push(kbAssoc.getAttString('changeId'));
+        this._addPrepareAgentDependency(kbAssoc, kbAssoc.getAttString('changeId'));
       }
-      changeIds.push(...kbAssociations);
     }
 
-    new cdk.CustomResource(this, 'PrepareAgent', {
-      serviceToken: crProvider.serviceToken,
-      resourceType: 'Custom::Bedrock-PrepareAgent',
-      properties: {
-        agentId: this.agentId,
-        changeIds,
-      },
-    });
 
     if (props.aliasName) {
       const alias = this.addAlias({
         agentId: this.agentId,
-        changeIds,
         aliasName: props.aliasName,
       });
       this.aliasId = alias.aliasId;
@@ -513,12 +523,29 @@ export class Agent extends Construct implements cdk.ITaggableV2 {
    * Add an alias to the agent.
    */
   public addAlias(props: Exclude<AgentAliasProps, 'agentId'>): AgentAlias {
-    return new AgentAlias(this, `AgentAlias-${props.aliasName}`, {
+    const alias = new AgentAlias(this, `AgentAlias-${props.aliasName}`, {
       agentId: this.agentId,
       agentVersion: props.agentVersion,
-      changeIds: props.changeIds,
+      changeIds: cdk.Lazy.list({ produce: () => this.changeIds }),
       aliasName: props.aliasName,
     });
+    alias.node.addDependency(this.prepareAgent);
+    return alias;
+  }
+
+  /**
+   * Register a dependency for prepareAgent.
+   *
+   * @param resource - The resource that will be registered as a dependency.
+   * @param changeId - The changeId of the resource that will be registered as a dependency.
+   *
+   * @internal This is an internal core function and should not be called directly.
+   */
+  public _addPrepareAgentDependency(resource: cdk.IResource, changeId?: string) {
+    this.prepareAgent.node.addDependency(resource);
+    if (changeId) {
+      this.changeIds.push(changeId);
+    }
   }
 }
 
diff --git a/src/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/index.ts b/src/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/index.ts
index 358b7d3..7be07ec 100644
--- a/src/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/index.ts
+++ b/src/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/index.ts
@@ -786,7 +786,7 @@ export class RagAppsyncStepfnOpensearch extends Construct {
       {
         maxConcurrency: 100,
       },
-    ).iterator(fileTransformationTask);
+    ).itemProcessor(fileTransformationTask);
 
     const jobFailed = new stepfn.Fail(this, 'Job Failed', {
       cause: 'Validation job failed',
diff --git a/src/patterns/gen-ai/aws-summarization-appsync-stepfn/index.ts b/src/patterns/gen-ai/aws-summarization-appsync-stepfn/index.ts
index 65129d1..3263e1e 100644
--- a/src/patterns/gen-ai/aws-summarization-appsync-stepfn/index.ts
+++ b/src/patterns/gen-ai/aws-summarization-appsync-stepfn/index.ts
@@ -791,7 +791,7 @@ export class SummarizationAppsyncStepfn extends Construct {
     // step function, run files in parallel
     const runFilesInparallel = new sfn.Map(this, 'Run Files in Parallel', {
       maxConcurrency: 100,
-    }).iterator(
+    }).itemProcessor(
       documentReaderTask.next(
         summaryfromCacheChoice
           .when(
diff --git a/yarn.lock b/yarn.lock
index bda40e8..2214700 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -826,10 +826,10 @@
   dependencies:
     ajv "^8.12.0"
 
-"@mrgrain/jsii-struct-builder@^0.7.10":
-  version "0.7.10"
-  resolved "https://registry.yarnpkg.com/@mrgrain/jsii-struct-builder/-/jsii-struct-builder-0.7.10.tgz#d0df55a4144380205e2116ae48f16951c854188a"
-  integrity sha512-DyV6RI2r85xd8V9U3DIChRDWc01Xhupv/OIUqp+c8n6aHNLT0RDnUSAOG6OFzdsm+jqg25vgwyrEwppcXvqWew==
+"@mrgrain/jsii-struct-builder@^0.7.11":
+  version "0.7.11"
+  resolved "https://registry.yarnpkg.com/@mrgrain/jsii-struct-builder/-/jsii-struct-builder-0.7.11.tgz#e31517d26e0da223bf3436ebc3e377f046aa89e6"
+  integrity sha512-VywG/kz6aqOQGDhGVQTuvKO5Z7SKfomuhn2gu0GTD1+myZFUd/UColyOYa7GvxREQhU9B+Vh2PQSckibm79iqg==
   dependencies:
     "@jsii/spec" "^1.94.0"
 
@@ -1046,15 +1046,15 @@
     "@types/yargs-parser" "*"
 
 "@typescript-eslint/eslint-plugin@^6":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz#bb0676af940bc23bf299ca58dbdc6589c2548c2e"
-  integrity sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz#9cf31546d2d5e884602626d89b0e0d2168ac25ed"
+  integrity sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==
   dependencies:
     "@eslint-community/regexpp" "^4.5.1"
-    "@typescript-eslint/scope-manager" "6.19.1"
-    "@typescript-eslint/type-utils" "6.19.1"
-    "@typescript-eslint/utils" "6.19.1"
-    "@typescript-eslint/visitor-keys" "6.19.1"
+    "@typescript-eslint/scope-manager" "6.20.0"
+    "@typescript-eslint/type-utils" "6.20.0"
+    "@typescript-eslint/utils" "6.20.0"
+    "@typescript-eslint/visitor-keys" "6.20.0"
     debug "^4.3.4"
     graphemer "^1.4.0"
     ignore "^5.2.4"
@@ -1063,46 +1063,46 @@
     ts-api-utils "^1.0.1"
 
 "@typescript-eslint/parser@^6":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.19.1.tgz#68a87bb21afaf0b1689e9cdce0e6e75bc91ada78"
-  integrity sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==
-  dependencies:
-    "@typescript-eslint/scope-manager" "6.19.1"
-    "@typescript-eslint/types" "6.19.1"
-    "@typescript-eslint/typescript-estree" "6.19.1"
-    "@typescript-eslint/visitor-keys" "6.19.1"
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.20.0.tgz#17e314177304bdf498527e3c4b112e41287b7416"
+  integrity sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==
+  dependencies:
+    "@typescript-eslint/scope-manager" "6.20.0"
+    "@typescript-eslint/types" "6.20.0"
+    "@typescript-eslint/typescript-estree" "6.20.0"
+    "@typescript-eslint/visitor-keys" "6.20.0"
     debug "^4.3.4"
 
-"@typescript-eslint/scope-manager@6.19.1":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz#2f527ee30703a6169a52b31d42a1103d80acd51b"
-  integrity sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==
+"@typescript-eslint/scope-manager@6.20.0":
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz#8a926e60f6c47feb5bab878246dc2ae465730151"
+  integrity sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==
   dependencies:
-    "@typescript-eslint/types" "6.19.1"
-    "@typescript-eslint/visitor-keys" "6.19.1"
+    "@typescript-eslint/types" "6.20.0"
+    "@typescript-eslint/visitor-keys" "6.20.0"
 
-"@typescript-eslint/type-utils@6.19.1":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz#6a130e3afe605a4898e043fa9f72e96309b54935"
-  integrity sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==
+"@typescript-eslint/type-utils@6.20.0":
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz#d395475cd0f3610dd80c7d8716fa0db767da3831"
+  integrity sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==
   dependencies:
-    "@typescript-eslint/typescript-estree" "6.19.1"
-    "@typescript-eslint/utils" "6.19.1"
+    "@typescript-eslint/typescript-estree" "6.20.0"
+    "@typescript-eslint/utils" "6.20.0"
     debug "^4.3.4"
     ts-api-utils "^1.0.1"
 
-"@typescript-eslint/types@6.19.1":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.19.1.tgz#2d4c9d492a63ede15e7ba7d129bdf7714b77f771"
-  integrity sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==
+"@typescript-eslint/types@6.20.0":
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.20.0.tgz#5ccd74c29011ae7714ae6973e4ec0c634708b448"
+  integrity sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==
 
-"@typescript-eslint/typescript-estree@6.19.1":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz#796d88d88882f12e85bb33d6d82d39e1aea54ed1"
-  integrity sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==
+"@typescript-eslint/typescript-estree@6.20.0":
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz#5b2d0975949e6bdd8d45ee1471461ef5fadc5542"
+  integrity sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==
   dependencies:
-    "@typescript-eslint/types" "6.19.1"
-    "@typescript-eslint/visitor-keys" "6.19.1"
+    "@typescript-eslint/types" "6.20.0"
+    "@typescript-eslint/visitor-keys" "6.20.0"
     debug "^4.3.4"
     globby "^11.1.0"
     is-glob "^4.0.3"
@@ -1110,25 +1110,25 @@
     semver "^7.5.4"
     ts-api-utils "^1.0.1"
 
-"@typescript-eslint/utils@6.19.1":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.19.1.tgz#df93497f9cfddde2bcc2a591da80536e68acd151"
-  integrity sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==
+"@typescript-eslint/utils@6.20.0":
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.20.0.tgz#0e52afcfaa51af5656490ba4b7437cc3aa28633d"
+  integrity sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==
   dependencies:
     "@eslint-community/eslint-utils" "^4.4.0"
     "@types/json-schema" "^7.0.12"
     "@types/semver" "^7.5.0"
-    "@typescript-eslint/scope-manager" "6.19.1"
-    "@typescript-eslint/types" "6.19.1"
-    "@typescript-eslint/typescript-estree" "6.19.1"
+    "@typescript-eslint/scope-manager" "6.20.0"
+    "@typescript-eslint/types" "6.20.0"
+    "@typescript-eslint/typescript-estree" "6.20.0"
     semver "^7.5.4"
 
-"@typescript-eslint/visitor-keys@6.19.1":
-  version "6.19.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz#2164073ed4fc34a5ff3b5e25bb5a442100454c4c"
-  integrity sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==
+"@typescript-eslint/visitor-keys@6.20.0":
+  version "6.20.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz#f7ada27f2803de89df0edd9fd7be22c05ce6a498"
+  integrity sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==
   dependencies:
-    "@typescript-eslint/types" "6.19.1"
+    "@typescript-eslint/types" "6.20.0"
     eslint-visitor-keys "^3.4.1"
 
 "@ungap/structured-clone@^1.2.0":
@@ -1521,10 +1521,10 @@ case@1.6.3, case@^1.6.3:
   resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9"
   integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==
 
-cdk-nag@^2.28.23:
-  version "2.28.23"
-  resolved "https://registry.yarnpkg.com/cdk-nag/-/cdk-nag-2.28.23.tgz#d26ff2bf3f5bc0ef1d8f949021ae1037e5e8d669"
-  integrity sha512-vMwrlucGJx/A5FQYdW0aBxuBjWYIdS7DkED4xcsePfzoD+9GMhEJ5cVePU5rNiM9P42a0o84oFwV+KDTOU7qEg==
+cdk-nag@^2.28.24:
+  version "2.28.24"
+  resolved "https://registry.yarnpkg.com/cdk-nag/-/cdk-nag-2.28.24.tgz#e4f034c700232f8ba8450338a84df84a12325d9c"
+  integrity sha512-OwoqNoS2zFuNI6xZ9U4oTRO5GgAPwUYOEeWH5Gw+tYQGRWhKaxYHl0vfEp7qgrr086YwmLZjJ3zbel+nwpXy8Q==
 
 chalk@^2.4.2:
   version "2.4.2"
@@ -2078,9 +2078,9 @@ downlevel-dts@^0.11.0:
     typescript next
 
 electron-to-chromium@^1.4.648:
-  version "1.4.648"
-  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz#c7b46c9010752c37bb4322739d6d2dd82354fbe4"
-  integrity sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==
+  version "1.4.650"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.650.tgz#b38ef9de16991b9f7b924246770576ab91ab3d64"
+  integrity sha512-sYSQhJCJa4aGA1wYol5cMQgekDBlbVfTRavlGZVr3WZpDdOPcp6a6xUnFfrt8TqZhsBYYbDxJZCjGfHuGupCRQ==
 
 emittery@^0.13.1:
   version "0.13.1"


Test patch:
diff --git a/test/cdk-lib/bedrock/__snapshots__/agent.test.ts.snap b/test/cdk-lib/bedrock/__snapshots__/agent.test.ts.snap
index 3f4a732..49c365a 100644
--- a/test/cdk-lib/bedrock/__snapshots__/agent.test.ts.snap
+++ b/test/cdk-lib/bedrock/__snapshots__/agent.test.ts.snap
@@ -26,6 +26,7 @@ exports[`Bedrock Agents Agent matches snapshot 1`] = `
       "DeletionPolicy": "Delete",
       "DependsOn": [
         "AgentAgentAliasprodAliasCRPolicyACECDEBD",
+        "AgentPrepareAgent9A21CF07",
         "BedrockCRProviderCRRole90406B17",
         "BedrockCRProviderCustomResourcesFunctionLogRetention32CED555",
         "BedrockCRProviderCustomResourcesFunction9A70E3A5",
@@ -67,6 +68,9 @@ exports[`Bedrock Agents Agent matches snapshot 1`] = `
       "UpdateReplacePolicy": "Delete",
     },
     "AgentAgentAliasprodAliasCRPolicyACECDEBD": {
+      "DependsOn": [
+        "AgentPrepareAgent9A21CF07",
+      ],
       "Metadata": {
         "cdk_nag": {
           "rules_to_suppress": [
@@ -409,6 +413,10 @@ exports[`Bedrock Agents Agent matches snapshot 1`] = `
     },
     "AgentPrepareAgent9A21CF07": {
       "DeletionPolicy": "Delete",
+      "DependsOn": [
+        "AgentD78B2CA1",
+        "AgentKBAssocKBteststackKBF59CBB076A4D106D",
+      ],
       "Properties": {
         "ServiceToken": {
           "Fn::GetAtt": [