DEV Community

Kynth Studios
Kynth Studios

Posted on • Originally published at tally.kynth.studio

Predicting When a Client Will Actually Pay: Modeling Invoice Timing With an AI Agent

The single hardest thing about getting paid isn't writing the invoice. It's the follow-up — knowing when to nudge a quiet client, and doing it in a tone that doesn't torch the relationship. Most tools solve this with a dumb cron job: "send a reminder 7 days after the due date." That's wrong for almost everyone, and here's why.

The problem with fixed reminder schedules

Payment behavior isn't uniform. One client pays like clockwork on day 32 of a "net 30" invoice — not late, just their rhythm. Another pays on day 5 but only if you remind them on day 3. A blanket "day 7 past due" reminder annoys the first client (who was always going to pay) and misses the second (who needed the poke earlier).

So the real problem is per-client timing prediction, not scheduling. You want to model each client's payment distribution and act at the point where a reminder has the highest marginal effect — the moment they're most likely to convert intent into a transfer.

Modeling payment rhythm as a per-client distribution

Every invoice gives you a labeled data point: (sent_date, due_date, paid_date, amount, was_reminded). Over time, per client, that's a distribution of "days from send to pay." The naive move is to average it. Don't — averages hide the shape, and the shape is the whole signal.

We model each client's pay-day as a distribution and track two things that matter more than the mean:

  • Dispersion — a tight distribution (always day 30–32) means a reminder before day 30 is noise. A wide one means the client is reminder-sensitive.
  • Reminder lift — comparing paid-day distributions with and without a nudge tells you whether reminders actually move this client, and by how much.
for client in clients:
    hist = paid_events(client)              # list of days-to-pay
    p50, p90 = quantiles(hist, [.5, .9])
    lift = mean(days_without_reminder) - mean(days_with_reminder)

    # act just before the client's own habitual pay point,
    # but only if a nudge historically helps them
    if lift > MIN_LIFT_DAYS:
        send_at = due_date + p50 - REMINDER_LEAD
    else:
        send_at = due_date + p90     # let reliable-but-slow payers be
Enter fullscreen mode Exit fullscreen mode

The else branch is the one people skip, and it's the most important. A client who reliably pays on day 45 doesn't need three reminders — they need zero until day 44. Suppressing unnecessary nudges is as valuable as sending well-timed ones, because every needless reminder trains the client to ignore you.

Cold start: the first invoice has no history

With no per-client data, you fall back to a hierarchical prior: start from the population distribution (or a segment — agencies pay differently than startups), then let each new payment pull that client's estimate toward their own behavior. Bayesian updating does this cleanly. After two or three invoices, the client-specific signal dominates the prior. Before that, you're at least not guessing blind.

Drafting in the user's voice — the calibration problem

Timing gets the money moving; tone keeps the client. The reminder has to sound like you, not like a collections agency. We feed an LLM a few of the user's real past messages as style exemplars, plus structured context (days overdue, prior reminders sent, relationship length) so the model can calibrate escalation:

  • First nudge on a reliable client → light, assume-good-faith.
  • Third nudge, 30 days over → firmer, still professional.

The trick is that escalation is a function of the client's own history, not a global template. Same overdue count, different tone, depending on whether this client has ghosted before. Pass that history into the prompt and the model calibrates it far better than any if/else ladder you'd hand-write.

What makes it an agent, not a script

It closes the loop. Every paid invoice updates the distribution, re-estimates lift, and reschedules the next client's reminders. It decides not just what to send but whether to send at all — and the "send nothing" decision is a first-class action. That feedback loop is the difference between automation and an agent that gets better at your specific book of clients over time.


We built this as Tally — it watches every invoice, learns each client's rhythm, and drafts reminders in your voice at the moment they actually pay. Try it free → https://kynth.studio/l/tally

Top comments (0)