Commit 4469333
authored
feat(payments): add AgentCore Payments as first-class CLI resource (#1261)
* feat(payments): add AgentCore Payments as first-class CLI resource
Adds AgentCore Payments as a first-class resource type in the CLI:
- `agentcore add/remove payment-manager` and `payment-connector`
(CoinbaseCDP + StripePrivy), CLI + TUI wizard
- Cascading delete of connectors + credentials + .env.local cleanup
- CDK-backed deploy via AgentCorePaymentManager / AgentCorePaymentConnector
L3 constructs, including runtime-role payment data-plane IAM grants
- Payment credential provider setup (imperative, AgentCore Identity vault)
- CFN output parsing into deployed-state
- Invoke flags: --payment-instrument-id, --payment-session-id, --auto-session
- Strands template wires AgentCorePaymentsPlugin; PAYMENT_SYSTEM_PROMPT
references the plugin-provided http_request tool
Schema:
- payments[] in agentcore.json, .optional() (non-breaking: absent configs
are not rewritten with payments: [])
- payment manager name regex matches CreatePaymentManager API (no underscore);
connector names allow underscores per CreatePaymentConnector
- getOrCreatePaymentSession unwraps the CreatePaymentSession `paymentSession`
response so --auto-session forwards a real session id
Verified end-to-end on Base Sepolia: real on-chain USDC settle via the
SDK plugin (bedrock-agentcore >= 1.12.0 / PR #493).
* fix(payments): route vended CDK spec access through specAny
The vended cdk/bin/cdk.ts compiles against the published @aws/agentcore-cdk
schema type, which lags the CLI's AgentCoreProjectSpec (no payments/harnesses
fields). Restore `const specAny = spec as any` and route payments/harnesses/
gateway field access through it, fixing TS2304 (specAny undefined) and TS2339
(payments missing) introduced while resolving the rebase conflict in this file.
Regenerates the asset snapshot to match.
* ci(e2e): wire CoinbaseCDP creds into payment deploy test
The payment E2E deploy test (payment-strands-bedrock.test.ts) gates on
CDP_API_KEY_ID / CDP_API_KEY_SECRET / CDP_WALLET_SECRET but the workflow
never supplied them, so it silently skipped in CI.
- Map CDP_* env vars in the GA test step from the E2E secret's
CDP_* JSON keys (surfaced as E2E_CDP_* by parse-json-secrets).
- Add payment-strands-bedrock.test.ts to the GA run command and
exclude it from change-detection GA_EXTRA to avoid double-running.
Requires CDP_API_KEY_ID / CDP_API_KEY_SECRET / CDP_WALLET_SECRET added
to the E2E Secrets Manager secret. Absent (e.g. forks) -> test
self-skips via its hasCdpCreds gate.
* feat(payments): scope invoke payments to an end user via --payment-user-id
Payment instruments and sessions are scoped per end user (wallet owner), but
`agentcore invoke` never sent that identity to the agent: --user-id went only to
the runtime/Identity header (dropped by the runtime), and the invoke body carried
no user_id. The agent (main.py) already reads payload.get("user_id"), so it always
fell back to "default-user" and looked up the wallet under the wrong identity
("Instrument not found").
- Add --payment-user-id; write it into the invoke body as user_id. Falls back to
--user-id; when neither is set the agent's own "default-user" fallback applies
(we never bake that value into the wire). --user-id stays the Identity-header axis.
- Warn (stderr, non-fatal) when a payments-enabled invoke has no resolved payment
identity, so spend is not silently commingled under "default-user".
- Scope --auto-session's created session to the resolved payment identity so the
session, instrument, and body user_id all align.
- Interactive TUI: payment flags (without a prompt) now carry the payment context
across the whole chat session instead of forcing CLI mode; header shows
"Payments: active (wallet owner: <id>)". --auto-session remains CLI-only.
- Tests: buildInvokePayload backward-compat + snake_case wire shape; the no-identity
warning matrix; --auto-session user scoping; payment-flag mode routing.
- Docs: --payment-user-id, the two-user_id model, out-of-band instrument creation,
and the one-time WalletHub delegated-signing consent step.
No CDK or agent-template changes needed: scoping is data-plane (invoke body), and
the template already reads payload.user_id.
* docs(payments): document delegated-signing setup and verified end-to-end settlement
Refine the payments doc against the CDP delegated-signing docs and a verified
on-chain settlement (Base Sepolia), so the WalletHub/grant flow is accurate:
- Grant delegated signing now describes BOTH required layers: the project-level
CDP "Delegated Signing" toggle (developer, once) AND the per-wallet WalletHub
grant (end user, once). Hedge the OTP wording (CDP's primary, not only, method)
and note WalletHub fronts CDP's createDelegation — there is no API to grant.
- Add "End-to-end: get a transaction through" — the full create -> deploy ->
create+fund instrument -> grant -> invoke recipe, for both command and
interactive modes.
- Explain the incognito requirement (avoid carrying a developer Coinbase session)
and document transient on-chain settlement failures (retry succeeds; funds not
debited on failure), with matching troubleshooting rows.
* fix(payments): persist autoPayment and defaultSpendLimit defaults
`add payment-manager` previously dropped autoPayment and defaultSpendLimit
when not explicitly passed, so the documented defaults never reached
agentcore.json. Materialize them via schema .default() (matching the
evaluator precedent) and in PaymentManagerPrimitive.add() using nullish
coalescing so an explicit --auto-payment false is preserved.
* docs(payments): clarify defaultSpendLimit is auto-session-only
defaultSpendLimit reads as a deployed-manager budget, but the service has
no manager-level budget concept — it only sizes the session that
`invoke --auto-session` mints for local testing. Relabel the CLI flag help,
the TUI wizard hint, and the docs tables to say so explicitly, and correct
the payment-manager overview that implied manager-level 'budget defaults'.
* refactor(payments): remove vestigial 'pattern' field
The payment-manager 'pattern' (interceptor | tool-based) was collected via
CLI flag and TUI wizard, persisted, then silently dropped before deploy
(never mapped in the vended bin/cdk.ts), and 'tool-based' was implemented
in no layer — shim, SDK plugin, or config. Interceptor is the only real
behavior (settlement is never an agent tool, per the payments design).
Remove 'pattern' from the schema, CLI flag, persist path, TUI wizard step,
status detail, docs, and tests. Existing agentcore.json files carrying
'pattern' still parse cleanly (the schema is not .strict(), so Zod strips
the unknown key); covered by a back-compat assertion in
agentcore-project.test.ts. Status now shows auto-pay state instead.
* feat(payments): split add TUI into Payment Manager + Connector rows
Payments was the only resource hidden behind a single 'Payment' menu entry
that opened a second manager/connector picker — a nested menu no other
resource has. Replace it with two top-level selectable rows ('Payment
Manager', 'Payment Connector'), each routing straight into its wizard via a
new AddPaymentFlow initialAction prop that skips the intermediate picker.
Also fixes `agentcore add payment-manager` / `add payment-connector` with no
args: their interactive fallback now passes initialResource so they land
directly in the right wizard instead of the generic resource menu. Esc/back
(including the error state) returns to the main Add list when launched
directly, never the skipped picker.
* fix(payments): show payments in the TUI status view
The interactive `status` screen (ResourceGraph) iterated every resource type
except payments, so a deployed Payment Manager and its connectors were
silently absent — even though the data was already computed by the shared
status path and `status --type payment` showed it. Add a Payments section
modeled on the Gateways block (manager as parent, connectors indented as
children), keyed on `payment:<name>` to pick up live deploy status, and
include payments in the empty-state guard.
* feat(payments): support --auto-session in the interactive invoke TUI
`--auto-session` was CLI-only: it forced non-interactive mode and was never
threaded into the TUI. Now `agentcore invoke --auto-session` (no prompt)
launches the interactive chat and mints/reuses a payment session ONCE at TUI
start — scoped to the resolved payment identity, reused on every turn (held in
a ref since it is only read in invoke()'s closure, never rendered). Mirrors the
CLI mint in action.ts, including its try/catch so a mint failure surfaces as a
TUI error screen instead of a hard exit.
The --auto-session + --payment-session-id mutual exclusion is enforced at the
command boundary before rendering. With a prompt or --json, --auto-session
still runs one-shot CLI as before.
* feat(invoke): group --help flags into labelled sections
`agentcore invoke --help` listed ~30 flags as one flat block. Apply the same
pattern as `add ab-test` (opt.hidden + addHelpText): keep Core flags in the
default Options list and group the rest under Payments / Output / MCP & Advanced
sections, with Harness and Model-override sections gated behind preview so they
only appear when those flags are registered.
* test(payments): drop stale 'pattern' from unit-test fixtures
Follow-up to 0ec6cac (pattern removal): four unit-test fixtures still passed
the removed 'pattern' field to add()/manager literals. They were fixed in the
working tree but missed from that commit's `git add`, leaving HEAD's tests
referencing a field the production type no longer has (clean-checkout typecheck
failed). Commit the fixtures so HEAD typechecks standalone.
* fix(payments): fail fast when a connector credential ARN is unresolved
The vended bin/cdk.ts mapped an unresolved payment credentialProviderArn to an
empty string, which then failed opaquely server-side at CreatePaymentConnector.
Throw an actionable error at synth time naming the connector, manager, and
missing credential instead. Snapshot updated (vended asset).
* fix(payments): use isZipExcludedEntry at the zip-packaging sites
The rebase left collectFiles/collectFilesSync calling shouldExcludeEntry with
a rootDir arg that isn't in scope there (TS2304). Restore the two-helper split
from the original branch: shouldExcludeEntry (copy stage, has rootDir) and
isZipExcludedEntry (zip stage, no rootDir) — both drop build artefacts and
.env secret files; only the copy stage skips the config dir at root.
* test(payments): give cfgMgr a connector before validate in e2e
The 'accepts paymentToolAllowlist and networkPreferences' case reused the
connector-less cfgMgr and expected `validate` to exit 0, but validate
correctly rejects any manager with zero connectors. The two new fields
parse fine; the failure was the 'has no connectors' business rule. Attach
a connector to cfgMgr before injecting the fields and validating, and hoist
the inline fs import to the top per AGENTS.md.1 parent 23947ad commit 4469333
114 files changed
Lines changed: 12160 additions & 120 deletions
File tree
- .github/workflows
- docs
- e2e-tests
- integ-tests
- src
- assets
- __tests__/__snapshots__
- cdk
- bin
- lib
- test
- python
- a2a/langchain_langgraph/base
- agui
- googleadk/base
- langchain_langgraph/base
- http
- autogen/base
- langchain_langgraph/base
- openaiagents/base
- strands
- base
- capabilities/payments
- cli
- aws
- __tests__
- cdk/toolkit-lib
- cloudformation
- __tests__
- commands
- deploy
- dev
- invoke
- __tests__
- logs/__tests__
- remove
- status
- validate
- __tests__
- external-requirements/__tests__
- logging
- operations
- agent/generate
- deploy
- __tests__
- dev
- __tests__
- primitives
- __tests__
- telemetry/schemas
- templates
- tui
- components
- __tests__
- hooks
- screens
- add
- __tests__
- deploy
- invoke
- payment
- remove
- __tests__
- lib
- packaging
- __tests__
- utils
- schema/schemas
- __tests__
- primitives
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
| 126 | + | |
126 | 127 | | |
127 | 128 | | |
128 | 129 | | |
| |||
131 | 132 | | |
132 | 133 | | |
133 | 134 | | |
| 135 | + | |
134 | 136 | | |
135 | 137 | | |
136 | 138 | | |
| |||
153 | 155 | | |
154 | 156 | | |
155 | 157 | | |
156 | | - | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
157 | 168 | | |
158 | 169 | | |
159 | 170 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | | - | |
| 37 | + | |
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| 91 | + | |
| 92 | + | |
91 | 93 | | |
92 | 94 | | |
93 | 95 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
140 | 140 | | |
141 | 141 | | |
142 | 142 | | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
| |||
473 | 473 | | |
474 | 474 | | |
475 | 475 | | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
476 | 554 | | |
477 | 555 | | |
478 | 556 | | |
| |||
739 | 817 | | |
740 | 818 | | |
741 | 819 | | |
| 820 | + | |
| 821 | + | |
742 | 822 | | |
743 | 823 | | |
744 | 824 | | |
745 | 825 | | |
746 | 826 | | |
747 | 827 | | |
748 | | - | |
749 | | - | |
750 | | - | |
751 | | - | |
752 | | - | |
753 | | - | |
754 | | - | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
755 | 836 | | |
756 | 837 | | |
757 | 838 | | |
| |||
815 | 896 | | |
816 | 897 | | |
817 | 898 | | |
818 | | - | |
819 | | - | |
820 | | - | |
821 | | - | |
822 | | - | |
823 | | - | |
824 | | - | |
825 | | - | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
835 | 920 | | |
836 | 921 | | |
837 | 922 | | |
| |||
0 commit comments