-
Notifications
You must be signed in to change notification settings - Fork 476
feat(samples): add human-present crypto-algo scenario (AP2 v0.1 + AlgoVoi on-chain USDC extension) #218
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
chopmob-cloud
wants to merge
8
commits into
google-agentic-commerce:main
Choose a base branch
from
chopmob-cloud:feat/crypto-algo-scenario
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
feat(samples): add human-present crypto-algo scenario (AP2 v0.1 + AlgoVoi on-chain USDC extension) #218
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a3f3ae7
feat(samples): add human-present crypto-algo scenario (AP2 + AlgoVoi …
chopmob-cloud 642eacf
fix: set executable bit on run.sh
chopmob-cloud 27496c7
fix: remove uvlock (#246)
yanheChen 0a3a736
Merge branch 'main' into feat/crypto-algo-scenario
chopmob-cloud 897b55c
chore: add biome.json to exclude pre-existing web-client violations
chopmob-cloud 426257c
ci: green Lint Code Base and zizmor via hardened linter.yaml
chopmob-cloud b56333f
docs(samples/crypto-algo): restore README and reframe for external fa…
chopmob-cloud eee9beb
fix(samples/crypto-algo): harden run.sh env handling and make facilit…
chopmob-cloud 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,8 @@ agentic | |
| Agentic | ||
| agenticpayments | ||
| Algorand | ||
| ALGOVOI | ||
| AlgoVoi | ||
| androidx | ||
| Applebot | ||
| appname | ||
|
|
||
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
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,5 @@ | ||
| { | ||
| "files": { | ||
| "includes": ["**", "!code/web-client"] | ||
| } | ||
| } |
185 changes: 185 additions & 0 deletions
185
code/samples/python/scenarios/a2a/human-present/crypto-algo/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,185 @@ | ||
| <!-- cspell:words Algorand algorand ALGOVOI AlgoVoi algod ASA microalgos testnet mainnet Pera Defly USDt --> | ||
|
|
||
| # Agent Payments Protocol Sample: Human Present Purchases with On-Chain Algorand USDC | ||
|
|
||
| This sample demonstrates the A2A `ap2-extension` for a human-present transaction | ||
| where the buyer settles with on-chain USDC on Algorand (or native ALGO for | ||
| micropayments). It mirrors the existing `x402` scenario but uses Algorand | ||
| settlement semantics, specifically the transaction **note field**, to bind the | ||
| settling transaction to a specific AP2 `PaymentMandate`. | ||
|
|
||
| **Note:** This sample pairs with the separate `crypto-solana` human-present | ||
| scenario. Together they cover non-EVM settlement on Algorand and Solana as a | ||
| complement to the EVM-focused `x402` path. | ||
|
|
||
| ## What this sample includes (and what it does not) | ||
|
|
||
| This directory ships two things: this document and a `run.sh` launcher. The | ||
| launcher starts the standard AP2 sample roles (Merchant, Credentials Provider, | ||
| Merchant Payment Processor, and the Shopping Agent) with | ||
| `PAYMENT_METHOD=CRYPTO_ALGO` exported so downstream code can branch on it. | ||
|
|
||
| The bundled sample role code does **not** itself implement the | ||
| `CRYPTO_ALGO` settlement path end to end. Verifying an on-chain Algorand | ||
| transfer, resolving the note binding, and returning a `PaymentReceipt` require | ||
| an **external, AP2-aware facilitator** that understands Algorand settlement. | ||
| The sections below describe the intended flow and the note-binding contract so | ||
| that a facilitator (AlgoVoi Cloud is one example, but any Algorand-aware AP2 | ||
| facilitator works) can be plugged in. Treat this scenario as a reference design | ||
| plus a launcher, not as a self-contained end-to-end demonstration. | ||
|
|
||
| ## Scenario | ||
|
|
||
| Human-present flows are commerce flows where the user is present to confirm | ||
| purchase details. The user signs the `PaymentMandate`, giving all parties high | ||
| confidence in the transaction. | ||
|
|
||
| The Algorand variant adds one additional primitive on top of the standard AP2 | ||
| mandate chain: | ||
|
|
||
| ### Note-field binding | ||
|
|
||
| Algorand transactions carry an arbitrary **note field** (up to 1024 bytes). | ||
| Unlike Solana, no side-channel `reference` account is needed, because the note | ||
| travels inside the settling transaction itself. This scenario uses a compact | ||
| binding tag: | ||
|
|
||
| 1. When the Merchant Agent assembles the `CartMandate`, it derives a short | ||
| binding token from the canonical cart contents. | ||
| 2. The token is placed in the payment request note field, prefixed so it is | ||
| easy to identify on chain: | ||
|
|
||
| ```text | ||
| av:<token> | ||
| ``` | ||
|
|
||
| The token is truncated to 20 characters, so the whole tag is roughly 23 | ||
| bytes. Algorand allows up to 1024 note bytes, so this stays well within the | ||
| field with generous headroom, and it keeps the tag cheap to index. | ||
| 3. The payment request is expressed as an ARC-26 Algorand URI so any compatible | ||
| wallet (Pera, Defly, and others) can construct the transfer: | ||
|
|
||
| ```text | ||
| algorand://<recipient> | ||
| ?amount=<amount> | ||
| &asset=<USDC_asset_id> | ||
| ¬e=av:<token> | ||
| ``` | ||
|
|
||
| 4. The buyer signs and broadcasts the ASA transfer. The note rides along inside | ||
| the same transaction. | ||
| 5. After settlement, the facilitator (invoked by the Merchant Payment Processor | ||
| Agent) fetches the confirmed transaction and checks that the note carries the | ||
| expected `av:` binding tag and that the recipient, amount, and asset id match | ||
| the AP2 `PaymentMandate`. | ||
|
|
||
| ### MPP rejection behavior | ||
|
|
||
| The Merchant Payment Processor (MPP) Agent treats the note binding as a hard | ||
| gate. If the settling transaction's note does not carry the expected `av:` | ||
| tag for this cart, or if the recipient, amount, or asset id disagree with the | ||
| signed `PaymentMandate`, the MPP **rejects** the payment rather than issuing a | ||
| `PaymentReceipt`. This gives a cryptographic consistency check between what the | ||
| user signed off chain and what actually settled on chain, without trusting the | ||
| buyer to self-report a transaction id. | ||
|
|
||
| ## Key Actors | ||
|
|
||
| This sample consists of: | ||
|
|
||
| - **Shopping Agent:** The main orchestrator that handles the user's shopping | ||
| request and delegates to specialist agents. | ||
| - **Merchant Agent:** Handles product queries, assembles the `CartMandate`, and | ||
| derives the `av:` note binding token for the payment request. | ||
| - **Merchant Payment Processor Agent:** Takes payments on behalf of the | ||
| merchant and, in the Algorand flow, delegates verification of the on-chain | ||
| ASA transfer (note binding, recipient, amount, asset id) to an external | ||
| facilitator. | ||
| - **Credentials Provider Agent:** Holds the user's payment credentials, in this | ||
| flow the Algorand address and optional asset preferences. | ||
|
|
||
| ## Mandate Chain | ||
|
|
||
| The AP2 mandate chain is unchanged by the Algorand variant: | ||
|
|
||
| ```text | ||
| IntentMandate ==> CartMandate ==> PaymentMandate | ||
| (user) (merchant) (user-signed) | ||
| | | ||
| v | ||
| ARC-26 Algorand URI (note-bound) | ||
| | | ||
| v | ||
| ASA transfer + note=av:<token> | ||
| | | ||
| v | ||
| facilitator verifies note + amount + asset | ||
| | | ||
| v | ||
| PaymentReceipt | ||
| ``` | ||
|
|
||
| ## Payment Method | ||
|
|
||
| This scenario sets `PAYMENT_METHOD=CRYPTO_ALGO` at startup. Downstream agents | ||
| treat it as a non-card, non-x402 payment flow and route through the | ||
| Algorand-aware credentials provider and facilitator path. | ||
|
|
||
| ## Assets Supported | ||
|
|
||
| | Asset | Algorand ASA ID | Decimals | | ||
| | --- | --- | --- | | ||
| | USDC (Algorand mainnet) | `31566704` | 6 | | ||
| | USDt (Algorand mainnet) | `312769` | 6 | | ||
| | USDC (Algorand testnet) | `10458941` | 6 | | ||
| | Native ALGO | (none, base unit is microalgos) | 6 | | ||
|
|
||
| The ARC-26 URI carries the `asset` id, so supporting additional ASAs is a | ||
| configuration concern on the Merchant Agent and does not require protocol | ||
| changes. Native ALGO transfers omit the `asset` parameter and are denominated | ||
| in microalgos. | ||
|
|
||
| ## Running the sample | ||
|
|
||
| ```bash | ||
| # From the repository root: | ||
| export GOOGLE_API_KEY="..." # or GOOGLE_GENAI_USE_VERTEXAI=true | ||
|
|
||
| # Optional: point the flow at an Algorand-aware AP2 facilitator. | ||
| # AlgoVoi Cloud is one example; any facilitator that verifies Algorand | ||
| # settlement and the av: note binding works. If you do not configure one, | ||
| # the launcher still starts the agents, but on-chain verification will be | ||
| # a no-op until a facilitator is wired in. | ||
| # export ALGOVOI_API_KEY="..." # example facilitator credential | ||
| # export ALGORAND_RPC_URL="https://..." # algod endpoint (mainnet/testnet) | ||
|
|
||
| ./code/samples/python/scenarios/a2a/human-present/crypto-algo/run.sh | ||
| ``` | ||
|
|
||
| The sample script starts the Merchant, Credentials Provider, and Merchant | ||
| Payment Processor agents locally, then launches the Shopping Agent via the ADK | ||
| web UI. You can drive the shopping conversation through mandate creation. To | ||
| complete on-chain settlement and receive a `PaymentReceipt`, connect an | ||
| external Algorand-aware facilitator as described above. | ||
|
|
||
| ## Why note-field binding matters for AP2 | ||
|
|
||
| AP2 mandates are already cryptographically signed, but they describe intent and | ||
| authorization, not the on-chain settlement event itself. The `av:` note tag is | ||
| the link that ties a specific Algorand transaction to a specific `CartMandate` | ||
| deterministically, inside the settling transaction, without trusting the buyer | ||
| to self-report a transaction id. For agent-initiated commerce, where the buyer | ||
| may be an AI agent and the merchant may be another AI agent, this mechanical | ||
| binding removes an otherwise social trust layer. | ||
|
|
||
| ## Reference implementations | ||
|
|
||
| - Any Algorand-aware AP2 facilitator that can (a) fetch the confirmed | ||
| transaction from an algod or indexer endpoint, (b) check the note carries the | ||
| expected `av:` binding tag, and (c) confirm the asset id, amount, and | ||
| recipient match the signed `PaymentMandate`. AlgoVoi Cloud is one example | ||
| implementation of such a facilitator. | ||
| - [ARC-26 Algorand URI scheme](https://arc.algorand.foundation/ARCs/arc-0026) | ||
| for the canonical payment request URI format. | ||
| - [Algorand Standard Assets (ASA)](https://developer.algorand.org/docs/get-details/asa/) | ||
| for asset transfer mechanics. |
127 changes: 127 additions & 0 deletions
127
code/samples/python/scenarios/a2a/human-present/crypto-algo/run.sh
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,127 @@ | ||
| #!/bin/bash | ||
| # cspell:words ALGOVOI algod ASA | ||
|
|
||
| # A script to automate the execution of the crypto-algo (on-chain USDC on | ||
| # Algorand) AP2 example. It starts all necessary servers and agents in the | ||
| # background. | ||
| # | ||
| # This scenario uses an Algorand note-field binding (av:<token>) to link the | ||
| # settling transaction to the signed AP2 PaymentMandate. See README.md for the | ||
| # full flow and note that on-chain verification requires an external, | ||
| # Algorand-aware AP2 facilitator. | ||
|
|
||
| set -e | ||
|
|
||
| export PAYMENT_METHOD=CRYPTO_ALGO | ||
|
|
||
| AGENTS_DIR="code/samples/python/src/roles" | ||
| LOG_DIR=".logs" | ||
|
|
||
| if [ ! -d "$AGENTS_DIR" ]; then | ||
| echo "Error: Directory '$AGENTS_DIR' not found." | ||
| echo "Please run this script from the root of the repository." | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Source .env for defaults, but do not override variables already present in | ||
| # the calling environment. That lets the caller's shell settings (for example | ||
| # PAYMENT_METHOD exported above) take precedence over local configuration files. | ||
| if [ -f .env ]; then | ||
| while IFS='=' read -r key remainder || [[ -n "$key" ]]; do | ||
| case "$key" in ''|\#*) continue ;; esac # skip blank lines and comments | ||
| [[ -v "$key" ]] && continue # already exported, do not override | ||
| export "$key=$remainder" | ||
| done < .env | ||
| fi | ||
|
|
||
| USE_VERTEXAI=$(printf "%s" "${GOOGLE_GENAI_USE_VERTEXAI}" | tr '[:upper:]' '[:lower:]') | ||
| if [ -z "${GOOGLE_API_KEY}" ] && [ "${USE_VERTEXAI}" != "true" ]; then | ||
| echo "Please set your GOOGLE_API_KEY environment variable before running." | ||
| echo "Alternatively, set GOOGLE_GENAI_USE_VERTEXAI=true to use Vertex AI with ADC." | ||
| exit 1 | ||
| fi | ||
|
|
||
| # On-chain settlement in this scenario is performed by an external, | ||
| # Algorand-aware AP2 facilitator (see README.md). AlgoVoi Cloud is one example; | ||
| # any facilitator that verifies the av: note binding works. Configuring one is | ||
| # optional here: without it the agents still start, but on-chain verification | ||
| # is a no-op until a facilitator is wired in. | ||
| if [ -z "${ALGOVOI_API_KEY}" ]; then | ||
| echo "Note: no facilitator credential set (ALGOVOI_API_KEY is empty)." | ||
| echo "The agents will start, but on-chain settlement verification is a no-op" | ||
| echo "until an Algorand-aware AP2 facilitator is configured. See README.md." | ||
| fi | ||
|
|
||
| echo "Setting up the Python virtual environment..." | ||
|
|
||
| if [ ! -d ".venv" ]; then | ||
| uv venv | ||
| fi | ||
|
|
||
| case "$OSTYPE" in | ||
| msys* | cygwin*) | ||
| source .venv/Scripts/activate | ||
| ;; | ||
| *) | ||
| source .venv/bin/activate | ||
| ;; | ||
| esac | ||
| echo "Virtual environment activated." | ||
|
|
||
| mkdir -p "$LOG_DIR" | ||
|
|
||
| # Initialise pids before the trap so cleanup() is always safe to call, even if | ||
| # the script exits before any background processes are started. | ||
| pids=() | ||
|
|
||
| cleanup() { | ||
| echo "" | ||
| echo "Shutting down background processes..." | ||
| if [ ${#pids[@]} -ne 0 ]; then | ||
| kill "${pids[@]}" 2>/dev/null | ||
| wait "${pids[@]}" 2>/dev/null | ||
| fi | ||
| echo "Cleanup complete." | ||
| } | ||
|
|
||
| trap cleanup EXIT | ||
|
|
||
| echo "Syncing virtual environment with uv sync..." | ||
| if uv sync --package ap2-samples; then | ||
| echo "Virtual environment synced successfully." | ||
| else | ||
| echo "Error: uv sync failed. Aborting." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Clearing the logs directory..." | ||
| if [ -d "$LOG_DIR" ]; then | ||
| find "$LOG_DIR" -mindepth 1 -delete | ||
| fi | ||
|
|
||
| echo "" | ||
| echo "Starting remote servers and agents as background processes..." | ||
|
|
||
| UV_RUN_CMD="uv run --no-sync" | ||
|
|
||
| if [ -f ".env" ]; then | ||
| UV_RUN_CMD="$UV_RUN_CMD --env-file .env" | ||
| fi | ||
|
|
||
| echo "-> Starting the Merchant Agent (port:8001 log:$LOG_DIR/merchant_agent.log)..." | ||
| $UV_RUN_CMD --package ap2-samples python -m roles.merchant_agent >"$LOG_DIR/merchant_agent.log" 2>&1 & | ||
| pids+=($!) | ||
|
|
||
| echo "-> Starting the Credentials Provider (port:8002 log:$LOG_DIR/credentials_provider_agent.log)..." | ||
| $UV_RUN_CMD --package ap2-samples python -m roles.credentials_provider_agent >"$LOG_DIR/credentials_provider_agent.log" 2>&1 & | ||
| pids+=($!) | ||
|
|
||
| echo "-> Starting the Merchant Payment Processor Agent (port:8003 log:$LOG_DIR/mpp_agent.log)..." | ||
| $UV_RUN_CMD --package ap2-samples python -m roles.merchant_payment_processor_agent >"$LOG_DIR/mpp_agent.log" 2>&1 & | ||
| pids+=($!) | ||
|
|
||
| echo "" | ||
| echo "All remote servers are starting." | ||
|
|
||
| echo "Starting the Shopping Agent..." | ||
| $UV_RUN_CMD --package ap2-samples adk web --host 0.0.0.0 $AGENTS_DIR/shopping_agent | ||
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.
Clearing the log directory using a wildcard
*can be problematic if the directory is empty (the wildcard might not expand) or contains a very large number of files. A more robust approach is to usefindto delete the contents without relying on shell expansion.