fix(export): make generated Strands runtimes deployable - #2154
fix(export): make generated Strands runtimes deployable#2154aidandaly24 wants to merge 11 commits into
Conversation
|
Claude Security Review: no high-confidence findings. (run) |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## refactor #2154 +/- ##
============================================
- Coverage 97.22% 97.19% -0.04%
============================================
Files 507 507
Lines 33809 33943 +134
============================================
+ Hits 32872 32992 +120
- Misses 937 951 +14 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
AgentCore Harness Review
Verdict: Looks good
Nice, tightly-scoped fix. I walked through the template updates, the exporter changes, and the new EC2-backed VPC lookup and didn't find anything that needs to change before merge. A few observations, none of which are blockers:
HarnessClient.resolveVpcIdFromSubnetsis wired cleanly throughAwsClients/CoreClientand the ec2 client is cached like the others; the new tests cover the multi-VPC / no-VPC / happy paths without mocking anything below the SDK boundary. 👍- The switch to a strict ARN regex in
parseHarnessArnis the right call, and the behavior change of always trusting the ARN's region (rather than falling back to CLI region) is now consistent betweenharnessIdFromArnandregionFromHarnessArn. The test inharness.test.ts(arn:aws:lambda:...) and the partition test inserviceHarness.test.ts(arn:aws-cn:...) cover the important edges. - The
main.pytemplate'slimits = { … } or Noneidiom is intentional: whenhasExecutionLimitsis true solely becausetimeoutSecondsis set, both{{#if}}branches inside the dict literal are stripped, so it evaluates toNone. As long asagent.stream_async(..., limits=None, ...)is accepted by strands-agents 1.54 (per the verification notes in the PR description, it is), this is fine. serviceHarness.tsnow surfaces$unknownunion members as export notes instead of silently dropping them (skills, memory, environment, environment artifact, filesystem configs). Good coverage inserviceHarness.test.ts.- Header credential names / python function names now hash their inputs, so
X-Api-KeyvsX_Api_Keyno longer collide — nice; that's exercised by the new "keeps normalized header names distinct" test. readStrandsVersionregex was updated to tolerate the newstrands-agents[extras]form.- No new features here that would need telemetry instrumentation; existing plumbing is untouched.
LGTM to merge.
ed3b929 to
bee4e65
Compare
|
Claude Security Review: no high-confidence findings. (run) |
| // results to. CloudWatch is a distinct service from the AgentCore data plane, | ||
| // so it gets its own client/factory rather than reusing `data`. | ||
| logs(config: ClientConfig): CloudWatchLogsClient; | ||
| ec2(config: ClientConfig): EC2Client; |
There was a problem hiding this comment.
Why do we need an EC2 client?
| .send(new GetHarnessCommand({ harnessId: id })); | ||
| } | ||
|
|
||
| async resolveVpcIdFromSubnets(subnetIds: string[], options: CoreOptions): Promise<string> { |
There was a problem hiding this comment.
Why do we need to do this? The API doesn't require this: https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_NetworkConfiguration.html
| spec.networkConfig && | ||
| !spec.networkConfig.vpcId | ||
| ) { | ||
| spec.networkConfig.vpcId = await config.core.harness.resolveVpcIdFromSubnets( |
There was a problem hiding this comment.
I'm not sure this need to be in scope. The main thing is generating the code that the user can then use. The user can also configure VPC stuff on their own.
|
Claude Security Review: no high-confidence findings. (run) |
The pinned @aws/agentcore-cdk rejects additionalParams on every provider but lite_llm, and re-parses harness.json at synth. Dropping the CLI refinement moved that failure from `project add harness` to `project build`, where it surfaces as a raw zod dump — reachable via `project create --additional-params`, whose provider defaults to bedrock. Restore the refinement, and drop the field with an export note on the --arn path instead of hard-failing, since a harness authored outside this CLI can carry it.
Export layers the generated agent into the harness's image by writing a `FROM <containerUri>` Dockerfile, which turns a no-build harness into a CodeBuild build. CodeBuild's CreateProject needs an explicit vpcId and cannot infer one from subnets, so the exported project failed at `project build` with a raw zod dump from CDK synth. Neither source of a harness carries a vpcId — the service's VpcConfig has no such field, and a local containerUri harness is never built so its schema rightly does not demand one. Export is what creates the requirement, so add --vpc-id and fail before writing anything when it is needed and absent. No AWS lookup is involved: getHarness remains the only request on the --arn path.
Commit 8570ab2 added an `ec2:` stub key and a fake client, which pushed one object past prettier's width and shifted a blank line. b3fbb3d removed the EC2 code but left the reflowed formatting, so the PR still showed two core test files as changed with no bug behind them. Both files now match the base byte for byte.
Three follow-ups from auditing the new commits against surrounding code: - reuse NetworkConfigSchema.shape.vpcId for the flag instead of restating its regex, matching how every other validated flag reuses a projectSchemas schema (BuildTypeSchema, ProtocolModeSchema, NetworkModeSchema); the inline regex was the only one in src/handlers - the remedy said `--vpc-id vpc-xxxxxxxx`, which VPC_ID_PATTERN rejects because x is not a hex digit, so copy-pasting it produced a second error; use the <placeholder> form the other free-form remedies use - document the flag in README, which enumerates this command's flags in prose - cover both new mapper branches in export.test.ts, which owns mapHarnessToExportPlan branch coverage and already tests the sibling throw
Mutation-tested every test this PR adds by breaking the behaviour each one
claims to cover and re-running it. Three results worth acting on:
- the lite_llm half of "notes additionalParams..." asserted what the
pre-existing "maps openai and litellm model configs" already asserts with the
same fixture value; both fail on the same mutation, so it was pure duplication
- "requires --vpc-id..." claimed in its comment to fail before writing anything
but only asserted rejection, so relocating the throw after the write would have
kept it green; now snapshots agentcore.json and checks the agent dir is absent
- the ARN test never pinned the 12-digit account group; loosening \d{12} to \d+
passed. It now fails, verified by applying that mutation.
Everything else detected its mutation and stays as is.
|
Claude Security Review: no high-confidence findings. (run) |
Summary
strands-agents 1.54.xAPIs and provider extrasEXPORT_NOTES.mdinstead of silently dropping them--vpc-idtoproject export harness: export rewrites acontainerUriharness as a Dockerfile build so the agent code can be layered in, which makes CodeBuild's VPC id mandatory where the source harness never needed oneadditionalParamsrestricted to thelite_llmprovider, and drop it with an export note on the--arnpath rather than writing a spec the pinned CDK rejects at synthVerification
Source gate
bun install --frozen-lockfilebun test src: 2,597 pass, 0 failbun run typecheckbun run lint:checkbun run format:checkbun run buildbun run secrets:checkGenerated Python matrix
Generated real exports and ran
uv sync,compileall, andimport mainfor:All five resolved
strands-agents 1.54.0and imported successfully. OpenAI/Mantle resolvedopenai 2.54.0, Gemini resolvedgoogle-genai 2.20.0, and LiteLLM resolvedlitellm 1.96.0. A generated-module probe invoked the Bedrock entrypoint twice and verified fresh cancellation signals plus identical per-invocation limits (LIMITS_OK).Live AWS
Account
603141041947, regionus-east-1, profiledeploy:ExportHarnessFix0831_source-jBo3nhtmm2to READY and invoked itus-west-2, proving ARN-region precedence)ExportHarnessFix0831_exported_agent-hLU1ha80fdExportHarnessFix0831_exported_arn_agent-ItzBMG47U0end_turn, and the requested markerExportHarnessFix0831_mcp_runtime-6ZSyRO2yMEMCP_CONTEXT_OKThe current refactor deploy path consumes project credentials as references rather than provisioning them, so the exporter now states that the named provider must exist instead of claiming deploy creates it.
Follow-up after review
AlexanderRichey's review asked why the EC2 client existed; theDescribeSubnetslookup wasremoved in
b3fbb3dd. Reviewing that removal surfaced that dropping it left the underlying problemunaddressed, and that a separate guard had been deleted:
--vpc-id(48cae1e6). The RuntimeNetworkConfigurationAPI genuinely has novpcId— thereview comment is correct — but CodeBuild's
CreateProjectrequires one, and export is what turnsa no-build
containerUriharness into a build by emittingFROM <containerUri>. Neither source ofa harness can supply it: the service's
VpcConfighas no such field, and a localcontainerUriharness is never built, so its schema rightly does not demand one. The flag lets the caller supply
it, and export now fails before writing anything when it is needed and absent. No AWS lookup is
involved:
getHarnessremains the only request on the--arnpath.additionalParamsguard (b178ac65). Removing thelite_llm-only refinement moved a cleanfailure at
project add harnessto a raw zod dump atproject build, since the pinned CDKre-parses
harness.jsonat synth and still rejects the field on other providers. Restored, withthe
--arnmapper dropping it under an export note so a harness authored outside this CLI stillexports.
f82282b9reverts formatting residue the EC2 removal left in two test files, so both now matchthe base byte for byte.
60f499a1aligns the flag with repo conventions: reuseNetworkConfigSchema.shape.vpcIdratherthan restating its regex, use the
<placeholder>remedy form (the previousvpc-xxxxxxxxexamplecould not satisfy the flag's own pattern), and document the flag in
README.md.e504774cfollows a mutation pass over every test this PR adds — each one had the behaviour itcovers deliberately broken to confirm it fails. One duplicated assertion was removed, and two gaps
closed: the
--vpc-idfailure test now asserts nothing was written, and the ARN test now pins the12-digit account group (loosening
\d{12}to\d+previously passed).Verified by generating a real project with a VPC +
containerUriharness and parsing the resultingagentcore.jsonwithAgentEnvSpecSchemafrom@aws/agentcore-cdk@0.1.0-alpha.45, the version thegenerated project pins: the pre-fix output is rejected with
networkConfig.vpcId is required for Container builds in VPC mode, and the--vpc-idoutput isaccepted. This path was not re-run against live AWS — it needs a VPC container harness, which the
matrix above does not cover.
Cleanup
AgentCore-ExportHarnessFix0831-default: deleted