@aws/agentcore 1.0.0-preview.1 → 1.0.0-preview.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -110,11 +110,14 @@ async function main() {
110
110
  memoryName?: string;
111
111
  containerUri?: string;
112
112
  hasDockerfile?: boolean;
113
+ dockerfileName?: string;
114
+ harnessDir?: string;
113
115
  tools?: { type: string; name: string }[];
114
116
  apiKeyArn?: string;
115
117
  }[] = [];
116
118
  for (const entry of specAny.harnesses ?? []) {
117
- const harnessPath = path.resolve(projectRoot, entry.path, 'harness.json');
119
+ const harnessDir = path.resolve(projectRoot, entry.path);
120
+ const harnessPath = path.resolve(harnessDir, 'harness.json');
118
121
  try {
119
122
  const harnessSpec = JSON.parse(fs.readFileSync(harnessPath, 'utf-8'));
120
123
  harnessConfigs.push({
@@ -123,6 +126,8 @@ async function main() {
123
126
  memoryName: harnessSpec.memory?.name,
124
127
  containerUri: harnessSpec.containerUri,
125
128
  hasDockerfile: !!harnessSpec.dockerfile,
129
+ dockerfileName: harnessSpec.dockerfile,
130
+ harnessDir,
126
131
  tools: harnessSpec.tools,
127
132
  apiKeyArn: harnessSpec.model?.apiKeyArn,
128
133
  });
@@ -184,7 +189,7 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/cdk.json should match
184
189
  "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": true,
185
190
  "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
186
191
  "@aws-cdk/core:checkSecretUsage": true,
187
- "@aws-cdk/core:target-partitions": ["aws", "aws-cn"],
192
+ "@aws-cdk/core:target-partitions": ["aws", "aws-cn", "aws-us-gov"],
188
193
  "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
189
194
  "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
190
195
  "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
@@ -296,10 +301,26 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/lib/cdk-stack.ts shou
296
301
  AgentCoreMcp,
297
302
  type AgentCoreProjectSpec,
298
303
  type AgentCoreMcpSpec,
304
+ ContainerSourceAssetFromPath,
305
+ AgentEcrRepository,
306
+ ContainerBuildProject,
307
+ ContainerImageBuilder,
299
308
  } from '@aws/agentcore-cdk';
300
309
  import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
301
310
  import { Construct } from 'constructs';
302
311
 
312
+ export interface HarnessConfig {
313
+ name: string;
314
+ executionRoleArn?: string;
315
+ memoryName?: string;
316
+ containerUri?: string;
317
+ hasDockerfile?: boolean;
318
+ dockerfileName?: string;
319
+ harnessDir?: string;
320
+ tools?: { type: string; name: string }[];
321
+ apiKeyArn?: string;
322
+ }
323
+
303
324
  export interface AgentCoreStackProps extends StackProps {
304
325
  /**
305
326
  * The AgentCore project specification containing agents, memories, and credentials.
@@ -316,15 +337,7 @@ export interface AgentCoreStackProps extends StackProps {
316
337
  /**
317
338
  * Harness role configurations. Each entry creates an IAM execution role for a harness.
318
339
  */
319
- harnesses?: {
320
- name: string;
321
- executionRoleArn?: string;
322
- memoryName?: string;
323
- containerUri?: string;
324
- hasDockerfile?: boolean;
325
- tools?: { type: string; name: string }[];
326
- apiKeyArn?: string;
327
- }[];
340
+ harnesses?: HarnessConfig[];
328
341
  }
329
342
 
330
343
  /**
@@ -342,10 +355,46 @@ export class AgentCoreStack extends Stack {
342
355
 
343
356
  const { spec, mcpSpec, credentials, harnesses } = props;
344
357
 
358
+ // Build container images for harnesses that specify a dockerfile (no containerUri).
359
+ // Produces CDK outputs consumed by the imperative harness deployer.
360
+ const harnessesForCdk = harnesses ? [...harnesses] : [];
361
+ if (harnesses) {
362
+ for (let i = 0; i < harnesses.length; i++) {
363
+ const h = harnesses[i]!;
364
+ if (h.hasDockerfile && !h.containerUri && h.harnessDir) {
365
+ const pascalName = h.name.replace(/(^|_)([a-z])/g, (_: string, __: string, c: string) => c.toUpperCase());
366
+ const sourceAsset = new ContainerSourceAssetFromPath(this, \`Harness\${pascalName}SourceAsset\`, {
367
+ sourcePath: h.harnessDir,
368
+ });
369
+ const ecrRepo = new AgentEcrRepository(this, \`Harness\${pascalName}EcrRepo\`, {
370
+ projectName: spec.name,
371
+ agentName: \`harness-\${h.name}\`,
372
+ });
373
+ const buildProject = ContainerBuildProject.getOrCreate(this);
374
+ buildProject.grantPushTo(ecrRepo.repository);
375
+ sourceAsset.asset.grantRead(buildProject.role);
376
+
377
+ const builder = new ContainerImageBuilder(this, \`Harness\${pascalName}ContainerBuild\`, {
378
+ buildProject,
379
+ sourceAsset,
380
+ repository: ecrRepo,
381
+ dockerfile: h.dockerfileName ?? 'Dockerfile',
382
+ });
383
+
384
+ new CfnOutput(this, \`Harness\${pascalName}ContainerUriOutput\`, {
385
+ value: builder.containerUri,
386
+ });
387
+
388
+ // Pass the built containerUri to the harness role construct so it gets ECR pull permissions
389
+ harnessesForCdk[i] = { ...h, containerUri: builder.containerUri };
390
+ }
391
+ }
392
+ }
393
+
345
394
  // Create AgentCoreApplication with all agents and harness roles
346
395
  this.application = new AgentCoreApplication(this, 'Application', {
347
396
  spec,
348
- harnesses,
397
+ harnesses: harnessesForCdk.length > 0 ? harnessesForCdk : undefined,
349
398
  });
350
399
 
351
400
  // Create AgentCoreMcp if there are gateways configured
@@ -65,11 +65,14 @@ async function main() {
65
65
  memoryName?: string;
66
66
  containerUri?: string;
67
67
  hasDockerfile?: boolean;
68
+ dockerfileName?: string;
69
+ harnessDir?: string;
68
70
  tools?: { type: string; name: string }[];
69
71
  apiKeyArn?: string;
70
72
  }[] = [];
71
73
  for (const entry of specAny.harnesses ?? []) {
72
- const harnessPath = path.resolve(projectRoot, entry.path, 'harness.json');
74
+ const harnessDir = path.resolve(projectRoot, entry.path);
75
+ const harnessPath = path.resolve(harnessDir, 'harness.json');
73
76
  try {
74
77
  const harnessSpec = JSON.parse(fs.readFileSync(harnessPath, 'utf-8'));
75
78
  harnessConfigs.push({
@@ -78,6 +81,8 @@ async function main() {
78
81
  memoryName: harnessSpec.memory?.name,
79
82
  containerUri: harnessSpec.containerUri,
80
83
  hasDockerfile: !!harnessSpec.dockerfile,
84
+ dockerfileName: harnessSpec.dockerfile,
85
+ harnessDir,
81
86
  tools: harnessSpec.tools,
82
87
  apiKeyArn: harnessSpec.model?.apiKeyArn,
83
88
  });
@@ -9,7 +9,7 @@
9
9
  "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": true,
10
10
  "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
11
11
  "@aws-cdk/core:checkSecretUsage": true,
12
- "@aws-cdk/core:target-partitions": ["aws", "aws-cn"],
12
+ "@aws-cdk/core:target-partitions": ["aws", "aws-cn", "aws-us-gov"],
13
13
  "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
14
14
  "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
15
15
  "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
@@ -3,10 +3,26 @@ import {
3
3
  AgentCoreMcp,
4
4
  type AgentCoreProjectSpec,
5
5
  type AgentCoreMcpSpec,
6
+ ContainerSourceAssetFromPath,
7
+ AgentEcrRepository,
8
+ ContainerBuildProject,
9
+ ContainerImageBuilder,
6
10
  } from '@aws/agentcore-cdk';
7
11
  import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
8
12
  import { Construct } from 'constructs';
9
13
 
14
+ export interface HarnessConfig {
15
+ name: string;
16
+ executionRoleArn?: string;
17
+ memoryName?: string;
18
+ containerUri?: string;
19
+ hasDockerfile?: boolean;
20
+ dockerfileName?: string;
21
+ harnessDir?: string;
22
+ tools?: { type: string; name: string }[];
23
+ apiKeyArn?: string;
24
+ }
25
+
10
26
  export interface AgentCoreStackProps extends StackProps {
11
27
  /**
12
28
  * The AgentCore project specification containing agents, memories, and credentials.
@@ -23,15 +39,7 @@ export interface AgentCoreStackProps extends StackProps {
23
39
  /**
24
40
  * Harness role configurations. Each entry creates an IAM execution role for a harness.
25
41
  */
26
- harnesses?: {
27
- name: string;
28
- executionRoleArn?: string;
29
- memoryName?: string;
30
- containerUri?: string;
31
- hasDockerfile?: boolean;
32
- tools?: { type: string; name: string }[];
33
- apiKeyArn?: string;
34
- }[];
42
+ harnesses?: HarnessConfig[];
35
43
  }
36
44
 
37
45
  /**
@@ -49,10 +57,46 @@ export class AgentCoreStack extends Stack {
49
57
 
50
58
  const { spec, mcpSpec, credentials, harnesses } = props;
51
59
 
60
+ // Build container images for harnesses that specify a dockerfile (no containerUri).
61
+ // Produces CDK outputs consumed by the imperative harness deployer.
62
+ const harnessesForCdk = harnesses ? [...harnesses] : [];
63
+ if (harnesses) {
64
+ for (let i = 0; i < harnesses.length; i++) {
65
+ const h = harnesses[i]!;
66
+ if (h.hasDockerfile && !h.containerUri && h.harnessDir) {
67
+ const pascalName = h.name.replace(/(^|_)([a-z])/g, (_: string, __: string, c: string) => c.toUpperCase());
68
+ const sourceAsset = new ContainerSourceAssetFromPath(this, `Harness${pascalName}SourceAsset`, {
69
+ sourcePath: h.harnessDir,
70
+ });
71
+ const ecrRepo = new AgentEcrRepository(this, `Harness${pascalName}EcrRepo`, {
72
+ projectName: spec.name,
73
+ agentName: `harness-${h.name}`,
74
+ });
75
+ const buildProject = ContainerBuildProject.getOrCreate(this);
76
+ buildProject.grantPushTo(ecrRepo.repository);
77
+ sourceAsset.asset.grantRead(buildProject.role);
78
+
79
+ const builder = new ContainerImageBuilder(this, `Harness${pascalName}ContainerBuild`, {
80
+ buildProject,
81
+ sourceAsset,
82
+ repository: ecrRepo,
83
+ dockerfile: h.dockerfileName ?? 'Dockerfile',
84
+ });
85
+
86
+ new CfnOutput(this, `Harness${pascalName}ContainerUriOutput`, {
87
+ value: builder.containerUri,
88
+ });
89
+
90
+ // Pass the built containerUri to the harness role construct so it gets ECR pull permissions
91
+ harnessesForCdk[i] = { ...h, containerUri: builder.containerUri };
92
+ }
93
+ }
94
+ }
95
+
52
96
  // Create AgentCoreApplication with all agents and harness roles
53
97
  this.application = new AgentCoreApplication(this, 'Application', {
54
98
  spec,
55
- harnesses,
99
+ harnesses: harnessesForCdk.length > 0 ? harnessesForCdk : undefined,
56
100
  });
57
101
 
58
102
  // Create AgentCoreMcp if there are gateways configured
@@ -4,7 +4,7 @@
4
4
  {
5
5
  "Effect": "Allow",
6
6
  "Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
7
- "Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
7
+ "Resource": "arn:*:logs:*:*:log-group:/aws/lambda/*"
8
8
  }
9
9
  ]
10
10
  }