UCP standardises how AI agents discover merchant capabilities, initiate checkout sessions,
and receive order updates. AGP is the governance layer that sits above it — ensuring
every agent calling POST /checkout-sessions has the authority to do so,
has been policy-checked, and leaves an immutable audit trail.
UCP handles the what of agentic commerce — what a merchant supports, what a platform can do, what a checkout session contains. AGP handles the who authorised it — which agent, under what delegated authority, within what spend constraints, cleared by which policy, approved by which human (if required).
Neither protocol replaces the other. A UCP checkout session without AGP governance is an agent acting without provenance. AGP governance without UCP is a policy engine with no commerce semantics. Together they form a complete, auditable agentic commerce stack.
| UCP concept | AGP equivalent |
|---|---|
| Platform profile | AGP Skill Manifest — declares what the agent is capable of and under what governance constraints it operates. |
| Capability intersection | AGP Capability Token — proof of delegated authority scoped to specific permitted actions and spend limits. Dynamic, not just declared. |
| Checkout session | AGP Commerce Session + Action Envelope — the session is the intent; the envelope is the governance gate before the session is created. |
| Idempotency key | AGP Action Envelope ID — serves dual purpose: idempotency guard and governance receipt. |
| Order lifecycle webhook | AGP Event Ledger — every state transition logged immutably; full replay available. |
| Signals (fraud/risk context) | AGP Attested Context — trust classification, taint flags, jurisdiction, evidence bundle. |
Before calling any UCP endpoint that initiates spend, the agent runs the AGP pipeline
to obtain a signed action envelope. The envelope ID is then attached as
X-AGP-Action-ID alongside the standard UCP-Agent header.
pip install agp-sdk
import httpx from agp import AGPClient agp = AGPClient("https://your-agp-server", client_id="shopping-agent", client_secret="...") # Step 1: Run the AGP pipeline before touching UCP with agp.task_session( principal_id="shopping-agent", requested_outcome="Purchase Sony WH-1000XM5 headphones from merchant", risk_tier="medium", ) as session: session.bind( sponsoring_entity="consumer-platform", accountable_owner="platform@example.com", jurisdiction="EU", ) session.issue_capability( subject_agent="shopping-agent", issuer="consumer-platform", principal_id="shopping-agent", permitted_actions=["dev.ucp.shopping.checkout"], constraints={ "max_amount_usd": 500, # enforced by AGP gate "categories": ["electronics"], }, ) session.decide( agent_id="shopping-agent", selected_action="dev.ucp.shopping.checkout", rationale="User requested headphones, item verified in stock, price $349 within limit", uncertainty_score=0.08, ) session.evaluate(verdict="allow") receipt = session.execute( agent_id="shopping-agent", tool_id="dev.ucp.shopping.checkout", operation={"merchant": "merchant.example.com", "amount_usd": 349}, capability_token_ref=session.capability_token.capability_id, ) action_id = receipt.action_id # Step 2: Call UCP with both headers response = httpx.post( "https://merchant.example.com/checkout-sessions", json={ "line_items": [{"id": "sony-wh1000xm5", "quantity": 1, "price": 349}], "buyer": {"name": "...", "email": "..."}, "currency": "USD", }, headers={ "UCP-Agent": 'profile="https://platform.example.com/.well-known/ucp-platform"', "X-AGP-Action-ID": action_id, # AGP governance proof "Idempotency-Key": receipt.action_id, }, ) # 201 Created — checkout session open, action logged to AGP ledger
action_id as both the X-AGP-Action-ID governance header and the UCP Idempotency-Key. If the agent retries, the AGP server returns the same envelope (idempotent) and the merchant sees the same key — no duplicate checkout sessions, no duplicate governance records.
Merchants implementing UCP can require AGP governance on inbound agent requests.
Verify the X-AGP-Action-ID header before processing any checkout session
from an AI agent. Human checkout flows (no AGP header) are handled normally.
import httpx from fastapi import FastAPI, Header, HTTPException, Request app = FastAPI() AGP_SERVER = "https://your-agp-server" AGP_TOKEN = "..." # merchant's own AGP service token async def verify_agp_envelope(action_id: str, expected_tool: str, max_amount: float) -> dict: """Verify the agent's AGP action envelope before creating a checkout session.""" async with httpx.AsyncClient() as client: r = await client.get( f"{AGP_SERVER}/agp/action-envelopes/{action_id}", headers={"Authorization": f"Bearer {AGP_TOKEN}"}, ) if r.status_code != 200: raise HTTPException(403, detail="AGP envelope invalid or revoked") envelope = r.json() # Verify the envelope is scoped to the right UCP capability if envelope["tool_id"] != expected_tool: raise HTTPException(403, detail=f"Envelope not scoped for {expected_tool}") # Verify the authorised amount covers this checkout authorised = envelope.get("operation", {}).get("amount_usd", 0) if authorised < max_amount: raise HTTPException(403, detail="Checkout amount exceeds AGP-authorised limit") return envelope @app.post("/checkout-sessions", status_code=201) async def create_checkout_session( request: Request, body: dict, ucp_agent: str | None = Header(None, alias="UCP-Agent"), agp_action_id: str | None = Header(None, alias="X-AGP-Action-ID"), ): total = sum(item["price"] * item["quantity"] for item in body["line_items"]) if ucp_agent and agp_action_id: # AI agent request — verify AGP governance before proceeding envelope = await verify_agp_envelope( action_id=agp_action_id, expected_tool="dev.ucp.shopping.checkout", max_amount=total, ) # Envelope verified — governance is on record, safe to proceed # Standard UCP checkout session creation session_id = _create_checkout_session(body) return {"id": session_id, "status": "ready_for_complete", ...}
For large transactions or regulated categories, set the AGP task to risk_tier: "high"
and the policy verdict to require_approval. The checkout session is only initiated
after a human approves — the agent holds the action envelope ID and submits the UCP call
once approval is recorded.
# High-spend checkout: policy requires human approval before UCP call with agp.task_session( principal_id="shopping-agent", requested_outcome="Purchase enterprise software licence — $4,800", risk_tier="high", ) as session: session.bind(...).issue_capability( ..., constraints={"max_amount_usd": 5000, "categories": ["software"]} ) session.decide(...) session.evaluate(verdict="require_approval") # → task status: APPROVAL_PENDING # Agent notifies user: "£4,800 purchase awaiting your approval. Task: {session.task_id}" # After human approves via your approval UI: session.approve(approver_id="user@example.com") receipt = session.execute(...) # now cleared # Now safe to call UCP httpx.post("https://merchant.example.com/checkout-sessions", ..., headers={"X-AGP-Action-ID": receipt.action_id, ...})
AGP includes a commerce-session.json schema that links an AGP task to a
UCP checkout session — giving you a single object that carries both the governance record
and the commerce context for any downstream system that needs to reason about both.
// AGP commerce session — links task governance to UCP checkout { "object_type": "commerce_session", "task_id": "tsk_01HX...", "action_envelope_id": "act_01HA...", "ucp_session_id": "chk_123456789", // UCP checkout session ID "merchant": "merchant.example.com", "currency": "USD", "total_amount": 349.00, "status": "checkout_initiated" }
max_amount_usd, categories, merchants — are validated server-side before the envelope is issued. An agent cannot initiate a $5,000 checkout on a token capped at $500, even if the UCP merchant would accept the request.