Build an Agentic Commerce Assistant
The Agentic Commerce Assistant is a complete reference application, not a chat wrapper around a product API. It retrieves through Samesake, revalidates commercial facts through Porulle, pauses before checkout through Kuralle, and sends only a tokenized payment method to Stripe.
Understand the substrates
Section titled “Understand the substrates”| Substrate | What it owns |
|---|---|
| Kuralle Core | Typed tools, policy, durable run state, approval/resume, replay, and traces |
| Pi Driver | Pi's provider-native model/tool loop behind Kuralle's runtime contract |
cf-agent | One Durable Object coordination atom per shopper session |
| Durable Object SQLite | Conversation-local messages, cart state, approval interrupt, and effect journal |
| PostgreSQL + pgvector | Shared Porulle records, Samesake indexes, and Node/Bun sessions |
| Samesake | Candidate generation, hybrid retrieval, filters, grounding, and constraint traces |
| Porulle | Current catalog entity, price, inventory, cart, order, and checkout truth |
| Stripe | Tokenized payment confirmation |
| AI Gateway | One governed route for OpenAI chat and embeddings |
| Queue + Workflow | Buffered catalog events and retryable multi-step indexing |
| Hyperdrive | Cloudflare-to-PostgreSQL connection pooling |
| Signed shopper identity | HTTP-only cookie, server-owned session namespace, and attributed approval actor |
This boundary is why @earendil-works/pi-agent-core fits without becoming the application framework. Pi runs the model/tool turn protocol. Kuralle still intercepts tool calls, applies policy, stores the resumable run, records the human decision, and guards effect replay. The flow would become unsafe if a direct Pi tool callback bypassed that Kuralle boundary.
Understand the design lineage
Section titled “Understand the design lineage”Uber Cart Assistant separates ambiguous cart planning and relevance judgments from deterministic retrieval, pricing, eligibility, quantity validation, constraints, and cart assembly. This example keeps the same probabilistic-versus-deterministic boundary, but extends it through approval and payment: Samesake retrieves candidates, Porulle revalidates every cart line and owns checkout, and Kuralle prevents the model from crossing the consequential-action boundary by itself.
Amazon Rufus demonstrates why shopping answers need retrieval from trusted catalog and Store API evidence rather than model memory. Shopify Sidekick shows the operational value of keeping tool responsibilities focused and evaluating agent changes against real task behavior. Here those lessons become typed tools, a narrow Porulle client, retrieval constraint traces, deterministic money handling, focused contract tests, and an end-to-end approval exercise.
Run the local path
Section titled “Run the local path”Clone and install Kuralle and Porulle:
git clone https://github.com/kuralle/kuralle-agents.gitgit clone https://github.com/asyncdotengineering/porulle.git
cd kuralle-agents && bun installcd ../porulle && bun installCreate a shared PostgreSQL database:
createdb kuralle_agentic_commercepsql kuralle_agentic_commerce -c 'CREATE EXTENSION IF NOT EXISTS vector'Configure and seed the Porulle origin:
cd porulle/apps/agentic-commerce-origincp .env.example .envbun run db:pushbun run seedbun run startBefore seeding, set STRIPE_SECRET_KEY to your account's test-mode secret and keep PUBLIC_URL=http://localhost:4000. The seed output includes a scoped storefrontKey; handle it as a secret.
In another terminal, configure the Kuralle app:
cd kuralle-agents/apps/examples/agentic-commerce-assistantcp .env.example .envSet the shared DATABASE_URL, your Cloudflare account/gateway details, the Porulle URL and scoped key, an application-specific Samesake key, and a random COMMERCE_IDENTITY_SECRET of at least 32 characters. Use pm_card_visa only in Stripe test mode.
Generate a local Cloudflare token with:
wrangler auth tokenVerify the gateway independently:
curl --request POST \ "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/ai/run" \ --header "Authorization: Bearer $CLOUDFLARE_API_KEY" \ --header "cf-aig-gateway-id: $CLOUDFLARE_GATEWAY_ID" \ --header 'Content-Type: application/json' \ --data '{"model":"openai/gpt-4.1","input":{"messages":[{"role":"user","content":"Reply with gateway-ok"}],"max_tokens":32}}'The probe uses Cloudflare's account-level AI Run API. The application uses AI Gateway's provider-native OpenAI endpoint because Pi's adapter needs that streaming protocol; embeddings travel through the same gateway.
Bootstrap Samesake and start the portable server:
bun run bootstrapbun run nodeOpen http://localhost:8787 and ask:
Find a weatherproof daypack under $120, add the best match, show my cart, and check out.Discovery is retrieval-led. cart_add reads Porulle again, and create_order pauses. Only an explicit approval resumes checkout.
Deploy the Cloudflare path
Section titled “Deploy the Cloudflare path”Use a dedicated Neon database or branch and enable vector. Apply the Porulle schema, seed the catalog, and run the Samesake bootstrap against the Neon connection string. Direct Node/Bun connections should use sslmode=verify-full.
Create the edge resources:
bunx wrangler hyperdrive create kuralle-agentic-commerce-db \ --connection-string='your_neon_connection_string'bunx wrangler queues create kuralle-commerce-eventsbunx wrangler queues create kuralle-commerce-events-dlqPut the Hyperdrive ID into each wrangler.jsonc, replace example URLs and account values, then upload secrets interactively:
cd porulle/apps/agentic-commerce-originbunx wrangler secret put STRIPE_SECRET_KEYbunx wrangler secret put STRIPE_WEBHOOK_SECRETbun run worker:deploy
cd ../../../kuralle-agents/apps/examples/agentic-commerce-assistantbunx wrangler secret put CLOUDFLARE_API_KEYbunx wrangler secret put SAMESAKE_API_KEYbunx wrangler secret put PORULLE_STOREFRONT_KEYbunx wrangler secret put ADMIN_TOKENbunx wrangler secret put COMMERCE_IDENTITY_SECRETbun run cf:deployThe deployment provisions the Durable Object and catalog Workflow from configuration. The Queue must exist before deployment. Hyperdrive supplies the PostgreSQL connection to Workers without putting the database password in Worker variables. Approved checkout remains in the resumed agent turn: the Durable Object serializes the effect and Porulle receives the stable content key as its idempotency key.
If you want Stripe to reconcile asynchronous payment events, register
https://your-porulle-origin/api/payments/webhook as a Stripe test-mode webhook
and use its endpoint signing secret for STRIPE_WEBHOOK_SECRET. Porulle verifies
the signature, deduplicates event IDs, and applies
payment_intent.succeeded only to the order identified by Stripe metadata.
Exercise approval and recovery
Section titled “Exercise approval and recovery”Both runtimes expose:
POST /api/chatPOST /api/chat/approvalSend { conversationId, message } to /api/chat and retain the signed,
HTTP-only cookie returned by the server. When checkout pauses, preserve
pendingApproval.requestId; send it with the same conversationId, cookie, and
an approve or deny decision to /api/chat/approval.
The browser-supplied conversation ID is only a label. The server namespaces the real session or Durable Object key under the verified shopper identity, binds the object to that identity, creates the signal ID, and records that identity as the approval actor. The Durable Object journals the pending interrupt independently of the HTTP response, so a reconnect surfaces the same approval while a different identity cannot resume it. Both runtimes reject an absent or mismatched pending request with HTTP 409 before entering the model loop.
Verify the contracts
Section titled “Verify the contracts”cd kuralle-agentsbun run --cwd apps/examples/agentic-commerce-assistant typecheckbun run --cwd apps/examples/agentic-commerce-assistant testbun run --cwd apps/examples/agentic-commerce-assistant cf:check
cd ../porullebun run --cwd packages/core check-typesbun run --cwd packages/adapter-stripe testbun run --cwd apps/agentic-commerce-origin check-typesbun run --cwd apps/agentic-commerce-origin testbun run --cwd apps/agentic-commerce-origin worker:checkRead the example's full operating guide for the environment reference, direct HTTP examples, catalog synchronization, and production-hardening checklist.