Skip to content

Commit ad25aba

Browse files
authored
feat(bedrock-agentcore): add fromImageUri method to AgentRuntimeArtifact (#36263)
### Issue # (if applicable) N/A ### Reason for this change Users currently need ECR repository constructs (`fromEcrRepository`) or local Docker assets (`fromAsset`) to reference container images in AgentCore runtimes. This creates friction when: - Container URIs come from CloudFormation parameters or stack outputs - Referencing images in external registries (Docker Hub, private registries) - Working with cross-stack or cross-account image references ### Description of changes Added `fromImageUri()` static method to `AgentRuntimeArtifact` class: - Created `ImageUriArtifact` class extending `AgentRuntimeArtifact` - Accepts container URI as a string (supports CloudFormation tokens/expressions) - No automatic IAM permissions granted (user manages permissions separately) - Follows existing patterns from `EcrImage` and `AssetImage` classes This provides a fourth deployment option alongside `fromEcrRepository()`, `fromAsset()`, and `fromS3()`. ### Description of how you validated changes **Unit tests added:** - Basic URI reference test - CloudFormation token support test - Verification that no permissions are required **Manual testing:** bash cd packages/@aws-cdk/aws-bedrock-agentcore-alpha yarn build yarn test All tests pass. **Production usage:** This change has been built locally and used successfully in my application to reference container images via CloudFormation parameters. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 617bcba commit ad25aba

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

packages/@aws-cdk/aws-bedrock-agentcore-alpha/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,41 @@ const runtimeInstance = new agentcore.Runtime(this, "MyAgentRuntime", {
249249
});
250250
```
251251

252+
#### Option 4: Use an ECR container image URI
253+
254+
Reference an ECR container image directly by its URI. This is useful when you have a pre-existing ECR image URI from CloudFormation parameters or cross-stack references. No IAM permissions are automatically granted - you must ensure the runtime has ECR pull permissions.
255+
256+
```typescript fixture=default
257+
// Direct URI reference
258+
const agentRuntimeArtifact = agentcore.AgentRuntimeArtifact.fromImageUri(
259+
"123456789012.dkr.ecr.us-east-1.amazonaws.com/my-agent:v1.0.0"
260+
);
261+
262+
const runtime = new agentcore.Runtime(this, "MyAgentRuntime", {
263+
runtimeName: "myAgent",
264+
agentRuntimeArtifact: agentRuntimeArtifact,
265+
});
266+
```
267+
268+
You can also use CloudFormation parameters or references:
269+
270+
```typescript fixture=default
271+
// Using a CloudFormation parameter
272+
const imageUriParam = new cdk.CfnParameter(this, "ImageUri", {
273+
type: "String",
274+
description: "Container image URI for the agent runtime",
275+
});
276+
277+
const agentRuntimeArtifact = agentcore.AgentRuntimeArtifact.fromImageUri(
278+
imageUriParam.valueAsString
279+
);
280+
281+
const runtime = new agentcore.Runtime(this, "MyAgentRuntime", {
282+
runtimeName: "myAgent",
283+
agentRuntimeArtifact: agentRuntimeArtifact,
284+
});
285+
```
286+
252287
### Granting Permissions to Invoke Bedrock Models or Inference Profiles
253288

254289
To grant the runtime permissions to invoke Bedrock models or inference profiles:

packages/@aws-cdk/aws-bedrock-agentcore-alpha/lib/runtime/runtime-artifact.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ export abstract class AgentRuntimeArtifact {
7474
return new S3Image(s3Location, runtime, entrypoint);
7575
}
7676

77+
/**
78+
* Reference an image using an ECR container URI
79+
*
80+
* Use this when referencing ECR images from CloudFormation parameters or cross-stack references.
81+
*
82+
* **Note:** No IAM permissions are automatically granted. You must ensure the runtime has
83+
* ECR pull permissions for the repository.
84+
*
85+
* @param containerUri The ECR container image URI (format: {account}.dkr.ecr.{region}.amazonaws.com/{repository}:{tag})
86+
*/
87+
public static fromImageUri(containerUri: string): AgentRuntimeArtifact {
88+
return new ImageUriArtifact(containerUri);
89+
}
90+
7791
/**
7892
* Called when the image is used by a Runtime to handle side effects like permissions
7993
*/
@@ -188,3 +202,28 @@ class S3Image extends AgentRuntimeArtifact {
188202
} as any;
189203
}
190204
}
205+
206+
class ImageUriArtifact extends AgentRuntimeArtifact {
207+
constructor(private readonly containerUri: string) {
208+
super();
209+
210+
// Validate ECR container URI format per CloudFormation requirements
211+
const ecrPattern = /^\d{12}\.dkr\.ecr\.([a-z0-9-]+)\.amazonaws\.com\/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*\/)*[a-z0-9]+(?:[._-][a-z0-9]+)*)([:@]\S+)$/;
212+
if (!Token.isUnresolved(containerUri) && !ecrPattern.test(containerUri)) {
213+
throw new ValidationError(
214+
`Invalid ECR container URI format: ${containerUri}. Must be an ECR URI: {account}.dkr.ecr.{region}.amazonaws.com/{repository}:{tag}`,
215+
);
216+
}
217+
}
218+
219+
public bind(_scope: Construct, _runtime: Runtime): void {
220+
// No permissions are granted automatically when using a direct URI.
221+
// Users must manage ECR pull permissions separately.
222+
}
223+
224+
public _render(): CfnRuntime.AgentRuntimeArtifactProperty {
225+
return {
226+
containerUri: this.containerUri,
227+
} as any;
228+
}
229+
}

packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/runtime-artifact.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,61 @@ describe('AgentRuntimeArtifact tests', () => {
117117
expect(rendered1.containerUri).toBe(rendered2.containerUri);
118118
});
119119

120+
test('Should create artifact from image URI', () => {
121+
const containerUri = '123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:v1.0.0';
122+
const artifact = AgentRuntimeArtifact.fromImageUri(containerUri);
123+
124+
const runtime = new Runtime(stack, 'test-runtime', {
125+
runtimeName: 'test_runtime',
126+
agentRuntimeArtifact: artifact,
127+
});
128+
129+
artifact.bind(stack, runtime);
130+
const rendered: any = artifact._render();
131+
132+
expect(rendered.containerUri).toBe(containerUri);
133+
});
134+
135+
test('Should support CloudFormation tokens in image URI', () => {
136+
const token = cdk.Fn.ref('ImageUriParameter');
137+
const artifact = AgentRuntimeArtifact.fromImageUri(token);
138+
139+
const runtime = new Runtime(stack, 'test-runtime', {
140+
runtimeName: 'test_runtime',
141+
agentRuntimeArtifact: artifact,
142+
});
143+
144+
artifact.bind(stack, runtime);
145+
const rendered: any = artifact._render();
146+
147+
expect(rendered.containerUri).toBe(token);
148+
});
149+
150+
test('Should not require permissions for image URI', () => {
151+
const artifact = AgentRuntimeArtifact.fromImageUri('123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:latest');
152+
153+
const runtime = new Runtime(stack, 'test-runtime', {
154+
runtimeName: 'test_runtime',
155+
agentRuntimeArtifact: artifact,
156+
});
157+
158+
// Bind should not throw or require any permissions
159+
expect(() => artifact.bind(stack, runtime)).not.toThrow();
160+
161+
const rendered: any = artifact._render();
162+
expect(rendered.containerUri).toBe('123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:latest');
163+
});
164+
165+
test('Should reject non-ECR container URIs', () => {
166+
expect(() => {
167+
AgentRuntimeArtifact.fromImageUri('docker.io/myimage:latest');
168+
}).toThrow(/Invalid ECR container URI format/);
169+
170+
expect(() => {
171+
AgentRuntimeArtifact.fromImageUri('ghcr.io/owner/repo:tag');
172+
}).toThrow(/Invalid ECR container URI format/);
173+
});
174+
120175
test('Should use static construct ID for asset image regardless of directory', () => {
121176
// Create two separate stacks to test that the construct ID is always 'AgentRuntimeArtifact'
122177
const stack1 = new cdk.Stack(app, 'test-stack-1', {

0 commit comments

Comments
 (0)