Testing & Development Guide

February 17, 2026 · View on GitHub

TL;DR

  • Start backend (port 10999), then frontend (port 3000)
  • Happy path: search → add to cart → checkout → pay
  • Debug with verbose logging and endpoint verification

Setup Flow

Setup and Test Flow

Figure 1: Setup and test flow — Start Backend (port 10999), then Frontend (port 3000), verify endpoints, then proceed to testing: Search Products → Add to Cart → Complete Payment.

Quick Start

1. Start Backend

cd a2a/business_agent
uv sync
cp env.example .env          # Add GOOGLE_API_KEY
uv run business_agent        # Starts on :10999

2. Start Frontend

cd a2a/chat-client
npm install
npm run dev                  # Starts on :3000

3. Verify Endpoints

# Agent card (A2A discovery)
curl -s http://localhost:10999/.well-known/agent-card.json | jq .

# UCP profile (merchant capabilities)
curl -s http://localhost:10999/.well-known/ucp | jq .

# Client profile (client capabilities)
curl -s http://localhost:3000/profile/agent_profile.json | jq .

Testing Workflows

Happy Path (Complete Purchase)

  1. Open http://localhost:3000
  2. Type "show me cookies"
  3. Click "Add to Checkout" on a product
  4. Enter email when prompted: test@example.com
  5. Enter address: 123 Main St, San Francisco, CA 94105
  6. Click "Complete Payment"
  7. Select a payment method
  8. Click "Confirm Purchase"
  9. Verify order confirmation appears with order ID and permalink

Expected State Transitions:

  • After step 3: status: "incomplete"
  • After step 5: status: "incomplete" (ready for payment start)
  • After step 6: status: "ready_for_complete"
  • After step 8: status: "completed"

Error Scenarios

ScenarioHow to TestExpected Behavior
No checkout existsCall get_checkout without adding items"Checkout not created" error
Missing addressSkip address, call start_paymentAgent prompts for address
Missing emailSkip email, call start_paymentAgent prompts for email
Invalid productadd_to_checkout("INVALID-ID", 1)"Product not found" error
Quantity updateAdd item, then update_checkout with qty=0Item removed from checkout

Debugging Guide

Debug Strategy

When something breaks, follow this systematic approach:

Debug Strategy Decision Tree

Figure 2: Debug strategy decision tree — Systematically check backend, frontend, browser console, UCP-Agent header, and capability negotiation to isolate issues.

Enable Verbose Logging

# main.py - add at top
import logging
logging.basicConfig(level=logging.DEBUG)

Inspect Tool State

# In any tool - add temporarily for debugging
def my_tool(tool_context: ToolContext, param: str) -> dict:
    print("=== DEBUG ===")
    print("State keys:", list(tool_context.state.keys()))
    print("Checkout ID:", tool_context.state.get(ADK_USER_CHECKOUT_ID))
    print("UCP Metadata:", tool_context.state.get(ADK_UCP_METADATA_STATE))
    # ... rest of tool

Check A2A Messages

// App.tsx - in handleSendMessage, add before fetch
console.log("Request:", JSON.stringify(request, null, 2));

// After response
console.log("Response:", JSON.stringify(data, null, 2));

Test A2A Directly (bypass UI)

curl -X POST http://localhost:10999/ \
  -H "Content-Type: application/json" \
  -H "UCP-Agent: profile=\"http://localhost:3000/profile/agent_profile.json\"" \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "message/send",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"type": "text", "text": "show me products"}]
      }
    }
  }'

Common Issues

IssueLikely CauseFix
Server won't startMissing GOOGLE_API_KEYAdd key to .env file
"Profile fetch failed"Frontend not runningStart chat-client on :3000
"Version unsupported"Profile version mismatchAlign version in both ucp.json and agent_profile.json
"Checkout not found"Session expired or no itemsCall add_to_checkout first
UI not updatingMissing contextIdCheck contextId in response, ensure it's passed to next request
"Missing UCP metadata"Header not sentVerify UCP-Agent header in request
Payment methods emptyCredentialProviderProxy issueCheck browser console for mock provider errors

Troubleshooting Guide

Setup Failures

Error MessageCauseSolution
Address already in use :10999Agent already running or port in usekill $(lsof -t -i:10999) or use different port
GOOGLE_API_KEY not foundMissing or empty .env fileCreate .env from env.example, add your key
No module named 'business_agent'Not in virtualenv or deps not installedRun uv sync in business_agent/ directory
npm ERR! ENOENT package.jsonWrong directorycd chat-client before running npm install
Connection refused :10999Backend not runningStart backend first with uv run business_agent

Runtime Errors

SymptomDebug Steps
"Checkout not found"1. Check contextId is passed from previous response
2. Verify session hasn't expired
3. Add an item first with add_to_checkout
Products not returning1. Enable DEBUG logging
2. Check if search_shopping_catalog tool is being called
3. Verify products.json exists and is valid JSON
Payment flow hangs1. Check browser console for CredentialProviderProxy errors
2. Verify mock payment methods are returned
3. Check start_payment was called successfully
UI not updating after action1. Verify contextId threading in App.tsx
2. Check response structure in browser DevTools
3. Look for React state update issues

Step-by-Step Diagnosis

Problem: Agent returns generic errors

# Step 1: Enable verbose logging
# Edit main.py, add at top:
import logging
logging.basicConfig(level=logging.DEBUG)

# Step 2: Restart agent and check logs
uv run business_agent

# Step 3: Look for specific error messages in output

Problem: Capability negotiation failing

# Step 1: Verify both profiles are accessible
curl -s http://localhost:10999/.well-known/ucp | jq .version
curl -s http://localhost:3000/profile/agent_profile.json | jq .version

# Step 2: Ensure versions match
# Both should return the same version string

# Step 3: Check UCP-Agent header is being sent
# In browser DevTools > Network, look for requests to localhost:10999
# Verify UCP-Agent header contains profile URL

Problem: Tools not being called by LLM

# Check 1: Tool is registered
# In agent.py, verify tool is in tools=[] list

# Check 2: Tool docstring is clear
# LLM needs clear description to know when to use the tool
@tool
def my_tool(tool_context: ToolContext, query: str) -> dict:
    """Search for products matching the query.

    Args:
        query: Product name or description to search for
    """
    # ...

# Check 3: Add debug output to confirm tool is called
def my_tool(tool_context: ToolContext, query: str) -> dict:
    print(f"=== TOOL CALLED: my_tool({query}) ===")
    # ...

Browser Debugging

Check Network Requests:

  1. Open DevTools (F12) → Network tab
  2. Filter by "localhost:10999"
  3. Click on request → Headers tab
  4. Verify UCP-Agent header is present
  5. Click Response tab to see A2A response

Check Console Errors:

  1. Open DevTools → Console tab
  2. Look for red error messages
  3. Common issues:
    • CORS errors → Backend not running
    • JSON parse errors → Malformed response
    • TypeError → Missing data in response

Reference

Ports & URLs

ServicePortEndpoints
Backend10999/ (A2A), /.well-known/agent-card.json, /.well-known/ucp
Frontend3000/, /profile/agent_profile.json

Environment Variables

VariableRequiredPurpose
GOOGLE_API_KEYYesGemini API access for LLM

Key Files for Debugging

SymptomCheck This FileWhat to Look For
Tool not calledagent.pyTool in tools=[] list
State issuesconstants.pyState key names
Checkout errorsstore.pyState machine logic
UCP negotiationucp_profile_resolver.pyVersion/capability matching
Frontend errorsApp.tsxRequest/response handling