Inspiration

Small online shops lose hours every week to PayPal admin: answering "what should I buy" questions, issuing refunds, uploading tracking numbers, paying suppliers and affiliates, checking disputes, adding up the day's sales. AI agents can do all of that now. The problem is trust: nobody lets a model move their money. Countersign is built around one rule: the agent prepares every money movement, and only a human click executes it.

What it does

One AI agent, both sides of the counter.

Shop (agentic commerce). A buyer types what they want in plain language, for example "a gift for my dad who likes coffee, under $40". The agent searches the real catalog and proposes a cart with a reason for each item. The server prices it, applies shipping, enforces the budget, and creates an itemized PayPal Orders v2 order. PayPal Smart Buttons render bound to that exact order. On approval the server captures and the agent confirms with the receipt and capture ID.

Owner console (back office). The owner talks to the same agent:

  • "How did we do this week?" returns orders, gross, refunds, PayPal fees, net and top sellers.
  • "Refund order 1002" produces an approval card: amount from the order record, buyer, and the exact PayPal endpoint. Click Approve and PayPal returns the refund ID.
  • "Pay what we owe Bean and Burr Roasters" produces a Payouts approval card. Amount comes from the payee ledger, and payouts only go to payees in the directory.
  • "Add UPS tracking to order 1005" uploads through PayPal order tracking after approval.
  • Disputes, live order status and payout status on demand.
  • Every tool call, proposal, approval and block is written to an audit trail with the PayPal response attached.

How we built it

  • One Cloudflare Worker, single page UI with Shop and Owner tabs, Cloudflare D1 for orders, carts, payees, pending actions and audit.
  • AI: Llama 3.3 70B on Workers AI with native function calling, in a custom tool loop with a response normalizer and repeat guard.
  • PayPal APIs: OAuth2 client credentials, Orders v2 (create, capture, track), Payments v2 captures and refunds, Payouts v1, Disputes v1, JS SDK Smart Buttons.
  • Read tools run immediately. Every propose_* tool only writes a pending action row. Approve atomically claims the action, re-validates it against current records, then calls PayPal. A second Approve on the same card returns 409.

Challenges we ran into

  • Models invent numbers. We made every amount come from the server: cart totals from the catalog, refunds from the order record, payouts from the payee ledger. A custom amount is accepted only if the owner typed that exact number.
  • When a money request is refused, a model tends to quietly propose a smaller one. The server now blocks any second money proposal in the same turn and the agent has to go back to the owner.
  • Open-weight tool calling quirks: repeated calls, tool calls inside text, "ready for approval" with no card. Each one got a server-side fix.

Accomplishments that we're proud of

Everything in the demo is real sandbox traffic: itemized orders created and captured, full, partial and per-item refunds, payouts with batch IDs, tracking uploads. The guardrails hold when you try to break them: a $1000 refund on a $57 order, a payout to an outside email, an affiliate payout above the balance owed, and a cart over budget are all refused by the server.

What we learned

The useful line for agentic commerce is not "can the model call the API". It is "who decides the amount, and who clicks". Putting both on the server and the human makes an agent a shop owner can actually turn on.

What's next for Countersign

Owner login and multi-shop support, PayPal webhooks to auto-reconcile disputes and refunds, scheduled supplier payouts that still require one approval, and a production rollout with real merchants.

Try it

Live demo: https://countersign.lively-frost-fa7e.workers.dev On the Shop tab, ask for something with a budget and click "Pay with sandbox test card (judges)". On the Owner tab, ask for a refund or a payout and approve the card. Sandbox only, no real money moves.

Built With

Share this project:

Updates

Submission history