Inspiration

When a small food brand sells through a big distributor, it rarely gets paid in full. The distributor keeps part of every payment for promotions, display fees, shortages and spoilage, and the brand has to work out on its own whether each charge was allowed. Most never check, because checking one charge means finding the clause in the contract, the store sales for that week, the email that changed the terms, and the earlier payment that may already cover it.

It isn't a small problem:

  • Omaha Industries sued UNFI (D.R.I., Jan 2024), saying UNFI charged back $268,816.94 against about $326,780 of product, about 82%, and never accounted for it (Supply Chain Dive).
  • NYSM Organics sued UNFI (Nov 2024) over discounts taken after the payment window and constant deductions (Grocery Dive).
  • Saks' own SEC filings say its merchants collected about $34M of markdown allowances vendors didn't owe, and Saks repaid about $48M with interest (SEC LR-20266).
  • Coles was ordered to pay a $10M penalty in Australia for conduct toward suppliers, including payments outside its trading terms (Food & Drink Business).
  • In the UK Groceries Code Adjudicator's 2026 survey of 2,600+ suppliers, slow resolution of invoice discrepancies was the most common issue (gov.uk).

Big companies pay recovery firms to fight these. A founder with a part-time bookkeeper just eats the loss. We wanted to give that founder a deductions analyst that never gets tired, never fights a fair charge, and asks before it guesses.

What it does

Clawback is a team of AI agents that checks every deduction a distributor takes out of a payment against the signed contract. It disputes the wrong ones with proof, accepts the fair ones, asks the owner only when the contract is genuinely unclear (once, then remembers), emails the dispute after the owner approves it, follows the distributor's replies, and records the result in QuickBooks.

Seats it fills: deductions analyst and collections specialist.

The moment: Northmart pays Peak Bar Co. $41,350 on a $48,200 invoice, taking $6,850 in six charges. In about a minute Clawback decides all six:

Charge Taken Decision Why
C1 Week 1 promo, 1,200 × $1.50 $1,800 Split: $600 disputed, $1,200 fair The contract (§3.1) says $1.00 a bar
C2 Week 2 promo $980 Dispute Already paid on Mar 14 (ref NM-2178)
C3 Apr 1–7 promo $330 Accept Looks wrong, but the approved broker extended the promo by email on Mar 28
C4 Week 4 promo, 1,540 bars $1,540 Dispute The 5,000-bar cap (§3.2) was used up by weeks 1–3
C5 Mint promo $1,000 Dispute Mint isn't a product in the contract
C6 Display fee $1,200 Asks the owner once, then Rule #1, then Accept §5.4 leaves it "at its discretion"
Total $6,850 $4,120 disputed · $2,730 accepted · 1 question

What makes it trustworthy:

  • It finds the email that makes a charge fair. C3 has April dates on a March promo, but the broker is on the owner's approved-sender list and extended the deal by email. Northmart's own email claiming "the rate is $1.50" is shown as a claim and never applied: the other side can't rewrite the contract by email.
  • It asks once, never twice. The owner answers "accept if notice is at least 14 days." That becomes Rule #1, stored in Moss. Next month, a $1,200 fee with 18 days' notice is accepted and an $800 fee with 5 days' notice is disputed, both by Rule #1, with zero questions, even when the clause is worded differently.
  • Every question has a severity. Like a code review, each question is flagged High, Medium or Low with one sentence of why, so the owner sees what matters first.
  • It rehearses the comeback before it files. For each dispute line it predicts the distributor's rebuttal and files only if the evidence answers it.
  • It writes and sends the dispute email, but only after you approve it. The agent drafts a professional dispute email (clause quotes, sales rows, math, one paragraph per line); the owner clicks Review and send, and it goes out from the brand's Gmail. Replies are read automatically and appear in the dispute thread with a notification.
  • It concedes when shown proof. If the distributor attaches the signed amendment raising the cap to 6,000 bars, Clawback withdraws $1,000 of C4 and keeps $540 disputed.
  • Only a person moves money. The $2,730 credit memo waits for the owner's approval; then plain code, not an agent, writes it to QuickBooks and leaves the disputed $4,120 open on the invoice.
  • Every number opens its source. Each charge's evidence card shows the highlighted contract sentence, the math, the rehearsed comeback, and every AI call behind the decision with the model that answered.

A real product, not a single demo screen. You sign in to a supplier workspace (each supplier sees only its own data) that tracks six distributors (Northmart, UNFI, KeHE, Sam's Club, Walmart and Five Below), with a company overview of what was taken, what's disputed with evidence, what's been recovered and what needs you. New payments are watched from the bank (Capital One Nessie) and QuickBooks; when one arrives the app says "New payment received" and you run the agents. A remittance PDF can also be uploaded: Claude reads it and code checks every line adds up before a run starts.

How we built it

Seven agents, one rule: AI reads and explains, code does the math, people approve money.

  1. Payment reader (Claude + code check): reads a remittance into charges; code verifies every line is printed word for word and the lines add up.
  2. Two contract readers (Claude and Gemini): each reads the contract and emails into typed terms with the exact sentence. A term counts only if the sentence is found word for word, every number is in it, and both models agree. A disagreement goes to the owner instead of becoming a dispute.
  3. Calculator (plain Python): the expected amount per charge: rate, products, dates, extensions, the cap counted week by week from store sales, earlier payments. Unit-tested against every number in the scenario. No AI computes money.
  4. Investigator (Claude): a one-line finding with confidence and evidence IDs; code checks every number and ID exists.
  5. Decision gate (code): a fixed, ordered policy (skip / ask / accept / dispute / split), with a $5,000 auto-dispute limit, a 0.9 confidence floor and the owner's saved rules matched by Moss.
  6. Negotiator (Claude): rehearses the rebuttal, drafts the dispute email, classifies replies, concedes on a valid document. An outbound filter blocks any dollar figure or quote that isn't in a finding.
  7. Bookkeeper (code): writes the credit memo to QuickBooks only after the owner approves.

Stack: Python 3.11, FastAPI, Pydantic (strict JSON for every agent output: one retry with the error, then route to a person), Server-Sent Events to stream every step live, Next.js + Tailwind + Framer Motion for the UI, Postgres on Tiger Data (store sales as a TimescaleDB hypertable with a continuous aggregate for the cap check), Moss for rule memory, Gemini as the second reader, Capital One Nessie for the deposit trigger, QuickBooks Online sandbox, Gmail (SMTP + IMAP) for dispute email, a Fetch.ai uAgent on Agentverse, Docker Compose + Caddy on a Vultr VM, at clawback.biz (a GoDaddy Registry .biz domain). Designed in Figma (Figma Make screens, then implemented through Figma's MCP server in Claude Code).

Safety by design: documents, emails and distributor replies are data, never instructions; only approved senders or a document signed by both parties can change a contract; hash-chained audit log of every action; per-supplier tenant isolation; sign-in with hashed passwords and session cookies; rate limits on live AI runs.

Proof it works (what's real, what's simulated)

  • Eval: 30 of 30 correct, 0 wrong automatic actions. 30 planted charges (12 dispute, 12 accept, 6 ask) with the answer key written before the first run. Amounts right to the cent on all 30; 0 unnecessary questions.
  • Repeatable: 5 live runs in a row gave identical decisions ($4,120 disputed, 1 question), 65–73 seconds each, about $0.38 of Claude per run.
  • Real: the AI reading (Claude + Gemini, live), the math and decision rules, the QuickBooks sandbox writes, the Nessie deposit, the Gmail dispute email and reply tracking, the Moss rule match, the eval score.
  • Simulated: Peak Bar Co. is our fictional brand; the distributor programs, emails, sales data and charges are written by us, modeled on real ones. The real cases above are cited from their sources; none of those companies took part.

Challenges we ran into

  • Stopping the AI from inventing contract terms. Two models plus a word-for-word quote check plus "every number must appear in the quote" was the combination that finally made a hallucinated clause impossible to act on.
  • Making "ask once" really mean once. An owner's free-text answer has to become a rule that matches next month's differently worded clause, but never a different kind of fee. Moss similarity plus same clause type plus same distributor did it.
  • Emails that change deals. Telling a real amendment (approved broker, or signed by both sides) from a distributor's self-serving claim was the heart of the trust problem.
  • Keeping the demo honest and live. Every run is generated live; we built a record/replay layer so the demo survives bad Wi-Fi without faking a result.

Accomplishments that we're proud of

  • 30/30 on the planted eval with zero wrong automatic actions: the worst failure is a question to a person, never a wrong dispute.
  • It accepts $2,730 of fair charges, including one that looked wrong until it found the email. It's not a "dispute everything" bot.
  • A dispute goes from finding to a sent email with evidence in under two minutes, with a human approving every step that matters.

What we learned

The hard part of finance automation isn't the math; it's deciding which sources to trust and knowing when to ask. Separating "AI reads" from "code computes" from "people approve" made every decision explainable to a judge, an owner or a distributor.

What's next for Clawback

Real distributor portals via browser automation (UNFI, KeHE, Walmart Retail Link), a remittance inbox that starts runs from forwarded emails, Google Drive as the contract source, ERP adapters (NetSuite, Xero) beside QuickBooks, and SOC 2-style controls for production.

Architecture: every stage, every decision, every connector

Inputs (connectors): Capital One Nessie bank deposits and QuickBooks Online payments (pollers), a remittance upload (PDF/CSV/text) or the distributor portal's "Send payment" → shown as "New payment received" until the admin clicks Run the agents. Contracts, amendments, notices and broker/distributor emails per account; store sales, prior payments, promo plan, delivery and price records in Postgres on Tiger Data.

  1. Payment in (code + Claude): the Payment reader (Claude) lists each deduction; code checks every line is printed word for word and that lines add up to gross − paid and to invoiced − received within $1, or the run can't start.
  2. Read the deal (Claude Opus + Gemini 3.6 Flash): two independent readers return typed terms (rate, products, cap, dates, fee discretion, amendment, fee schedule) each with an exact quote. Code keeps a term only if the quote is found word for word, every number is in the quote, and both readers agree. Quote fails → rejected; readers disagree → disputed (forces a question). Emails change the deal only from an approved sender or if signed by both sides; otherwise they're shown as a claim.
  3. Check each charge: the Calculator (plain Python, unit-tested) runs product check → dates (+amendments) → unit cap walked week by week from store sales → duplicate check against prior payments → allowed = covered units × rate; delta = taken − allowed (fees: up to the stated max; shortages vs proof of delivery, price vs price list, spoilage vs allowance). The Investigator (Claude) writes a ≤25-word finding with confidence and evidence IDs; code checks every number and ID. The Negotiator rehearses the distributor's rebuttal and must answer it from evidence. Decision gate (code, first match wins): 1 quote failed → Skip · 2 readers disagree → Ask · 10 dispute window closed → Accept with a note · 3 discretion + saved rule matched in Moss (similarity ≥ 0.85, same clause type, same distributor) → apply the rule · 4 discretion, no rule → Ask · 5 within $1 → Accept · 6 under the deal → Accept · 7 over by > $1 and ≤ $5,000 with confidence ≥ 0.9, ≥ 2 sources and the comeback answered → Dispute (Split if part is allowed) · 8 same but > $5,000 → Ask first · 9 anything else → Ask. Each question gets a severity: High at ≥ $1,000 or ≥ 5% of the payment, Medium ≥ $250, raised when a dispute window is ≤ 14 days away.
  4. Your answer (person): the owner answers once; the Rule writer (Claude) turns it into a rule saved in Postgres and indexed in Moss (UNDO removes it).
  5. File the dispute (Negotiator + Email writer, Claude): one dispute per payment; an outbound filter blocks any dollar figure or quote not in a finding (one retry, then held); the total is checked against the $5,000 limit again; the admin clicks Review and send → Gmail SMTP with the evidence packet PDF. An IMAP poller reads replies every 30 s: a new document is re-read and, if it's a valid amendment, the agents recompute and concede the difference; a claim without a document gets the evidence back; anything else goes to the owner. Each reply rings the bell.
  6. Your approval (person): credit memos over $1,000 wait for the admin's yes; never an agent.
  7. QuickBooks (Bookkeeper, code): one credit-memo line per accepted charge, applied to the invoice; the disputed balance stays open with a note; an idempotent request ID means a retry never posts twice.

Platform: FastAPI + Pydantic (every AI output is strict JSON; one retry with the error, then Ask), Server-Sent Events to Next.js, events/rules/audit chain in Postgres on Tiger Data (store_sales hypertable + continuous aggregate for the cap), a hash-chained audit log, per-supplier tenant isolation with hashed passwords and session cookies, rate limits on live runs, record/replay fixtures keyed by request hash, a Fetch.ai Agentverse agent (read-only summary + answering the owner's question), and Docker Compose + Caddy on a Vultr VM at clawback.biz.

Sponsor tools we used, and how

  • Hyphenate: the whole product is an autonomous finance system for the deductions-analyst and collections seats: limited access (it can't move money), a clean record (hash-chained audit log), and knowing when to ask (one question, flagged by severity).
  • Microsoft (Built for the Real World): customer understanding (real UNFI/KeHE/Walmart cases), measurable usefulness (30/30 eval, ~70 s and ~$0.38 per run), a path to production (portals, ERP adapters, SOC 2-style controls), responsible design (people approve money; documents are data, never instructions), end to end (deposit to QuickBooks).
  • Anthropic (Claude for Public Benefit): for founders and part-time bookkeepers of small food brands selling through big distributors. Claude reads remittances and contracts, investigates each charge, rehearses the distributor's comeback, and drafts the dispute email; code checks every Claude output, and a person approves anything that moves money.
  • Google Gemini (MLH): Gemini is the second, independent contract reader. A term counts only when Claude and Gemini agree; when they disagree, the owner is asked instead of the agent guessing.
  • Moss: the owner's answers become rules stored in Moss and matched by meaning, so next month's differently worded clause is decided by Rule #1 with no question.
  • Tiger Data (MLH): the production database is Postgres on Tiger Data; weekly store sales is a TimescaleDB hypertable with a continuous aggregate, and the promo-cap check is a time query.
  • Vultr (MLH): the API, the web app and Caddy run with Docker Compose on a Vultr cloud VM serving the live site.
  • GoDaddy Registry (MLH): clawback.biz, a .biz domain, because it claws back what distributors wrongly take.
  • Capital One Nessie: the distributor's short payment is a deposit into the brand's Nessie checking account; a poller watches it and the app says "New payment received".
  • Figma: Figma Make generated the first screens, the frames live in our Figma file, and Claude Code read them through Figma's MCP server to build the components.
  • Fetch.ai: the Clawback Assistant, a uAgents agent with the Agent Chat Protocol registered on Agentverse (agent1qtqhltj3d3u46j3nelxphsn8ezgzwhgrpx54r7m6m0x7l3mg08h757x2pa2): ask it in ASI:One what a distributor took, see open disputes, and answer the pending question. It is read-only and never approves money.
  • Atlassian (security for agents acting on a user's behalf): documents, emails and distributor replies are treated as data, never instructions; only approved senders or a document signed by both parties can change a contract; an outbound filter blocks any figure or quote not in a finding; agents can't approve money (separation of duties); per-supplier isolation, rate limits and a tamper-evident audit chain.

Try it out

Live at https://clawback.biz (sign in: testuser / test123).

Built With

Share this project:

Updates

Submission history