代理互操作桥:把 GreenHelix 代理与 x402、ACP、A2A、MCP、Visa TAP、Google AP2/UCP、PayPal Agent Ready 以及 OpenAI ACP 生态系统对接。
Notice: This is an educational guide with illustrative code examples. It does not execute code or install dependencies. All examples use the GreenHelix sandbox ( https://sandbox.greenhelix.net) which provides 500 free credits — no API key required to get started.
Referenced credentials (you supply these in your own environment):
WALLET_ADDRESS: Blockchain wallet address for receiving payments (public address only — no private keys)AGENT_SIGNING_KEY: Cryptographic signing key for agent identity (Ed25519 key pair for request signing)STRIPE_API_KEY: Stripe API key for card payment processing (scoped to payment intents only)
Your GreenHelix agent fleet is processing 10,000 escrow-backed transactions per day. Identity verification is locked down, trust scores are climbing, and your marketplace listings are generating inbound leads. Then a potential partner sends a message: "We run on Google A2A. Can your agents accept task requests from ours?" Another partner follows: "Our billing runs through x402 micropayments. Can your services respond to HTTP 402 flows?" A third asks: "We expose everything through MCP. Can your agents discover and call our tools?" A fourth says: "Our enterprise agents authorize payments through Visa TAP. Can you accept those?" A fifth: "We use Google's AP2 for micropayments and UCP for service orchestration." A sixth: "Our entire merchant base runs PayPal Agent Ready. Can your agents plug in?" A seventh: "We built our agent commerce on OpenAI's ACP. Can your services accept Agentic Commerce Protocol flows?" You search for integration guides and find protocol comparison articles -- dozens of them. x402 vs. ACP. A2A vs. MCP. Visa TAP vs. Google AP2. Comparison matrices. Architecture diagrams. What you cannot find is a single guide that shows you how to build working bridges between these protocols and your GreenHelix infrastructure. Not theory. Not comparison tables. Working Python classes that translate payment proofs, map identity schemas, convert task formats, and expose tool definitions across protocol boundaries. This is that guide.
Your GreenHelix agent fleet is processing 10,000 escrow-backed transactions per day. Identity verification is locked down, trust scores are climbing, and your marketplace listings are generating inbound leads. Then a potential partner sends a message: "We run on Google A2A. Can your agents accept task requests from ours?" Another partner follows: "Our billing runs through x402 micropayments. Can your services respond to HTTP 402 flows?" A third asks: "We expose everything through MCP. Can your agents discover and call our tools?" A fourth says: "Our enterprise agents authorize payments through Visa TAP. Can you accept those?" A fifth: "We use Google's AP2 for micropayments and UCP for service orchestration." A sixth: "Our entire merchant base runs PayPal Agent Ready. Can your agents plug in?" A seventh: "We built our agent commerce on OpenAI's ACP. Can your services accept Agentic Commerce Protocol flows?"
You search for integration guides and find protocol comparison articles -- dozens of them. x402 vs. ACP. A2A vs. MCP. Visa TAP vs. Google AP2. Comparison matrices. Architecture diagrams. What you cannot find is a single guide that shows you how to build working bridges between these protocols and your GreenHelix infrastructure. Not theory. Not comparison tables. Working Python classes that translate payment proofs, map identity schemas, convert task formats, and expose tool definitions across protocol boundaries.
This is that guide.
The 2026 agent protocol landscape has expanded from four major protocols to nine or more. The original four -- x402, ACP, A2A, and MCP -- have matured significantly into their v2 generations. x402 v2 is now backed by the x402 Foundation (Coinbase, Cloudflare, Stripe, AWS, and Microsoft) and has processed over 100 million payments. A2A v2 adds streaming-first task execution and enhanced Agent Card schemas. MCP 1.5+ introduces Streamable HTTP transport, resource subscriptions, and structured tool annotations. Meanwhile, five new heavyweight entrants have arrived: Visa's Transaction Authorization Protocol (TAP), Google's Agent Payments Protocol v2 (AP2) and Universal Commerce Protocol (UCP), PayPal's Agent Ready platform, and OpenAI's Agentic Commerce Protocol (OpenAI ACP). Each brings a different philosophy, a different merchant base, and a different set of integration requirements.
Every bridge class in this guide runs against the GreenHelix API at https://api.greenhelix.net/v1. Every code example is production-ready. By the end, your GreenHelix agents will accept x402 v2 micropayments, process ACP checkout flows, respond to A2A v2 task requests, expose services as MCP 1.5+ tools, authorize payments through Visa TAP, process Google AP2 payments and UCP task orchestration, integrate with PayPal's Agent Ready merchant network, and accept OpenAI ACP commerce flows -- without abandoning the escrow, identity, and trust infrastructure you have already built.
As of April 2026, the agentic web has splintered into at least nine major protocols, each backed by a different technology giant or financial network, each solving a different slice of the agent commerce problem, and none of them talking to each other. The landscape has more than doubled in the past six months alone.
x402 v2 (x402 Foundation: Coinbase, Cloudflare, Stripe, AWS, Microsoft) revived the HTTP 402 status code to enable pay-per-request micropayments. A server returns 402 with a payment requirement. The client settles the payment -- typically in USDC on Base or Solana -- and retries the request with a payment proof header. The x402 Foundation, formalized in late 2025 with five founding members, has processed over 100 million payments since launch. Version 2 of the protocol adds fiat settlement through Stripe and AWS payment rails, batch payment proofs for multi-step workflows, and a standardized facilitator discovery mechanism via /.well-known/x402-facilitator.json. It excels at sub-cent API billing. It has no concept of escrow, identity, or service discovery.
ACP (OpenAI, Stripe) -- the Agentic Commerce Protocol -- extends Stripe Checkout for AI agents. An agent browses a merchant catalog, selects a product, and completes a Stripe-based checkout flow. ACP powers Instant Checkout in ChatGPT for merchants on Etsy, Shopify, and Instacart. With the arrival of Visa TAP and PayPal Agent Ready, ACP now competes directly for the enterprise merchant segment it once had largely to itself. ACP's differentiator remains its deep Stripe integration and the ChatGPT distribution channel, but it must now defend its position against protocols backed by incumbents with vastly larger existing merchant bases.
A2A v2 (Google, with 50+ partners) -- the Agent-to-Agent protocol -- defines a standard for agents to discover each other via Agent Cards (JSON metadata at /.well-known/agent.json), exchange tasks with structured message parts, and stream progress updates via Server-Sent Events. Version 2 introduces streaming-first task execution (replacing the poll-based model as the primary path), enhanced Agent Card schemas with capability negotiation and protocol versioning, and a standardized push notification mechanism using webhooks. It remains transport-agnostic and focused on task orchestration, not payments. An A2A v2 agent can describe its capabilities, negotiate interaction modes, and stream partial results, but cannot accept payment without bolting on a separate payment protocol.
MCP 1.5+ (Anthropic, donated to Linux Foundation) -- the Model Context Protocol -- standardizes how AI models interact with external tools. An MCP server exposes tool schemas (JSON Schema definitions of inputs and outputs). An MCP client -- typically an LLM -- discovers available tools, calls them with structured inputs, and receives structured outputs. MCP 1.5 introduces Streamable HTTP transport (replacing the older SSE-based transport), resource subscriptions for real-time data feeds, structured tool annotations (read-only vs. destructive, idempotent vs. non-idempotent), and OAuth 2.1 authorization flows for remote servers. With 10,000+ servers and enterprise adoption accelerating, MCP is the de facto standard for tool integration in Claude, Cursor, Windsurf, and dozens of other AI clients. It has no built-in payment, identity, or marketplace layer.
Visa TAP (Visa) -- the Transaction Authorization Protocol -- brings traditional card network authorization to agent commerce. TAP uses enhanced 3-D Secure 2 (3DS2) flows for agent identity verification and EMV tokenization for secure payment credentials. Visa TAP does not issue new payment rails; it extends the existing Visa network to support AI agent transactions. An agent presents a Visa TAP token, the acquiring bank authorizes the transaction through the existing VisaNet infrastructure, and settlement occurs through standard card network settlement. TAP's advantage is instant access to 100+ million merchants already accepting Visa. Its disadvantage is card-network transaction fees (1.5-3.5%) that make sub-cent micropayments economically infeasible.
Google AP2 (Google) -- the Agent Payments Protocol v2 -- is built on the real-time payment patterns proven by UPI (India) and Pix (Brazil). AP2 supports six payment types: micropayments (sub-cent), standard transactions, subscriptions, escrow, split payments, and batch settlements. AP2 uses a hub-and-spoke architecture where Google acts as the payment hub, agents register as spokes, and payments settle through Google's treasury infrastructure. AP2 targets the same micropayment niche as x402 but adds subscription and escrow primitives that x402 lacks.
Google UCP (Google) -- the Universal Commerce Protocol -- is Google's answer to the service discovery and task orchestration problem. Where A2A handles task exchange between agents, UCP provides a higher-level commerce layer: service catalogs, pricing negotiation, SLA definitions, and multi-step workflow orchestration. UCP and A2A are complementary -- A2A handles the task-level communication, UCP handles the commercial wrapper around it. In practice, a UCP service listing includes an A2A endpoint for task execution and an AP2 endpoint for payment.
PayPal Agent Ready (PayPal, Braintree) -- uses Fastlane tokens for one-tap agent authentication and Braintree's GraphQL API for payment processing. Agent Ready targets PayPal's existing 400+ million consumer accounts and 35+ million merchant accounts. An agent authenticating through Agent Ready can access the consumer's PayPal wallet, Venmo balance, or linked bank accounts. For merchants, Agent Ready integrates through Braintree's existing SDKs with a new agent_context parameter that flags the transaction as agent-initiated. Agent Ready's advantage is the largest existing consumer wallet base in Western markets. Its disadvantage is PayPal-only settlement with no crypto or real-time payment rail options.
OpenAI ACP (OpenAI) -- the Agentic Commerce Protocol -- is OpenAI's dedicated agent-to-agent commerce framework, distinct from the earlier ACP (Stripe-based checkout). OpenAI ACP defines a commerce graph where agents publish service manifests (capabilities, pricing tiers, SLAs, and accepted payment methods), discover each other through a centralized registry, and negotiate terms programmatically before executing transactions. OpenAI ACP supports multiple payment backends -- Stripe, x402, and direct bank transfers -- through a pluggable payment adapter layer. The protocol includes built-in dispute resolution, usage metering, and refund flows. Its differentiator is deep integration with ChatGPT Plugins and the OpenAI agent platform, giving service providers access to OpenAI's consumer and enterprise distribution channels. Its disadvantage is vendor lock-in: the registry and dispute resolution are centralized through OpenAI infrastructure.
TAP (Token Agent Protocol) -- an emerging protocol for on-chain agent coordination using ERC-8183 and ERC-8004. It provides smart-contract escrow and on-chain agent registries. It requires Ethereum gas for every state transition, making it expensive for high-frequency interactions.
If your agents live in the GreenHelix ecosystem, you already have escrow-backed payments, cryptographic identity, trust scoring, marketplace discovery, event-driven webhooks, and 128 tools accessible through a single API. The problem is not capability. The problem is reach.
A potential client running x402-native infrastructure cannot pay your GreenHelix agent because your agent does not speak x402. A partner running Google A2A cannot discover your agent because you do not publish an Agent Card. An MCP client cannot call your services because your tools are not exposed as MCP tool definitions. An ACP agent cannot purchase your service because you do not have an ACP-compatible product listing. An enterprise running Visa TAP cannot authorize payments to your agent. A Google AP2/UCP deployment cannot discover or pay your services. A PayPal merchant cannot process agent transactions through your endpoint. An agent in the OpenAI ACP ecosystem cannot find your service manifest or negotiate terms with your agent.
Every protocol boundary is a lost transaction. Every missing bridge is a partner who goes elsewhere. With nine protocols and counting, the cost of not bridging is nine times what it was a year ago.
The solution is not to abandon GreenHelix and rewrite everything for each protocol. The solution is an adapter pattern: a thin protocol translation layer that sits between the external protocol and your GreenHelix infrastructure.
text
External Protocol Bridge Layer GreenHelix
┌──────────────┐ ┌─────────────────────┐ ┌──────────────┐
│ x402 Client │────▶│ X402Bridge │────▶│ create_escrow│
│ ACP Agent │────▶│ ACPBridge │────▶│ create_ │
│ A2A Agent │────▶│ A2ABridge │────▶│ payment_ │
│ MCP Client │────▶│ MCPBridge │────▶│ intent │
│ Visa TAP │────▶│ VisaTAPBridge │────▶│ register_ │
│ Google AP2 │────▶│ AP2UCPBridge │────▶│ agent │
│ PayPal Ready │────▶│ PayPalBridge │────▶│ publish_event│
│ OpenAI ACP │────▶│ OpenAIACPBridge │────▶│ search_ │
└──────────────┘ │ │ │ services │
│ IdentityMapper │────▶│ │
│ PaymentRouter │────▶│ │
│ EventBridge │────▶│ │
└─────────────────────┘ └──────────────┘
Each bridge class handles three responsibilities: translate the incoming protocol message into a GreenHelix API call, execute the call against the REST API ( POST /v1/{tool}), and translate the GreenHelix response back into the external protocol's expected format. The bridges share a common GreenHelixClient base class and a unified IdentityMapper for cross-protocol identity resolution.
The remainder of this guide builds each bridge, starting with x402.
The x402 protocol is elegant in its simplicity. It adds a payment layer directly to HTTP by leveraging the 402 Payment Required status code that has existed in the HTTP specification since 1997 but was never standardized until Coinbase and Cloudflare defined a concrete implementation in late 2025. Version 2, released in early 2026, extends the original with fiat settlement paths, batch payment proofs, and facilitator discovery.
The flow has four steps:
X-PAYMENT-PROOF header containing the transaction hash, facilitator signature, and settlement method.The server validates the payment proof, verifies settlement with the facilitator, and serves the response. The entire flow adds one round-trip to the normal request-response cycle. For micropayments -- $0.001 to $0.10 per request -- the overhead is acceptable.
To accept x402 payments, your GreenHelix agent needs to do three things: issue 402 responses with correct payment headers, validate incoming payment proofs, and record the payment in GreenHelix's ledger via escrow. The escrow step is critical -- it means every x402 payment is tracked, auditable, and subject to the same trust and compliance infrastructure as native GreenHelix transactions.
python
import requests
import hashlib
import time
import json
from typing import Optional
class GreenHelixClient:
"""Base client for all bridge classes."""
def __init__(self, api_key: str, base_url: str = "https://api.greenhelix.net/v1"):
self.api_key = api_key
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
})
def execute(self, tool: str, inputs: dict) -> dict:
"""Execute a GreenHelix tool."""
resp = self.session.post(
f"{self.base_url}/v1",
json={"tool": tool, "input": inputs},
)
resp.raise_for_status()
return resp.json()
class X402Bridge:
"""Translates x402 v2 micropayment flows into GreenHelix escrow transactions.
Supports both crypto (USDC on Base/Solana) and fiat (Stripe/AWS) settlement
paths introduced in x402 v2.
"""
SUPPORTED_SETTLEMENT = {"crypto", "stripe", "aws"}
def __init__(self, client: GreenHelixClient, agent_id: str,
facilitator_url: str, payment_address: str,
accepted_settlements: list = None):
self.client = client
self.agent_id = agent_id
self.facilitator_url = facilitator_url
self.payment_address = payment_address
self.accepted_settlements = accepted_settlements or ["crypto", "stripe"]
def create_402_response(self, price_usd: float, resource_id: str) -> dict:
"""Generate the headers for an HTTP 402 response.
Returns a dict of headers to attach to the 402 response.
x402 v2 adds settlement method negotiation and batch proof support.
"""
return {
"X-PAYMENT-REQUIRED": "true",
"X-PAYMENT-AMOUNT": str(price_usd),
"X-PAYMENT-CURRENCY": "USD",
"X-PAYMENT-ADDRESS": self.payment_address,
"X-PAYMENT-FACILITATOR": self.facilitator_url,
"X-PAYMENT-RESOURCE": resource_id,
"X-PAYMENT-EXPIRY": str(int(time.time()) + 300), # 5 min window
"X-PAYMENT-VERSION": "2",
"X-PAYMENT-SETTLEMENTS": ",".join(self.accepted_settlements),
}
def validate_payment_proof(self, proof_header: str) -> dict:
"""Validate an x402 payment proof against the facilitator.
Returns the validated payment details or raises ValueError.
"""
try:
proof_data = json.loads(proof_header)
except json.JSONDecodeError:
raise ValueError("Malformed payment proof header")
tx_hash = proof_data.get("tx_hash")
facilitator_sig = proof_data.get("facilitator_signature")
amount = proof_data.get("amount")
if not all([tx_hash, facilitator_sig, amount]):
raise ValueError("Payment proof missing required fields")
# Verify with the facilitator that the payment settled
verify_resp = requests.post(
f"{self.facilitator_url}/verify",
json={
"tx_hash": tx_hash,
"expected_address": self.payment_address,
"expected_amount": str(amount),
},
timeout=10,
)
if verify_resp.status_code != 200:
raise ValueError(f"Facilitator rejected proof: {verify_resp.text}")
return verify_resp.json()
def record_in_greenhelix(self, payment_proof: dict,
resource_id: str, payer_id: str) -> dict:
"""Record the x402 payment as a GreenHelix escrow for auditability.
Creates a completed escrow that records the external payment in the
GreenHelix ledger, preserving the full audit trail.
"""
escrow = self.client.execute("create_escrow", {
"payer_agent_id": payer_id,
"payee_agent_id": self.agent_id,
"amount": str(payment_proof["amount"]),
"description": (
f"x402 payment for resource {resource_id}. "
f"TX: {payment_proof['tx_hash']}. "
f"Facilitator: {self.facilitator_url}"
),
"escrow_type": "standard",
"metadata": json.dumps({
"protocol": "x402",
"tx_hash": payment_proof["tx_hash"],
"resource_id": resource_id,
}),
})
return escrow
def handle_request(self, request_headers: dict, resource_id: str,
price_usd: float, payer_id: str) -> dict:
"""Full x402 flow: check for proof, validate, record, or return 402.
Returns either a 402 response dict or a success dict with the
recorded escrow.
"""
proof_header = request_headers.get("X-PAYMENT-PROOF")
if not proof_header:
return {
"status": 402,
"headers": self.create_402_response(price_usd, resource_id),
}
payment_proof = self.validate_payment_proof(proof_header)
escrow = self.record_in_greenhelix(payment_proof, resource_id, payer_id)
return {
"status": 200,
"escrow_id": escrow.get("escrow_id"),
"payment_recorded": True,
}
To make your GreenHelix service discoverable by x402 clients, wrap it in a lightweight HTTP server that returns 402 for unauthenticated requests. Here is a Flask example:
python
from flask import Flask, request, jsonify
app = Flask(__name__)
client = GreenHelixClient(api_key="your-api-key")
bridge = X402Bridge(
client=client,
agent_id="my-summarizer-agent",
facilitator_url="https://facilitator.x402.org",
payment_address="0xYourUSDCAddress",
)
@app.route("/api/summarize", methods=["POST"])
def summarize():
result = bridge.handle_request(
request_headers=dict(request.headers),
resource_id="summarize-v1",
price_usd=0.05,
payer_id=request.headers.get("X-AGENT-ID", "unknown"),
)
if result["status"] == 402:
return jsonify({"error": "payment_required"}), 402, result["headers"]
# Payment verified -- execute the actual service via GreenHelix
service_result = client.execute("search_services", {
"query": "summarization",
"agent_id": "my-summarizer-agent",
})
return jsonify({
"result": service_result,
"escrow_id": result["escrow_id"],
})
Why escrow, not direct deposit? Recording x402 payments as escrow entries -- even though the payment already settled on-chain -- gives you the full GreenHelix audit trail. Every x402 payment appears in your ledger alongside native payments. Trust scores, compliance reports, and financial reconciliation work across both payment sources.
Expiry windows. The X-PAYMENT-EXPIRY header gives the client 5 minutes to complete payment. This prevents replay attacks where a client reuses an old payment proof for a new request. The facilitator enforces the expiry on the settlement side; your bridge enforces it on the proof validation side.
Idempotency. The tx_hash from the payment proof is unique per transaction. If a client retries with the same proof, your bridge should check whether an escrow with that tx_hash already exists before creating a duplicate. Add a cache or database lookup keyed on tx_hash in production.
The Agentic Commerce Protocol, developed jointly by OpenAI and Stripe, enables AI agents to purchase products and services from merchants through Stripe-powered checkout flows. ACP defines three entities: the buyer agent (an AI that wants to purchase something), the merchant (a service with a Stripe account and product catalog), and the orchestrator (typically ChatGPT or another host application that manages the checkout UI).
The flow:
ACP is designed for agent-to-merchant transactions. It assumes the merchant has a Stripe account, a product catalog, and a fulfillment pipeline. Your GreenHelix agent is not a Stripe merchant. But it can act as one with the right bridge.
The first step is making your GreenHelix services visible to ACP agents. ACP product listings follow a specific schema. Your bridge translates GreenHelix marketplace entries into that schema.
python
class ACPBridge:
"""Translates ACP checkout flows into GreenHelix payment intents."""
def __init__(self, client: GreenHelixClient, agent_id: str,
stripe_webhook_secret: str = ""):
self.client = client
self.agent_id = agent_id
self.stripe_webhook_secret = stripe_webhook_secret
def greenhelix_service_to_acp_listing(self, service: dict) -> dict:
"""Convert a GreenHelix marketplace service into an ACP product listing.
ACP expects a specific schema for product discovery. This method
maps GreenHelix fields to ACP fields.
"""
return {
"id": service.get("service_id"),
"name": service.get("name"),
"description": service.get("description"),
"price": {
"amount": int(float(service.get("price", "0")) * 100),
"currency": "usd",
},
"fulfillment_type": "digital",
"provider": {
"name": service.get("provider_agent_id", self.agent_id),
"protocol": "greenhelix",
},
"metadata": {
"greenhelix_service_id": service.get("service_id"),
"greenhelix_agent_id": self.agent_id,
},
}
def sync_listings_to_acp(self) -> list:
"""Pull all services from GreenHelix marketplace and convert to ACP format."""
services = self.client.execute("search_services", {
"provider_agent_id": self.agent_id,
})
service_list = services.get("services", [])
return [
self.greenhelix_service_to_acp_listing(s) for s in service_list
]
def handle_acp_purchase(self, acp_intent: dict) -> dict:
"""Translate an ACP purchase intent into a GreenHelix payment intent.
When an ACP agent initiates checkout for one of your listings,
this method creates the corresponding GreenHelix payment intent
and returns the mapping.
"""
greenhelix_service_id = (
acp_intent.get("metadata", {}).get("greenhelix_service_id")
)
if not greenhelix_service_id:
raise ValueError("ACP intent missing greenhelix_service_id metadata")
buyer_agent_id = acp_intent.get("buyer", {}).get("agent_id", "acp-buyer")
amount_cents = acp_intent.get("amount", 0)
amount_usd = str(amount_cents / 100)
# Create a GreenHelix payment intent that mirrors the ACP transaction
payment_intent = self.client.execute("create_payment_intent", {
"payer_agent_id": buyer_agent_id,
"payee_agent_id": self.agent_id,
"amount": amount_usd,
"description": (
f"ACP checkout for service {greenhelix_service_id}. "
f"ACP intent: {acp_intent.get('id', 'unknown')}"
),
"metadata": json.dumps({
"protocol": "acp",
"acp_intent_id": acp_intent.get("id"),
"stripe_payment_intent": acp_intent.get("stripe_pi_id"),
}),
})
return {
"greenhelix_payment_intent": payment_intent,
"acp_intent_id": acp_intent.get("id"),
"status": "payment_intent_created",
}
def handle_acp_fulfillment(self, acp_intent_id: str,
greenhelix_payment_id: str,
result: dict) -> dict:
"""Complete the ACP fulfillment flow after service delivery.
After your GreenHelix agent completes the work, this method
formats the result in ACP's expected fulfillment schema and
publishes a completion event.
"""
# Publish the completion event in GreenHelix
self.client.execute("publish_event", {
"event_type": "acp.fulfillment.completed",
"agent_id": self.agent_id,
"payload": json.dumps({
"acp_intent_id": acp_intent_id,
"greenhelix_payment_id": greenhelix_payment_id,
"result": result,
}),
})
# Return ACP-formatted fulfillment response
return {
"intent_id": acp_intent_id,
"status": "fulfilled",
"result": result,
"provider": {
"protocol": "greenhelix",
"agent_id": self.agent_id,
},
}
def register_as_acp_merchant(self, service_name: str,
service_description: str,
price_usd: float) -> dict:
"""Register your GreenHelix agent as both a GreenHelix marketplace
service and an ACP-compatible merchant.
Creates the GreenHelix marketplace entry and returns the ACP-formatted
listing for registration with ACP directories.
"""
# Register in GreenHelix marketplace
gh_service = self.client.execute("register_service", {
"agent_id": self.agent_id,
"name": service_name,
"description": service_description,
"price": str(price_usd),
"tags": json.dumps(["acp-compatible", "bridge"]),
})
# Convert to ACP listing format
acp_listing = self.greenhelix_service_to_acp_listing(gh_service)
return {
"greenhelix_service": gh_service,
"acp_listing": acp_listing,
}
The key insight is that ACP payments settle through Stripe, while GreenHelix payments settle through the gateway's internal ledger. Your bridge creates a corresponding GreenHelix payment intent for every ACP checkout, linking the two via metadata. This gives you dual-ledger auditability: Stripe's records for the fiat side, GreenHelix's records for the agent commerce side.
When an ACP agent initiates checkout:
handle_acp_purchase() to create the GreenHelix payment intent.handle_acp_fulfillment() records completion in both systems.python
# Webhook handler for incoming ACP purchase events
@app.route("/webhooks/acp", methods=["POST"])
def acp_webhook():
event = request.json
event_type = event.get("type")
if event_type == "checkout.initiated":
result = acp_bridge.handle_acp_purchase(event.get("intent"))
return jsonify(result)
elif event_type == "payment.completed":
# Stripe has confirmed payment -- now fulfill via GreenHelix
intent_id = event["intent"]["id"]
payment_id = event["intent"]["greenhelix_payment_id"]
# Execute your GreenHelix-backed service
service_result = client.execute("search_services", {
"service_id": event["intent"]["metadata"]["greenhelix_service_id"],
})
fulfillment = acp_bridge.handle_acp_fulfillment(
acp_intent_id=intent_id,
greenhelix_payment_id=payment_id,
result=service_result,
)
return jsonify(fulfillment)
return jsonify({"status": "ignored"}), 200
ACP identifies merchants by Stripe account ID. GreenHelix identifies agents by agent_id and Ed25519 public key. Your bridge must maintain a mapping between these identities. The IdentityMapper class in Chapter 10 handles this -- but at the ACP layer, you store the Stripe account ID alongside the GreenHelix agent registration:
python
# When registering, link GreenHelix identity to Stripe identity
identity_mapper.register_mapping(
greenhelix_agent_id="my-summarizer-agent",
protocol="acp",
external_id="acct_1234567890", # Stripe account ID
metadata={"stripe_account_type": "express"},
)
Google's Agent-to-Agent protocol defines a standard for agents to discover each other and exchange work. Version 2 refines the original with streaming-first execution, enhanced capability negotiation, and push notifications. Four concepts are central:
Agent Cards (v2). Every A2A agent publishes a JSON metadata file at /.well-known/agent.json. The v2 card schema adds protocol version negotiation, supported interaction modes (streaming, push, poll), capability tags for semantic matching, and optional payment endpoint references. Think of it as a machine-readable resume with contract terms.
Tasks. When one agent wants to hire another, it creates a Task. The task has an ID, a description, input data (as "message parts" -- text, files, structured data), and a lifecycle: submitted -> working -> completed (or failed, canceled). In v2, streaming is the primary interaction mode -- the hiring agent receives task updates via Server-Sent Events in real time, with polling as a fallback.
Messages. Task progress is communicated through messages. Each message contains one or more "parts" -- text parts, file parts, or data parts. The agent processing the task sends messages as it works, and a final message with the result when done.
Push Notifications (v2). A2A v2 introduces a standardized push notification mechanism. Agents can register webhook URLs during task creation, and the executing agent delivers status updates to those URLs. This replaces the need for long-lived SSE connections in asynchronous workflows.
A2A deliberately does not include payments. It is a task orchestration protocol. Your bridge adds GreenHelix's payment layer to A2A's task orchestration.
Your GreenHelix agent has a registered identity with capabilities, a public key, and a trust score. An A2A agent has an Agent Card with skills, authentication info, and endpoint URLs. The bridge maps between them.
python
class A2ABridge:
"""Translates A2A task requests into GreenHelix service calls and
publishes GreenHelix agents as A2A-discoverable."""
def __init__(self, client: GreenHelixClient, agent_id: str,
base_url: str = "https://your-agent.example.com"):
self.client = client
self.agent_id = agent_id
self.base_url = base_url
def generate_agent_card(self) -> dict:
"""Generate an A2A v2 Agent Card from GreenHelix agent identity.
Pulls the agent's identity and marketplace listings from GreenHelix
and formats them as an A2A v2-compliant Agent Card with capability
negotiation and payment endpoint references.
"""
identity = self.client.execute("get_agent_identity", {
"agent_id": self.agent_id,
})
services = self.client.execute("search_services", {
"provider_agent_id": self.agent_id,
})
service_list = services.get("services", [])
skills = []
for svc in service_list:
skills.append({
"id": svc.get("service_id"),
"name": svc.get("name"),
"description": svc.get("description"),
"tags": svc.get("tags", []),
"examples": [
f"Use this skill to {svc.get('description', 'perform a task')}"
],
})
return {
"name": identity.get("name", self.agent_id),
"description": identity.get("description", ""),
"url": self.base_url,
"version": "2.0.0",
"protocolVersion": "2.0",
"capabilities": {
"streaming": True,
"pushNotifications": True,
"stateTransitionHistory": True,
},
"authentication": {
"schemes": ["bearer"],
"credentials": None, # Provided at runtime
},
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": skills,
"provider": {
"organization": "GreenHelix",
"url": "https://api.greenhelix.net",
},
"supportsPayment": {
"protocols": ["greenhelix", "x402", "ap2"],
"endpoint": f"{self.base_url}/payment",
},
"x-greenhelix": {
"agent_id": self.agent_id,
"public_key": identity.get("public_key"),
"trust_score": identity.get("trust_score"),
},
}
def handle_a2a_task(self, task_request: dict) -> dict:
"""Translate an incoming A2A task request into a GreenHelix service call.
Extracts the task description and input parts, maps them to a
GreenHelix service execution, and returns the result formatted
as A2A task messages.
"""
task_id = task_request.get("id", f"a2a-{int(time.time())}")
skill_id = task_request.get("skill_id")
input_parts = task_request.get("message", {}).get("parts", [])
# Extract text input from A2A message parts
text_input = ""
structured_input = {}
for part in input_parts:
if part.get("type") == "text":
text_input += part.get("text", "")
elif part.get("type") == "data":
structured_input.update(part.get("data", {}))
# Look up the GreenHelix service corresponding to this skill
service = self.client.execute("search_services", {
"service_id": skill_id,
"provider_agent_id": self.agent_id,
})
# Create a payment intent for the A2A task if the service has a price
payment_result = None
caller_id = task_request.get("caller_agent_id", "a2a-caller")
service_price = service.get("price", "0")
if float(service_price) > 0:
payment_result = self.client.execute("create_payment_intent", {
"payer_agent_id": caller_id,
"payee_agent_id": self.agent_id,
"amount": service_price,
"description": f"A2A task {task_id} for skill {skill_id}",
"metadata": json.dumps({
"protocol": "a2a",
"a2a_task_id": task_id,
}),
})
# Publish event for tracking
self.client.execute("publish_event", {
"event_type": "a2a.task.received",
"agent_id": self.agent_id,
"payload": json.dumps({
"task_id": task_id,
"skill_id": skill_id,
"caller": caller_id,
}),
})
return {
"id": task_id,
"status": {"state": "working"},
"messages": [
{
"role": "agent",
"parts": [
{
"type": "text",
"text": f"Task accepted. Processing via GreenHelix agent {self.agent_id}.",
}
],
}
],
"greenhelix_payment": payment_result,
}
def complete_a2a_task(self, task_id: str, result_text: str,
result_data: dict = None) -> dict:
"""Mark an A2A task as completed and return the result.
Formats the GreenHelix service output as A2A message parts.
"""
parts = [{"type": "text", "text": result_text}]
if result_data:
parts.append({"type": "data", "data": result_data})
# Publish completion event
self.client.execute("publish_event", {
"event_type": "a2a.task.completed",
"agent_id": self.agent_id,
"payload": json.dumps({
"task_id": task_id,
"result_summary": result_text[:200],
}),
})
return {
"id": task_id,
"status": {"state": "completed"},
"messages": [
{
"role": "agent",
"parts": parts,
}
],
}
def publish_agent_card(self) -> dict:
"""Register the agent card in GreenHelix and return it for serving.
The card should be served at /.well-known/agent.json on your
agent's HTTP endpoint.
"""
card = self.generate_agent_card()
# Also register a webhook so GreenHelix events can notify A2A callers
self.client.execute("register_webhook", {
"agent_id": self.agent_id,
"url": f"{self.base_url}/a2a/tasks/webhook",
"events": json.dumps([
"a2a.task.received",
"a2a.task.completed",
]),
})
return card
To make your agent visible to A2A clients, serve the Agent Card at the well-known URL:
python
@app.route("/.well-known/agent.json")
def agent_card():
card = a2a_bridge.generate_agent_card()
return jsonify(card)
@app.route("/a2a/tasks", methods=["POST"])
def create_task():
task_request = request.json
result = a2a_bridge.handle_a2a_task(task_request)
return jsonify(result), 201
@app.route("/a2a/tasks/<task_id>", methods=["GET"])
def get_task(task_id):
# In production, retrieve task state from your storage
return jsonify({"id": task_id, "status": {"state": "working"}})
A2A has no payment primitive. Your bridge adds one by creating a GreenHelix payment intent for every task. The caller agent must have a GreenHelix wallet (or you create a temporary one via the IdentityMapper). The payment intent ID is returned in the task response, and the caller's payment must be confirmed before your agent delivers the final result. This transforms A2A from a free task protocol into a paid service protocol with escrow-backed guarantees.
The Model Context Protocol defines a client-server architecture for tool integration. An MCP server exposes a catalog of tools, each described by a JSON Schema that specifies the tool's name, description, input parameters, and output format. An MCP client -- typically an LLM runtime like Claude, Cursor, or a custom agent -- connects to the server, discovers available tools, calls them with structured inputs, and receives structured outputs.
MCP 1.5 introduces Streamable HTTP transport (replacing the older SSE-only transport for remote servers), making deployment simpler and more compatible with standard HTTP infrastructure. The protocol defines these core methods:
tools/list -- returns the catalog of available tools with annotations.tools/call -- executes a specific tool with provided arguments.resources/list -- returns available data resources (optional).resources/subscribe -- subscribes to resource changes (new in 1.5).MCP 1.5 also adds structured tool annotations: readOnlyHint, destructiveHint, idempotentHint, and openWorldHint. These annotations tell MCP clients whether a tool reads data, modifies state, or can be safely retried -- critical information for agent commerce tools that handle payments. OAuth 2.1 authorization for remote MCP servers means your bridge can enforce authentication without custom middleware.
With 10,000+ servers and enterprise adoption accelerating after the Linux Foundation donation, MCP is the de facto standard for tool integration in the AI ecosystem. By exposing your GreenHelix services as MCP tools, any MCP-compatible client can discover and call them without knowing anything about the GreenHelix API.
The bridge translates GreenHelix's tool catalog into MCP tool schemas and wraps each the REST API ( POST /v1/{tool}) call as an MCP tool invocation.
python
class MCPBridge:
"""Wraps GreenHelix execute API as MCP-compatible tool definitions."""
def __init__(self, client: GreenHelixClient, agent_id: str,
exposed_tools: list = None):
self.client = client
self.agent_id = agent_id
# Only expose specific tools, not the full 128-tool catalog
self.exposed_tools = exposed_tools or []
self._tool_schemas = {}
def define_tool_schema(self, tool_name: str, description: str,
input_schema: dict, price_usd: float = 0,
read_only: bool = True, idempotent: bool = True,
destructive: bool = False) -> dict:
"""Define an MCP 1.5 tool schema for a GreenHelix tool.
Each exposed tool gets a JSON Schema definition with MCP 1.5
annotations that MCP clients use for discovery, safety
classification, and invocation.
"""
schema = {
"name": f"greenhelix_{tool_name}",
"description": description,
"inputSchema": {
"type": "object",
"properties": input_schema,
},
"annotations": {
"readOnlyHint": read_only,
"destructiveHint": destructive,
"idempotentHint": idempotent,
"openWorldHint": True,
},
"x-greenhelix": {
"tool": tool_name,
"agent_id": self.agent_id,
"price_usd": price_usd,
},
}
self._tool_schemas[tool_name] = schema
return schema
def register_standard_tools(self) -> list:
"""Register a curated set of GreenHelix tools as MCP 1.5 tool definitions.
Returns the list of MCP tool schemas for tools/list responses.
Each tool includes MCP 1.5 annotations for safety classification.
"""
tools = []
tools.append(self.define_tool_schema(
tool_name="search_services",
description="Search the GreenHelix agent marketplace for services matching a query.",
input_schema={
"query": {
"type": "string",
"description": "Search query for finding agent services",
},
"tags": {
"type": "string",
"description": "Comma-separated tags to filter by",
},
},
read_only=True,
idempotent=True,
))
tools.append(self.define_tool_schema(
tool_name="get_agent_identity",
description="Retrieve the identity and trust score of a GreenHelix agent.",
input_schema={
"agent_id": {
"type": "string",
"description": "The agent ID to look up",
},
},
read_only=True,
idempotent=True,
))
tools.append(self.define_tool_schema(
tool_name="send_message",
description="Send a message to a GreenHelix agent.",
input_schema={
"sender_agent_id": {
"type": "string",
"description": "Your agent ID",
},
"receiver_agent_id": {
"type": "string",
"description": "The recipient agent ID",
},
"content": {
"type": "string",
"description": "The message content",
},
},
read_only=False,
idempotent=False,
destructive=False,
))
# Add custom tools from exposed_tools list
for tool_name in self.exposed_tools:
if tool_name not in self._tool_schemas:
tools.append(self.define_tool_schema(
tool_name=tool_name,
description=f"Execute the {tool_name} GreenHelix tool.",
input_schema={
"input": {
"type": "object",
"description": f"Input parameters for {tool_name}",
},
},
))
return tools
def handle_tools_list(self) -> dict:
"""Handle an MCP tools/list request.
Returns a JSON-RPC 2.0 response with all registered tool schemas.
"""
if not self._tool_schemas:
self.register_standard_tools()
return {
"jsonrpc": "2.0",
"result": {
"tools": list(self._tool_schemas.values()),
},
}
def handle_tools_call(self, tool_name: str, arguments: dict,
caller_id: str = "mcp-client") -> dict:
"""Handle an MCP tools/call request.
Translates the MCP tool call into a GreenHelix execute API call
and formats the response as a JSON-RPC 2.0 result.
"""
# Strip the greenhelix_ prefix if present
gh_tool_name = tool_name.replace("greenhelix_", "")
if gh_tool_name not in self._tool_schemas:
return {
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": f"Tool not found: {tool_name}",
},
}
# Check if this tool has a price -- if so, create a payment intent
schema = self._tool_schemas[gh_tool_name]
price = schema.get("x-greenhelix", {}).get("price_usd", 0)
payment_info = None
if price > 0:
payment_info = self.client.execute("create_payment_intent", {
"payer_agent_id": caller_id,
"payee_agent_id": self.agent_id,
"amount": str(price),
"description": f"MCP tool call: {gh_tool_name}",
"metadata": json.dumps({
"protocol": "mcp",
"tool": gh_tool_name,
}),
})
# Execute the GreenHelix tool
result = self.client.execute(gh_tool_name, arguments)
# Publish event for cross-protocol tracking
self.client.execute("publish_event", {
"event_type": "mcp.tool.called",
"agent_id": self.agent_id,
"payload": json.dumps({
"tool": gh_tool_name,
"caller": caller_id,
"has_payment": price > 0,
}),
})
return {
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": json.dumps(result, indent=2),
}
],
"x-greenhelix-payment": payment_info,
},
}
MCP servers communicate over stdio (for local tools) or Streamable HTTP (for remote tools, replacing the older SSE transport in MCP 1.5). Here is a minimal Streamable HTTP-based MCP server that wraps your GreenHelix bridge:
python
@app.route("/mcp", methods=["POST"])
def mcp_endpoint():
rpc_request = request.json
method = rpc_request.get("method")
params = rpc_request.get("params", {})
rpc_id = rpc_request.get("id")
if method == "tools/list":
response = mcp_bridge.handle_tools_list()
elif method == "tools/call":
response = mcp_bridge.handle_tools_call(
tool_name=params.get("name"),
arguments=params.get("arguments", {}),
caller_id=request.headers.get("X-AGENT-ID", "mcp-client"),
)
else:
response = {
"jsonrpc": "2.0",
"error": {"code": -32601, "message": f"Unknown method: {method}"},
}
response["id"] = rpc_id
return jsonify(response)
Once your MCP server is running, any MCP client can discover and call your GreenHelix services without modification. Claude, Cursor, or any custom LLM agent connects to your MCP endpoint, calls tools/list to discover available tools, and calls tools/call with the appropriate arguments. The bridge handles the translation transparently.
The critical advantage is discoverability. MCP clients expect tools to describe themselves via JSON Schema. By wrapping your GreenHelix services as MCP tools, you make them first-class citizens in the MCP ecosystem. An LLM can reason about which tool to use based on the schema description, without any GreenHelix-specific knowledge.
For paid tools, the bridge handles payment automatically. The x-greenhelix-payment field in the response tells the caller that a payment intent was created. Sophisticated MCP clients can read this field and present the payment to the user; simpler clients ignore it and the payment settles in the background via the GreenHelix ledger.
Visa's Transaction Authorization Protocol extends the existing card network infrastructure to support AI agent transactions. TAP does not create new payment rails. Instead, it adds an agent authorization layer on top of VisaNet, the same network that processes 65,000 transactions per second for human cardholders.
The TAP flow:
agent_context object that identifies the transaction as agent-initiated.TAP's advantage is instant access to 100+ million merchants already accepting Visa. Any merchant with a Visa terminal or payment gateway can accept TAP payments without modification -- the agent context is transparent to the merchant's existing infrastructure. The disadvantage is card-network interchange fees (1.5-3.5%) that make sub-cent micropayments economically infeasible, and batch settlement latency that conflicts with real-time agent workflows.
Your bridge translates Visa TAP authorization flows into GreenHelix payment intents and escrow entries, giving you dual-ledger visibility across both the card network and GreenHelix systems.
python
class VisaTAPBridge:
"""Translates Visa TAP agent payment authorizations into GreenHelix
payment intents with card-network settlement tracking."""
def __init__(self, client: GreenHelixClient, agent_id: str,
merchant_id: str, acquiring_bank_endpoint: str,
tap_certificate_path: str):
self.client = client
self.agent_id = agent_id
self.merchant_id = merchant_id
self.acquiring_bank_endpoint = acquiring_bank_endpoint
self.tap_certificate_path = tap_certificate_path
def create_tap_authorization(self, tap_token: str, amount_usd: float,
payer_agent_id: str,
description: str = "") -> dict:
"""Submit a Visa TAP authorization request and record it in GreenHelix.
Sends the authorization through the acquiring bank, then creates
a corresponding GreenHelix payment intent for dual-ledger tracking.
"""
# Build the TAP authorization request
auth_request = {
"token": tap_token,
"amount": int(amount_usd * 100), # Cents
"currency": "USD",
"merchant_id": self.merchant_id,
"agent_context": {
"agent_id": self.agent_id,
"transaction_type": "agent_initiated",
"tap_version": "1.0",
"3ds2_method": "certificate",
},
"description": description,
}
# Submit to acquiring bank
auth_response = requests.post(
f"{self.acquiring_bank_endpoint}/authorize",
json=auth_request,
cert=self.tap_certificate_path,
timeout=15,
)
if auth_response.status_code != 200:
raise ValueError(
f"TAP authorization failed: {auth_response.text}"
)
auth_result = auth_response.json()
authorization_code = auth_result.get("authorization_code")
if not authorization_code:
raise ValueError(
f"TAP authorization declined: {auth_result.get('decline_reason')}"
)
# Record in GreenHelix ledger for dual-ledger auditability
payment_intent = self.client.execute("create_payment_intent", {
"payer_agent_id": payer_agent_id,
"payee_agent_id": self.agent_id,
"amount": str(amount_usd),
"description": (
f"Visa TAP payment. Auth: {authorization_code}. "
f"{description}"
),
"metadata": json.dumps({
"protocol": "visa_tap",
"authorization_code": authorization_code,
"tap_token_last4": tap_token[-4:],
"merchant_id": self.merchant_id,
"settlement_method": "card_network",
"expected_settlement": "T+1",
}),
})
# Publish tracking event
self.client.execute("publish_event", {
"event_type": "tap.authorization.completed",
"agent_id": self.agent_id,
"payload": json.dumps({
"authorization_code": authorization_code,
"amount": str(amount_usd),
"payer_agent_id": payer_agent_id,
"greenhelix_payment_id": payment_intent.get("payment_id"),
}),
})
return {
"authorization_code": authorization_code,
"greenhelix_payment_intent": payment_intent,
"settlement_expected": "T+1",
"status": "authorized",
}
def handle_tap_settlement_webhook(self, settlement_event: dict) -> dict:
"""Process a Visa TAP settlement confirmation webhook.
Called when the card network batch settlement completes (typically
T+1). Updates the corresponding GreenHelix payment intent status.
"""
auth_code = settlement_event.get("authorization_code")
settled_amount = settlement_event.get("settled_amount_cents", 0) / 100
net_amount = settlement_event.get("net_amount_cents", 0) / 100
interchange_fee = settled_amount - net_amount
self.client.execute("publish_event", {
"event_type": "tap.settlement.completed",
"agent_id": self.agent_id,
"payload": json.dumps({
"authorization_code": auth_code,
"settled_amount": str(settled_amount),
"net_amount": str(net_amount),
"interchange_fee": str(interchange_fee),
}),
})
return {
"authorization_code": auth_code,
"settled": True,
"net_amount": str(net_amount),
"interchange_fee": str(interchange_fee),
}
def validate_tap_token(self, tap_token: str) -> dict:
"""Validate a Visa TAP token before processing a transaction.
Checks token format, expiry, and whether the token is on the
network's revocation list.
"""
validation_resp = requests.post(
f"{self.acquiring_bank_endpoint}/validate-token",
json={"token": tap_token},
cert=self.tap_certificate_path,
timeout=10,
)
if validation_resp.status_code != 200:
return {"valid": False, "reason": "Token validation failed"}
result = validation_resp.json()
return {
"valid": result.get("valid", False),
"token_type": result.get("token_type"), # credit, debit, prepaid
"funding_source": result.get("funding_source"),
"expiry": result.get("expiry"),
}
Interchange fee tracking. Card network fees are significant for agent commerce -- 1.5-3.5% per transaction. The bridge tracks interchange fees in GreenHelix metadata so you can calculate true net revenue per transaction, not just gross volume. This is critical for pricing optimization when serving both TAP and lower-fee protocols like x402.
Settlement lag. Unlike x402 (near-instant on-chain settlement) or GreenHelix escrow (instant within the platform), Visa TAP settles in T+1 or T+2 batches. Your bridge creates the GreenHelix payment intent at authorization time but should not release escrow funds until settlement confirmation arrives via the settlement webhook. This prevents paying out on transactions that are later reversed.
Minimum transaction size. At 1.5-3.5% interchange plus a per-transaction fixed fee ($0.10-$0.30), TAP is economically viable only for transactions above approximately $2.00. For micropayments below that threshold, route to x402 or AP2 instead. The PaymentRouter in Chapter 11 handles this automatically.
Google's Agent Payments Protocol v2 is built on real-time payment patterns proven by UPI (India's Unified Payments Interface, processing 12+ billion transactions per month) and Pix (Brazil's instant payment system). AP2 supports six payment types: micropayments (sub-cent), standard transactions, subscriptions, escrow, split payments, and batch settlements.
AP2 uses a hub-and-spoke architecture. Google acts as the payment hub. Agents register as spokes with a Google AP2 account. When Agent A wants to pay Agent B, the payment flows through Google's treasury infrastructure: A's balance is debited, B's balance is credited, and settlement occurs in real time (sub-second for pre-funded accounts) or T+1 for bank-linked accounts.
The Universal Commerce Protocol is Google's service discovery and commercial orchestration layer. Where A2A handles task-level communication between agents, UCP wraps commercial terms around those tasks: service catalogs with pricing, SLA definitions, pricing negotiation flows, multi-step workflow orchestration, and dispute resolution.
A UCP service listing includes:
UCP and A2A are complementary. A2A handles the "how do agents talk to each other" problem. UCP handles the "under what commercial terms" problem.
The bridge handles both AP2 payments and UCP service orchestration, translating between Google's infrastructure and GreenHelix's escrow and marketplace systems.
python
class AP2UCPBridge:
"""Translates Google AP2 payments and UCP service orchestration into
GreenHelix payment intents and marketplace listings."""
def __init__(self, client: GreenHelixClient, agent_id: str,
ap2_account_id: str, ap2_api_key: str,
ap2_base_url: str = "https://payments.googleapis.com/ap2/v2"):
self.client = client
self.agent_id = agent_id
self.ap2_account_id = ap2_account_id
self.ap2_api_key = ap2_api_key
self.ap2_base_url = ap2_base_url
self._ap2_session = requests.Session()
self._ap2_session.headers.update({
"Authorization": f"Bearer {ap2_api_key}",
"Content-Type": "application/json",
})
def receive_ap2_payment(self, ap2_payment_event: dict) -> dict:
"""Process an incoming Google AP2 payment and record it in GreenHelix.
Called when a Google AP2 agent sends payment to your AP2 account.
Creates a corresponding GreenHelix payment intent for dual-ledger
tracking.
"""
payment_id = ap2_payment_event.get("payment_id")
amount = ap2_payment_event.get("amount")
currency = ap2_payment_event.get("currency", "USD")
payer_ap2_id = ap2_payment_event.get("payer_account_id")
payment_type = ap2_payment_event.get("payment_type", "standard")
# Verify the payment with Google's AP2 API
verify_resp = self._ap2_session.get(
f"{self.ap2_base_url}/payments/{payment_id}",
timeout=10,
)
if verify_resp.status_code != 200:
raise ValueError(f"AP2 payment verification failed: {verify_resp.text}")
verified = verify_resp.json()
if verified.get("status") != "settled":
raise ValueError(
f"AP2 payment not settled: {verified.get('status')}"
)
# Record in GreenHelix
payment_intent = self.client.execute("create_payment_intent", {
"payer_agent_id": f"ap2:{payer_ap2_id}",
"payee_agent_id": self.agent_id,
"amount": str(amount),
"description": (
f"Google AP2 {payment_type} payment. "
f"AP2 ID: {payment_id}"
),
"metadata": json.dumps({
"protocol": "google_ap2",
"ap2_payment_id": payment_id,
"payment_type": payment_type,
"currency": currency,
"settlement_method": "google_treasury",
}),
})
return {
"ap2_payment_id": payment_id,
"greenhelix_payment_intent": payment_intent,
"status": "recorded",
}
def send_ap2_payment(self, recipient_ap2_id: str, amount_usd: float,
description: str = "",
payment_type: str = "standard") -> dict:
"""Send a Google AP2 payment from your account and record it in GreenHelix.
Used when your GreenHelix agent needs to pay a Google AP2 agent.
"""
payment_resp = self._ap2_session.post(
f"{self.ap2_base_url}/payments",
json={
"payer_account_id": self.ap2_account_id,
"payee_account_id": recipient_ap2_id,
"amount": str(amount_usd),
"currency": "USD",
"payment_type": payment_type,
"description": description,
},
timeout=15,
)
if payment_resp.status_code not in (200, 201):
raise ValueError(f"AP2 payment failed: {payment_resp.text}")
ap2_result = payment_resp.json()
# Record outbound payment in GreenHelix
self.client.execute("publish_event", {
"event_type": "ap2.payment.sent",
"agent_id": self.agent_id,
"payload": json.dumps({
"ap2_payment_id": ap2_result.get("payment_id"),
"recipient": recipient_ap2_id,
"amount": str(amount_usd),
"payment_type": payment_type,
}),
})
return ap2_result
def greenhelix_service_to_ucp_listing(self, service: dict) -> dict:
"""Convert a GreenHelix marketplace service into a UCP service listing.
UCP listings include pricing schedules, SLA terms, and endpoint
references for both A2A task execution and AP2 payment.
"""
return {
"service_id": service.get("service_id"),
"name": service.get("name"),
"description": service.get("description"),
"version": "1.0.0",
"pricing": {
"model": "per_call",
"amount": service.get("price", "0"),
"currency": "USD",
"volume_discounts": [],
},
"sla": {
"max_latency_ms": 5000,
"uptime_percent": 99.5,
"max_error_rate_percent": 1.0,
},
"endpoints": {
"a2a": f"https://your-agent.example.com/.well-known/agent.json",
"ap2_payment": self.ap2_account_id,
"greenhelix": f"https://api.greenhelix.net/v1",
},
"provider": {
"name": service.get("provider_agent_id", self.agent_id),
"protocol": "greenhelix",
"ap2_account": self.ap2_account_id,
},
"metadata": {
"greenhelix_service_id": service.get("service_id"),
"greenhelix_agent_id": self.agent_id,
},
}
def sync_listings_to_ucp(self) -> list:
"""Pull all services from GreenHelix marketplace and publish as UCP listings."""
services = self.client.execute("search_services", {
"provider_agent_id": self.agent_id,
})
service_list = services.get("services", [])
return [
self.greenhelix_service_to_ucp_listing(s) for s in service_list
]
def handle_ucp_negotiation(self, negotiation_request: dict) -> dict:
"""Handle a UCP pricing negotiation request.
UCP allows buyer agents to propose alternative terms (lower price,
different SLA, volume commitment). This method evaluates the
proposal against your configured policies and responds.
"""
proposed_price = float(negotiation_request.get("proposed_price", 0))
service_id = negotiation_request.get("service_id")
volume_commitment = negotiation_request.get("volume_commitment", 0)
# Look up current service pricing
service = self.client.execute("search_services", {
"service_id": service_id,
"provider_agent_id": self.agent_id,
})
list_price = float(service.get("price", "0"))
# Simple negotiation logic: accept if within 20% of list price
# or if volume commitment > 1000 calls
min_acceptable = list_price * 0.8
if proposed_price >= min_acceptable or volume_commitment > 1000:
return {
"status": "accepted",
"agreed_price": str(max(proposed_price, min_acceptable)),
"volume_commitment": volume_commitment,
"service_id": service_id,
}
else:
return {
"status": "counter_offer",
"counter_price": str(min_acceptable),
"message": (
f"Minimum price is {min_acceptable}. "
f"Volume discounts available above 1000 calls."
),
}
Both AP2 and x402 target sub-cent micropayments, but they differ in settlement architecture. x402 settles on-chain (or via Stripe in v2), giving you verifiable payment proofs but requiring facilitator infrastructure. AP2 settles through Google's treasury, giving you real-time balance updates but requiring a Google AP2 account and trusting Google as the settlement counterparty.
For GreenHelix agents, the practical decision comes down to your counterparty's ecosystem. If they are in the Google ecosystem (using A2A for task orchestration), AP2 is the natural payment complement. If they are using x402-native infrastructure (Coinbase, Cloudflare), x402 is simpler. The PaymentRouter in Chapter 11 automates this selection.
PayPal Agent Ready extends PayPal's existing infrastructure for AI agent transactions. It has two components:
Fastlane Authentication. Agents authenticate using Fastlane tokens -- one-tap authentication credentials that link an agent to a consumer's PayPal account. The consumer pre-authorizes the agent during a one-time setup, and subsequent transactions require only the Fastlane token. This is PayPal's answer to the "agent authorization" problem: how does a consumer grant spending authority to an AI agent without sharing credentials?
Braintree Agent API. Transactions are processed through Braintree's GraphQL API with a new agent_context parameter. The parameter includes the agent's identity, the authorization scope (spending limits, merchant restrictions), and the consumer's Fastlane token. Braintree routes the transaction through PayPal's standard payment processing, with the agent context logged for compliance and dispute resolution.
Agent Ready targets PayPal's 400+ million consumer accounts and 35+ million merchant accounts. An agent authenticated through Agent Ready can access the consumer's PayPal wallet, Venmo balance, or linked bank accounts. Settlement is through PayPal's standard disbursement: instant to PayPal balance, T+1 to bank accounts.
python
class PayPalAgentReadyBridge:
"""Translates PayPal Agent Ready transactions into GreenHelix payment
intents with Braintree settlement tracking."""
def __init__(self, client: GreenHelixClient, agent_id: str,
braintree_merchant_id: str, braintree_api_key: str,
braintree_api_secret: str,
braintree_environment: str = "production"):
self.client = client
self.agent_id = agent_id
self.braintree_merchant_id = braintree_merchant_id
self.braintree_api_key = braintree_api_key
self.braintree_api_secret = braintree_api_secret
self.braintree_environment = braintree_environment
self._bt_base_url = (
"https://payments.braintree-api.com/graphql"
if braintree_environment == "production"
else "https://payments.sandbox.braintree-api.com/graphql"
)
def process_agent_ready_payment(self, fastlane_token: str,
amount_usd: float,
payer_agent_id: str,
description: str = "") -> dict:
"""Process a PayPal Agent Ready payment and record it in GreenHelix.
Charges the consumer's PayPal account via the Fastlane token
and creates a corresponding GreenHelix payment intent.
"""
# Execute Braintree GraphQL mutation with agent context
mutation = """
mutation ChargePayPalAccount($input: ChargePayPalAccountInput!) {
chargePayPalAccount(input: $input) {
transaction {
id
status
amount { value currencyCode }
paypal { payerId payerEmail }
}
}
}
"""
variables = {
"input": {
"paymentMethodId": fastlane_token,
"transaction": {
"amount": str(amount_usd),
"agentContext": {
"agentId": self.agent_id,
"transactionType": "AGENT_INITIATED",
"authorizationScope": "PRE_AUTHORIZED",
},
"description": description,
},
},
}
bt_response = requests.post(
self._bt_base_url,
json={"query": mutation, "variables": variables},
auth=(self.braintree_api_key, self.braintree_api_secret),
timeout=15,
)
if bt_response.status_code != 200:
raise ValueError(
f"Braintree request failed: {bt_response.text}"
)
result = bt_response.json()
tx_data = (
result.get("data", {})
.get("chargePayPalAccount", {})
.get("transaction", {})
)
if not tx_data or tx_data.get("status") != "SETTLING":
raise ValueError(
f"PayPal transaction failed: {json.dumps(result.get('errors', []))}"
)
braintree_tx_id = tx_data["id"]
# Record in GreenHelix ledger
payment_intent = self.client.execute("create_payment_intent", {
"payer_agent_id": payer_agent_id,
"payee_agent_id": self.agent_id,
"amount": str(amount_usd),
"description": (
f"PayPal Agent Ready payment. "
f"Braintree TX: {braintree_tx_id}. {description}"
),
"metadata": json.dumps({
"protocol": "paypal_agent_ready",
"braintree_tx_id": braintree_tx_id,
"paypal_payer_id": tx_data.get("paypal", {}).get("payerId"),
"settlement_method": "paypal",
}),
})
self.client.execute("publish_event", {
"event_type": "paypal.payment.completed",
"agent_id": self.agent_id,
"payload": json.dumps({
"braintree_tx_id": braintree_tx_id,
"amount": str(amount_usd),
"payer_agent_id": payer_agent_id,
"greenhelix_payment_id": payment_intent.get("payment_id"),
}),
})
return {
"braintree_tx_id": braintree_tx_id,
"greenhelix_payment_intent": payment_intent,
"status": "settling",
}
def validate_fastlane_token(self, fastlane_token: str) -> dict:
"""Validate a Fastlane token before processing a transaction.
Checks token validity, authorization scope, and spending limits.
"""
query = """
query ValidatePaymentMethod($id: ID!) {
node(id: $id) {
... on PayPalAccount {
payerId
email
agentAuthorization {
scope
spendingLimit { value currencyCode }
expiresAt
}
}
}
}
"""
resp = requests.post(
self._bt_base_url,
json={"query": query, "variables": {"id": fastlane_token}},
auth=(self.braintree_api_key, self.braintree_api_secret),
timeout=10,
)
if resp.status_code != 200:
return {"valid": False, "reason": "Validation request failed"}
data = resp.json().get("data", {}).get("node", {})
auth = data.get("agentAuthorization", {})
return {
"valid": bool(data.get("payerId")),
"payer_id": data.get("payerId"),
"email": data.get("email"),
"scope": auth.get("scope"),
"spending_limit": auth.get("spendingLimit", {}).get("value"),
"expires_at": auth.get("expiresAt"),
}
def greenhelix_service_to_agent_ready_listing(self, service: dict) -> dict:
"""Convert a GreenHelix marketplace service into a PayPal Agent Ready
merchant listing format."""
return {
"merchant_id": self.braintree_merchant_id,
"service_id": service.get("service_id"),
"name": service.get("name"),
"description": service.get("description"),
"price": {
"value": service.get("price", "0"),
"currency_code": "USD",
},
"agent_ready": {
"supports_fastlane": True,
"supports_venmo": True,
"agent_initiated": True,
},
"metadata": {
"greenhelix_service_id": service.get("service_id"),
"greenhelix_agent_id": self.agent_id,
},
}
Both Agent Ready and ACP solve the "agent buys from merchant" problem, but they target different merchant bases. ACP routes through Stripe; Agent Ready routes through Braintree/PayPal. In practice, many merchants accept both, so the choice comes down to which payment method the consumer (or consuming agent) has authorized. If the consumer's agent has a Fastlane token, use Agent Ready. If the agent has a Stripe payment method, use ACP. The PaymentRouter in Chapter 11 selects the optimal path based on available credentials.
OpenAI's Agentic Commerce Protocol defines a commerce graph for AI agent services. Unlike the earlier ACP (Stripe-based checkout, covered in Chapter 3), OpenAI ACP is a full-stack commerce framework with five layers:
Service Manifests. Agents publish structured manifests describing their capabilities, pricing tiers, SLAs, accepted payment methods, and terms of service. Manifests are registered in OpenAI's centralized service registry and discoverable through both API queries and ChatGPT's agent plugin marketplace.
Discovery and Matching. Buyer agents query the registry to find services matching their requirements. The registry supports semantic search, capability filtering, price comparison, and SLA matching. Results are ranked by a combination of relevance, provider reputation, and pricing.
Term Negotiation. Before executing a transaction, buyer and seller agents can negotiate terms programmatically. The negotiation protocol supports price proposals, counter-offers, volume commitments, and custom SLA modifications. Non-negotiable listings skip this step.
Transaction Execution. Payments flow through a pluggable payment adapter layer. OpenAI ACP supports Stripe, x402, and direct bank transfers as payment backends. The protocol creates a transaction record that links the service manifest, negotiated terms, payment confirmation, and fulfillment result.
Dispute Resolution. OpenAI ACP includes built-in dispute flows. If the buyer claims non-delivery or quality issues, the dispute is escalated through OpenAI's resolution process, which can issue refunds, adjust provider reputation scores, or suspend service listings.
The bridge exposes GreenHelix services as OpenAI ACP service manifests and translates incoming ACP transactions into GreenHelix payment intents with full escrow backing.
python
class OpenAIACPBridge:
"""Translates OpenAI ACP service manifests and transactions into
GreenHelix marketplace listings and escrow-backed payment intents."""
def __init__(self, client: GreenHelixClient, agent_id: str,
openai_acp_api_key: str,
openai_acp_base_url: str = "https://api.openai.com/v1/acp"):
self.client = client
self.agent_id = agent_id
self.openai_acp_api_key = openai_acp_api_key
self.openai_acp_base_url = openai_acp_base_url
self._acp_session = requests.Session()
self._acp_session.headers.update({
"Authorization": f"Bearer {openai_acp_api_key}",
"Content-Type": "application/json",
})
def greenhelix_service_to_acp_manifest(self, service: dict) -> dict:
"""Convert a GreenHelix marketplace service into an OpenAI ACP
service manifest for registration in the ACP service registry."""
return {
"manifest_version": "1.0",
"service_id": service.get("service_id"),
"name": service.get("name"),
"description": service.get("description"),
"provider": {
"id": self.agent_id,
"name": service.get("provider_agent_id", self.agent_id),
"protocol": "greenhelix",
},
"pricing": {
"tiers": [
{
"name": "standard",
"price_per_call": service.get("price", "0"),
"currency": "USD",
"rate_limit": 1000, # calls per hour
},
],
"negotiable": True,
},
"sla": {
"max_latency_ms": 5000,
"uptime_percent": 99.5,
"support_channel": "webhook",
},
"accepted_payment_methods": [
"stripe", "x402", "greenhelix_escrow",
],
"capabilities": service.get("tags", []),
"fulfillment": {
"type": "real_time",
"endpoint": f"https://api.greenhelix.net/v1",
"protocol": "greenhelix_execute",
},
"metadata": {
"greenhelix_service_id": service.get("service_id"),
"greenhelix_agent_id": self.agent_id,
},
}
def register_manifests_in_acp(self) -> list:
"""Register all GreenHelix services as OpenAI ACP service manifests."""
services = self.client.execute("search_services", {
"provider_agent_id": self.agent_id,
})
service_list = services.get("services", [])
registered = []
for svc in service_list:
manifest = self.greenhelix_service_to_acp_manifest(svc)
resp = self._acp_session.post(
f"{self.openai_acp_base_url}/manifests",
json=manifest,
timeout=10,
)
if resp.status_code in (200, 201):
registered.append({
"service_id": svc.get("service_id"),
"acp_manifest_id": resp.json().get("manifest_id"),
"status": "registered",
})
else:
registered.append({
"service_id": svc.get("service_id"),
"status": "failed",
"error": resp.text,
})
return registered
def handle_acp_transaction(self, acp_transaction: dict) -> dict:
"""Process an incoming OpenAI ACP transaction request.
Creates a GreenHelix escrow for the transaction amount, executes
the requested service, and returns the fulfillment result in ACP
format. The escrow ensures the buyer's payment is held until
fulfillment is confirmed.
"""
manifest_id = acp_transaction.get("manifest_id")
service_id = acp_transaction.get("service_id")
buyer_id = acp_transaction.get("buyer", {}).get("id", "acp-buyer")
amount = acp_transaction.get("agreed_price",
acp_transaction.get("list_price", "0"))
payment_method = acp_transaction.get("payment_method", "stripe")
transaction_id = acp_transaction.get("transaction_id")
# Create GreenHelix escrow for buyer protection
escrow = self.client.execute("create_escrow", {
"payer_agent_id": f"openai-acp:{buyer_id}",
"payee_agent_id": self.agent_id,
"amount": str(amount),
"description": (
f"OpenAI ACP transaction {transaction_id}. "
f"Service: {service_id}. Manifest: {manifest_id}"
),
"escrow_type": "standard",
"metadata": json.dumps({
"protocol": "openai_acp",
"acp_transaction_id": transaction_id,
"acp_manifest_id": manifest_id,
"payment_method": payment_method,
}),
})
# Publish tracking event
self.client.execute("publish_event", {
"event_type": "openai_acp.transaction.received",
"agent_id": self.agent_id,
"payload": json.dumps({
"transaction_id": transaction_id,
"service_id": service_id,
"buyer_id": buyer_id,
"amount": str(amount),
"escrow_id": escrow.get("escrow_id"),
}),
})
return {
"transaction_id": transaction_id,
"escrow_id": escrow.get("escrow_id"),
"status": "accepted",
"fulfillment_status": "pending",
}
def complete_acp_fulfillment(self, transaction_id: str,
escrow_id: str,
result: dict) -> dict:
"""Complete an OpenAI ACP transaction after service fulfillment.
Releases the escrow and sends the fulfillment result back to the
ACP registry for buyer confirmation.
"""
# Notify ACP registry of fulfillment
fulfill_resp = self._acp_session.post(
f"{self.openai_acp_base_url}/transactions/{transaction_id}/fulfill",
json={
"status": "fulfilled",
"result": result,
"provider_id": self.agent_id,
},
timeout=10,
)
# Publish completion event
self.client.execute("publish_event", {
"event_type": "openai_acp.transaction.fulfilled",
"agent_id": self.agent_id,
"payload": json.dumps({
"transaction_id": transaction_id,
"escrow_id": escrow_id,
"fulfillment_status": "completed",
}),
})
return {
"transaction_id": transaction_id,
"escrow_id": escrow_id,
"status": "fulfilled",
"acp_confirmation": fulfill_resp.json() if fulfill_resp.ok else None,
}
def handle_acp_negotiation(self, negotiation_request: dict) -> dict:
"""Handle an OpenAI ACP term negotiation request.
Evaluates the buyer's proposed terms against the service manifest
and responds with acceptance, rejection, or counter-offer.
"""
service_id = negotiation_request.get("service_id")
proposed_price = float(negotiation_request.get("proposed_price", 0))
proposed_volume = negotiation_request.get("volume_commitment", 0)
# Look up current service pricing
service = self.client.execute("search_services", {
"service_id": service_id,
"provider_agent_id": self.agent_id,
})
list_price = float(service.get("price", "0"))
# Negotiation policy: accept >= 80% of list price, or
# >= 60% with volume commitment > 5000
min_price = list_price * 0.8
volume_min_price = list_price * 0.6
if proposed_price >= min_price:
return {
"status": "accepted",
"agreed_price": str(proposed_price),
"volume_commitment": proposed_volume,
}
elif proposed_price >= volume_min_price and proposed_volume > 5000:
return {
"status": "accepted",
"agreed_price": str(proposed_price),
"volume_commitment": proposed_volume,
"note": "Volume discount applied",
}
else:
return {
"status": "counter_offer",
"counter_price": str(min_price),
"message": (
f"Minimum price: {min_price}. Volume discount "
f"(60% of list) available for 5000+ call commitments."
),
}
Three protocols now handle the "agent commerce" problem. ACP (Chapter 3) is Stripe-native checkout for the ChatGPT distribution channel. OpenAI ACP is a broader commerce framework with multi-backend payment support and built-in dispute resolution. UCP (Chapter 7) is Google's answer with SLA negotiation and A2A integration.
The key differences for bridge builders:
Your GreenHelix bridge supports all three simultaneously. The IdentityMapper (Chapter 10) links your agent's identity across all three registries, and the PaymentRouter (Chapter 11) selects the optimal payment path for each transaction.
Your GreenHelix agent is my-summarizer-agent with Ed25519 public key MCowBQYDK2Vw.... In x402, it is identified by its USDC payment address 0xAb5801a7.... In ACP, it is a Stripe account acct_1234567890. In A2A, it is discoverable at https://your-agent.example.com/.well-known/agent.json. In MCP, it is the server at https://your-agent.example.com/mcp. In Visa TAP, it is a merchant ID with a TAP certificate. In Google AP2, it is an AP2 account ID. In UCP, it is a service provider in Google's commerce registry. In PayPal Agent Ready, it is a Braintree merchant ID. In OpenAI ACP, it is a provider ID in OpenAI's service registry.
One agent. Ten identities. Zero automatic cross-referencing.
When an A2A agent calls your service and then later initiates an x402 payment, how do you know it is the same entity? When an MCP client calls your tool and you want to check its trust score in GreenHelix, how do you resolve the MCP client identity to a GreenHelix agent ID? When a Visa TAP authorization arrives, how do you link it to the OpenAI ACP transaction that triggered it? Without an identity mapping layer, every protocol interaction is a stranger transaction with no reputation context.
The IdentityMapper maintains bidirectional mappings between GreenHelix agent IDs and external protocol identities. It stores mappings in GreenHelix's own identity system via metadata fields, making the registry auditable and persistent.
python
class IdentityMapper:
"""Maps agent identities across GreenHelix and all nine external protocols."""
SUPPORTED_PROTOCOLS = {
"x402", "acp", "a2a", "mcp", "tap",
"visa_tap", "ap2", "ucp", "paypal_agent_ready", "openai_acp",
}
def __init__(self, client: GreenHelixClient):
self.client = client
# In-memory cache; production should use persistent storage
self._mappings = {} # {greenhelix_id: {protocol: external_id}}
self._reverse = {} # {(protocol, external_id): greenhelix_id}
def register_mapping(self, greenhelix_agent_id: str, protocol: str,
external_id: str, metadata: dict = None) -> dict:
"""Register an identity mapping between GreenHelix and an external protocol.
Also verifies that the GreenHelix agent exists before creating
the mapping.
"""
if protocol not in self.SUPPORTED_PROTOCOLS:
raise ValueError(
f"Unsupported protocol: {protocol}. "
f"Supported: {self.SUPPORTED_PROTOCOLS}"
)
# Verify the GreenHelix agent exists
identity = self.client.execute("verify_agent", {
"agent_id": greenhelix_agent_id,
})
if not identity.get("verified"):
raise ValueError(
f"Agent {greenhelix_agent_id} not found or not verified"
)
# Store the mapping
if greenhelix_agent_id not in self._mappings:
self._mappings[greenhelix_agent_id] = {}
self._mappings[greenhelix_agent_id][protocol] = {
"extern