Skip to content

fix(invoke): add bearer-token support to the A2A invoke path for CUSTOM_JWT (#815)#1647

Merged
aidandaly24 merged 3 commits into
aws:mainfrom
aidandaly24:fix/815
Jun 29, 2026
Merged

fix(invoke): add bearer-token support to the A2A invoke path for CUSTOM_JWT (#815)#1647
aidandaly24 merged 3 commits into
aws:mainfrom
aidandaly24:fix/815

Conversation

@aidandaly24

@aidandaly24 aidandaly24 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

Closes #815 — A2A agents with CUSTOM_JWT auth are uninvokable.

An A2A-protocol agent configured with CUSTOM_JWT authorization cannot be invoked. The CLI auto-fetches a bearer token but silently drops it on the A2A path and falls back to SigV4, so every invoke fails with a confusing service error:

AccessDeniedException: Authorization method mismatch. The agent is configured for a
different authorization method than what was used in your request. (OAuth or SigV4)

There is no workaround short of a code change, and no warning at add time. The bug affects all three invoke surfaces: agentcore invoke, the TUI, and the dev web-UI.

Fix

Thread the bearer token through the A2A invoke path, mirroring how the HTTP path already works. A2A uses the same InvokeAgentRuntime data plane and /runtimes/{arn}/invocations endpoint as HTTP, which already supports bearer auth — so when a token is present, the request should be a raw HTTPS POST with an Authorization: Bearer header rather than a SigV4-signed SDK call.

Change Location
Add bearerToken?: string to A2AInvokeOptions src/cli/aws/agentcore.ts
In invokeA2ARuntime: when bearerToken is set, POST the JSON-RPC body with Authorization: Bearer <token> (via buildInvokeUrl / buildBearerInvokeHeaders) and parse via the existing parseA2AResponse; otherwise fall back to the SigV4 client unchanged src/cli/aws/agentcore.ts
Pass the token through the CLI invoke path src/cli/commands/invoke/action.ts
Pass the token through the TUI invoke path src/cli/tui/screens/invoke/useInvokeFlow.ts
Pass the token through the dev web-UI path src/cli/operations/dev/web-ui/handlers/invocations.ts

The no-token path is unchanged, so non-JWT A2A agents keep using SigV4 exactly as before.

Testing

Validated end-to-end against a real deployed agent and a real JWT issuer, not just unit tests.

Live deploy + invoke (build 0.21.0, us-east-1):

  1. Stood up a real OIDC issuer — a Cognito user pool with a resource server (agentcore/invoke scope) and a client-credentials app client — and confirmed token issuance + OIDC discovery.

  2. Created an A2A + CUSTOM_JWT agent (--protocol A2A --authorizer-type CUSTOM_JWT --discovery-url <cognito-oidc> --allowed-clients <id> ...) and deployed it. get-agent-runtime confirmed serverProtocol: A2A with the customJWTAuthorizer wired to the Cognito issuer; runtime READY.

  3. Invoked with a real bearer token — succeeded:

    $ agentcore invoke "What is 21 plus 21? Use the add_numbers tool." \
        --bearer-token <jwt> --session-id <43-char-id>
    21 plus 21 equals **42**.
    
  4. Reproduced the pre-fix failure on the same runtime — a SigV4-signed request returned the exact AccessDeniedException: Authorization method mismatch error this fix eliminates on the bearer path. So the bug is confirmed real and the fix confirmed effective on the same deployed agent.

Automated tests:

  • New src/cli/aws/__tests__/agentcore-a2a-bearer.test.ts (2/2) — asserts the bearer path uses fetch with Authorization: Bearer <token> and never the SigV4 client, and that the no-token path still falls back to SigV4.

  • 45/45 related regression tests pass (resolve, payments, deployed-invocations).

  • build / typecheck / lint / format all green in CI.

  • I ran npm run test:unit and npm run test:integ

  • I ran npm run typecheck

  • I ran npm run lint

  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots — N/A, no src/assets/ changes

Related Issue

Closes #815

Documentation PR

N/A — bug fix; no devguide change required.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

…M_JWT runtimes

A2A-protocol agents configured with CUSTOM_JWT authorization could not be
invoked: the CLI auto-fetched a bearer token but invokeA2ARuntime always used
the SigV4 client, dropping the token and triggering an "Authorization method
mismatch" service error.

Add bearerToken support to A2AInvokeOptions and, when set, send a raw HTTP POST
of the JSON-RPC body with an Authorization: Bearer header via buildInvokeUrl /
buildBearerInvokeHeaders, parsing the response through parseA2AResponse. Thread
the token through all three call sites (invoke action, TUI invoke flow, dev
web-UI invocations handler).

Fixes aws#815
@github-actions github-actions Bot added the size/m PR size: M label Jun 26, 2026
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.21.0.tgz

How to install

gh release download pr-1647-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-0.21.0.tgz

@aidandaly24 aidandaly24 changed the title fix(invoke): add bearer-token support to the A2A invoke path (#815) fix(invoke): add bearer-token support to the A2A invoke path for CUSTOM_JWT (#815) Jun 26, 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 Jun 26, 2026
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Jun 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 26, 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 Jun 26, 2026

@agentcore-cli-automation agentcore-cli-automation left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks good to merge.

The fix mirrors the existing invokeWithBearerTokenStreaming pattern correctly:

  • buildInvokeUrl + buildBearerInvokeHeaders are reused — no logic duplication.
  • The bearer branch is gated on options.bearerToken and the SigV4 path is left untouched as a fallback.
  • All three call sites (action.ts, invocations.ts, useInvokeFlow.ts) are updated, and resolveInvokeTarget already auto-fetches the token upstream for the CLI/TUI paths, so existing CUSTOM_JWT users get the fix transparently.

Tests are appropriately scoped — mocking only at the true I/O boundaries (@aws-sdk/client-bedrock-agentcore and globalThis.fetch) and asserting both the bearer path and the SigV4 fallback. No excessive mocking.

No new telemetry is needed since InvokeAttrs already captures auth_type (src/cli/telemetry/schemas/command-run.ts:138).

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 26, 2026
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Jun 26, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 26, 2026
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 26, 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 Jun 26, 2026

@agentcore-cli-automation agentcore-cli-automation left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks good to merge.

The fix is correct and minimal:

  • The bearer branch is properly gated on options.bearerToken in invokeA2ARuntime (agentcore.ts:960-977) and the SigV4 path is left intact as the fallback. The bearer code reuses buildInvokeUrl and buildBearerInvokeHeaders, mirroring invokeWithBearerTokenStreaming and mcpRpcCallWithBearer — this also resolves the TODO at agentcore.ts:708.
  • All three A2A call sites are threaded: action.ts:596, useInvokeFlow.ts:786, and invocations.ts:463/559 (via the new bearerToken field on DeployedInvokeParams). resolveInvokeTarget auto-fetches the token for CUSTOM_JWT agents upstream, so existing users get the fix transparently.
  • Response handling stays symmetric with the SigV4 path: a single res.text() fed through parseA2AResponse and wrapped in singleValueStream. The bearer path additionally surfaces the runtime session id from the response headers, which is a small bonus.
  • Tests mock only at true I/O boundaries (the @aws-sdk/client-bedrock-agentcore SDK client and globalThis.fetch) and assert both the bearer path (Authorization header, JSON-RPC body shape, no SDK call) and the SigV4 fallback (no fetch call, SDK invoked). No excessive mocking, and the pattern matches agentcore-mcp-bearer.test.ts.
  • No new telemetry is needed: InvokeAttrs.auth_type (command-run.ts:138) is already derived from options.bearerToken in buildInvokeAttrs (invoke/utils.ts:29), so the A2A+JWT path will be reported as bearer_token automatically.

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 26, 2026
@aidandaly24 aidandaly24 marked this pull request as ready for review June 29, 2026 13:49
@aidandaly24 aidandaly24 requested a review from a team June 29, 2026 13:49
@aidandaly24 aidandaly24 merged commit 2eeba2b into aws:main Jun 29, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A2A invoke does not support CUSTOM_JWT authentication

3 participants