CALL-E Hackathon · Shopify App

Phone work for Shopify stores,
done by an agent and gated by policy

Call carriers that have no API. Reach customers who ignore email. Resolve stuck orders that would otherwise be refunded. Every action gated by a deterministic policy engine — the AI gathers evidence, it never authorises.

What it actually does

Two call legs. The AI places calls, navigates phone trees, holds, talks to humans, and returns structured evidence. A separate policy engine decides what to do with it.

📞

Carrier leg

The carrier says delivered, the customer says otherwise. CallmeMaybe calls the carrier, navigates the IVR, holds for an agent, opens a package trace, and returns a trace reference, carrier disposition, promised response date, and hold time — as structured data.

API of last resort
📱

Customer leg

The order can't ship and the customer stopped answering email. CallmeMaybe calls them, challenges a one-time verification code before disclosing anything, captures one clear resolution decision, reads consequential details back, and records spoken confirmation.

Escalation channel
trigger CALL-E policy Shopify ──────────────────────────────────────────────────────────────────────────── merchant sees a ──▶ places the call, ──▶ deterministic ──▶ re-read order, blocked order, holds, navigates engine decides abort if it or customer the IVR, adapts, automatic / drifted, requests support returns a approval / mutate, write schema-valid result escalate a receipt

Safety architecture

An LLM deciding to cancel an order is a liability. CallmeMaybe keeps the model on the side of the line where it's good — holding a conversation — and keeps authorisation entirely deterministic.

Model never authorises

policy.server.ts is a pure function over a policy record, an order snapshot, and the call result. Same inputs, same decision, every time. No model call in the path.

Irreversible → approval

Cancellations, returns and carrier traces default to APPROVAL. Refunds and replacements are never automatic — they write a note for a human.

Identity before disclosure

A one-time code, two attempts, and the task instruction forbids revealing order details before the code is satisfied.

Drift check before mutation

Before executing, the system re-reads the order from Shopify and compares it to the snapshot the decision was based on. Any change to fulfillment status, financial status, or cancellation aborts the execution.

Issue type Requires verification Default mode Max one action
Address change Customer AUTOMATIC Yes
Cancellation Customer APPROVAL Yes
Return / exchange Customer APPROVAL Yes
Delivery problem Customer AUTOMATIC
Carrier trace None APPROVAL
Order status inquiry Customer INFORMATIONAL

Tech stack

Three external dependencies. No analytics, no error tracker, no email provider.

React Router v7 + Shopify App Framework Prisma + SQLite Polaris + App Bridge CALL-E TypeScript SDK Shopify Admin GraphQL AES-256-GCM at rest Shopify CLI + Cloudflare

Quick start

npm install cp .env.example .env npx prisma migrate dev npx tsx prisma/seed.ts npm run verify:calle shopify app dev