Inspiration

Small suppliers are paid by milestone, and the contract sets the rules for every invoice: when you may invoice, what the client must accept first, how many days they have to pay and what paying late costs. In practice those clauses are read once, at signing. Invoices go out early and get rejected, or go out late and wait; reminders are written from memory. We build tender software at Lucius AI, where every requirement is quoted from its page, and wanted the same discipline on the billing side.

What it does

  • Read: upload a contract or purchase order (PDF). Gemini returns the parties, the contract value, the payment terms, the condition for invoicing, the late payment clause and every milestone with its amount, due date and acceptance criteria, each with a verbatim quote and its page.
  • Check: every quote is matched against the text of its page. Anything not found is flagged on screen, never hidden. The sample reads 11 of 11 quotes found.
  • Gate the invoice on proof of delivery: upload the evidence as a file (the client's acceptance email as a PDF, a signed certificate as an image, a handover note as a Word file) or type a note. Gemini checks it against the milestone's quoted acceptance criteria and the contract's condition for invoicing, item by item: met, not met or not shown, each with the file's own words. For a PDF or Word file every quote is checked against the file's text by code ("Found in the file"), and a "met" whose words are not in the file does not count. Items read from an image are marked "Confirm by eye" and never count as met on their own. The invoice is offered only when every item is met. In the sample, the client's acceptance email meets 4 of 4; the dataset handover note is held because it has 980 responses where the contract asks for 1,200 and the data dictionary "will follow next week". You can send over a hold only with a stated reason, which is recorded in the ledger. The file is read for the check and not kept.
  • Invoice through PayPal: on your approval the invoice is created and sent with the PayPal Invoicing API (v2). It carries the contract reference, the milestone, and the contract's own payment line with its page in the note, so the client sees why it is due.
  • Get paid on PayPal: the client pays on PayPal's own invoice page (in the demo video, with a sandbox test card). On the hosted demo a sandbox button records the client's payment with the Agent Toolkit, so anyone can watch PayPal confirm it.
  • Hear back from PayPal: a PayPal webhook (signature verified with PayPal's verify-webhook-signature API) marks the milestone paid, and the page updates by itself.
  • Ask the billing agent: Gemini function calling over the PayPal Agent Toolkit's own tool definitions. list_invoices, get_invoice and search_invoicing run straight away; send_invoice_reminder is never executed by the model: it becomes a proposal you approve on the page, and only then does the toolkit send it. Before the due date the agent drafts a courteous reminder with the payment terms and the due date; the late-payment clause is quoted only once an invoice is overdue.
  • Keep the books in AG Grid: the payment schedule (select a row to open the milestone), the invoices (PayPal status, due and overdue days, reminders, paid, the client's PayPal link) and a ledger of every invoice event: drafted, sent, reminded, payment recorded, paid, cancelled, and any hold you overrode with your reason, each with its amount, time and source (the app's own PayPal call or PayPal's verified webhook). The ledger can be searched and downloaded as CSV.
  • Money at a glance: invoiced, paid and still to collect, per contract.

How we built it

Python and FastAPI with a single vanilla-JS page, on Cloud Run. PyMuPDF for page text; Gemini (gemini-3.8-flash on Vertex AI) with JSON-schema output for the reading and the delivery check, and function calling for the billing agent. Evidence files are recognised by their first bytes (PDF, PNG, JPEG, .docx), bounded in size, pages and pixels, read with PyMuPDF (the .docx XML scanned for its text runs) and never stored; every quote the model returns is checked against the file's text by code. The tables are AG Grid Community 36.2.0 (MIT), pinned from jsDelivr with a subresource-integrity hash and themed with AG Grid's Theming API (themeQuartz.withParams) bound to the page's colour tokens, light and dark; cell renderers build DOM nodes, never HTML, and the CSV export quotes anything a spreadsheet would run as a formula. If the CDN is blocked the page falls back to plain tables. PayPal: Invoicing API v2 (create, send, get, remind) through a small async client, Webhooks with signature verification, and the PayPal Agent Toolkit's framework-free core (tool names, descriptions, argument schemas and handlers) for the agent and for recording the sandbox payment. The agent sees only the invoices of the contract on screen, because the sandbox merchant account is shared by everyone who tries the demo. Per-visitor limits keep the public demo inside its budget.

Challenges we ran into

  • Our first sandbox app never received the Invoicing scope; a fresh sandbox business account and app fixed it.
  • The client's pay link is not in the create response; it is in the invoice's detail.metadata.recipient_view_url after sending.
  • The delivery check could not judge "a work plan for every later milestone" until it was given the contract's milestone list: it held a complete note about half the time; with the schedule in the prompt it passed 4 of 4 and still held the vague note.
  • The agent first answered in PayPal's status codes and ISO dates, repeated the reminder text it had just queued, and drafted late-interest language for an invoice that was not due. Plain-word statuses, written-out dates and a due-date rule fixed all three.
  • The toolkit's full install pulls in agent frameworks we do not use; we install its core without them and call its tools directly.
  • A quote check needs text. For a PDF or Word file the code can confirm that every quoted sentence is in the file; nothing read from an image can be checked that way, so those items are "Confirm by eye" and never count as met by themselves.

Accomplishments that we're proud of

Nothing reaches the client without a person approving it, and every claim the app makes about the contract links to its page. The full story, from upload to a webhook-confirmed payment, runs end to end on the hosted demo.

What we learned

An agent is much easier to trust when its write actions are proposals by construction, not by prompt. And an LLM's judgment of "is this milestone done" depends as much on the context it is given (the whole schedule, the invoicing condition) as on the model.

What's next

Partial payments and credit notes, reminders on a schedule the contract allows, scanned evidence read with OCR so its quotes can be checked too, and purchase orders from the buyer side.

Try it

Live demo (PayPal sandbox, fictional sample contract): https://clause-and-pay-384599766402.europe-west1.run.app Code (Apache 2.0): https://github.com/ailucius/clause-and-pay

Built by Lucius AI Systems, Inc. (ailucius.com). In the video the narration is an AI voice and waits are sped up where marked on screen; the client pays on PayPal's sandbox invoice page with a PayPal test card, and no real money moves.

Built With

Share this project:

Updates

Submission history