Cymbal Retail Agent - AI Assistant Context

April 17, 2026 · View on GitHub

Purpose: This file provides context for AI coding assistants (Claude Code, Gemini CLI, Cursor, Codex, etc.) to understand and extend the Cymbal Retail Agent codebase.

AI-powered shopping agent built with Google ADK, demonstrating UCP commerce integration via A2A protocol.

Tech Stack

LayerTechnology
Agent FrameworkGoogle ADK (Agent Development Kit)
LLMGemini 3.0 Flash
Commerce ProtocolUCP (Universal Commerce Protocol)
Agent ProtocolA2A (Agent-to-Agent) JSON-RPC 2.0
BackendPython 3.13, Uvicorn, Starlette, Pydantic
FrontendReact 19, TypeScript, Vite, Tailwind

Directory Structure

a2a/
├── business_agent/src/business_agent/
│   ├── agent.py              # ADK agent with 8 shopping tools
│   ├── agent_executor.py     # A2A ↔ ADK bridge
│   ├── store.py              # Mock retail store (replace for production)
│   ├── main.py               # Uvicorn server entry point
│   ├── ucp_profile_resolver.py # UCP capability negotiation
│   ├── payment_processor.py  # Mock payment processing
│   ├── constants.py          # State keys and extension URLs
│   ├── helpers/type_generator.py # Dynamic Pydantic checkout types
│   ├── a2a_extensions/       # A2A extension implementations
│   └── data/                 # JSON configs and product images
├── chat-client/
│   ├── App.tsx               # React main component, A2A messaging
│   ├── components/           # ProductCard, Checkout, PaymentMethodSelector
│   ├── types.ts              # TypeScript interfaces
│   └── profile/agent_profile.json # Client UCP capabilities
├── docs/                     # Detailed documentation (see below)
├── DEVELOPER_GUIDE.md        # Developer overview and reading roadmap
├── README.md                 # Quick start and demo
└── SKILLS.md                 # This file (AI assistant context)

Core Concepts

TermDefinition
A2AAgent-to-Agent Protocol - How agents discover and communicate
UCPUniversal Commerce Protocol - Standard commerce data types
ADKAgent Development Kit - Google's framework for building agents
ToolPython function the LLM can invoke (has ToolContext parameter)
CapabilityFeature set the agent supports (e.g., dev.ucp.shopping.checkout)

State Keys (constants.py)

# Session state keys - naming conventions:
# - user:     User-scoped data (persists across turns)
# - __xxx__   System/internal data (managed by framework)
# - temp:     Temporary data (cleared after use)

ADK_USER_CHECKOUT_ID = "user:checkout_id"           # Current checkout session ID
ADK_PAYMENT_STATE = "__payment_data__"               # PaymentInstrument from client
ADK_UCP_METADATA_STATE = "__ucp_metadata__"          # Negotiated UCP capabilities
ADK_EXTENSIONS_STATE_KEY = "__session_extensions__"  # Active A2A extensions
ADK_LATEST_TOOL_RESULT = "temp:LATEST_TOOL_RESULT"   # Last tool result for output

# Response data keys (used in tool returns)
UCP_CHECKOUT_KEY = "a2a.ucp.checkout"                # Checkout data in response
UCP_PAYMENT_DATA_KEY = "a2a.ucp.checkout.payment_data"
UCP_RISK_SIGNALS_KEY = "a2a.ucp.checkout.risk_signals"

# Extension constants
A2A_UCP_EXTENSION_URL = "https://ucp.dev/2026-01-23/specification/overview?v=2026-01-23"
UCP_AGENT_HEADER = "UCP-Agent"                       # HTTP header for client profile

Agent Tools (agent.py)

ToolPurposeReturns
search_shopping_catalog(query)Search products by keywordProductResults
add_to_checkout(product_id, quantity)Add item to checkoutCheckout
remove_from_checkout(product_id)Remove item from checkoutCheckout
update_checkout(product_id, quantity)Update item quantityCheckout
get_checkout()Get current checkout stateCheckout
update_customer_details(email, address...)Set buyer and delivery infoCheckout
start_payment()Validate checkout, set ready statusCheckout
complete_checkout()Process payment, create orderCheckout + OrderConfirmation

Checkout State Machine

incomplete → ready_for_complete → completed
     ↑              ↑                 ↑
  add item    start_payment    complete_checkout
StateMeaningTransition
incompleteMissing buyer email or fulfillment addressAdd required info
ready_for_completeAll info collected, awaiting paymentCall complete_checkout()
completedOrder created with OrderConfirmationTerminal state

UCP Capabilities

dev.ucp.shopping.checkout      # Base checkout capability
dev.ucp.shopping.fulfillment   # Shipping (extends checkout)
dev.ucp.shopping.discount      # Promotional codes (extends checkout)
dev.ucp.shopping.buyer_consent # Consent management (extends checkout)

Common Tasks

Add a New Tool

# In agent.py
def my_tool(tool_context: ToolContext, param: str) -> dict:
    """Tool docstring (visible to LLM for reasoning)."""
    # 1. Access state
    checkout_id = tool_context.state.get(ADK_USER_CHECKOUT_ID)
    metadata = tool_context.state.get(ADK_UCP_METADATA_STATE)

    # 2. Validate
    if not metadata:
        return {"message": "Missing UCP metadata", "status": "error"}

    # 3. Business logic
    result = store.some_method(...)

    # 4. Update state if needed
    tool_context.state[ADK_USER_CHECKOUT_ID] = result.id

    # 5. Return UCP-formatted response
    return {UCP_CHECKOUT_KEY: result.model_dump(mode="json")}

# Add to root_agent tools list
root_agent = Agent(..., tools=[..., my_tool])

Add a Product

Edit data/products.json:

{
  "productID": "NEW-001",
  "name": "New Product",
  "image": ["http://localhost:10999/images/new.jpg"],
  "brand": { "name": "Brand" },
  "offers": {
    "price": "9.99",
    "priceCurrency": "USD",
    "availability": "InStock"
  }
}

Modify Checkout Flow

Key methods in store.py:

  • add_to_checkout() - Creates checkout, adds items
  • _recalculate_checkout() - Updates totals, tax, shipping
  • start_payment() - Validates readiness, transitions state
  • place_order() - Creates OrderConfirmation

Key Files for Changes

ChangeFile
Add/modify toolsagent.py
Checkout logicstore.py
A2A/ADK bridgingagent_executor.py
UCP profilesdata/ucp.json, chat-client/profile/agent_profile.json
Productsdata/products.json
Frontend componentschat-client/components/
Frontend typeschat-client/types.ts

Commands

# Start backend
cd a2a/business_agent && uv sync && uv run business_agent

# Start frontend
cd a2a/chat-client && npm install && npm run dev

# Verify endpoints
curl http://localhost:10999/.well-known/agent-card.json
curl http://localhost:10999/.well-known/ucp

Response Format Pattern

# For UCP data (checkout, products)
return {
    UCP_CHECKOUT_KEY: checkout.model_dump(mode="json"),
    "status": "success",
}

# For errors
return {"message": "Error description", "status": "error"}

Production Considerations

WARNING: This sample is NOT production-ready. See docs/08-production-notes.md.

ComponentCurrentProduction
Session StorageIn-memoryRedis
Checkout StoragePython dictPostgreSQL
AuthenticationNoneJWT/API key
SecretsPlaintext .envSecret Manager

Documentation

GuideTopics
GlossaryKey terms, acronyms, external resources
ArchitectureSystem components, data flow, mock store
ADK AgentTools, callbacks, prompt engineering
UCP IntegrationCapabilities, profiles, negotiation
Commerce FlowsCheckout lifecycle, payment flow
FrontendReact components, A2A client
ExtendingAdd tools, products, capabilities
Testing GuideTesting, debugging, troubleshooting
Production NotesSecurity gaps, deployment checklist

External Resources

ResourceURL
ADK Docshttps://google.github.io/adk-docs/
A2A Protocolhttps://a2a-protocol.org/latest/
UCP Specificationhttps://ucp.dev/2026-01-23/specification/overview/
Gemini APIhttps://ai.google.dev/gemini-api/docs

Dependencies

Backend (pyproject.toml):

  • google-adk[a2a]>=1.22.0
  • ucp-sdk==0.1.0
  • pydantic>=2.12.3

Frontend (package.json):

  • react ^19.2.0
  • vite ^6.2.0