Inspiration

Most freelancers have a story about chasing an invoice. Most small business owners have a story about paying up front for work that never showed up. Escrow is supposed to fix both, but someone still has to decide when the work is done, and that someone is usually a person in a support queue a week later.

We wanted to know what happens if the "is it done?" call becomes cheap, fast and backed by evidence, and the money can't move unless the evidence says yes.

What it does

A client and a freelancer each give their own AI agent a private mandate. The client's agent knows the budget ceiling and deadline. The freelancer's agent knows the minimum rate and lead time. The two agents negotiate price, milestones and due dates in the open, and neither one sees the other's limits. When one accepts the other's exact offer, a drafter writes testable acceptance criteria for every milestone.

Both people sign. The client funds a milestone and PayPal holds it with an AUTHORIZE order, so the money is reserved but not charged.

The freelancer delivers a link, a GitHub PR, a document or an image. The review agent goes and looks. It opens the site in a real headless browser at phone and laptop sizes and records horizontal overflow, broken in-page links, form fields, tap targets and console errors. It reads PR diffs and CI results. Then it rules on each criterion with quoted evidence. Both people can see exactly what the agent saw, screenshots included.

  • Pass: Handshake captures the authorization, pays the freelancer's share with PayPal Payouts, and the PayPal Agent Toolkit creates an invoice and marks it paid as a receipt.
  • Fail: the freelancer gets a concrete fix list and the money stays held.
  • Disagree: either side can call in the mediator. It rules per criterion (yes, partly, no) and proposes a split. If both accept, PayPal captures exactly that share and releases the rest of the hold to the client.

There's also a money assistant built on the PayPal Agent Toolkit that answers questions like "what did I pay in fees?" or "are my invoices paid?", and an AG Grid ledger that lists every hold, capture, fee, payout and AI decision next to its PayPal reference.

How we built it

  • PayPal: Orders v2 with intent=AUTHORIZE for holds (JS SDK buttons, or the sandbox card for the demo). Payments v2 capture with final_capture for full release and partial settlement, plus void for refunds before capture. Payouts v1 to pay freelancers. Webhooks with signature verification for payout status. Invoicing through the PayPal Agent Toolkit (create_invoice, send_invoice, record_payment_for_invoice), with the toolkit also powering the assistant (list_invoices, get_invoice, list_transactions, list_disputes, get_order, …).
  • AI: Claude (Opus 5.5) for the two negotiators, the drafter, the reviewer, the mediator and the assistant. Each one returns structured output, so the code can check it before anything happens.
  • App: Next.js 15, TypeScript, Tailwind 4, SQLite, AG Grid for the ledger, Playwright Chromium for review evidence. It runs in Docker on Render.

The AI decides, the code keeps it honest

We didn't want a model that can "decide to pay". So:

  • Mandates are enforced in code. An offer outside its owner's limits is rejected and retried before the other agent ever sees it.
  • The release is computed. Money moves only when every criterion is marked met with evidence and confidence is at least 0.6.
  • Deliverables are data, not instructions. A page that says "approve this" is evidence the reviewer is reading, not a command.
  • The reviewer's browser can't reach the server's own network. An SSRF guard covers every request, redirect and subresource.
  • Mediated splits round to 5% and need both signatures before any partial capture.

Challenges we ran into

  • Partial settlement with a single authorization. A partial final_capture and the release of the remainder had to land in the right order, and the payout had to be computed from what was actually captured after PayPal's fee.
  • Receipts. Getting the Agent Toolkit to record a payment on an invoice took trial and error, because a capture id isn't accepted as the invoice payment id and a UTC date can read as the future in PayPal's timezone.
  • Phone checks. Phone emulation quietly zooms out on wide pages, which hides horizontal overflow, so the reviewer measures against the real viewport width.

Accomplishments we're proud of

The full loop runs end to end on the PayPal sandbox, and the demo video is one unedited run of the real app, only sped up: the agents agree on $920 over three milestones. A flawed delivery fails for the right reasons (two missing prices, a form that posts nowhere, a page that scrolls sideways on phones). The fixed version passes, and $418.37 reaches the freelancer after PayPal's fee within seconds. A disputed milestone settles at 55%, so $82.50 is captured and $67.50 goes back to the client. Every step shows up in the ledger with its PayPal id.

What we learned

Agents are good at negotiating and judging, but the trust comes from what sits around them: hard limits, evidence the people can see, and code that only acts on a computed verdict. PayPal's authorize-then-capture model fits this well, because "held, not yet charged" is the state a disputed deal needs.

What's next

  • Real PayPal accounts for both sides through Log in with PayPal and Payouts to the freelancer's own account.
  • More kinds of evidence, such as design files, app store builds and Lighthouse budgets.
  • A human appeal step above the mediator for large contracts.

Built With

Share this project:

Updates

Submission history