DEV Community

Jupudi Sri veena
Jupudi Sri veena

Posted on

The Backend That Makes My Payment-Recovery Agent Remember the Right Things

A payment fails. Someone on finance pulls up the customer, sees a balance and a due date, and sends the same email reminder they'd send anyone. They have no idea this customer ignored that exact email three weeks ago — and paid within hours of a WhatsApp message instead. The invoice wasn't the real problem. The missing memory was. That's the gap I built PayEcho to close. It's a payment-recovery and credit-decision agent that uses Hindsight — a memory layer built for AI agents — to remember a customer's past payment behavior, previous recovery attempts, responses, repayment delays, and outcomes. It then uses that history to make sharper, more personalized recommendations for the next overdue invoice or credit decision. The core idea is simple: past customer behavior flows into Hindsight, the agent recalls it later, and that memory produces a better next decision than a stateless system ever could. Two Kinds of Data, Two Different Jobs The backend splits cleanly into two stores that do completely different work. The transactional side — customers, invoices, amounts, due dates — lives in an ordinary relational database. Nothing interesting happens there on purpose; it just answers "what does this customer currently owe." The experience side is where the actual intelligence lives. Every recovery action PayEcho takes — a reminder, a follow-up, a credit review — gets its outcome written into Hindsight: what channel was used, how the customer responded, whether it worked, how long it took. That's the data that needs to inform a future decision, not just get logged and forgotten, and mixing it into the same store as the invoice data was my first instinct and it was wrong. A relational database is great at answering what a balance is. It's bad at answering what tends to work when a specific customer ignore an email.

The Comparison That Explains Everything Take a customer with a Rs. 50,000 overdue invoice. Their actual history: an email reminder was sent and ignored, a WhatsApp reminder was sent and they responded, and a follow-up three days later got them to pay. Without memory, PayEcho's recommendation for this customer's next overdue invoice is identical to what it would say about a customer it has never seen before: “Send a polite email reminder, and follow up in 3–5 business days if no response.” With Hindsight in the loop, the recall step pulls that exact sequence of events, and the recommendation becomes: “ABC previously ignored email reminders but responded to WhatsApp, and completed payment after a 3-day follow-up. Recommend WhatsApp outreach with a scheduled 3-day follow-up.” Same invoice, same model — the only thing that changed is what the backend handed it before it answered. That single comparison is, honestly, the entire value proposition of the project.

Retain Discipline Mattered More Than Recall Cleverness My first pass at writing to Hindsight was lazy — a single string like "sent a reminder, customer paid." It technically works, but when I tried to recall it later and build a recommendation from it, the model had nothing specific to reason with: no channel, no timing, no sense of what actually caused the payment versus what just happened to coincide with it. The version that produces good recommendations is deliberate about what it stores — invoice ID, amount, every channel tried with its result, the final resolution, and days to resolve. That single change, being specific at write time, did more for recommendation quality than any amount of prompt tuning on the read side. If I had to name the one lesson that mattered most from building this, it's that a vague memory can't be rescued by a clever prompt. Where the Credit-Decision Use Case Fits InThe recovery-reminder loop was the first thing I built, but the credit-decision use case turned out to matter more. If a customer with a pattern of repeated late payments asks for new credit or a payment extension, PayEcho surfaces their full repayment history — how many times they've been late, what it took to recover past invoices, typical resolution time — to whoever is approving the request. It doesn't auto-approve or auto-deny anything here, and that's a hard rule, not a nice-to-have. Risk tolerance is a judgment call that belongs to a person, not a model. What memory does is make sure the person making that call actually has the full picture instead of whatever they happen to remember from the last conversation. Designing for the Parts That Will Eventually Fail LLM calls fail, get rate-limited, or occasionally return malformed output, and I didn't want a flaky network call to take down a recommendation flow mid-demo or, worse, in production. The fix is unglamorous: wrap the model call in a retry with backoff, and fall back to a clear default recommendation instead of surfacing an error to whoever's using the dashboard. New customers needed the same kind of intentional handling — with no recall history at all, "no memory found" became its own explicit backend state rather than something buried inside the prompt, which made the contrast between a new customer and a returning one obvious both in the logs and on screen. What I'd Tell Someone Building Something Similar Storing history isn't the same as using it — if the output doesn't visibly change because of what was recalled, you've built an expensive log viewer, not a learning agent. What you write matters more than how cleverly you read it back. Design for the zero-history case on purpose, not as an afterthought. And keep a human in the loop for anything touching real money — the agent recommends, a person decides, and that boundary made the whole system feel trustworthy instead of reckless.


Tech StackMemory: Hindsight Cloud by Vectorize | LLM: Groq — openai/gpt-oss-120b | Backend: FastAPI (Python) | Data: Postgres/SQLite | Frontend: a simple React/HTML dashboard. The architecture stays intentionally small — the intelligence comes from what the memory layer is fed, not from how many moving parts the backend has. Why This Matters Beyond Payment Recovery The retain-then-recall pattern behind PayEcho isn't specific to collections. Any workflow where a past outcome should shape a future decision — support tickets, sales follow-ups, operations reviews — has the same shape: an event happens, something gets tried, an outcome gets recorded, and the next similar event should be informed by what actually happened last time rather than treated as brand new. Most agent projects skip this entirely and call the result intelligent anyway. The difference is easy to miss in a demo and impossible to miss in production, which is exactly why I think the backend decision — not the prompt, not the dashboard — is the part worth getting right first.

Top comments (0)