30 Days of AI Agents Buying From a Real WooCommerce Store. Here's What the Data Says.
Engineering the Agentic Checkout: Protocol Compliance, Observability, and Production Metrics
Current Situation Analysis
The gap between AI agent discovery and transaction completion has long been treated as an unsolved engineering problem. Industry discourse frequently labels this phase the "messy middle," emphasizing trust verification, liability attribution, and state management between intent formation and payment execution. Most development efforts have focused on improving LLM reasoning capabilities or building proprietary agent frameworks, assuming that transactional friction requires heavy custom integration per merchant.
This assumption overlooks a critical architectural reality: agentic commerce does not fail because of model limitations. It fails because of protocol non-compliance, missing idempotency guarantees, and inadequate observability. When agents interact with e-commerce systems, they do not browse. They execute deterministic workflows against published capability manifests. The friction emerges when merchant systems lack explicit contract definitions, fail to handle stateless intent payloads, or silently reject malformed payment instrument references.
Production data from a live WooCommerce deployment (40,000 SKUs, real tax calculations, active wallet debits) over a 30-day window demonstrates that the middle is not inherently messy. It becomes manageable when three conditions are met: explicit capability discovery via standardized manifests, strict schema validation for checkout state transitions, and mandatory audit logging for every transactional step. The deployment recorded β¬1,269 in AI-driven revenue across 39 completed orders, with an average order value of β¬32.54. Session conversion reached 76.5%, and the average API call count per session settled at 1.5, significantly below the protocol benchmark of 4. These metrics indicate that agents are not failing; they are operating with cached intent, skipping redundant discovery phases, and executing streamlined checkout flows when the underlying contract is clean.
WOW Moment: Key Findings
The most counterintuitive finding from the production run is the inverse relationship between call volume and transaction efficiency. Traditional e-commerce analytics optimize for engagement depth. Agentic commerce optimizes for intent precision.
| Approach | Avg Calls/Session | Session Conversion | Revenue/Session | Integration Overhead |
|---|---|---|---|---|
| Human Checkout (Mobile) | 12-18 | 2.0% - 4.0% | β¬0.08 - β¬0.16 | Standard UI/UX |
| Spec Benchmark (UCP) | 4.0 | ~60% (estimated) | β¬15.00 - β¬20.00 | Manual endpoint mapping |
| Production Observed | 1.5 | 76.5% | β¬32.54 | Zero-touch manifest parsing |
The 1.5 average call count does not indicate skipped validation or incomplete state transitions. It reflects intent caching. Agents read the capability manifest (/.well-known/ucp or equivalent) during their initial session, parse the operating instructions, and store the contract locally. Subsequent visits bypass discovery entirely, submitting pre-validated checkout payloads directly to the transaction endpoint. This behavior transforms the checkout flow from a multi-step negotiation into a single-state execution.
The 76.5% conversion rate further clarifies the operational reality. Human conversion metrics measure browsing-to-purchase friction. Agent conversion measures protocol compliance. When an agent reaches the create_checkout phase on a well-implemented endpoint, the transaction completes successfully 76.5% of the time. The remaining sessions are primarily discovery or validation probes that never intended to finalize a purchase. Stripping out non-transactional sessions pushes the completion rate above 85%.
This finding matters because it shifts the engineering focus from building conversational fallbacks to enforcing strict contract compliance. Agents do not need chat interfaces. They need predictable state machines, explicit error codes, and idempotent execution paths.
Core Solution
Building a production-ready agentic checkout layer requires treating AI agents as first-class API consumers. The architecture must prioritize manifest discovery, intent validation, idempotent state transitions, and immutable audit trails. Below is a TypeScript implementation pattern that abstracts the WooCommerce UCP flow into a reusable commerce adapter.
Architecture Decisions
- Manifest-First Discovery: Agents must resolve capabilities before attempting transactions. The adapter publishes a structured manifest containing supported endpoints, required headers, payment instrument formats, and idempotency rules.
- Intent Scoping: Checkout requests must declare explicit intent (
browse,validate,purchase). This prevents accidental state mutations and enables precise audit filtering. - Strict Payment Instrument Validation: Wallet references must distinguish between handler names (e.g.,
com.terrawallet.store_credit) and instrument IDs (e.g.,terrawallet-1). The adapter enforces type-safe resolution before payment execution. - Idempotency Enforcement: Every checkout request requires a deterministic key. The adapter normalizes payload structure to prevent stringified JSON serialization errors.
- Observability by Default: Every state transition logs to an append-only audit stream. Failed attempts capture request context, validation errors, and recovery paths.
Implementation
import { z } from 'zod';
// Contract definitions
const PaymentInstrumentSchema = z.object({
handler: z.string().min(1),
instrumentId: z.string().min(1),
scope: z.enum(['purchase', 'refund', 'validate']).default('purchase')
});
const CheckoutPayloadSchema = z.object({
sessionId: z.string().uuid(),
intent: z.enum(['discovery', 'validation', 'purchase']),
cartItems: z.array(z.object({
sku: z.string(),
quantity: z.number().int().positive(),
priceCents: z.number().int().nonnegative()
})),
paymentInstrument: PaymentInstrumentSchema,
idempotencyKey: z.string().min(1)
});
type CheckoutPayload = z.infer<typeof CheckoutPayloadSchema>;
// Core adapter
class CommerceProtocolAdapter {
private auditLog: Array<{ timestamp: string; event: string; context: unknown }> = [];
private idempotencyCache: Map<string, boolean> = new Map();
publishManifest(): Record<string, unknown> {
return {
protocol: 'ucp/v1',
endpoints: {
discovery: '/.well-known/ucp',
checkout: '/api/v1/checkout',
payment: '/api/v1/payments'
},
requirements: {
idempotencyHeader: 'X-Idempotency-Key',
authScheme: 'Bearer',
supportedInstruments: ['wallet', 'card', 'store_credit']
},
intentScopes: ['discovery', 'validation', 'purchase']
};
}
async handleAgentIntent(payload: unknown): Promise<{ status: string; transactionId?: string; error?: string }> {
const validation = CheckoutPayloadSchema.safeParse(payload);
if (!validation.success) {
this.logEvent('validation_failed', { errors: validation.error.format() });
return { status: 'rejected', error: 'Invalid payload schema' };
}
const data = validation.data;
// Idempotency enforcement
if (this.idempotencyCache.has(data.idempotencyKey)) {
this.logEvent('idempotent_hit', { key: data.idempotencyKey });
return { status: 'duplicate', error: 'Request already processed' };
}
if (data.intent === 'discovery' || data.intent === 'validation') {
this.logEvent('intent_processed', { intent: data.intent, sessionId: data.sessionId });
return { status: 'acknowledged' };
}
// Payment instrument resolution
const resolvedInstrument = await this.resolvePaymentInstrument(data.paymentInstrument);
if (!resolvedInstrument) {
this.logEvent('payment_rejected', { instrument: data.paymentInstrument });
return { status: 'failed', error: 'Invalid payment instrument reference' };
}
// Execute checkout
const transactionId = await this.executeCheckout(data, resolvedInstrument);
this.idempotencyCache.set(data.idempotencyKey, true);
this.logEvent('checkout_completed', { transactionId, sessionId: data.sessionId });
return { status: 'completed', transactionId };
}
private async resolvePaymentInstrument(instrument: z.infer<typeof PaymentInstrumentSchema>): Promise<string | null> {
// Simulate handler lookup vs instrument ID validation
const validHandlers = ['com.terrawallet.store_credit', 'com.stripe.card', 'com.paypal.wallet'];
if (!validHandlers.includes(instrument.handler)) return null;
return `${instrument.handler}:${instrument.instrumentId}`;
}
private async executeCheckout(payload: CheckoutPayload, instrumentRef: string): Promise<string> {
const totalCents = payload.cartItems.reduce((sum, item) => sum + (item.priceCents * item.quantity), 0);
const transactionId = `txn_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
// Simulate payment gateway call
console.log(`Processing ${totalCents} cents via ${instrumentRef} for ${transactionId}`);
return transactionId;
}
private logEvent(event: string, context: unknown): void {
this.auditLog.push({ timestamp: new Date().toISOString(), event, context });
}
getAuditTrail(): typeof this.auditLog {
return [...this.auditLog];
}
}
Why This Architecture Works
- Schema-First Validation: Using Zod ensures that malformed payloads (like stringified JSON idempotency keys) are rejected before state mutation occurs.
- Intent Separation: Explicit intent scoping prevents discovery probes from triggering payment flows, reducing unnecessary gateway calls and audit noise.
- Idempotency Caching: The adapter tracks processed keys in memory. In production, this should be backed by Redis or a distributed cache to survive restarts.
- Instrument Resolution: Separating handler names from instrument IDs prevents silent lookup failures. The adapter validates both before proceeding.
- Append-Only Logging: Every decision point is recorded. This satisfies liability requirements and enables post-incident reconstruction without relying on external monitoring tools.
Pitfall Guide
1. Idempotency Key Serialization Mismatch
Explanation: Agents frequently serialize complex objects as JSON strings when the spec expects nested structures. This causes schema validation failures and duplicate transaction attempts.
Fix: Enforce strict type boundaries at the API gateway. Use middleware to deserialize incoming headers/payloads before routing to the checkout handler. Reject requests where typeof key === 'string' && key.startsWith('{').
2. Payment Instrument ID vs Handler Name Confusion
Explanation: Merchants often store wallet references using handler names (com.terrawallet.store_credit) while agents submit instrument IDs (terrawallet-1). A single lookup path fails silently when the formats diverge.
Fix: Implement a dual-resolution strategy. Validate the handler against an allowlist, then map the instrument ID to an internal ledger reference. Return explicit 400 errors with resolution hints instead of 401 or 500.
3. OAuth Token Lifecycle Blind Spots
Explanation: Merchant-side token revocation is rarely propagated to agents. Expired Bearer tokens trigger 401 responses without recovery instructions, causing agents to retry indefinitely or abandon sessions.
Fix: Add token validation on initial connection. Implement a 401 recovery header (WWW-Authenticate: Bearer error="expired_token") and auto-clear stale sessions. Require agents to refresh tokens before checkout submission.
4. Endpoint Path Divergence
Explanation: Probes or middleware sometimes override manifest endpoints. OAuth tokens stored against /api/mcp fail when MCP calls route to /wp-json/ucpready/v1/mcp. One path mismatch breaks the entire flow.
Fix: Publish absolute endpoint URLs in the manifest. Validate incoming request paths against the published contract. Reject mismatched routes with 404 and a Location header pointing to the correct endpoint.
5. Missing Intent Scoping & Audit Trails
Explanation: Treating all agent requests as checkout attempts generates false positives in revenue reporting and obscures discovery behavior. Without structured logs, liability attribution becomes impossible.
Fix: Require an intent field in every payload. Route discovery/validation requests to read-only handlers. Log every state transition with request context, validation results, and final status. Export logs to an immutable storage layer.
6. Over-Fetching Discovery Data
Explanation: Agents repeatedly request full catalog manifests instead of caching capability declarations. This increases latency, wastes bandwidth, and triggers rate limits.
Fix: Implement ETag and Cache-Control headers on manifest endpoints. Return 304 Not Modified when the contract hasn't changed. Document caching expectations in the manifest itself.
7. Silent Failure Modes in Payment Validation
Explanation: Payment gateways often return generic errors (insufficient_funds, invalid_instrument) without mapping them to agent-recoverable states. Agents interpret these as permanent failures and abandon sessions.
Fix: Normalize payment errors into a structured response schema. Include recoverable: true/false, next_action, and retry_after fields. Allow agents to adjust cart size or switch instruments before retrying.
Production Bundle
Action Checklist
- Publish a structured capability manifest at
/.well-known/ucpwith explicit endpoint URLs, auth requirements, and supported payment instruments. - Implement schema validation for all incoming checkout payloads. Reject malformed idempotency keys and mismatched instrument references before state mutation.
- Separate discovery, validation, and purchase intents. Route non-purchase requests to read-only handlers to prevent accidental transactions.
- Add OAuth token validation on connection. Return explicit
401recovery headers and auto-clear stale sessions. - Enforce idempotency using a distributed cache. Track processed keys and return deterministic responses for duplicate requests.
- Log every state transition to an append-only audit stream. Include request context, validation results, and final status for liability tracking.
- Normalize payment gateway errors into agent-recoverable formats. Include retry instructions and instrument-switching guidance.
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|---|---|---|
| High-volume agent traffic (>100 sessions/day) | Distributed idempotency cache + manifest ETags | Prevents duplicate processing and reduces bandwidth | Low (Redis/Cloudflare) |
| Multi-merchant marketplace | Centralized manifest registry + per-tenant instrument resolution | Ensures consistent contract enforcement across stores | Medium (Registry service + tenant routing) |
| Strict compliance requirements (GDPR/PCI) | Append-only audit logs + explicit intent scoping | Satisfies liability attribution and data minimization | Low (Log aggregation + schema validation) |
| Legacy e-commerce platform | Protocol adapter layer + endpoint path normalization | Bridges modern agent expectations with legacy routing | Medium (Adapter middleware + path mapping) |
| Autonomous purchasing without human confirmation | Mandatory audit trails + payment instrument allowlists | Prevents unauthorized transactions and enables post-incident review | Low (Logging + allowlist enforcement) |
Configuration Template
// commerce.config.ts
export const UCPManifest = {
protocol: 'ucp/v1',
endpoints: {
discovery: '/.well-known/ucp',
checkout: '/api/v1/checkout',
payments: '/api/v1/payments'
},
requirements: {
idempotencyHeader: 'X-Idempotency-Key',
authScheme: 'Bearer',
supportedInstruments: ['wallet', 'card', 'store_credit'],
maxCartItems: 50,
currency: 'EUR'
},
caching: {
manifestTTL: 3600,
etagEnabled: true,
intentScopes: ['discovery', 'validation', 'purchase']
},
observability: {
auditRetentionDays: 90,
logLevel: 'info',
exportFormat: 'jsonl'
}
};
// middleware/idempotency.ts
import { createHash } from 'crypto';
export function generateIdempotencyKey(payload: unknown): string {
const serialized = JSON.stringify(payload, Object.keys(payload as any).sort());
return createHash('sha256').update(serialized).digest('hex');
}
Quick Start Guide
- Publish the Manifest: Deploy the capability manifest to
/.well-known/ucp. Include endpoint URLs, auth requirements, supported payment instruments, and caching directives. - Implement Schema Validation: Add Zod or equivalent validation to your checkout endpoint. Reject payloads with malformed idempotency keys, missing intent fields, or invalid instrument references.
- Route by Intent: Separate discovery/validation requests from purchase requests. Return
200 OKwith capability summaries for non-purchase intents. Process purchases through the payment handler. - Enforce Idempotency: Cache processed idempotency keys in Redis or a distributed store. Return deterministic responses for duplicate requests to prevent double-charging.
- Enable Audit Logging: Log every state transition with request context, validation results, and final status. Export logs to immutable storage for liability tracking and post-incident analysis.
The agentic checkout layer is not a conversational interface. It is a state machine governed by explicit contracts, strict validation, and immutable observability. When those foundations are in place, the middle stops being messy and starts generating predictable revenue.
Mid-Year Sale β Unlock Full Article
Base plan from just $4.99/mo or $49/yr
Sign in to read the full article and unlock all tutorials.
Sign In / Register β Start Free Trial7-day free trial Β· Cancel anytime Β· 30-day money-back
