Try it live: quote-to-cash.lookadev.com (PayPal sandbox, no real money; no setup needed). The video shows a full run.

Inspiration

I build software for small service businesses: cleaners, clinics, local shops. They all sell the same way. A customer asks "how much?" in a chat, the owner works out a price, writes an invoice in another app, sends a link, and then has to chase the money. The chasing is the step that gets forgotten, and it is where money is lost.

What it does

Quote-to-Cash Agent takes that chat all the way to a paid PayPal invoice, with the owner in control of every price.

  1. The customer asks in chat. The agent finds out what they need, when, and who to bill, asking only for what is missing.
  2. The agent prices the job from the owner's catalogue and puts the quote on the owner's desk. The model chooses services and quantities; it cannot set or change a price.
  3. The owner taps Approve. Only then does the agent create and send a PayPal invoice and drop the pay link into the chat.
  4. Payment lands. The customer pays on PayPal's own page. The server watches the invoice; when PayPal marks it paid, the agent thanks the customer and confirms the booking.
  5. Payment doesn't land. After the due date the agent sends a PayPal reminder and one polite nudge.
  6. "I paid by bank transfer." The agent asks the owner to check the account and records the payment on the PayPal invoice only after the owner confirms. It never marks money as received on the customer's word.
  7. Regular customers. "Could you come every two weeks?" The agent quotes it as a plan; the owner approves the price, frequency, first visit and number of visits once; the agent sets up a PayPal recurring invoice series that bills every visit on its own.

How I built it

  • PayPal Agent Toolkit (@paypal/agent-toolkit) against the PayPal sandbox, using the Invoicing tools: create_invoice, send_invoice, get_invoice, send_invoice_reminder, record_payment_for_invoice, plus create_recurring_series and activate_recurring_series for plans. The model sees the toolkit's own tool schemas, except the two that create money (create_invoice and the recurring plan), which I narrowed to the customer's name and email.
  • Claude through the official Anthropic TypeScript SDK, with tool use. Shop events (owner approved, invoice paid, invoice overdue) go into the same conversation, so the agent reacts to them in context.
  • The live demo runs on Cloudflare Workers, with one Durable Object per visitor's conversation and a shared budget that caps Claude calls per day. A Node server runs the same code locally. The demo UI is a single HTML file: a customer chat on one side, the owner's desk on the other, with a progress rail from quote to paid and the invoice shown as a receipt.

Challenges I ran into

The hard part was letting a model drive invoicing without letting it decide money. Prompt rules are not enough, so the guardrails live in code and have tests:

  • prices come only from the catalogue, and the invoice lines, currency and charges are built by the server from the approved quote;
  • no invoice before the owner approves, and an older Approve button cannot approve a newer quote;
  • the agent can only touch the invoice that belongs to its conversation;
  • no payment is recorded without the owner's confirmation, and no reminder goes out on a paid invoice.

One test has the model try to add its own shipping charge and price to an invoice; only the approved quote reaches PayPal. A security review of my first version found exactly that hole, which is why the create_invoice schema is now name and email only.

I also found that the toolkit returns PayPal's response JSON-encoded twice, which hid the pay link and the paid status until I unwrapped it.

Accomplishments that I'm proud of

The full loop runs against the real PayPal sandbox and is live for anyone to try: quote, approval, invoice sent, a buyer paying on PayPal's page and the agent confirming it, reminders, an owner-confirmed bank transfer, and recurring plans.

What I learned

Agentic commerce is mostly about deciding what the agent may not do. The useful agent here is the one that does the boring steps reliably and hands the money decisions to a person in one tap.

What's next

  • Put it in front of a real business messaging channel.
  • Replace polling with PayPal invoicing webhooks.
  • Store many conversations instead of one, keyed by the customer's phone number.

Built With

Share this project:

Updates

Submission history