feat(payments): host browser use case on AgentCore Runtime + scoped IAM + observability (#1495)
--------- Co-authored-by: Guy Bachar <guybac@amazon.com>
This commit is contained in:
+4
-1
@@ -262,4 +262,7 @@ Test-Downloads/
|
||||
### Claude Code Assistant ###
|
||||
.claude/
|
||||
CLAUDE.md
|
||||
plan/
|
||||
plan/
|
||||
|
||||
### draw.io source files (keep rendered PNG only) ###
|
||||
*.drawio
|
||||
+5
@@ -49,3 +49,8 @@ NETWORK=base-sepolia
|
||||
# Deploy the CDK stack first: cd content-provider && PAY_TO=0x<your-wallet> bash deploy.sh
|
||||
# Then paste the printed CloudFront URL here.
|
||||
CONTENT_DISTRIBUTION_URL=https://<your-cloudfront-id>.cloudfront.net
|
||||
|
||||
# ── AgentCore Runtime (Step 5) ────────────────────────────────────────────
|
||||
# Name used when the AgentCore CLI scaffolds and deploys the agent.
|
||||
# Override only if you want to deploy multiple variants in the same account.
|
||||
AGENT_NAME=PayForContentBrowserAgent
|
||||
|
||||
@@ -11,3 +11,8 @@ content-provider/cdk/node_modules/
|
||||
content-provider/cdk/dist/
|
||||
content-provider/cdk/cdk.out/
|
||||
content-provider/cdk/package-lock.json
|
||||
|
||||
# AgentCore CLI scaffold + deploy artifacts (generated by Step 5).
|
||||
# The agent source of truth is in agent/. The scaffold under payforcontent/
|
||||
# is reproducible by re-running the notebook.
|
||||
payforcontent/
|
||||
|
||||
+184
-93
@@ -1,4 +1,4 @@
|
||||
# Pay for Content — Browser Use Case
|
||||
# Pay for Content — Browser Use Case (AgentCore Runtime)
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -8,14 +8,15 @@ each transaction."
|
||||
|
||||
Without AgentCore payments, an agent that needs to pay for content must either hold
|
||||
a private key (exposing credentials to the model) or interrupt the user to complete
|
||||
the payment manually. This use case shows a third path: the agent delegates signing to
|
||||
AgentCore payments, stays within human-set payment limits, and completes the entire
|
||||
browse-pay-extract flow autonomously.
|
||||
the payment manually. This use case shows a third path: the agent **leverages AgentCore
|
||||
Payments for payment processing**, stays within human-set payment limits, and completes
|
||||
the entire browse-pay-extract flow autonomously from a managed Runtime container.
|
||||
|
||||
The agent uses the **AgentCore Browser Tool** to navigate a paywalled website, reads
|
||||
the embedded x402 payment requirement from the page DOM, calls `ProcessPayment` to
|
||||
generate a cryptographic USDC proof, interacts with the paywall UI, and returns the
|
||||
unlocked content — all without any private key exposure or human intervention.
|
||||
The agent is **deployed to AgentCore Runtime** under `ProcessPaymentRole`, uses the
|
||||
**AgentCore Browser Tool** to navigate a paywalled website, reads the embedded x402
|
||||
payment requirement from the page DOM, calls `ProcessPayment` to generate a payment
|
||||
proof, interacts with the paywall UI, and returns the unlocked content — without any
|
||||
private key exposure or human intervention.
|
||||
|
||||
### Use Case Details
|
||||
|
||||
@@ -23,11 +24,12 @@ unlocked content — all without any private key exposure or human intervention.
|
||||
|:--------------------|:--------------------------------------------------------------|
|
||||
| Use case type | Agentic browser automation with autonomous micropayment |
|
||||
| Agent type | Single |
|
||||
| Hosting | AgentCore Runtime (managed microVM, role-segregated) |
|
||||
| Payment protocol | x402 (HTTP 402 Payment Required) |
|
||||
| Agentic Framework | Strands Agents |
|
||||
| LLM model | Anthropic Claude Sonnet 4.6 |
|
||||
| Complexity | Intermediate |
|
||||
| SDK used | boto3 + AgentCore SDK + AgentCorePaymentsPlugin (Strands) |
|
||||
| SDK used | boto3 + AgentCore SDK + AgentCorePaymentsPlugin (Strands) + AgentCore CLI |
|
||||
| Wallet type | Embedded crypto wallet (AgentCore-provisioned, Coinbase CDP) |
|
||||
| Network | Base Sepolia testnet (`eip155:84532`); Solana Devnet available |
|
||||
|
||||
@@ -35,91 +37,123 @@ unlocked content — all without any private key exposure or human intervention.
|
||||
|
||||
## Architecture
|
||||
|
||||
There are three distinct phases: **resource provisioning** (runs once), **session setup**
|
||||
(runs before each agent invocation), and **agent runtime** (the live payment flow).
|
||||
The content provider is operator-deployed infrastructure — it is not created by the notebook.
|
||||
There are four distinct phases: **resource provisioning** (runs once), **session setup**
|
||||
(runs before each agent invocation), **deploy** (runs on agent code change), and
|
||||
**invoke** (the live payment flow). The content provider is a separate piece of
|
||||
infrastructure that you deploy from this repo's `content-provider/` CDK stack — it
|
||||
is not created by the notebook.
|
||||
|
||||
> **Note on SDK choice:** the notebook uses boto3 clients (`bedrock-agentcore-control`
|
||||
> and `bedrock-agentcore`) for Payments resource management because the AgentCore
|
||||
> Python SDK does not yet expose `CreatePaymentManager` / `CreatePaymentSession`
|
||||
> / `CreatePaymentInstrument`. The agent itself (running on Runtime) uses the
|
||||
> `bedrock-agentcore[strands-agents]` SDK and `AgentCorePaymentsPlugin` for
|
||||
> payment processing — that side is fully SDK-driven.
|
||||
|
||||
```
|
||||
RESOURCE PROVISIONING (notebook Step 3, ControlPlaneRole)
|
||||
─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Two-client setup │
|
||||
│ │
|
||||
│ cp_client ──► CP endpoint ──► CreatePaymentCredentialProvider │
|
||||
│ (bedrock-agentcore-control) CreatePaymentManager │
|
||||
│ CreatePaymentConnector │
|
||||
│ │
|
||||
│ mgmt_client ──► DP endpoint ──► CreatePaymentInstrument │
|
||||
│ (bedrock-agentcore) (EmbeddedCryptoWallet) │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
cp_client ──► bedrock-agentcore-control ──► CreatePaymentCredentialProvider,
|
||||
CreatePaymentManager,
|
||||
CreatePaymentConnector
|
||||
mgmt_client ──► bedrock-agentcore ──► CreatePaymentInstrument
|
||||
|
||||
AgentCore provisions the on-chain wallet — no pre-existing CDP wallet required.
|
||||
Result: CREDENTIAL_PROVIDER_ARN, MANAGER_ARN, PAYMENT_CONNECTOR_ID, PAYMENT_INSTRUMENT_ID
|
||||
|
||||
|
||||
SESSION SETUP (notebook Step 4, ManagementRole)
|
||||
─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Notebook / App AgentCore payments
|
||||
────────────────── ──────────────────────────────
|
||||
CreatePaymentSession ────────────────► payment limits=$1.00 USD, expiry=60 min
|
||||
(ManagementRole via STS) paymentSessionId ──────────────► passed to agent
|
||||
Notebook (ManagementRole) AgentCore payments
|
||||
───────────────────────── ──────────────────────────────
|
||||
CreatePaymentSession ─────────────────► budget=$1.00 USD, expiry=60 min
|
||||
paymentSessionId
|
||||
|
||||
|
||||
AGENT RUNTIME (notebook Step 6, ProcessPaymentRole)
|
||||
DEPLOY AGENT TO RUNTIME (notebook Step 5, AgentCore CLI)
|
||||
─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
User
|
||||
│ "Retrieve the article and pay for it"
|
||||
agent/payment_agent.py agentcore CLI AWS
|
||||
agent/requirements.txt + agentcore deploy (CodeBuild builds
|
||||
agent/Dockerfile from Dockerfile)
|
||||
(BedrockAgentCoreApp + ──► create / deploy ──► AgentRuntime
|
||||
AgentCoreBrowser + (execution role:
|
||||
process_x402_payment) ProcessPaymentRole)
|
||||
+ ECR image
|
||||
+ CodeBuild project
|
||||
+ CloudWatch logs
|
||||
|
||||
|
||||
INVOKE (notebook Step 6, ManagementRole → AgentCore Runtime)
|
||||
─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Notebook (ManagementRole)
|
||||
│
|
||||
│ InvokeAgentRuntime(arn,
|
||||
│ paywall_url, session_id,
|
||||
│ instrument_id, manager_arn)
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Strands Agent (Claude Sonnet 4.6) │
|
||||
│ │
|
||||
│ Tool 1: AgentCoreBrowser Tool 2: process_x402_payment │
|
||||
│ (managed cloud Chromium) (calls ProcessPayment API) │
|
||||
└───────────┬────────────────────────────┬─────────────┘
|
||||
│ HTTPS │ AWS API (ProcessPaymentRole)
|
||||
▼ ▼
|
||||
┌───────────────────────┐ ┌───────────────────────────────┐
|
||||
│ Content Provider │ │ AgentCore payments │
|
||||
│ (team-hosted demo or │ │ ProcessPayment API │
|
||||
│ your own deploy) │ │ │
|
||||
│ │ │ ┌────────────────────────┐ │
|
||||
│ HTTP 200 │ │ │ Embedded Wallet │ │
|
||||
│ x402 requirement │ │ │ (Coinbase CDP) │ │
|
||||
│ in DOM script tag │ │ │ Base Sepolia testnet │ │
|
||||
│ │ │ └────────────────────────┘ │
|
||||
│ proof submitted via │◄───┤ status: PROOF_GENERATED │
|
||||
│ paywall UI → unlock │ └───────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ AgentCore Runtime microVM (ProcessPaymentRole) │
|
||||
│ │
|
||||
│ Strands Agent (Claude Sonnet 4.6) │
|
||||
│ Tool 1: AgentCoreBrowser ──► managed cloud Chromium │
|
||||
│ Tool 2: process_x402_payment ──► PaymentManager │
|
||||
│ Plugin: AgentCorePaymentsPlugin (payment query tools) │
|
||||
└───────────┬──────────────────────────────┬───────────────────┘
|
||||
│ HTTPS │ AWS API (ambient creds)
|
||||
▼ ▼
|
||||
┌───────────────────────┐ ┌───────────────────────────────┐
|
||||
│ Content Provider │ │ AgentCore payments │
|
||||
│ (team-hosted demo or │ │ ProcessPayment API │
|
||||
│ your own deploy) │ │ │
|
||||
│ │ │ ┌────────────────────────┐ │
|
||||
│ HTTP 200 │ │ │ Embedded Wallet │ │
|
||||
│ x402 requirement │ │ │ (Coinbase CDP) │ │
|
||||
│ in DOM script tag │ │ │ Base Sepolia testnet │ │
|
||||
│ │ │ └────────────────────────┘ │
|
||||
│ proof submitted via │ ◄────┤ status: PROOF_GENERATED │
|
||||
│ paywall UI → unlock │ └───────────────────────────────┘
|
||||
└───────────────────────┘
|
||||
│ article text
|
||||
▼
|
||||
Agent returns content + amount paid to user
|
||||
Agent returns content + amount paid to caller
|
||||
|
||||
|
||||
OPERATOR CLEANUP (automatic on session expiry)
|
||||
OBSERVABILITY (Step 7, automatic)
|
||||
─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Session expires automatically after expiryTimeInMinutes elapses.
|
||||
Agent can no longer spend once the session is past its expiry.
|
||||
Each invocation emits a CloudWatch GenAI Observability trace covering
|
||||
the agent loop, tool calls, payment SDK calls, and ProcessPayment API
|
||||
latency. Metrics in the bedrock-agentcore namespace.
|
||||
|
||||
|
||||
CLEANUP
|
||||
─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
agentcore remove all -y — tears down Runtime, ECR, log groups
|
||||
Session expiry — agent can no longer spend after expiry
|
||||
```
|
||||
|
||||
**Key design points:**
|
||||
|
||||
- **Embedded wallet:** AgentCore provisions the on-chain wallet — no pre-existing CDP
|
||||
- **Hosted on AgentCore Runtime.** The agent runs inside a managed microVM under
|
||||
`ProcessPaymentRole`. Role separation is enforced by infrastructure: the container
|
||||
assumes `ProcessPaymentRole` directly, and that role has an explicit Deny on session
|
||||
and instrument management. The agent code never calls `sts:AssumeRole`.
|
||||
- **Notebook = app backend.** The notebook (under `ManagementRole`) creates the session
|
||||
with a budget, then calls `InvokeAgentRuntime` with the session/instrument/manager
|
||||
context in the payload. The agent is stateless and wallet-agnostic — the same
|
||||
deployment serves any user the backend authorises.
|
||||
- **Embedded wallet.** AgentCore provisions the on-chain wallet — no pre-existing CDP
|
||||
wallet or funded account is required. The `linkedAccounts` email field ties the wallet
|
||||
to a user identity. Coinbase embedded wallets are provisioned synchronously (no OTP step).
|
||||
- **Two clients, two endpoints:** `cp_client` → CP (`bedrock-agentcore-control.{region}.amazonaws.com`)
|
||||
for all control-plane operations including `CreatePaymentCredentialProvider`; `mgmt_client` /
|
||||
`agent_dp_client` → DP (`bedrock-agentcore.{region}.amazonaws.com`) for instrument, session, and payment.
|
||||
- The notebook (not the agent) creates the session via `ManagementRole`. The agent only
|
||||
ever uses `ProcessPaymentRole`, which has an explicit IAM Deny on session management.
|
||||
- The content provider must be deployed to a public HTTPS URL before running the agent —
|
||||
`AgentCoreBrowser` is a cloud-managed browser and cannot reach `localhost`.
|
||||
- The agent never holds a private key. Signing is delegated to the AgentCore-managed
|
||||
embedded wallet. This example uses Coinbase CDP; it can be adapted for Stripe/Privy by
|
||||
swapping the credential provider configuration in Step 3.
|
||||
- **Browser tool.** `AgentCoreBrowser` is a managed cloud Chromium session reached over
|
||||
WebSocket from inside the Runtime container. The content provider must be deployed to
|
||||
a public HTTPS URL — the browser cannot reach `localhost`.
|
||||
- **No private keys.** Signing is delegated to the AgentCore-managed embedded wallet.
|
||||
Coinbase CDP today; swap the credential provider configuration in Step 3 for StripePrivy.
|
||||
|
||||
---
|
||||
|
||||
@@ -127,9 +161,19 @@ OPERATOR CLEANUP (automatic on session expiry)
|
||||
|
||||
- AWS account with Amazon Bedrock AgentCore access
|
||||
- Python 3.10+ and Jupyter Notebook (or JupyterLab)
|
||||
- Node.js 20+ (for the AgentCore CLI and content-provider CDK)
|
||||
- AWS CLI v2 configured with credentials (`aws configure`)
|
||||
- IAM roles created — run `bash setup_roles.sh` and record the ARNs in `.env`
|
||||
- Content provider deployed to AWS — run `cd content-provider && PAY_TO=0x<your-wallet> bash deploy.sh` and set `CONTENT_DISTRIBUTION_URL` in `.env` (Node.js 18+ and AWS CDK v2 required; see [content-provider/README.md](content-provider/README.md))
|
||||
- AWS CDK v2 installed (used by the AgentCore CLI under the hood)
|
||||
- AgentCore CLI installed: `npm install -g @aws/agentcore`
|
||||
> **No local Docker required.** Step 5 builds the agent's container image in
|
||||
> AWS CodeBuild via the CLI's CDK app. You only need Docker if you want to use
|
||||
> `agentcore dev` for local hot-reload development.
|
||||
- IAM roles created — run `bash setup_roles.sh` and record the ARNs in `.env`. This
|
||||
script configures `ProcessPaymentRole` to also serve as the AgentCore Runtime
|
||||
execution role (ECR pull, CloudWatch logs, X-Ray, Bedrock model invocation,
|
||||
browser tool), with explicit Deny on session/instrument management. It also adds
|
||||
`InvokeAgentRuntime` to `ManagementRole` so the notebook can call the deployed agent.
|
||||
- Content provider deployed to AWS — run `cd content-provider && PAY_TO=0x<your-wallet> bash deploy.sh` and set `CONTENT_DISTRIBUTION_URL` in `.env` (see [content-provider/README.md](content-provider/README.md))
|
||||
- A Coinbase Developer Platform (CDP) account with an API key
|
||||
- API key name, private key, and wallet secret are required (see `.env.sample`)
|
||||
- **Enable Delegated Signing** in your CDP project before running the agent:
|
||||
@@ -191,16 +235,51 @@ jupyter notebook pay_for_content_browser.ipynb
|
||||
|
||||
Run all cells in order. The notebook will:
|
||||
1. Load configuration and verify environment variables
|
||||
2. Initialise all three boto3 clients
|
||||
2. Initialise the two app-backend boto3 clients (`ControlPlaneRole`, `ManagementRole`)
|
||||
3. Provision the embedded wallet resource stack (once per user):
|
||||
CredentialProvider → PaymentManager → PaymentConnection → EmbeddedCryptoWallet Instrument
|
||||
CredentialProvider → PaymentManager → PaymentConnector → EmbeddedCryptoWallet Instrument
|
||||
— then pause for you to fund the wallet via WalletHub and the Circle faucet
|
||||
3e. Verify wallet USDC balance via `GetPaymentInstrumentBalance` (ProcessPaymentRole)
|
||||
4. Create a payment session with payment limits (operator-controlled)
|
||||
5. Build a Strands agent with `AgentCoreBrowser` and `process_x402_payment`
|
||||
6. Invoke the agent to retrieve a premium article
|
||||
7. Verify the spend was recorded via `GetPaymentSession`
|
||||
8. Cleanup — curtail session with minimum expiry
|
||||
3e. Verify wallet USDC balance via `GetPaymentInstrumentBalance` (briefly assumes
|
||||
`ProcessPaymentRole` locally, only for the balance check)
|
||||
4. Create a payment session with budget and expiry (`ManagementRole`)
|
||||
4b. **Enable Payment Manager observability** — runs the 4-step vended log
|
||||
delivery setup (`PutDeliverySource` × 2 → `PutDeliveryDestination` × 2 →
|
||||
`CreateDelivery` × 2) so the Payment Manager shows up in the AgentCore
|
||||
Observability → Payments dashboard with sessions, transactions, and
|
||||
`Agents using Payments` attribution
|
||||
5. Deploy `agent/payment_agent.py` to AgentCore Runtime via the AgentCore CLI:
|
||||
`agentcore create` + `agentcore add agent --build Container`, copy in
|
||||
[`agent/Dockerfile`](agent/Dockerfile), then `agentcore deploy` (CodeBuild builds
|
||||
the image, pushes to ECR, creates the AgentRuntime). Pinned to Python 3.13,
|
||||
`ProcessPaymentRole` execution role, 10-min idle / 30-min max lifecycle.
|
||||
6. Invoke the deployed agent via `InvokeAgentRuntime` with the session/instrument
|
||||
context in the payload, then verify spend via `GetPaymentSession`
|
||||
7. View the session trace in CloudWatch GenAI Observability — Runtime, Agent,
|
||||
Browser-tool, and Payment Manager telemetry all stitched in one dashboard
|
||||
8. Cleanup — `agentcore remove all` to tear down the Runtime deployment
|
||||
|
||||
### Observability coverage
|
||||
|
||||
| Layer | How it's enabled | Where you see it |
|
||||
|---|---|---|
|
||||
| Runtime | Auto via `agentcore deploy` (`opentelemetry-instrument` CMD) | All-traces dashboard |
|
||||
| Agent (Strands) | OTEL spans through the Runtime distro | Inside each trace's waterfall |
|
||||
| Browser tool | Strands `AgentCoreBrowser` emits client-side spans | Inside each trace's waterfall |
|
||||
| Payment Manager | Vended log delivery (Step 4b) | **Payments tab** of the AgentCore Observability dashboard |
|
||||
|
||||
The dashboard's *Agents using Payments* counter increments only when the SDK
|
||||
sends the `X-Amzn-Bedrock-AgentCore-Payments-Agent-Name` header, which it does
|
||||
automatically when `PaymentManager` and `AgentCorePaymentsPluginConfig` are
|
||||
constructed with `agent_name=`. `agent/payment_agent.py` reads `AGENT_NAME` from
|
||||
the container environment and passes it to both.
|
||||
|
||||
> **Browser observability caveat:** the AgentCore Browser service does not
|
||||
> currently support per-resource vended log delivery. `PutDeliverySource` rejects
|
||||
> browser ARNs with: *valid resource types are runtime / gateway / memory /
|
||||
> payment-manager / code-interpreter / workload-identity*. Browser-tool actions
|
||||
> still appear as spans inside the agent trace via the OTEL distro
|
||||
> (`browser session start`, `navigate`, `cleanup`), so the *useful* visibility
|
||||
> is captured — but no separate Browser-service dashboard exists today.
|
||||
|
||||
---
|
||||
|
||||
@@ -255,32 +334,44 @@ Real x402 sites will have different selectors — the agent discovers payment fo
|
||||
elements dynamically using semantic cues (button text, input types, aria-labels)
|
||||
rather than hardcoded IDs.
|
||||
|
||||
### Alternative: x402 via AgentCore Gateway
|
||||
|
||||
You can also access x402-protected endpoints directly via **Amazon Bedrock AgentCore
|
||||
Gateway**, which handles the payment header exchange at the API level without a browser.
|
||||
See the **Pay for Data** use case for that pattern.
|
||||
|
||||
---
|
||||
|
||||
## IAM Role Design
|
||||
|
||||
| Role | Operations | Denied |
|
||||
|:-----|:-----------|:-------|
|
||||
| `ControlPlaneRole` | `CreatePaymentCredentialProvider`, `CreatePaymentManager`, `CreatePaymentConnector`, `CreatePaymentInstrument` | `ProcessPayment`, session management |
|
||||
| `ManagementRole` | `CreatePaymentSession`, `GetPaymentSession` | `ProcessPayment` |
|
||||
| `ProcessPaymentRole` | `ProcessPayment`, `GetPaymentInstrumentBalance` | All setup and session management ops |
|
||||
|
||||
The notebook assumes all three roles via STS at startup. The agent only ever uses
|
||||
`ProcessPaymentRole` credentials — it cannot modify its own session payment limits, create
|
||||
new sessions, or access wallet credentials.
|
||||
| Role | Operations allowed | Denied | Used by |
|
||||
|:-----|:-------------------|:-------|:--------|
|
||||
| `ControlPlaneRole` | `CreatePaymentCredentialProvider`, `CreatePaymentManager`, `CreatePaymentConnector`, `CreatePaymentInstrument` | `ProcessPayment`, session management | Notebook (Step 3) |
|
||||
| `ManagementRole` | `CreatePaymentSession`, `GetPaymentSession`, `InvokeAgentRuntime` | `ProcessPayment` | Notebook (Step 4, Step 6) |
|
||||
| `ProcessPaymentRole` | `ProcessPayment`, `GetPaymentInstrument`, `GetPaymentInstrumentBalance`, browser tool, ECR pull, CloudWatch logs/metrics, X-Ray, Bedrock model invocation | All setup and session management ops (`CreatePaymentSession`, `CreatePaymentInstrument`, etc.) | **AgentCore Runtime** as execution role |
|
||||
| `ResourceRetrievalRole` | Service-side payment-token retrieval | n/a (assumed by AWS service) | AgentCore service |
|
||||
|
||||
---
|
||||
|
||||
## Cleanup
|
||||
|
||||
The payment session created in Step 4 expires automatically after `SESSION_EXPIRY_MINUTES`
|
||||
(60 minutes by default) and stops accepting payments — no API call required.
|
||||
Tear down in this order when you're done:
|
||||
|
||||
To tear down the IAM roles created by `setup_roles.sh`, delete the four
|
||||
`AgentCorePayments*` roles from the IAM console or via the AWS CLI.
|
||||
1. **Runtime deployment** — `cd PayForContentRuntime && agentcore remove all -y`
|
||||
(removes the AgentRuntime, the ECR repo, the CodeBuild project, and CloudWatch logs).
|
||||
2. **Payment session** — expires automatically after `SESSION_EXPIRY_MINUTES`
|
||||
(60 minutes by default). No API call required to close it.
|
||||
3. **Payment manager / connector / instrument / credential provider** — delete via the
|
||||
AWS CLI or boto3 if you want a fully clean account.
|
||||
4. **Content provider** — `cd content-provider && cdk destroy` (removes the CloudFront
|
||||
distribution and Lambda@Edge function).
|
||||
5. **IAM roles** — delete the four `AgentCorePayments*` roles from the IAM console
|
||||
or via the AWS CLI when no longer needed.
|
||||
|
||||
---
|
||||
|
||||
## Shared responsibility
|
||||
|
||||
| Concern | AWS / AgentCore | You (the customer) |
|
||||
|:------------------------------|:---------------------------------------------------------|:----------------------------------------------------|
|
||||
| Runtime container isolation | microVM per session, automatic teardown | Set `idleTimeout`, `maxLifetime` to your workload |
|
||||
| Payment signing keys | Held in AgentCore identity / Coinbase CDP delegated | Enable Delegated Signing in CDP project |
|
||||
| Spend limits | Service enforces `maxSpendAmount` per session | Set per-session budget appropriate for the task |
|
||||
| IAM role segregation | Runtime assumes the execution role you specified | Author least-privilege role policies (see `setup_roles.sh`) |
|
||||
| Observability ingestion | Traces + metrics emitted automatically | Build alarms on the metrics you care about |
|
||||
| Wallet funding | Embedded wallet provisioned by AgentCore | Fund via faucet (testnet) or onramp (production) |
|
||||
| Browser session security | Containerized Chromium, ephemeral, optional recording | Avoid logging in to production accounts via the agent |
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
FROM public.ecr.aws/docker/library/python:3.13-slim-bookworm
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN useradd -m -u 1000 bedrock_agentcore
|
||||
|
||||
COPY requirements.txt ./
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
COPY --chown=bedrock_agentcore:bedrock_agentcore . .
|
||||
|
||||
# Playwright bundles a Node.js driver binary; ensure every file in the
|
||||
# driver directory is executable. Shell globs don't expand inside RUN
|
||||
# without /bin/bash -c, so we use a python one-liner.
|
||||
RUN python -c "import playwright, pathlib; d = pathlib.Path(playwright.__file__).parent / 'driver'; print('driver:', d); [p.chmod(0o755) for p in d.rglob('*') if p.is_file()]"
|
||||
|
||||
USER bedrock_agentcore
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
# AgentCore Runtime monitors container health at the platform level via the
|
||||
# service contract on :8080; this HEALTHCHECK exists for portability and to
|
||||
# satisfy security scanners. BedrockAgentCoreApp serves /ping by default.
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||
CMD curl -fsS http://localhost:8080/ping || exit 1
|
||||
|
||||
CMD ["opentelemetry-instrument", "python", "-m", "main"]
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
"""
|
||||
Pay for Content (Browser Use) — Strands agent for AgentCore Runtime.
|
||||
|
||||
The agent uses AgentCoreBrowser to navigate a paywalled page, reads the
|
||||
x402 requirement from the DOM, calls process_x402_payment to generate a
|
||||
proof, fills it into the paywall UI, and returns the unlocked content.
|
||||
|
||||
When deployed to AgentCore Runtime, the container runs under
|
||||
ProcessPaymentRole. The agent's PaymentManager uses the container's
|
||||
ambient credentials — there is no sts:AssumeRole inside the agent.
|
||||
|
||||
The app backend (notebook) creates the payment session under
|
||||
ManagementRole and passes all payment context via the invocation payload:
|
||||
|
||||
payment_manager_arn — Payment Manager ARN
|
||||
payment_session_id — fresh session with budget
|
||||
payment_instrument_id — wallet to pay from
|
||||
user_id — payment isolation key
|
||||
paywall_url — page to retrieve
|
||||
|
||||
Browser x402 pattern: the requirement is read from a <script> element in
|
||||
the DOM, not from an HTTP 402 response. The plugin's auto-intercept hook
|
||||
does not fire — process_x402_payment constructs the synthetic 402 shape
|
||||
PaymentManager expects.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from bedrock_agentcore.payments.integrations.strands import (
|
||||
AgentCorePaymentsPlugin,
|
||||
AgentCorePaymentsPluginConfig,
|
||||
)
|
||||
from bedrock_agentcore.payments.manager import PaymentManager
|
||||
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
||||
from strands import Agent, tool
|
||||
from strands_tools.browser import AgentCoreBrowser
|
||||
|
||||
app = BedrockAgentCoreApp()
|
||||
|
||||
REGION = os.environ.get("AWS_REGION", "us-west-2")
|
||||
MODEL_ID = os.environ.get("MODEL_ID", "us.anthropic.claude-sonnet-4-6")
|
||||
# Identifier reported in the AgentCore Payments observability dashboard's
|
||||
# "Agents using Payments" counter and on each payment span's
|
||||
# `payment_agent_name` attribute. Set via the
|
||||
# X-Amzn-Bedrock-AgentCore-Payments-Agent-Name HTTP header on every
|
||||
# data-plane call when PaymentManager is constructed with agent_name=.
|
||||
AGENT_NAME = os.environ.get("AGENT_NAME", "PayForContentBrowserAgent")
|
||||
|
||||
SYSTEM_PROMPT = """\
|
||||
You are a content retrieval agent with access to Amazon Bedrock AgentCore payments.
|
||||
You can autonomously browse paywalled websites and pay for premium content using the
|
||||
x402 micropayment protocol — without any human involvement in the payment step.
|
||||
|
||||
When asked to retrieve content from a URL, follow these steps in order:
|
||||
|
||||
1. Use the browser tool to navigate to the URL.
|
||||
2. Find the <script id="x402-requirement"> element and read its JSON content.
|
||||
3. Call process_x402_payment with the full JSON text of that element.
|
||||
4. Use the browser tool to interact with the paywall UI:
|
||||
- Discover payment form elements dynamically using button text, input types,
|
||||
and aria-labels — do not rely on hardcoded IDs from any particular site.
|
||||
- On the reference sample content provider the IDs are: pay-btn, proof-input,
|
||||
verify-btn, content — but real x402 sites will differ.
|
||||
5. Wait for the content to become visible, then extract and return it.
|
||||
6. Report the content retrieved and the amount paid in USDC.
|
||||
|
||||
Always be transparent about what you paid and what content you retrieved.
|
||||
"""
|
||||
|
||||
|
||||
@app.entrypoint
|
||||
def handle_request(payload, context=None):
|
||||
"""Handle a paywall retrieval request from the app backend.
|
||||
|
||||
Args:
|
||||
payload: dict with:
|
||||
prompt — natural-language task (may include the URL)
|
||||
paywall_url — target paywalled page
|
||||
payment_manager_arn — Payment Manager ARN
|
||||
user_id — payment isolation key
|
||||
payment_session_id — fresh session with budget
|
||||
payment_instrument_id — wallet to pay from
|
||||
context: AgentCore Runtime context (provides session_id, etc.)
|
||||
"""
|
||||
# `agentcore invoke` wraps a JSON arg as {"prompt": "<json-string>"}; unwrap it.
|
||||
raw_prompt = payload.get("prompt", "")
|
||||
if isinstance(raw_prompt, str) and raw_prompt.strip().startswith("{"):
|
||||
try:
|
||||
inner = json.loads(raw_prompt)
|
||||
if "payment_manager_arn" in inner:
|
||||
payload = inner
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
payment_manager_arn = payload.get("payment_manager_arn")
|
||||
user_id = payload.get("user_id")
|
||||
session_id = payload.get("payment_session_id")
|
||||
instrument_id = payload.get("payment_instrument_id")
|
||||
paywall_url = payload.get("paywall_url")
|
||||
prompt = payload.get("prompt") or (
|
||||
f"Please retrieve the premium article from {paywall_url}. "
|
||||
f"Pay for it using x402 and give me a summary of what it contains."
|
||||
)
|
||||
|
||||
missing = [
|
||||
name
|
||||
for name, value in [
|
||||
("payment_manager_arn", payment_manager_arn),
|
||||
("user_id", user_id),
|
||||
("payment_session_id", session_id),
|
||||
("payment_instrument_id", instrument_id),
|
||||
("paywall_url", paywall_url),
|
||||
]
|
||||
if not value
|
||||
]
|
||||
if missing:
|
||||
return {"error": f"Missing required fields in payload: {', '.join(missing)}"}
|
||||
|
||||
# PaymentManager uses the container's ambient credentials (ProcessPaymentRole
|
||||
# when deployed; whatever role is active when running locally for dev).
|
||||
# agent_name populates the X-Amzn-Bedrock-AgentCore-Payments-Agent-Name
|
||||
# header on every data-plane call so AgentCore Payments observability
|
||||
# can attribute spans/metrics back to this agent.
|
||||
payment_manager = PaymentManager(
|
||||
payment_manager_arn=payment_manager_arn,
|
||||
region_name=REGION,
|
||||
agent_name=AGENT_NAME,
|
||||
)
|
||||
|
||||
@tool
|
||||
def process_x402_payment(requirement_json: str) -> dict:
|
||||
"""Process an x402 v2 payment requirement and return a signed proof.
|
||||
|
||||
Args:
|
||||
requirement_json: JSON string of the x402 requirement read from
|
||||
the <script id="x402-requirement"> DOM element.
|
||||
|
||||
Returns:
|
||||
dict with proof_b64, amount, and status.
|
||||
"""
|
||||
requirement = json.loads(requirement_json)
|
||||
|
||||
first_accept = requirement["accepts"][0]
|
||||
amount_units = int(
|
||||
first_accept.get("maxAmountRequired") or first_accept.get("amount", 0)
|
||||
)
|
||||
# Token's smallest unit (e.g. 1_000_000 for USDC's 6 decimals) — the
|
||||
# value is reported back to the caller for display, not used for
|
||||
# routing or settlement.
|
||||
amount = amount_units / 1_000_000
|
||||
|
||||
# generate_payment_header expects an HTTP-402-shaped envelope.
|
||||
# In the browser pattern the requirement comes from a DOM script tag
|
||||
# rather than an HTTP 402 response, so we wrap it to match the SDK's
|
||||
# input contract.
|
||||
payment_required_request = {
|
||||
"statusCode": 402,
|
||||
"headers": {},
|
||||
"body": requirement,
|
||||
}
|
||||
|
||||
header_dict = payment_manager.generate_payment_header(
|
||||
user_id=user_id,
|
||||
payment_instrument_id=instrument_id,
|
||||
payment_session_id=session_id,
|
||||
payment_required_request=payment_required_request,
|
||||
client_token=str(uuid.uuid4()),
|
||||
)
|
||||
proof_b64 = list(header_dict.values())[0]
|
||||
|
||||
return {
|
||||
"proof_b64": proof_b64,
|
||||
"amount": amount,
|
||||
"status": "PROOF_GENERATED",
|
||||
}
|
||||
|
||||
payments_plugin = AgentCorePaymentsPlugin(
|
||||
config=AgentCorePaymentsPluginConfig(
|
||||
payment_manager_arn=payment_manager_arn,
|
||||
user_id=user_id,
|
||||
payment_instrument_id=instrument_id,
|
||||
payment_session_id=session_id,
|
||||
region=REGION,
|
||||
agent_name=AGENT_NAME,
|
||||
)
|
||||
)
|
||||
|
||||
agent_core_browser = AgentCoreBrowser(region=REGION)
|
||||
|
||||
agent = Agent(
|
||||
system_prompt=SYSTEM_PROMPT,
|
||||
tools=[agent_core_browser.browser, process_x402_payment],
|
||||
plugins=[payments_plugin],
|
||||
model=MODEL_ID,
|
||||
)
|
||||
|
||||
result = agent(prompt)
|
||||
text = result.message.get("content", [{}])[0].get("text", str(result))
|
||||
return {"response": text}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
bedrock-agentcore[strands-agents]>=1.9.0
|
||||
boto3>=1.43.6
|
||||
botocore>=1.43.6
|
||||
strands-agents[otel]>=1.0.0
|
||||
strands-agents-tools>=0.5.0
|
||||
aws-opentelemetry-distro
|
||||
python-dotenv>=1.0.0
|
||||
nest_asyncio>=1.5.0
|
||||
playwright>=1.40.0
|
||||
-264
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 439 KiB After Width: | Height: | Size: 537 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 561 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 448 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
+835
-57
File diff suppressed because one or more lines are too long
+5
-3
@@ -1,6 +1,8 @@
|
||||
strands-agents==1.36.0
|
||||
strands-agents-tools==0.5.0
|
||||
boto3==1.43.1
|
||||
botocore==1.43.3
|
||||
boto3>=1.43.6
|
||||
botocore>=1.43.6
|
||||
python-dotenv>=1.0.0
|
||||
bedrock-agentcore==1.4.4
|
||||
bedrock-agentcore>=1.9.0
|
||||
nest_asyncio>=1.5.0
|
||||
playwright>=1.40.0
|
||||
|
||||
+196
-20
@@ -7,10 +7,15 @@
|
||||
# opening the notebook.
|
||||
#
|
||||
# Roles created:
|
||||
# AgentCorePaymentsControlPlaneRole — provisioning (manager, connector, credential provider)
|
||||
# AgentCorePaymentsManagementRole — session lifecycle (create/get/update sessions, instruments)
|
||||
# AgentCorePaymentsProcessPaymentRole — agent runtime (ProcessPayment, GetPaymentInstrument, GetPaymentInstrumentBalance)
|
||||
# AgentCorePaymentsResourceRetrievalRole — service-side token retrieval (assumed by AgentCore service)
|
||||
# AgentCorePaymentsControlPlaneRole — provisioning (manager, connector, credential provider)
|
||||
# AgentCorePaymentsManagementRole — session lifecycle (create/get/update sessions, instruments)
|
||||
# AgentCorePaymentsProcessPaymentRole — agent runtime; doubles as the AgentCore Runtime
|
||||
# execution role (ProcessPayment, browser tool, ECR pull,
|
||||
# CloudWatch logs/metrics, X-Ray, model invocation).
|
||||
# Explicit Deny on session/instrument management so the
|
||||
# role-segregation boundary is enforced even though the
|
||||
# agent runs in a managed container.
|
||||
# AgentCorePaymentsResourceRetrievalRole — service-side token retrieval (assumed by AgentCore service)
|
||||
#
|
||||
# After running, copy the printed ARNs into your .env file.
|
||||
# =============================================================
|
||||
@@ -70,9 +75,11 @@ create_or_update_role() {
|
||||
}
|
||||
|
||||
# ── 1. ControlPlaneRole ───────────────────────────────────────────────────────
|
||||
# Used by notebook Steps 3a–3c: CreatePaymentCredentialProvider,
|
||||
# CreatePaymentManager, CreatePaymentConnector.
|
||||
# Uses bedrock-agentcore:* for breadth; explicitly denies ProcessPayment.
|
||||
# Administrator role per the AgentCore payments IAM doc:
|
||||
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/payments-iam-roles.html
|
||||
# Manages payment managers, connectors, and credential providers — never
|
||||
# executes payments. Each statement is scoped to the specific resource
|
||||
# pattern called out in the doc.
|
||||
|
||||
CONTROL_PLANE_TRUST=$(cat <<EOF
|
||||
{
|
||||
@@ -94,10 +101,46 @@ CONTROL_PLANE_POLICY=$(cat <<EOF
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "ControlPlaneOperations",
|
||||
"Sid": "AllowPaymentManagerOperations",
|
||||
"Effect": "Allow",
|
||||
"Action": "bedrock-agentcore:*",
|
||||
"Resource": "*"
|
||||
"Action": [
|
||||
"bedrock-agentcore:CreatePaymentManager",
|
||||
"bedrock-agentcore:GetPaymentManager",
|
||||
"bedrock-agentcore:ListPaymentManagers",
|
||||
"bedrock-agentcore:DeletePaymentManager",
|
||||
"bedrock-agentcore:UpdatePaymentManager"
|
||||
],
|
||||
"Resource": "arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowPaymentConnectorOperations",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:CreatePaymentConnector",
|
||||
"bedrock-agentcore:GetPaymentConnector",
|
||||
"bedrock-agentcore:ListPaymentConnectors",
|
||||
"bedrock-agentcore:DeletePaymentConnector",
|
||||
"bedrock-agentcore:UpdatePaymentConnector"
|
||||
],
|
||||
"Resource": "arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*/connector/*"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowCredentialProviderOperations",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:CreatePaymentCredentialProvider",
|
||||
"bedrock-agentcore:GetPaymentCredentialProvider",
|
||||
"bedrock-agentcore:ListPaymentCredentialProviders",
|
||||
"bedrock-agentcore:DeletePaymentCredentialProvider",
|
||||
"bedrock-agentcore:UpdatePaymentCredentialProvider"
|
||||
],
|
||||
"Resource": "arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:token-vault/*/paymentcredentialprovider/*"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowVendedLogDelivery",
|
||||
"Effect": "Allow",
|
||||
"Action": "bedrock-agentcore:AllowVendedLogDeliveryForResource",
|
||||
"Resource": "arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*"
|
||||
},
|
||||
{
|
||||
"Sid": "DenyDataPlanePaymentExecution",
|
||||
@@ -116,13 +159,21 @@ CONTROL_PLANE_POLICY=$(cat <<EOF
|
||||
"Resource": "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:bedrock-agentcore-identity*"
|
||||
},
|
||||
{
|
||||
"Sid": "PassRoles",
|
||||
"Sid": "PassResourceRetrievalRole",
|
||||
"Effect": "Allow",
|
||||
"Action": "iam:PassRole",
|
||||
"Resource": [
|
||||
"arn:aws:iam::${ACCOUNT_ID}:role/AgentCorePaymentsResourceRetrievalRole",
|
||||
"arn:aws:iam::${ACCOUNT_ID}:role/AgentCorePaymentsManagementRole"
|
||||
]
|
||||
"Resource": "arn:aws:iam::${ACCOUNT_ID}:role/AgentCorePaymentsResourceRetrievalRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"iam:PassedToService": "bedrock-agentcore.amazonaws.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Sid": "PassManagementRole",
|
||||
"Effect": "Allow",
|
||||
"Action": "iam:PassRole",
|
||||
"Resource": "arn:aws:iam::${ACCOUNT_ID}:role/AgentCorePaymentsManagementRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -167,7 +218,7 @@ MANAGEMENT_POLICY=$(cat <<EOF
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "InstrumentAndSessionManagement",
|
||||
"Sid": "AllowPaymentManagement",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:CreatePaymentInstrument",
|
||||
@@ -176,9 +227,21 @@ MANAGEMENT_POLICY=$(cat <<EOF
|
||||
"bedrock-agentcore:DeletePaymentInstrument",
|
||||
"bedrock-agentcore:CreatePaymentSession",
|
||||
"bedrock-agentcore:GetPaymentSession",
|
||||
"bedrock-agentcore:ListPaymentSessions"
|
||||
"bedrock-agentcore:ListPaymentSessions",
|
||||
"bedrock-agentcore:UpdatePaymentSession",
|
||||
"bedrock-agentcore:DeletePaymentSession"
|
||||
],
|
||||
"Resource": "*"
|
||||
"Resource": [
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*",
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*/instrument/*",
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*/session/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Sid": "InvokeDeployedAgent",
|
||||
"Effect": "Allow",
|
||||
"Action": "bedrock-agentcore:InvokeAgentRuntime",
|
||||
"Resource": "arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:runtime/*"
|
||||
},
|
||||
{
|
||||
"Sid": "DenyProcessPayment",
|
||||
@@ -213,6 +276,20 @@ PROCESS_PAYMENT_TRUST=$(cat <<EOF
|
||||
"Effect": "Allow",
|
||||
"Principal": { "AWS": ${CLIENT_PRINCIPAL} },
|
||||
"Action": "sts:AssumeRole"
|
||||
},
|
||||
{
|
||||
"Sid": "AllowAgentCoreRuntimeAssume",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "bedrock-agentcore.amazonaws.com" },
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"aws:SourceAccount": "${ACCOUNT_ID}"
|
||||
},
|
||||
"ArnLike": {
|
||||
"aws:SourceArn": "arn:aws:bedrock-agentcore:${REGION}:${ACCOUNT_ID}:runtime/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -226,10 +303,109 @@ PROCESS_PAYMENT_POLICY=$(cat <<EOF
|
||||
{
|
||||
"Sid": "AllowProcessPayment",
|
||||
"Effect": "Allow",
|
||||
"Action": "bedrock-agentcore:ProcessPayment",
|
||||
"Resource": [
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*",
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*/session/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Sid": "AllowPaymentReadOperations",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:ProcessPayment",
|
||||
"bedrock-agentcore:GetPaymentInstrument",
|
||||
"bedrock-agentcore:GetPaymentInstrumentBalance"
|
||||
"bedrock-agentcore:GetPaymentInstrumentBalance",
|
||||
"bedrock-agentcore:GetPaymentSession"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*",
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*/instrument/*",
|
||||
"arn:aws:bedrock-agentcore:*:${ACCOUNT_ID}:payment-manager/*/session/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Sid": "DenySessionManagement",
|
||||
"Effect": "Deny",
|
||||
"Action": [
|
||||
"bedrock-agentcore:CreatePaymentSession",
|
||||
"bedrock-agentcore:CreatePaymentInstrument",
|
||||
"bedrock-agentcore:CreatePaymentManager",
|
||||
"bedrock-agentcore:CreatePaymentConnector",
|
||||
"bedrock-agentcore:UpdatePaymentSession",
|
||||
"bedrock-agentcore:DeletePaymentInstrument",
|
||||
"bedrock-agentcore:DeletePaymentSession"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "RuntimeECRAccess",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:GetAuthorizationToken"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "RuntimeCloudWatchLogs",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:DescribeLogGroups",
|
||||
"logs:DescribeLogStreams",
|
||||
"logs:PutLogEvents"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:logs:${REGION}:${ACCOUNT_ID}:log-group:/aws/bedrock-agentcore/runtimes/*",
|
||||
"arn:aws:logs:${REGION}:${ACCOUNT_ID}:log-group:*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Sid": "RuntimeXRay",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"xray:PutTraceSegments",
|
||||
"xray:PutTelemetryRecords",
|
||||
"xray:GetSamplingRules",
|
||||
"xray:GetSamplingTargets"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "RuntimeCloudWatchMetrics",
|
||||
"Effect": "Allow",
|
||||
"Action": "cloudwatch:PutMetricData",
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"cloudwatch:namespace": "bedrock-agentcore"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Sid": "BedrockModelInvocation",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock:InvokeModel",
|
||||
"bedrock:InvokeModelWithResponseStream"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:bedrock:*::foundation-model/*",
|
||||
"arn:aws:bedrock:${REGION}:${ACCOUNT_ID}:*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Sid": "BrowserToolAccess",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:StartBrowserSession",
|
||||
"bedrock-agentcore:StopBrowserSession",
|
||||
"bedrock-agentcore:GetBrowserSession",
|
||||
"bedrock-agentcore:ListBrowserSessions",
|
||||
"bedrock-agentcore:UpdateBrowserStream",
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user