-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(payments): add Pay for Data (Heurist) use case #1465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
joshuamarksmith
wants to merge
13
commits into
awslabs:main
Choose a base branch
from
joshuamarksmith:feat/pay-for-data-heurist
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
b534cb2
feat(payments): add Pay for Data (Heurist) use case
1cb1967
Address PR review feedback
5943172
Fix ASCII architecture diagram alignment in notebook
d047f67
Apply ruff format to pass Python lint CI check
70378ae
Remove unused shutil import in notebook cleanup cell (ruff F401)
2391da9
Address leewc review comments
d6859cf
feat(pay-for-data): add AgentCore Runtime + Observability deployment
2f5cda5
fix(pay-for-data): add aws-opentelemetry-distro for full trace stitching
8811d77
fix: add noqa E402 for post-sys.path imports in runtime_agent.py
ccf7ed2
fix: ruff format + noqa E402 on from-line for multi-line import
1c9a135
fix: remove run.py (local-mode only); decouple prerequisites from tut…
01355a6
rename agent.py to local_agent.py for clarity
992d660
fix: pass agent_name to AgentCorePaymentsPluginConfig for observability
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
01-tutorials/13-AgentCore-payments/02-use-cases/pay-for-data/.env.example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # AgentCore payments credentials for the Heurist finance agent. | ||
| # See ../../01-tutorials/ for setup instructions. | ||
|
|
||
| AWS_REGION=us-west-2 | ||
| AWS_PROFILE=payments-admin | ||
| BEDROCK_PROFILE=payments-admin | ||
|
|
||
| # Payment manager ARN (created during setup) | ||
| PAYMENT_MANAGER_ARN=arn:aws:bedrock-agentcore:us-west-2:123456789012:payment-manager/your-manager-id | ||
|
|
||
| # Payment session and payment instrument (created per-user) | ||
| PAYMENT_SESSION_ID=payment-session-REPLACE_ME | ||
| PAYMENT_INSTRUMENT_ID=payment-instrument-REPLACE_ME | ||
|
|
||
| # User identifier for payment tracking | ||
| USER_ID=demo-user | ||
|
|
||
| # Bedrock model for the agent | ||
| BEDROCK_MODEL_ID=us.anthropic.claude-sonnet-4-20250514-v1:0 | ||
|
|
||
| # Heurist catalog configuration | ||
| HEURIST_CATALOG_URL=https://mesh.heurist.xyz/x402/agents?details=true | ||
| HEURIST_AGENT_IDS=ExaSearchDigestAgent,YahooFinanceAgent,FredMacroAgent,SecEdgarAgent | ||
|
|
||
| # Code Interpreter session name | ||
| CODE_INTERPRETER_SESSION_NAME=heurist-finance | ||
|
|
||
| # Agent limits | ||
| AGENT_TIMEOUT_SECONDS=300 | ||
| AGENT_MAX_TOKENS=64000 |
12 changes: 12 additions & 0 deletions
12
01-tutorials/13-AgentCore-payments/02-use-cases/pay-for-data/.gitignore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| .venv/ | ||
| dist/ | ||
| *.egg-info/ | ||
| __pycache__/ | ||
| *.py[cod] | ||
| .pytest_cache/ | ||
| .ruff_cache/ | ||
| .env | ||
| .ipynb_checkpoints/ | ||
| heurist_finance_agent/artifacts/* | ||
| !heurist_finance_agent/artifacts/.gitkeep | ||
| heurist_finance_agent/catalog_live_cache.json |
197 changes: 197 additions & 0 deletions
197
01-tutorials/13-AgentCore-payments/02-use-cases/pay-for-data/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| # Pay for Data — Heurist Finance Agent | ||
|
|
||
| ## Overview | ||
|
|
||
| A finance research agent that pays for real-time market data using **Amazon Bedrock AgentCore payments**. The agent calls paid [Heurist](https://heurist.xyz) endpoints for live prices, SEC filings, and macro indicators, analyzes the data with AgentCore Code Interpreter, and returns charts and reports as S3 presigned URLs — all without any manual payment code in the tools. | ||
|
|
||
| The agent is deployed to **AgentCore Runtime**: a managed container endpoint with HTTPS invocation, SigV4 auth, and automatic observability via CloudWatch. | ||
|
|
||
| Heurist endpoints use the [x402 protocol](https://x402.org) — they return HTTP 402 until a valid payment proof is attached. The `AgentCorePaymentsPlugin` handles payment end-to-end: it intercepts 402 responses, generates a USDC proof via the AgentCore payment manager, attaches it, and retries. Your tool code stays a plain `http_request` call. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ``` | ||
| App Backend (ManagementRole) AgentCore Runtime | ||
| | +------------------------------+ | ||
| | create_session(budget=$X) | runtime_agent.py | | ||
| | | BedrockAgentCoreApp | | ||
| |-- invoke(manager_arn, session_id, --> | + AgentCorePaymentsPlugin | | ||
| | instrument_id, prompt) | | | ||
| | | http_request -> 402 | | ||
| |<-- {response, artifacts: [{url}]} --- | -> ProcessPayment -> retry | | ||
| | | -> Code Interpreter | | ||
| | get_session(check spend) | -> export to S3 | | ||
| +------------------------------+ | ||
| | | ||
| v | ||
| CloudWatch GenAI Observability | ||
| (automatic via OpenTelemetry) | ||
| ``` | ||
|
|
||
| ## How It Works | ||
|
|
||
| `AgentCorePaymentsPlugin` handles the entire x402 payment lifecycle: | ||
|
|
||
| ```python | ||
| from bedrock_agentcore.payments.integrations.strands import ( | ||
| AgentCorePaymentsPlugin, | ||
| AgentCorePaymentsPluginConfig, | ||
| ) | ||
|
|
||
| payment_plugin = AgentCorePaymentsPlugin( | ||
| config=AgentCorePaymentsPluginConfig( | ||
| payment_manager_arn=PAYMENT_MANAGER_ARN, | ||
| user_id=USER_ID, | ||
| payment_instrument_id=PAYMENT_INSTRUMENT_ID, | ||
| payment_session_id=PAYMENT_SESSION_ID, | ||
| region="us-west-2", | ||
| ) | ||
| ) | ||
|
|
||
| agent = Agent( | ||
| model=BedrockModel(model_id=MODEL_ID), | ||
| tools=[http_request, code_interpreter, export_artifact_to_s3, ...], | ||
| plugins=[payment_plugin], | ||
| ) | ||
|
Comment on lines
+31
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to provide the code sample in readme? Can we add flow in How it work section? |
||
| ``` | ||
|
|
||
| See [`runtime_agent.py`](heurist_finance_agent/runtime_agent.py) for the full implementation. | ||
|
|
||
| ## Sample Details | ||
|
|
||
| | | | | ||
| |---|---| | ||
| | AgentCore components | AgentCore payments, AgentCore Code Interpreter, AgentCore Runtime | | ||
| | Agent framework | [Strands Agents](https://strandsagents.com/) | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Strands is Agent SDK. Its not framework. |
||
| | Model | Claude Sonnet 4 on Amazon Bedrock (configurable) | | ||
| | Payment protocol | [x402](https://x402.org) | | ||
| | Payment network | Base (USDC) | | ||
|
|
||
| ## Data Sources | ||
|
|
||
| Fetched at runtime from the [Heurist mesh registry](https://mesh.heurist.xyz/x402/agents?details=true). By default the sample loads tools from four agents: | ||
|
|
||
| | Agent | Representative tools | Typical price | | ||
| |-------|----------------------|---------------| | ||
| | `YahooFinanceAgent` | `price_history`, `quote_snapshot`, `futures_snapshot` | $0.002 | | ||
| | `FredMacroAgent` | `macro_series_snapshot`, `macro_regime_context` | $0.003 | | ||
| | `SecEdgarAgent` | `filing_timeline`, `filing_diff`, `xbrl_fact_trends` | $0.002 | | ||
| | `ExaSearchDigestAgent` | `exa_web_search`, `exa_scrape_url` | $0.005 | | ||
|
|
||
| Override with the `HEURIST_AGENT_IDS` environment variable. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - An **AgentCore payment manager** created in your AWS account | ||
| - A **payment instrument** created and funded (embedded crypto wallet, USDC on Base mainnet) | ||
| - Python 3.11+ | ||
| - AWS credentials with Bedrock and AgentCore access in `us-west-2` | ||
| - Node.js 20+ (for the `@aws/agentcore` CLI) | ||
| - Docker (running, for `agentcore deploy` container build) | ||
| - [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) installed globally | ||
|
|
||
| ## Layout | ||
|
|
||
| ``` | ||
| pay-for-data/ | ||
| ├── README.md | ||
| ├── requirements.txt | ||
| ├── .env.example | ||
| ├── pay-for-data.ipynb # notebook: deploy and invoke via AgentCore Runtime | ||
| └── heurist_finance_agent/ | ||
| ├── runtime_agent.py # AgentCore Runtime entry point (BedrockAgentCoreApp) | ||
| ├── catalog.py # fetches Heurist registry, formats for system prompt | ||
| ├── catalog_live_cache.json # synced catalog (bundled in Runtime image) | ||
| ├── config.py # loads .env | ||
| └── scripts/ | ||
| └── sync_registry.py # CLI: refreshes cached Heurist catalog``` | ||
|
|
||
| ## Quick Start | ||
|
|
||
| Open [`pay-for-data.ipynb`](pay-for-data.ipynb) and run the cells in order: | ||
|
|
||
| | Step | What happens | | ||
| |------|-------------| | ||
| | 1 | Configure credentials and confirm AWS identity | | ||
| | 2 | Sync the Heurist tool catalog (bundled in the container image) | | ||
| | 3 | Create the S3 artifacts bucket | | ||
| | 4 | Install the AgentCore CLI, scaffold and deploy | | ||
| | 5 | Add IAM permissions to the execution role | | ||
| | 6 | Invoke the deployed agent and inspect results | | ||
| | 7 | View observability traces in CloudWatch | | ||
| | 8 | Cleanup | | ||
|
|
||
| ## Payment Flow | ||
|
|
||
| When the agent calls a paid Heurist endpoint: | ||
|
|
||
| 1. `http_request` sends a POST to the endpoint URL. | ||
| 2. Heurist returns HTTP 402 with x402 payment terms (network, asset, amount, recipient). | ||
| 3. `AgentCorePaymentsPlugin` intercepts the response. | ||
| 4. The plugin asks the AgentCore payment manager to generate a payment proof. | ||
| 5. The payment manager uses the payment instrument to sign a USDC transfer and returns a proof. | ||
| 6. The plugin attaches the proof as `X-PAYMENT` and retries — Heurist validates and returns the data. | ||
|
|
||
| The plugin retries up to 3 times per tool call. Payment limits are enforced at the session scope — the agent cannot exceed `maxSpendAmount`. | ||
|
|
||
| ## How the Runtime Agent Works | ||
|
|
||
| `runtime_agent.py` implements the AgentCore Runtime service contract with full feature parity: | ||
|
|
||
| **Stateless, payload-driven** | ||
| All payment config (manager ARN, session ID, instrument ID) comes from the invocation payload. The container holds no credentials. The app backend (ManagementRole) creates payment sessions with spending limits before each invocation. The Runtime execution role (ProcessPaymentRole) can only spend within those limits. | ||
|
|
||
| **AgentCore Code Interpreter** | ||
| Code Interpreter is a remote AWS API — it works identically from a Runtime container as from any other environment. The agent uses it for pandas/matplotlib analysis and chart generation. | ||
|
|
||
| **S3 artifact storage** | ||
| Artifacts produced by Code Interpreter are uploaded to S3 and returned as presigned download URLs. The response shape is: | ||
|
|
||
| ```json | ||
| { | ||
| "response": "<markdown research summary>", | ||
| "artifacts": [ | ||
| {"name": "chart.png", "url": "https://...", "expires_in": 3600} | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| If `CI_ARTIFACTS_BUCKET` is not configured, the agent degrades gracefully: charts become markdown tables, text returns inline. | ||
|
|
||
| **Observability** | ||
| The `agentcore deploy` CLI configures the container to run under `opentelemetry-instrument`. Combined with `aws-opentelemetry-distro` (included in `pyproject.toml`), this provides: | ||
| - Strands agent spans (LLM calls, tool calls, agent turns) → CloudWatch GenAI Observability | ||
| - Code Interpreter calls stitched as child spans via W3C `traceparent` botocore instrumentation | ||
| - Payment calls (`ProcessPayment`, `GetPaymentInstrument`) as boto3 child spans | ||
|
|
||
| No instrumentation code required in `runtime_agent.py`. | ||
|
|
||
| **Execution role permissions** (attached by the notebook, Step 5): | ||
|
|
||
| | Permission set | Actions | Resource scope | | ||
| |---|---|---| | ||
| | Payment data-plane | `ProcessPayment`, `GetPaymentInstrument`, `GetPaymentSession` | `payment-manager/*` | | ||
| | Code Interpreter | `StartCodeInterpreterSession`, `InvokeCodeInterpreter`, `StopCodeInterpreterSession` | `code-interpreter/*` | | ||
| | S3 artifacts | `PutObject`, `GetObject` | `<bucket>/heurist-finance-artifacts/*` | | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| See [`.env.example`](.env.example). Required: | ||
|
|
||
| | Variable | Description | | ||
| |----------|-------------| | ||
| | `PAYMENT_MANAGER_ARN` | ARN of the AgentCore payment manager | | ||
| | `PAYMENT_SESSION_ID` | ID of an active payment session | | ||
| | `PAYMENT_INSTRUMENT_ID` | ID of a funded payment instrument (embedded crypto wallet) | | ||
| | `USER_ID` | User identifier for payment tracking | | ||
| | `BEDROCK_MODEL_ID` | Bedrock model (default: Claude Sonnet 4) | | ||
| | `HEURIST_AGENT_IDS` | Comma-separated Heurist agents to load | | ||
|
|
||
| These values are passed in the invocation payload at runtime. The `.env` bundled in the container image contains only non-sensitive service config: `CI_ARTIFACTS_BUCKET`, `AWS_REGION`, `BEDROCK_MODEL_ID`. | ||
|
|
||
| ## Notes | ||
|
|
||
| - Payment sessions expire. Create a fresh session before each invocation in automated workflows. | ||
| - Each paid call settles USDC on Base. Ensure your payment instrument is funded. | ||
| - Sync the catalog cache before building the container image (`sync_registry.py`). The cache is bundled in the image — the container does not call the Heurist registry at startup. | ||
| - Presigned artifact URLs expire after `CI_ARTIFACTS_TTL` seconds (default: 1 hour). Download or forward the URL to the end user promptly. | ||
1 change: 1 addition & 0 deletions
1
...torials/13-AgentCore-payments/02-use-cases/pay-for-data/heurist_finance_agent/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Heurist x402 finance agent package.""" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the tutorail dependency