fix: resolve the gateway target for A/B test invocation URLs (#1854) - #1874
Conversation
`getInvocationUrl` built config-bundle URLs from `record.agent` — the RUNTIME
name — but a gateway invocation path segment must be a gateway TARGET name.
Whenever the two differed, every request to the printed URL failed:
{"success":false,"error":"No Target found for Target name: CustomerSupportAB"}
A config-bundle test has no target of its own to substitute. Its variants are
configuration bundles, it attaches to the whole gateway, and the service splits
traffic with a gateway rule — so the path segment is whichever gateway target
the caller invokes, which the CLI cannot know. (Confirmed against the service:
config-bundle tests store only `configurationBundle` per variant, and the
config-bundle e2e creates one on a gateway with no targets at all.)
So report the gateway base URL and name what to append, rather than guessing a
path that 404s. Target-based tests are unchanged — their variants *are* targets,
so `variants[0].targetName` is a real path.
Gateway URL: https://<gatewayId>.gateway.bedrock-agentcore.<region>.amazonaws.com
→ append /<gateway-target>/invocations (see `agentcore status --json`)
`view ab-test --json` reports `gatewayUrl` + `invocationUrlHint` for
config-bundle tests instead of `invocationUrl`, so scripts reading
`.invocationUrl` get nothing rather than a URL that fails. Target-based keeps
`invocationUrl` unchanged.
Also corrects two comments that documented the bug as intended behaviour:
`docs/ab-tests.md` ("config-bundle uses the agent name") and a claim in
RunABTestFlow that targets deploy as `${project}-${target}` — the L3 CDK
deploys each target under its spec name verbatim.
|
Claude Security Review: no high-confidence findings. (run) |
Package TarballHow to installgh release download pr-1874-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-0.25.0.tgz |
Coverage Report
|
| return targetName ? `${baseUrl}/${targetName}/invocations` : undefined; | ||
| } | ||
| return record.agent ? `${baseUrl}/${record.agent}/invocations` : undefined; | ||
| return baseUrl; |
There was a problem hiding this comment.
This always returns only the gateway base URL. This breaks working same-name configurations and scripts consuming .invocationUrl, while leaving issue #1854’s workflow manual. Creation already loads gateway targets and runtime mappings, so it should emit a complete URL when one target uniquely matches, and expose candidates or a clear ambiguity when several match.
There was a problem hiding this comment.
I was thinking of this but I wanted to establish to the user that config bundles are applied to all gateway targets. However, I could go either with this.
notgitika
left a comment
There was a problem hiding this comment.
left a comment otherwise LGTM
Config-bundle tests printed an invocation URL built from the runtime name, but a gateway path segment must be a gateway TARGET name, so requests 404'd with "No Target found for Target name: <runtime>". Resolve the gateway target(s) fronting the runtime at create time — the link lives in `agentCoreGateways[].targets[].httpRuntime.runtime`, which create() already loads — and persist the result on the record: - exactly one match -> `targetName` -> a complete `invocationUrl` - several matches -> `targetCandidates` -> `invocationUrlCandidates` (pick one) - none -> neither -> `gatewayUrl` + `invocationUrlHint` This fixes both same-name and different-name configurations (the previous gateway-base-only output regressed the same-name case and left the workflow manual), and keeps `.invocationUrl` populated whenever a single target is known. The runtime name is never used as the path. Target-based tests are unchanged. `getInvocationUrl` stays synchronous — resolution happens once at create and is read from the record — so `view --json`, `printABTestDetail`, and the TUI detail view need no plumbing changes. Also corrects two comments that documented the bug as intended behaviour.
|
Claude Security Review: no high-confidence findings. (run) |
Problem
Closes #1854.
agentcore run ab-testin config-bundle mode printed an invocation URL built from the runtime name, but a gateway invocation path segment must be a gateway target name. Whenever the two differed, every request to the printed URL failed:{"success":false,"error":"No Target found for Target name: CustomerSupportAB"}The same wrong URL was stored in
.invocationUrlforagentcore view ab-test <id> --json, so scripts inherited it too.The cause is one line in
getInvocationUrl:record.agentcomes fromopts.runtime ?? opts.name(handler.ts), i.e. the runtime. It only happened to work when a gateway target was named identically to its runtime.Why not just look the target up
A config-bundle test has no target of its own to substitute:
configurationBundleARNs, and the schema forbidstargeton them (target: z.never().optional()).CreateGatewayRule/UpdateGatewayRule.configurationBundleper variant, ande2e-tests/ab-test-config-bundle.test.tscreates one on a gateway with no targets at all — it reaches RUNNING fine.So the path segment is whichever gateway target the caller chooses to invoke. The CLI cannot know it, and a gateway may have several targets fronting one runtime (a canary beside prod), where each is equally valid.
Change
Report the gateway base URL and name what to append, instead of guessing a path that 404s:
Target-based tests are unchanged — their variants are targets, so
variants[0].targetNameis a real path and they keep a completeInvocation URL.getInvocationUrlstays synchronous and pure, so all three call sites (view --json,printABTestDetail, the TUI detail view) pick this up with no plumbing changes.Also corrects two comments that documented the bug as intended behaviour:
docs/ab-tests.md— "config-bundle uses the agent name"RunABTestFlow.tsx— claimed targets deploy as${project}-${target}; the L3 CDK deploys each target under its spec name verbatim (Gateway.ts), which is what makes the spec name the URL path segment.--jsonshape changeFor config-bundle tests only,
invocationUrlis replaced bygatewayUrl+invocationUrlHint:This is deliberate: a script reading
.invocationUrlnow gets nothing rather than a URL that silently fails. Target-based output is untouched. Both docs pages are updated.Testing
tscclean; eslint/prettier/secretlint clean.Invocation URL:line.npm run bundle→npm i -g) for both modes, in--jsonand in the TUI (directview ab-test <id>and via the interactive list). Config-bundle detail view:Notes for reviewers
Two things I found while investigating but did not change, happy to file separately:
docs/ab-tests.mddocuments--max-duration-daysand--traffic-header, but neither flag is registered inrun/command.tsxandCreateABTestOptionshas no field for either.--gateway-filterscopes a config-bundle test to a target path (live tests do carry{"targetPaths":["/orders/*"]}). A future refinement could use a literal filter path as the printed URL's segment, but glob patterns make that ambiguous so I left it out.