Agent Commerce Discovery
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):
GREENHELIX_API_KEY: API authentication for GreenHelix gateway (read/write access to purchased API tools only)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)
Forty percent of digital commerce services are invisible to AI agents. Not because the services are bad, but because they are structured for humans -- HTML pages, marketing copy, PDF brochures -- and agents cannot parse any of it. The services exist, the demand exists, and the agents have budgets to spend. But the transaction never happens because the agent never finds the service. This is the discovery gap, and it is the single largest source of lost revenue in the agentic economy.
Between January 2025 and March 2026, AI-referred traffic to commerce services grew 805% year-over-year. Google Shopping Graph now indexes over 45 billion product listings with structured attributes. ChatGPT's product search handles 2.3 million commerce queries per day. Perplexity Shopping launched with 30+ retail partners and AI-native product cards. The agents are shopping. The question is whether they can find you.
This guide is the practitioner's manual for making your services discoverable to AI agents. It covers the full stack: knowledge graphs that model your service catalog as machine-readable entities, protocol endpoints that announce your capabilities through UCP, MCP, A2A, and ACP, structured data that agents can parse and compare, real-time catalog synchronization that prevents stale listings, trust signals that help agents rank you above competitors, and analytics that measure whether discovery is actually converting into transactions. Every chapter contains production Python code against the GreenHelix A2A Commerce Gateway -- 128 tools accessible at https://api.greenhelix.net/v1 via a single the REST API (POST /v1/{tool}) endpoint.
What You'll Learn
- Chapter 1: The Discovery Problem
- Chapter 2: Commerce Knowledge Graphs from Scratch
- Chapter 3: The Protocol Stack: UCP, MCP, A2A, ACP
- Chapter 4: Building .well-known Discovery Endpoints
- Chapter 5: Structured Data & Schema.org for Agent Readability
- Chapter 6: Real-Time Catalog Sync & Graph Maintenance
- Chapter 7: Trust Signals & Reputation in Agent Discovery
- Chapter 8: Measuring Discovery Performance
- Conclusion: The Discovery Flywheel
Full Guide
Agent Commerce Discovery: Knowledge Graphs, Protocol Endpoints & Structured Data for AI-Discoverable Services
Forty percent of digital commerce services are invisible to AI agents. Not because the services are bad, but because they are structured for humans -- HTML pages, marketing copy, PDF brochures -- and agents cannot parse any of it. The services exist, the demand exists, and the agents have budgets to spend. But the transaction never happens because the agent never finds the service. This is the discovery gap, and it is the single largest source of lost revenue in the agentic economy.
Between January 2025 and March 2026, AI-referred traffic to commerce services grew 805% year-over-year. Google Shopping Graph now indexes over 45 billion product listings with structured attributes. ChatGPT's product search handles 2.3 million commerce queries per day. Perplexity Shopping launched with 30+ retail partners and AI-native product cards. The agents are shopping. The question is whether they can find you.
This guide is the practitioner's manual for making your services discoverable to AI agents. It covers the full stack: knowledge graphs that model your service catalog as machine-readable entities, protocol endpoints that announce your capabilities through UCP, MCP, A2A, and ACP, structured data that agents can parse and compare, real-time catalog synchronization that prevents stale listings, trust signals that help agents rank you above competitors, and analytics that measure whether discovery is actually converting into transactions. Every chapter contains production Python code against the GreenHelix A2A Commerce Gateway -- 128 tools accessible at https://api.greenhelix.net/v1 via a single the REST API (POST /v1/{tool}) endpoint.
Table of Contents
- The Discovery Problem
- Commerce Knowledge Graphs from Scratch
- The Protocol Stack: UCP, MCP, A2A, ACP
- Building .well-known Discovery Endpoints
- Structured Data & Schema.org for Agent Readability
- Real-Time Catalog Sync & Graph Maintenance
- Trust Signals & Reputation in Agent Discovery
- Measuring Discovery Performance
Chapter 1: The Discovery Problem
Why 40% of Commerce Services Are Invisible
The number comes from a March 2026 analysis by Forrester: of 2,400 digital service providers surveyed, 40.3% had no machine-readable service description of any kind -- no JSON-LD, no OpenAPI spec, no agent card, no structured catalog. Their services existed only as human-readable web pages. For AI agents performing commerce queries, these services might as well not exist.
The root cause is architectural. Traditional web commerce optimized for a single consumer: a human with a browser. The human reads marketing copy, interprets images, navigates menus, and fills out checkout forms. Every element of the commerce experience -- product descriptions, pricing pages, comparison charts, testimonials -- is designed for visual consumption by a person sitting at a screen. AI agents consume none of this. An agent does not "see" your landing page. It sends structured queries to discovery endpoints, parses JSON responses, compares attributes programmatically, and executes transactions via API. If your service is not described in a format agents can query, you are invisible to the fastest-growing channel in digital commerce.
The Shift from Human Browsing to Agent Crawling
Human discovery follows a browse-and-click pattern: Google search, scan results, click through, read page, compare tabs, make decision. The entire flow assumes visual attention and manual navigation. Agent discovery follows a query-and-parse pattern: send structured query, receive structured response, compare attributes algorithmically, execute highest-ranked option. The flows have almost nothing in common.
| Dimension | Human Browsing | Agent Crawling |
|---|---|---|
| Discovery method | Keyword search, link following | Structured API queries, .well-known endpoint crawling |
| Content format | HTML, images, video | JSON-LD, OpenAPI specs, agent cards |
| Comparison method | Visual side-by-side, gut feeling | Programmatic attribute matching, scoring algorithms |
| Decision speed | Minutes to days | Milliseconds to seconds |
| Price sensitivity | Influenced by anchoring, framing | Exact numerical comparison with configurable thresholds |
| Trust evaluation | Reviews, brand recognition | Cryptographic verification, trust scores, claim chains |
| Transaction method | Shopping cart, checkout form | API call with payment proof |
The implication is stark: optimizing for human browsing does nothing for agent crawling. A beautifully designed landing page with compelling copy and high-resolution product photos generates zero signal for an agent that queries the REST API (POST /v1/{tool}) with {"tool": "search_services", "input": {"query": "data enrichment API under $0.01 per call with 99.9% uptime SLA"}}. The agent needs structured attributes, machine-readable pricing, and verifiable SLA terms. It needs to find your service through a discovery protocol, not a Google search.
How the Major Platforms Do Discovery
Google Shopping Graph indexes 45 billion product listings by crawling structured data from merchant websites. It prioritizes Merchant Center feeds (structured XML/JSON), followed by Schema.org JSON-LD embedded in product pages, followed by inferred attributes from unstructured HTML (lowest priority, lowest accuracy). Products with complete structured data appear in AI Overviews, Shopping tab results, and Gemini product recommendations. Products without structured data are deprioritized or excluded entirely.
ChatGPT Product Search (launched with GPT-4o shopping in April 2025) uses a combination of web crawling and direct merchant integrations. It surfaces product cards with structured attributes -- price, ratings, availability, specifications -- pulled from merchant APIs, affiliate feeds, and Schema.org markup. Merchants integrated through ACP (Agentic Commerce Protocol) get priority placement because ACP provides real-time inventory and pricing data that ChatGPT can trust to be current.
A2A Discovery (Google's Agent-to-Agent protocol) uses Agent Cards published at /.well-known/agent.json. An agent discovers another agent by fetching its Agent Card, which describes capabilities, supported input/output formats, authentication requirements, and service endpoints. A2A discovery is agent-to-agent, not agent-to-product -- it is how autonomous agents find other agents to delegate tasks to or purchase services from.
GreenHelix Marketplace provides a unified discovery layer across all these patterns. The search_services tool queries the marketplace index using structured attributes. The best_match tool returns the single best service for a given requirement set. The register_service tool publishes your service with structured metadata that agents can query. Your service appears in marketplace search results and can be discovered by any agent with API access.
The Cost of Being Undiscoverable
The 805% year-over-year growth in AI-referred traffic is not evenly distributed. It concentrates on services that are machine-readable. A March 2026 analysis of 500 SaaS products found that those with complete structured data (JSON-LD, OpenAPI spec, and at least one discovery protocol endpoint) captured 14x more AI-referred traffic than those without. The relationship was not proportional -- it was binary. Services were either discoverable or they were not. There was no middle ground of "partially discoverable."
The revenue impact is direct. AI-referred traffic converts at 2.3x the rate of organic search traffic because agents only send users (or other agents) to services that match the query criteria. An agent that finds your service has already verified that your pricing, capabilities, and availability meet the requirements. The "lead" is pre-qualified by the agent's scoring algorithm. Losing that channel means losing your highest-converting traffic source.
import requests
from typing import Any
GATEWAY_URL = os.environ.get("GREENHELIX_API_URL", "https://sandbox.greenhelix.net")
class DiscoveryClient:
"""Client for GreenHelix A2A Commerce Gateway discovery operations."""
def __init__(self, api_key: str):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
})
def execute(self, tool: str, input_data: dict[str, Any]) -> dict:
"""Execute a single tool on the gateway."""
resp = self.session.post(
f"{GATEWAY_URL}/v1",
json={"tool": tool, "input": input_data},
timeout=30,
)
resp.raise_for_status()
return resp.json()
def search_services(self, query: str, filters: dict | None = None) -> dict:
"""Search the GreenHelix marketplace for services."""
payload = {"query": query}
if filters:
payload["filters"] = filters
return self.execute("search_services", payload)
def best_match(self, requirements: dict) -> dict:
"""Find the single best service match for given requirements."""
return self.execute("best_match", requirements)
# Initialize -- used throughout this guide
client = DiscoveryClient(api_key="your-api-key-here")
# Example: search for data enrichment services
results = client.search_services(
query="data enrichment API",
filters={
"max_price_per_call": 0.01,
"min_uptime_sla": 99.9,
"protocols": ["ucp", "a2a"],
},
)
print(f"Found {len(results.get('services', []))} matching services")
This client object is referenced in every subsequent chapter. Store your API key in an environment variable (GREENHELIX_API_KEY), never in source code.
Key Takeaways
- 40% of digital services have zero machine-readable descriptions. They are invisible to AI agents regardless of quality.
- AI-referred commerce traffic grew 805% YoY. Services with complete structured data capture 14x more of this traffic.
- Agent discovery is query-and-parse, not browse-and-click. Optimizing for humans does nothing for agents.
- Google Shopping Graph, ChatGPT, A2A, and GreenHelix all rely on structured data. No structured data means no discovery.
- See P21 (Agent-Ready Commerce) for building the full agent-ready storefront on top of discovery.
Chapter 2: Commerce Knowledge Graphs from Scratch
What Is a Commerce Knowledge Graph?
A knowledge graph is a structured representation of entities, their properties, and the relationships between them. In commerce, the entities are services, providers, pricing tiers, SLAs, certifications, and transactions. The relationships connect them: a provider offers a service, a service has a pricing tier, a pricing tier includes an SLA, an SLA guarantees an uptime level. The properties are the machine-readable attributes: price per call, latency percentile, geographic availability, supported authentication methods.
Traditional databases store this data in tables. Knowledge graphs store it as triples: subject-predicate-object. "DataEnrichmentAPI" -- "hasPricing" -- "PayPerCallTier". "PayPerCallTier" -- "costPerCall" -- "0.005 USD". "DataEnrichmentAPI" -- "guarantees" -- "99.95% Uptime SLA". The advantage of the graph structure is that agents can traverse relationships without knowing the schema in advance. An agent can start from a service node, follow edges to discover pricing, SLA terms, trust scores, and provider identity -- all without a predefined query template.
Entities, Relationships, and Properties
A commerce knowledge graph for agent-discoverable services contains five core entity types:
| Entity Type | Description | Key Properties |
|---|---|---|
| Service | The product or capability being offered | name, description, category, version, status |
| Provider | The entity (agent or organization) offering the service | agent_id, public_key, registration_date, trust_score |
| PricingTier | A specific pricing configuration | tier_name, cost_per_call, monthly_cap, currency, billing_model |
| SLA | Service level agreement terms | uptime_guarantee, latency_p99, support_response_time |
| Certification | Verified claims about the service or provider | cert_type, issuer, valid_from, valid_until, verification_hash |
The relationships between these entities form the graph:
Provider --[offers]--> Service
Service --[hasPricing]--> PricingTier
Service --[guarantees]--> SLA
Provider --[holds]--> Certification
Service --[requires]--> Certification (for consumers)
Service --[dependsOn]--> Service (for composed services)
Modeling Your Service Catalog as a Graph
The first step is translating your existing service catalog into graph form. Most teams start with a flat list of services in a database table or a YAML config file. The graph transformation adds structure that agents can navigate.
import json
from dataclasses import dataclass, field, asdict
from typing import Optional
@dataclass
class SLA:
uptime_guarantee: float
latency_p99_ms: int
support_response_hours: int
penalty_per_violation_pct: float = 5.0
@dataclass
class PricingTier:
tier_name: str
cost_per_call: float
currency: str = "USD"
monthly_cap: Optional[float] = None
billing_model: str = "pay_per_call"
volume_discounts: dict = field(default_factory=dict)
@dataclass
class ServiceNode:
service_id: str
name: str
description: str
category: str
version: str
provider_agent_id: str
pricing_tiers: list[PricingTier] = field(default_factory=list)
sla: Optional[SLA] = None
tags: list[str] = field(default_factory=list)
dependencies: list[str] = field(default_factory=list)
supported_protocols: list[str] = field(default_factory=list)
status: str = "active"
class CommerceKnowledgeGraph:
"""In-memory knowledge graph for agent-discoverable services."""
def __init__(self):
self.services: dict[str, ServiceNode] = {}
self.edges: list[dict] = []
def add_service(self, service: ServiceNode) -> None:
"""Add a service node to the graph."""
self.services[service.service_id] = service
# Auto-generate relationship edges
for tier in service.pricing_tiers:
self.edges.append({
"subject": service.service_id,
"predicate": "hasPricing",
"object": tier.tier_name,
"properties": asdict(tier),
})
if service.sla:
self.edges.append({
"subject": service.service_id,
"predicate": "guarantees",
"object": f"{service.service_id}_sla",
"properties": asdict(service.sla),
})
for dep in service.dependencies:
self.edges.append({
"subject": service.service_id,
"predicate": "dependsOn",
"object": dep,
})
def query_by_attribute(self, **kwargs) -> list[ServiceNode]:
"""Query services by attribute filters."""
results = []
for service in self.services.values():
match = True
for key, value in kwargs.items():
if key == "max_cost_per_call":
if not any(
t.cost_per_call <= value
for t in service.pricing_tiers
):
match = False
elif key == "min_uptime":
if not service.sla or service.sla.uptime_guarantee < value:
match = False
elif key == "category":
if service.category != value:
match = False
elif key == "protocol":
if value not in service.supported_protocols:
match = False
if match:
results.append(service)
return results
def to_jsonld(self) -> list[dict]:
"""Export the graph as JSON-LD for agent consumption."""
output = []
for service in self.services.values():
node = {
"@context": "https://schema.org",
"@type": "Service",
"@id": f"urn:greenhelix:service:{service.service_id}",
"name": service.name,
"description": service.description,
"category": service.category,
"version": service.version,
"provider": {
"@type": "Organization",
"identifier": service.provider_agent_id,
},
"offers": [
{
"@type": "Offer",
"name": tier.tier_name,
"price": str(tier.cost_per_call),
"priceCurrency": tier.currency,
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": str(tier.cost_per_call),
"priceCurrency": tier.currency,
"unitText": "per API call",
"billingModel": tier.billing_model,
},
}
for tier in service.pricing_tiers
],
}
if service.sla:
node["termsOfService"] = {
"uptimeGuarantee": service.sla.uptime_guarantee,
"latencyP99Ms": service.sla.latency_p99_ms,
"supportResponseHours": service.sla.support_response_hours,
}
output.append(node)
return output
def sync_to_marketplace(self, discovery_client) -> list[dict]:
"""Register all services on GreenHelix marketplace."""
results = []
for service in self.services.values():
cheapest_tier = min(
service.pricing_tiers,
key=lambda t: t.cost_per_call,
) if service.pricing_tiers else None
result = discovery_client.execute("register_service", {
"agent_id": service.provider_agent_id,
"service_name": service.name,
"description": service.description,
"category": service.category,
"tags": service.tags,
"pricing": {
"model": cheapest_tier.billing_model if cheapest_tier else "contact",
"base_price": str(cheapest_tier.cost_per_call) if cheapest_tier else "0",
"currency": cheapest_tier.currency if cheapest_tier else "USD",
},
"sla": asdict(service.sla) if service.sla else None,
"protocols": service.supported_protocols,
})
results.append(result)
return results
# Build a sample graph
graph = CommerceKnowledgeGraph()
graph.add_service(ServiceNode(
service_id="data-enrichment-v2",
name="DataEnrich Pro",
description="Real-time company data enrichment with 95% match rate",
category="data-enrichment",
version="2.1.0",
provider_agent_id="agent-dataenrich-prod",
pricing_tiers=[
PricingTier("starter", cost_per_call=0.005, monthly_cap=100.0),
PricingTier("growth", cost_per_call=0.003, monthly_cap=500.0,
volume_discounts={"10000": 0.002, "100000": 0.001}),
],
sla=SLA(uptime_guarantee=99.95, latency_p99_ms=200,
support_response_hours=4),
tags=["enrichment", "company-data", "real-time", "api"],
supported_protocols=["ucp", "a2a", "mcp"],
))
graph.add_service(ServiceNode(
service_id="sentiment-analysis-v3",
name="SentimentLens",
description="Multi-language sentiment analysis with aspect extraction",
category="nlp",
version="3.0.1",
provider_agent_id="agent-sentimentlens-prod",
pricing_tiers=[
PricingTier("basic", cost_per_call=0.001),
PricingTier("premium", cost_per_call=0.008,
volume_discounts={"50000": 0.005}),
],
sla=SLA(uptime_guarantee=99.9, latency_p99_ms=150,
support_response_hours=8),
tags=["nlp", "sentiment", "multilingual", "aspect-extraction"],
supported_protocols=["ucp", "mcp"],
))
# Query the graph
cheap_services = graph.query_by_attribute(
max_cost_per_call=0.005,
min_uptime=99.9,
)
print(f"Services matching criteria: {[s.name for s in cheap_services]}")
# Export as JSON-LD
jsonld = graph.to_jsonld()
print(json.dumps(jsonld[0], indent=2))
JSON-LD and Schema.org Vocabulary
JSON-LD (JavaScript Object Notation for Linked Data) is the standard format for embedding structured data in web pages and API responses. It uses @context to map property names to Schema.org URIs, @type to declare the entity type, and @id to provide a globally unique identifier. AI agents -- whether they are Google's crawlers, ChatGPT's shopping engine, or a GreenHelix marketplace indexer -- parse JSON-LD to extract structured attributes.
The Schema.org vocabulary provides standardized types for commerce: Service, Offer, Organization, PriceSpecification, AggregateRating, Review. Using these types ensures your data is interoperable across all agent ecosystems. A service described as @type: Service with offers containing @type: Offer and priceSpecification will be parsed identically by Google Shopping Graph, Perplexity Shopping, and GreenHelix search_services.
The to_jsonld() method in the CommerceKnowledgeGraph class above handles the conversion. The critical detail is using string representations for prices (str(tier.cost_per_call)) rather than floats, avoiding floating-point precision issues that cause agents to reject or miscompare pricing data. See P18 (Pricing & Monetization) for the full treatment of decimal-safe pricing.
Key Takeaways
- A commerce knowledge graph models services as entities with typed relationships: provider offers service, service has pricing, pricing includes SLA.
- Five core entity types: Service, Provider, PricingTier, SLA, Certification. Each has machine-readable properties.
- JSON-LD with Schema.org vocabulary is the interoperability standard. All major agent platforms parse it.
- Build the graph in code, export as JSON-LD for web crawlers, and sync to GreenHelix marketplace via
register_servicefor agent-native discovery.- Always use string-typed prices to avoid floating-point comparison failures.
Chapter 3: The Protocol Stack: UCP, MCP, A2A, ACP
Four Protocols, Four Jobs
The agentic commerce stack has consolidated around four protocols, each solving a distinct problem in the discovery-to-transaction lifecycle. Implementing the wrong one first wastes months. Implementing all four without understanding the dependencies creates a maintenance burden that outweighs the benefit. This chapter provides the decision framework.
UCP (Unified Commerce Protocol) is the discovery and capability advertisement layer. A UCP profile published at /.well-known/ucp tells agents what your service does, how it is priced, what payment methods it accepts, and where to find its API. UCP is the front door. Without it, agents that crawl for services have no standard entry point. UCP profiles are JSON documents with a defined schema: capabilities, pricing, authentication requirements, SLA terms, and payment methods. Think of it as a machine-readable business card that also includes the full menu and the credit card terminal specs.
MCP (Model Context Protocol) is the tool execution layer. An MCP server exposes tools -- functions with JSON Schema-defined inputs and outputs -- that LLMs and agents can call. MCP handles tool discovery (listing available tools and their schemas), tool invocation (sending structured inputs and receiving structured outputs), and context management (maintaining state across multi-turn tool interactions). If UCP tells an agent your service exists, MCP tells it how to call your service.
A2A (Agent-to-Agent Protocol) is the task delegation layer. A2A defines how agents discover each other (Agent Cards at /.well-known/agent.json), exchange task requests (JSON-based task messages with structured parts), and stream progress updates (Server-Sent Events). A2A is designed for agent-to-agent workflows where one agent delegates a task to another, monitors progress, and receives results. It overlaps with MCP in discovery but diverges in execution: MCP is function-call oriented, A2A is task-oriented.
ACP (Agentic Commerce Protocol) is the payment and checkout layer. ACP extends Stripe Checkout for AI agents, providing structured product catalogs, cart management, and payment flow orchestration. ACP is the narrowest of the four protocols -- it specifically handles the commercial transaction, not discovery, not tool execution, not task delegation.
The Dependency Chain
The protocols are not independent. They form a dependency chain:
Discovery Execution Transaction
┌──────┐ ┌──────┐ ┌──────┐
│ UCP │───────▶│ MCP │─────────▶│ ACP │
│ │───────▶│ A2A │─────────▶│ │
└──────┘ └──────┘ └──────┘
UCP must come first. An agent cannot call your MCP tools or send you A2A tasks if it cannot discover you. MCP and A2A operate in parallel -- some agents prefer function calls (MCP), others prefer task delegation (A2A), many support both. ACP comes last because payment only matters after an agent has discovered your service and decided to use it.
Decision Matrix: Which Protocol to Implement First
| Factor | UCP First | MCP First | A2A First | ACP First |
|---|---|---|---|---|
| You sell API services | Yes -- agents need to discover your capabilities | Second -- expose tools after discovery | Optional -- most API consumers prefer MCP | Third -- add payment after execution works |
| You sell to LLM-powered agents | Yes | Yes -- LLMs call MCP tools natively | Lower priority | After MCP |
| You sell to autonomous agent fleets | Yes | Optional | Yes -- fleets use A2A for task delegation | After A2A |
| You are a marketplace | Yes | Yes -- expose search/purchase as tools | Yes -- agents discover marketplace via A2A | Yes -- checkout via ACP |
| You need payment immediately | Still first -- discovery before payment | No | No | No -- useless without discovery |
The universal answer: implement UCP first, then MCP or A2A depending on your buyer profile, then ACP.
Protocol Selection Logic
def select_protocols(
service_type: str,
buyer_profile: str,
needs_payment: bool,
existing_protocols: list[str],
) -> list[dict]:
"""Determine which discovery protocols to implement and in what order.
Returns prioritized list of protocols with implementation guidance.
"""
recommendations = []
# UCP is always first -- it is the discovery foundation
if "ucp" not in existing_protocols:
recommendations.append({
"protocol": "ucp",
"priority": 1,
"reason": "Discovery foundation -- agents cannot find you without it",
"effort_days": 2,
"endpoint": "/.well-known/ucp",
})
# MCP vs A2A depends on buyer profile
if buyer_profile in ("llm_agents", "api_consumers", "developers"):
if "mcp" not in existing_protocols:
recommendations.append({
"protocol": "mcp",
"priority": 2,
"reason": "LLM agents and API consumers prefer function-call semantics",
"effort_days": 3,
"endpoint": "/mcp/tools",
})
if "a2a" not in existing_protocols:
recommendations.append({
"protocol": "a2a",
"priority": 3,
"reason": "Secondary -- covers autonomous agent fleets",
"effort_days": 4,
"endpoint": "/.well-known/agent.json",
})
elif buyer_profile in ("autonomous_fleets", "enterprise_agents"):
if "a2a" not in existing_protocols:
recommendations.append({
"protocol": "a2a",
"priority": 2,
"reason": "Autonomous fleets use A2A for task delegation",
"effort_days": 4,
"endpoint": "/.well-known/agent.json",
})
if "mcp" not in existing_protocols:
recommendations.append({
"protocol": "mcp",
"priority": 3,
"reason": "Secondary -- covers LLM-based tool calling",
"effort_days": 3,
"endpoint": "/mcp/tools",
})
# ACP always comes after execution layer
if needs_payment and "acp" not in existing_protocols:
recommendations.append({
"protocol": "acp",
"priority": 4,
"reason": "Payment layer -- implement after discovery and execution",
"effort_days": 5,
"endpoint": "/acp/checkout",
})
return sorted(recommendations, key=lambda r: r["priority"])
# Example: SaaS API selling to LLM-powered agents
plan = select_protocols(
service_type="api_service",
buyer_profile="llm_agents",
needs_payment=True,
existing_protocols=[],
)
for step in plan:
print(f"Priority {step['priority']}: {step['protocol'].upper()} "
f"({step['effort_days']} days) -- {step['reason']}")
Registering Protocol Support on GreenHelix
Once you have implemented protocol endpoints, register them on the marketplace so agents know which protocols you support:
# Register your service with protocol metadata
result = client.execute("register_service", {
"agent_id": "agent-dataenrich-prod",
"service_name": "DataEnrich Pro",
"description": "Real-time company data enrichment API",
"category": "data-enrichment",
"tags": ["enrichment", "company-data", "api"],
"pricing": {
"model": "pay_per_call",
"base_price": "0.005",
"currency": "USD",
},
"protocols": ["ucp", "mcp", "a2a"],
"endpoints": {
"ucp": "https://dataenrich.example.com/.well-known/ucp",
"mcp": "https://dataenrich.example.com/mcp/tools",
"a2a": "https://dataenrich.example.com/.well-known/agent.json",
},
})
print(f"Service registered: {result}")
Agents searching the marketplace can then filter by protocol:
# Find services that support A2A
a2a_services = client.search_services(
query="data enrichment",
filters={"protocols": ["a2a"]},
)
Key Takeaways
- Four protocols form a stack: UCP (discovery), MCP (tool execution), A2A (task delegation), ACP (payment).
- UCP is always implemented first. Without discovery, no other protocol matters.
- MCP for LLM-powered agents, A2A for autonomous agent fleets. Most services should implement both.
- ACP handles payment and is always implemented last in the chain.
- Register protocol endpoints on GreenHelix via
register_serviceso agents can filter by supported protocol.- See P21 (Agent-Ready Commerce) Chapter 3 for detailed UCP/ACP/x402 payment rail comparison.
Chapter 4: Building .well-known Discovery Endpoints
The Discovery Endpoint Pattern
The .well-known URI pattern (RFC 8615) provides a standardized location for machine-readable metadata. Agents crawling for services check these paths before attempting any other discovery method. If your service is at https://api.example.com, agents will look for:
https://api.example.com/.well-known/ucp-- UCP service profilehttps://api.example.com/.well-known/agent.json-- A2A agent cardhttps://api.example.com/.well-known/ai-plugin.json-- OpenAI/ChatGPT plugin manifesthttps://api.example.com/.well-known/openapi.yaml-- OpenAPI specification
Missing any of these endpoints means missing agents that use that specific discovery method. The cost of serving static JSON at four paths is trivial. The cost of not serving it is invisibility to entire agent ecosystems.
UCP Profile: The Complete Service Advertisement
The UCP profile is the most comprehensive discovery document. It combines capability advertisement, pricing, payment methods, SLA terms, and API documentation references into a single JSON document.
import json
from datetime import datetime, timezone
def build_ucp_profile(
service_name: str,
service_description: str,
provider_agent_id: str,
capabilities: list[dict],
pricing_tiers: list[dict],
payment_methods: list[str],
sla: dict,
api_spec_url: str,
trust_score: float | None = None,
) -> dict:
"""Build a UCP profile document for /.well-known/ucp."""
profile = {
"ucp_version": "1.0",
"service": {
"name": service_name,
"description": service_description,
"provider": {
"agent_id": provider_agent_id,
"trust_score": trust_score,
"verification_status": "verified" if trust_score and trust_score > 0.7 else "unverified",
},
"status": "active",
"last_updated": datetime.now(timezone.utc).isoformat(),
},
"capabilities": capabilities,
"pricing": {
"tiers": pricing_tiers,
"currency": "USD",
"billing_models": list({t.get("billing_model", "pay_per_call") for t in pricing_tiers}),
},
"payment_methods": payment_methods,
"sla": sla,
"api": {
"specification": api_spec_url,
"format": "openapi-3.1",
"authentication": {
"type": "bearer",
"token_endpoint": None, # None for API-key auth
},
},
"discovery": {
"protocols": ["ucp", "mcp", "a2a"],
"mcp_endpoint": "/mcp/tools",
"a2a_agent_card": "/.well-known/agent.json",
},
}
return profile
# Build profile for our data enrichment service
ucp_profile = build_ucp_profile(
service_name="DataEnrich Pro",
service_description="Real-time company data enrichment with 95% match rate across 200M+ companies",
provider_agent_id="agent-dataenrich-prod",
capabilities=[
{
"name": "company_lookup",
"description": "Enrich company data from domain, name, or LinkedIn URL",
"input_schema": {"domain": "string", "company_name": "string?"},
"output_schema": {"company": "CompanyProfile"},
"latency_p99_ms": 200,
},
{
"name": "contact_enrichment",
"description": "Enrich contact details from email or name + company",
"input_schema": {"email": "string?", "name": "string?", "company": "string?"},
"output_schema": {"contact": "ContactProfile"},
"latency_p99_ms": 350,
},
],
pricing_tiers=[
{
"name": "starter",
"cost_per_call": "0.005",
"monthly_cap": "100.00",
"billing_model": "pay_per_call",
},
{
"name": "growth",
"cost_per_call": "0.003",
"monthly_cap": "500.00",
"billing_model": "pay_per_call",
"volume_discounts": {"10000": "0.002", "100000": "0.001"},
},
],
payment_methods=["greenhelix_escrow", "stripe", "x402_usdc"],
sla={
"uptime_guarantee": 99.95,
"latency_p99_ms": 200,
"support_response_hours": 4,
"data_retention_days": 30,
},
api_spec_url="https://dataenrich.example.com/.well-known/openapi.yaml",
trust_score=0.92,
)
print(json.dumps(ucp_profile, indent=2))
MCP Tool Manifest
The MCP tool manifest describes each tool's input and output schemas so LLMs can discover and call them:
def build_mcp_manifest(capabilities: list[dict]) -> dict:
"""Build an MCP tool manifest from service capabilities."""
tools = []
for cap in capabilities:
tool = {
"name": cap["name"],
"description": cap["description"],
"inputSchema": {
"type": "object",
"properties": {
…(truncated)