Inspiration
Freelancers and small agencies rarely lose money because they can't send an invoice. They lose it in the gaps: a "quick extra page" agreed in a chat, a delivery nobody formally accepted, a deposit that was "coming", a final payment chased for weeks. Invoicing tools bill for the work; nothing protects the promise behind it.
We wanted a workspace where every client promise is tracked from the first message to the moment PayPal confirms the money, with AI doing the busywork and a human approving anything that moves money.
What it does
PactPop is a free, open-source workspace for freelancers and small agencies. Eight AI agents (Intake, Scope, Pricing, Proposal, Operations, Finance, ProofFlow and PayFlow) take a client from request to payment:
- Client request page: the client describes the project in plain words; the Intake Agent turns it into requirements and follow-up questions.
- Agreements: agents draft scope, price and milestones from the business's own rate card. The client gets one private link to review, accept by name and pay the deposit with PayPal.
- ScopeWatch: when a client asks for more, the Scope Agent compares it with the signed agreement and prices a change order. Approving it creates a new agreement version and a new payable milestone.
- ProofFlow: delivery proof is checked against every agreed acceptance criterion. A passing check asks the owner to approve the delivery, which is what makes the next payment due.
- PayFlow + PayPal: the PayFlow Agent prepares real PayPal invoices (held for approval), checks payment status with PayPal, and can show an invoice sample right in the chat.
- TrustGate: every agent tool call is permission-checked on the server: allowed, needs approval, or blocked. Money actions have locked floors that no setting or prompt can relax.
- Documented money: every PayPal invoice and payment gets a printable invoice or receipt with PayPal's own record (IDs, status, fee, net) and a full paper trail, downloadable as PDF or image.
- AI chat with history and charts: conversations are saved and can be continued, and agents can show pie, donut, bar and line charts. The AI picks the view; the numbers always come from the database.
Poppy, our pup mascot, keeps watch over every promise.
How we built it
- App: Next.js 16 (App Router), React 19, TypeScript and Tailwind CSS v4; responsive for phones and tablets.
- Data: Drizzle ORM on PostgreSQL (Neon in production, embedded PGlite locally); hosted on Vercel.
- PayPal (Sandbox): a typed server-side client using Invoicing v2 (milestone invoices), Orders v2 (Smart Buttons checkout, created and captured on the server) and Webhooks (signature verified with PayPal, stored once per event id, then the invoice or order is re-read from PayPal before anything is recorded). Every write sends a
PayPal-Request-Id, so retries never duplicate. - AI: an orchestrator running a tool-use loop over 20 typed tools. It runs on Groq (
openai/gpt-oss-120b, with other models selectable), and Anthropic Claude is supported as an alternative. Every tool input is validated with Zod and passes TrustGate before it runs. - Money in code, not in the model: amounts are integer minor units and every price comes from the pricing engine:
$$\text{price} = r_{\text{page}}\,p + r_{\text{extra}}\,(p - p_0)^{+} + r_{\text{hour}}\,h, \qquad \text{deposit} = \left\lfloor \tfrac{d}{100}\,\text{price} \right\rceil$$
The model estimates units ($p$ pages, $h$ hours); code computes the dollars.
- Quality: Vitest unit and integration tests, plus Playwright runs against the live PayPal Sandbox.
- Development used Claude Code as an AI pair programmer; it isn't part of the running app.
Challenges we ran into
Testing against the real PayPal Sandbox found bugs we would never have seen with mock data:
- Cents read as dollars: a model read
150000(cents) as \$150,000. Tool results now give the model formatted money only. - Duplicate checkouts: React's development mode rendered PayPal's buttons twice, creating duplicate orders and closing the payment window.
- Paying too early: the final milestone was payable right after the deposit. Only due payments (the deposit, or work the owner approved) can now be checked out, and the server enforces it.
- Free-tier rate limits: multi-step agent runs hit the AI provider's per-minute limits, so the orchestrator waits for
retry-afterand tells the user. - Dates and webhooks: PayPal sometimes sends dates without a time, and webhooks can arrive seconds after a payment; we confirm everything with a server-side read instead of trusting a single message.
Accomplishments that we're proud of
- A complete, working loop on real PayPal Sandbox APIs: client request → agreement → scope change → proof check → PayPal invoice or checkout → verified webhook → documented receipt.
- AI that prepares and people who decide: no price, payment or agreement change happens without code-computed amounts and, where money moves, a human approval.
- Every dollar is traceable: each payment links back to the promise it fulfils, with PayPal's own record attached.
- It's free and open source (MIT), and works on desktop, phones and tablets.
What we learned
- Webhooks are a trigger, not the truth: the safest pattern is verify, store once, then re-read from PayPal.
- Let AI choose, let code decide: models are great at understanding requests and picking tools, but money, permissions and state changes belong in deterministic code.
- Show the AI's work: owners trust agents more when they can see each tool call, each TrustGate decision and a paper trail.
What's next for PactPop
- Move from the PayPal Sandbox to live PayPal after review.
- Client-facing receipts and payment reminders.
- File uploads for delivery proof, with AI checks on images and documents.
- AI-assisted dispute packs built from the agreement history, ProofFlow checks and PayPal records.
- Multi-currency and team roles for agencies.
Built With
- ai-agents
- anthropic-claude
- drizzle-orm
- gpt-oss
- groq
- neon
- next.js
- node.js
- paypal
- paypal-invoicing-api
- paypal-orders-api
- paypal-sandbox
- paypal-webhooks
- pglite
- playwright
- postgresql
- react
- recharts
- tailwindcss
- three.js
- typescript
- vercel
- vitest
- zod