Skip to content

feat(project): vend a thin CDK app built on transformAgentCoreJson - #2249

Draft
AlexanderRichey wants to merge 2 commits into
refactorfrom
feat/thin-vended-cdk-app
Draft

feat(project): vend a thin CDK app built on transformAgentCoreJson#2249
AlexanderRichey wants to merge 2 commits into
refactorfrom
feat/thin-vended-cdk-app

Conversation

@AlexanderRichey

Copy link
Copy Markdown
Contributor

The CDK app agentcore project create vends into agentcore/cdk/ shrinks from a 181-line bin/cdk.ts plus a lib/cdk-stack.ts that cast the spec to any to two short files built on three library calls — readAgentCoreProject, resolveTargetStacks and transformAgentCoreJson — so how agentcore.json is interpreted ships as @aws/agentcore-cdk versions instead of as code on customers' machines, and lib/cdk-stack.ts becomes the place a customer adds their own resources and grants runtimes or harnesses access to them through the application's accessors.

Blocked on

  • Library PR: https://github.com/aws/agentcore-l3-cdk-constructs/pull/352 (aws/agentcore-l3-cdk-constructs, branch feat/application-transform-and-extension).
  • Its release as @aws/agentcore-cdk@0.1.0-alpha.53: the vended package.json pins that exact version, which does not exist on npm yet, so project create without --skip-install fails until it is published. scripts/sync-vended-cdk.ts re-pins dependencies["@aws/agentcore-cdk"] to the latest dist-tag at release-prepare time; the key path is unchanged.

Do not merge before both.

What changed

Vended tree, before → after

agentcore/cdk/                       agentcore/cdk/
├── .gitignore                       ├── .gitignore          (unchanged)
├── .npmignore                       ├── README.md           (rewritten)
├── .prettierrc                      ├── bin/cdk.ts          (rewritten, 29 lines)
├── README.md                        ├── cdk.json            (unchanged)
├── bin/cdk.ts        (181 lines)    ├── lib/cdk-stack.ts    (rewritten, 33 lines)
├── cdk.json                         ├── package.json        (jest/prettier gone, pin 0.1.0-alpha.53)
├── jest.config.js                   └── tsconfig.json       (include no longer names test/)
├── lib/cdk-stack.ts  (94 lines)
├── package.json
├── test/cdk.test.ts
└── tsconfig.json
  • bin/cdk.ts reads the project once, makes one AgentCoreStack per target with the env/tags/description the library returns, and passes transformAgentCoreJson(project.agentCoreJson, { projectRoot, credentials }) as the stack's application prop. Failure stays one stderr line, AgentCore CDK synthesis failed: <message>, exit 1, so the CLI's progress tail stays readable.
  • lib/cdk-stack.ts instantiates one AgentCoreApplication (construct id 'Application' kept) with a commented DynamoDB example. No as any, no SpecWithLatestFields; the unused StackNameOutput is dropped (the observability test that uses that key as fixture data is untouched).
  • Removed jest scaffolding (test/cdk.test.ts, jest.config.js, .prettierrc, npmignore.template; jest, ts-jest, @types/jest, prettier and the test/format* scripts). The library's vitest suite covers synthesis of everything the app can produce and this repository's tests cover the command lines; a customer who wants tests in their CDK app adds them. Fewer files to install on a customer's disk, and one fewer toolchain to keep current.
  • src/core/project/__snapshots__/manager.test.ts.snap: regenerated; the diff removes exactly the four files above from each of the five manifests.
  • src/core/observability.ts and src/core/project/backends/cdk.ts: the comments that cited src/assets/cdk/... now point at resolveTargetStacks and AgentCorePayments, which own those rules.
  • src/handlers/project/create/pathLimit.ts: a fresh npm install puts its deepest file 155 characters below the project root (agentcore/cdk/node_modules/aws-cdk-lib/product-stack-snapshots/nested/...template.json, i.e. aws-cdk-lib's own shipped fixtures, not the removed jest), so the old "about 100" comment was an under-estimate. The Windows limit is now derived from the measurement: project root ≤ 260 − 1 − 155 = 104 characters (was a flat 150, which would have let a 306-character deepest path through). Reviewers may want to weigh this; the constant's derivation and the measurement are in the file and the README's Windows note.
  • README.md: the project create entry says what agentcore/cdk contains; a new Extending the CDK app subsection; the Windows path note carries the measurement.
  • No changes to scripts/sync-vended-cdk.ts, scripts/build.ts, or the backend command lines (npm run cdk -- synth --quiet --output <cdk.out> with cwd = agentcore/cdk is asserted unchanged by the existing backend tests). No dependency changes; bun install --frozen-lockfile succeeds.

Verification

Static (this branch): bun install --frozen-lockfile, bun run lint:check, bun run format:check, bun run typecheck, bun run secrets:check all pass; bun test --coverage — 3179 pass, 0 fail across 224 files, 95.54% lines overall; bun run build, bun pm pack --ignore-scripts, bun run compile:linux-x64 and ./dist/bin/agentcore-linux-x64 --help pass, and the compiled binary embeds exactly the seven vended files (strings on the binary lists agentcore-assets/src/assets/cdk/{README.md,bin/cdk.ts,cdk.json,gitignore.template,lib/cdk-stack.ts,package.json,tsconfig.json}).

Live (account 501930284170, us-east-1, AGENTCORE_TELEMETRY_DISABLED=1, CLI run from this branch's source with bun run src/index.ts). Because 0.1.0-alpha.53 is unpublished, each scaffolded project was created with --skip-install --skip-git and then npm install <path>/aws-agentcore-cdk-0.1.0-alpha.53.tgz was run in agentcore/cdk, which installs the library PR's tarball in place of the pin plus the rest of package.json (node_modules/@aws/agentcore-cdk/package.json reports 0.1.0-alpha.53 and dist/index.js exports transformAgentCoreJson).

Setup once: cd agentcore-l3-cdk-constructs && npm run build && npm pack with package.json temporarily at 0.1.0-alpha.53 (reverted, not committed) → aws-agentcore-cdk-0.1.0-alpha.53.tgz (479 files). CLI=bun run <agentcore-cli>/src/index.ts.

5.1 Harness project L3E2Eknq5 (default project create)
# Command Observation
1 $CLI project create --name L3E2Eknq5 --skip-install --skip-git Tree: .gitignore, agentcore/{.env.local,agentcore.json,aws-targets.json}, agentcore/cdk/{.gitignore,README.md,bin/cdk.ts,cdk.json,lib/cdk-stack.ts,package.json,tsconfig.json}, app/L3E2Eknq5/{harness.json,system-prompt.md} — exactly the 3.1 tree. agentcore.json (with abTests: []), harness.json, system-prompt.md and the post-deploy aws-targets.json / .cli/deployed-state.json shapes are checked in under test/fixtures/harness-project/ (account id replaced by 123456789012).
2 cd L3E2Eknq5/agentcore/cdk && npm install <path>/aws-agentcore-cdk-0.1.0-alpha.53.tgz node_modules/@aws/agentcore-cdk/package.json"version": "0.1.0-alpha.53"; dist/index.js exports transformAgentCoreJson. Deepest installed path: 141 chars under agentcore/cdk (node_modules/aws-cdk-lib/product-stack-snapshots/nested/…v1.product.template.json).
3 $CLI project build Built project 'L3E2Eknq5' in 8.9 s. cdk.out holds one stack AgentCore-L3E2Eknq5, tags {agentcore:project-name: L3E2Eknq5} only, description AgentCore stack for L3E2Eknq5 (no deployment target configured); resources: AWS::IAM::Role, AWS::IAM::Policy, AWS::BedrockAgentCore::Harness, AWS::CDK::Metadata; six outputs exported as AgentCore-L3E2Eknq5-Harness-L3E2Eknq5-{Id,Arn,Status,Version,AgentRuntimeArn,RoleArn}.
4 $CLI project deploy --yes Created default deployment target: account 501930284170, region us-east-1Deployed project 'L3E2Eknq5' to target 'default'. aws cloudformation describe-stacks: CREATE_COMPLETE, description AgentCore stack for L3E2Eknq5 deployed to default (us-east-1), tags agentcore:project-name=L3E2Eknq5, agentcore:target-name=default, the six AgentCore-L3E2Eknq5-default-Harness-L3E2Eknq5-* exports. aws bedrock-agentcore-control get-harness --harness-id L3E2Eknq5_L3E2Eknq5-DQNg7Re28fstatus: READY, environmentVariables: null.
4 $CLI project status --json resources: [{ resourceType: harness, name: L3E2Eknq5, deploymentState: deployed, id: arn:aws:bedrock-agentcore:us-east-1:…:harness/L3E2Eknq5_L3E2Eknq5-DQNg7Re28f }] — resolved through the export-name contract.
4 $CLI project invoke harness --prompt "Reply with the single word: pong" --json stopReason: end_turn, transcript text pong, 898 ms.
5 Edit lib/cdk-stack.ts: new dynamodb.Table(this, 'Orders', { partitionKey: {pk, STRING}, removalPolicy: DESTROY }); const h = this.application.harness('L3E2Eknq5'); h.grantReadWrite(orders); h.addEnvironmentVariable('ORDERS_TABLE', orders.tableName); $CLI project deploy --yes Deployed project 'L3E2Eknq5' to target 'default'. describe-stack-resources: OrdersA9B65338 (AWS::DynamoDB::Table, CREATE_COMPLETE) in the same stack; harness UPDATE_COMPLETE (in place, not replaced); …DefaultPolicy… UPDATE_COMPLETE.
5 aws bedrock-agentcore-control get-harness --harness-id L3E2Eknq5_L3E2Eknq5-DQNg7Re28f --query harness.environmentVariables { ORDERS_TABLE: AgentCore-L3E2Eknq5-default-OrdersA9B65338-1QN3PFN2CVU3U }, status READY.
5 $CLI harness exec --id L3E2Eknq5_L3E2Eknq5-DQNg7Re28f --command 'echo $ORDERS_TABLE' --json exitCode: 0, output: "AgentCore-L3E2Eknq5-default-OrdersA9B65338-1QN3PFN2CVU3U\n" — the variable reached the runtime.
5 aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::…:role/L3E2Eknq5_L3E2Eknq5 --action-names dynamodb:PutItem dynamodb:GetItem --resource-arns <table arn> dynamodb:PutItem allowed, dynamodb:GetItem allowed.
6 $CLI project deploy --yes with no changes Deployed project …; stack LastUpdatedTime identical before and after (2026-09-09T01:25:45.259Z), no new stack events — nothing updated or replaced.
7 $CLI project remove all --yes then $CLI project deploy --yes remove all emptied every collection. The first deploy failed at synth by design: the extension code still called harness('L3E2Eknq5'), and the app printed AgentCore CDK synthesis failed: Unknown harness "L3E2Eknq5" in project "L3E2Eknq5". Available: none (exit 1) before touching AWS. Restored the vended lib/cdk-stack.ts and re-ran: Removing stack AgentCore-L3E2Eknq5-defaultRemoved project 'L3E2Eknq5' from target 'default' (exit 0). describe-stacks afterwards: stack not found (DELETE_COMPLETE at 01:31:31Z); harness, role, policy and table gone.
7 $CLI project status --json resources: [] (nothing deployed); deployed-state.json{ "targets": {} }.
5.2 Runtime project L3E2E1jh0 (--template agent-python-strands, CodeZip, Python)
# Command Observation
1–2 $CLI project create --name L3E2E1jh0 --template agent-python-strands --skip-install --skip-git; npm install <tgz> in agentcore/cdk; uv sync in app/agent_python_strands Spec declares runtime agent_python_strands (PYTHON_3_14) and memory agent_python_strandsMemory (four strategies). Tarball 0.1.0-alpha.53 installed.
3 $CLI project build One stack AgentCore-L3E2E1jh0, target-less.
4 $CLI project deploy --yes Default target created; Deployed project 'L3E2E1jh0' to target 'default'. status --json: runtime agent_python_strands and memory agent_python_strandsMemory both deployed with ARNs. get-agent-runtime: READY, env { MEMORY_AGENT_PYTHON_STRANDSMEMORY_ID: … }. $CLI runtime invoke --id L3E2E1jh0_agent_python_strands-PXdDrR4GTM --payload '{"prompt":"hello"}'statusCode 200, streamed Hello! How can I help you today?.
5 Edit lib/cdk-stack.ts with the same table, this.application.runtime('agent_python_strands').grantReadWrite(orders) + .addEnvironmentVariable('ORDERS_TABLE', orders.tableName); $CLI project deploy --yes Deployed. describe-stack-resources: OrdersA9B65338 CREATE_COMPLETE in the same stack; runtime UPDATE_COMPLETE (in place); role CREATE_COMPLETE (kept); DefaultPolicy UPDATE_COMPLETE.
5 aws bedrock-agentcore-control get-agent-runtime --agent-runtime-id L3E2E1jh0_agent_python_strands-PXdDrR4GTM --query environmentVariables { MEMORY_AGENT_PYTHON_STRANDSMEMORY_ID: …, ORDERS_TABLE: AgentCore-L3E2E1jh0-default-OrdersA9B65338-1VSZAPZOEDBI }, status READY.
5 aws iam simulate-principal-policy --policy-source-arn <runtime role> --action-names dynamodb:PutItem dynamodb:GetItem --resource-arns <table arn> both allowed.
5 $CLI runtime invoke --id … --payload '{"prompt":"hello"}' --json statusCode 200, streamed Hello! How can I help you today? — still answering.
7 Restore vended lib/cdk-stack.ts; $CLI project remove all --yes; $CLI project deploy --yes; $CLI project status --json Removing stack AgentCore-L3E2E1jh0-defaultRemoved project 'L3E2E1jh0' from target 'default' (exit 0); status --jsonresources: []; deployed-state.json{ "targets": {} }; stack DELETE_COMPLETE at 01:34:23Z.

Cleanup check (5.4): aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE … lists no AgentCore-L3E2E* stack (both appear only under DELETE_COMPLETE); aws iam list-roles, list-agent-runtimes, list-harnesses, list-memories and dynamodb list-tables return nothing with the L3E2E / AgentCore-L3E2E prefix. Pre-existing resources in the account were not touched. The scratch projects remain on the verification host only.

The optional container check (5.2, agent-python-strands-container) was not run: the Docker daemon on the verification host was down (docker info failed) and it is not required for the PRs.

Reviewer guide

  1. src/assets/cdk/bin/cdk.ts and src/assets/cdk/lib/cdk-stack.ts — the whole vended app.
  2. src/assets/cdk/package.json, tsconfig.json, README.md — the pin, the include list, the customer-facing docs.
  3. src/core/project/__snapshots__/manager.test.ts.snap — only removals.
  4. src/handlers/project/create/pathLimit.ts (+ test) — the measured Windows limit.
  5. src/core/observability.ts, src/core/project/backends/cdk.ts — comment-only.
  6. README.mdproject create entry, "Extending the CDK app", Windows note.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KEWrUu52DmcWE3sx4VEhKL

AlexanderRichey and others added 2 commits September 9, 2026 01:30
The CDK app `project create` writes into agentcore/cdk/ shrinks to two files. bin/cdk.ts
calls readAgentCoreProject, resolveTargetStacks and transformAgentCoreJson from
@aws/agentcore-cdk and instantiates one AgentCoreStack per target; lib/cdk-stack.ts
instantiates one AgentCoreApplication (construct id 'Application' unchanged) and is the
file a customer edits to add resources and grant runtimes or harnesses access to them.
Everything the old 181-line bin/cdk.ts did — reading the spec, every harness.json and
system-prompt.md, connector files and deployed-state.json, stack naming and tagging —
now lives in the library, so it changes with the library version rather than on
customers' disks. No `as any`: the types come from the pinned library. The unused
StackNameOutput output is dropped.

test/cdk.test.ts, jest.config.js, .prettierrc and npmignore.template are removed, and
jest, ts-jest, @types/jest and prettier leave the vended package.json with the test and
format scripts: the library's vitest suite and this repository's tests cover synthesis,
and a customer who wants tests in their CDK app adds them. The pin moves to
0.1.0-alpha.53, the first library release carrying transformAgentCoreJson;
dependencies["@aws/agentcore-cdk"] stays a plain exact version string for
scripts/sync-vended-cdk.ts.

The manager snapshot drops the four removed files. The observability and CDK-backend
comments that cited src/assets/cdk now point at the library helper and construct that own
the rule. pathLimit: a fresh install puts its deepest file 155 characters below the
project root (aws-cdk-lib's shipped fixtures, not jest), so the Windows limit is derived
from that measurement (104-character project root) instead of the old "about 100" guess.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEWrUu52DmcWE3sx4VEhKL
The project create entry in the command tree says what agentcore/cdk contains now, a new
"Extending the CDK app" subsection walks through lib/cdk-stack.ts, the accessors, grants,
environment variables and redeploying (noting that project status reports only the
resources agentcore.json declares), and the Windows path note carries the measured depth.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEWrUu52DmcWE3sx4VEhKL
@github-actions github-actions Bot added the size/l PR size: L label Sep 9, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added claude-security-reviewing Claude Code /security-review in progress agentcore-harness-reviewing AgentCore Harness review in progress labels Sep 9, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Sep 9, 2026

@agentcore-devx-automation agentcore-devx-automation Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AgentCore Harness Review

Verdict: Looks good

Nice cleanup — the vended bin/cdk.ts collapsing to three library calls (readAgentCoreProject / resolveTargetStacks / transformAgentCoreJson) removes a lot of type-loosened field reading from the user-editable app, and moving HarnessConfig resolution and the AgentCore-<project>-<target> naming rule into @aws/agentcore-cdk is the right direction. The pathLimit rationale is now grounded in an actual measurement (aws-cdk-lib's own shipped fixtures), and the arithmetic in the new 104/105 test checks out with path.join on both separators.

A couple of things worth confirming before merge (not blockers, since I can't verify them against alpha.53 locally — agentcore-l3-cdk-constructs in this workspace is still at alpha.22):

  • The old bin/cdk.ts explicitly treated targets.length === 0 as "synthesize one environment-agnostic stack so project build can typecheck before targets exist." That branch is gone; confirm resolveTargetStacks in alpha.53 does the same thing (returns a single env-agnostic entry), otherwise agentcore project build on a freshly created project — which runs unconditionally via projectManager.build in handlers/project/build/index.ts — will start failing.
  • targetStackName in src/core/observability.ts still duplicates the AgentCore-<project>-<target> + _→- rule. The updated comment acknowledges the source of truth now lives in the library; consider exporting a helper from @aws/agentcore-cdk in a follow-up so the two can't drift.

Nothing that requires changes in this PR.

@agentcore-devx-automation agentcore-devx-automation Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Sep 9, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.04%. Comparing base (d9ab959) to head (9deed5d).
⚠️ Report is 1 commits behind head on refactor.

Additional details and impacted files
@@            Coverage Diff            @@
##           refactor    #2249   +/-   ##
=========================================
  Coverage     97.04%   97.04%           
=========================================
  Files           566      566           
  Lines         39409    39410    +1     
=========================================
+ Hits          38244    38245    +1     
  Misses         1165     1165           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/l PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants