Free forever, no credit card.Get Started for Free →
← All posts
October 31, 2026 · 6 min read

You Billed Them Once. Why Did Your Scheduled Agent Invoice Them Again?

You Billed Them Once. Why Did Your Scheduled Agent Invoice Them Again? A customer pays for an order on Tuesday. On Wednesday, a second invoice for the same order lands in their inbox. Nobody asked for a second bill. The customer writes back, confused, and your finance team spends the afternoon proving only one payment is owed. Nothing in the workflow obviously failed. The schedule fired on time, the invoice was created, and the run log shows success. The duplicate is a memory error: the second

You Billed Them Once. Why Did Your Scheduled Agent Invoice Them Again?

A customer pays for an order on Tuesday. On Wednesday, a second invoice for the same order lands in their inbox. Nobody asked for a second bill. The customer writes back, confused, and your finance team spends the afternoon proving only one payment is owed.

Nothing in the workflow obviously failed. The schedule fired on time, the invoice was created, and the run log shows success. The duplicate is a memory error: the second run never learned that the first run already billed the order.

How one order becomes two invoices

The most common cause is the retry that looks like a fresh start. A scheduled agent creates an invoice, and the confirmation does not come back: the connection times out, the billing tool returns an unclear error, or the run crashes after the invoice exists but before the result is recorded. The agent reads that as failure and tries again, and the second attempt does not know the first one succeeded, because nothing recorded the success where the next run looks.

A second cause is the overlapping run. Two scheduled runs pick up the same batch of unbilled orders. Neither run can see the other's work in progress, so both bill the same order. This happens when a run takes longer than the gap between schedules, or when a missed schedule fires late and collides with the next one.

A third cause is the split identity problem. The order lives in one system under one ID, and the invoice lives in another under a different one. A guest checkout, a marketplace order, or a subscription renewed under a new reference can all produce two records for one purchase. An agent that matches on a single ID finds no existing invoice for the order it is looking at, so it creates one.

A fourth cause is the missing completion record. The agent bills the order, but the fact that it billed it is stored only in the run log, or in a field the next run never reads. Run logs are history, not memory. A log can tell a human what happened after the fact. It cannot stop the next run from doing it again.

In every case, the pattern is the same. The agent did not set out to double-bill anyone. It simply woke up, looked at the order, found no evidence that the order had already been invoiced, and did the reasonable thing: it invoiced it.

What the agent needs to know before it bills

Stopping duplicate invoices is not about making the agent more careful. It is about giving each run four facts it can check before it creates anything.

First, the order and its billing state, in one place: order ID, total, and whether an invoice already exists for it, with the invoice number and the date it was issued.

Second, the attempt history: every billing attempt for that order, including the ones that timed out or returned an unclear error. A timed-out attempt is not the same as a failed attempt. If an attempt went out and no confirmation came back, the next run should verify what happened before it tries again, not simply try again.

Third, a stable key for the work itself: one identifier for the job of billing this order, reused across retries instead of generated fresh each time. When the billing tool supports idempotency keys, that key lets the tool recognise a repeated attempt as the same job and return the original invoice. When it does not, the same key still lets your own check recognise the repeat before the create call ever runs.

Fourth, who owns the order right now: which run or workflow is currently handling it. A claim that expires if the run dies, so a stuck run cannot block billing forever, but a live claim stops a second run from picking up the same order.

With those four facts, the check before each invoice becomes simple: has this order already been invoiced, is an attempt already in flight, or is another run already handling it? If the answer to any of those is yes, the run stops.

The order of checks that actually prevents the duplicate

The order matters as much as the checks themselves. The run should claim the order first, so no overlapping run can take it at the same moment. Then it should look for an existing invoice by order, not just by invoice number, because the duplicate will always carry a new number. Then it should verify recent attempts, including timed-out ones, with the billing tool before creating anything new.

Only after all three checks pass should the run create the invoice, and it should record the result immediately, in the same place the next run will look. A result recorded at the end of a long run, or only in a log file, is a result the next run may never see.

A short daily reconciliation check, comparing orders against invoices, catches any duplicate that slipped through before a customer reports it.

One memory your scheduled agent can actually check

This is the gap Vilix AI closes for scheduled agents. It is a cloud-hosted memory layer, so there is no infrastructure to run and nothing to install. A scheduled agent connects to it over MCP, and the same memory is available to every tool the business uses.

Instead of a run log that only a human reads after the damage is done, the agent reads a living record before it acts: the order, its billing state, the attempts already made, the stable key for the job, and which run currently owns it. A timed-out attempt still shows up, so the next run verifies instead of blindly retrying. An overlapping run sees the claim and stops before it creates anything.

Vilix AI stores full conversation history, not just facts, so the record keeps the context around the billing too: the support thread where the customer questioned a charge, the reply that explained it, the note that this account wants one consolidated invoice. The next run does not just know the order was billed. It knows the story around the billing.

The free plan is free forever, and the Pro trial runs seven days with no credit card required. The memory stays portable too: everything can be exported or deleted at any time.

The test to run this week

Pull the last ten duplicate invoices your team had to void. For each one, ask a single question: at the moment the second invoice was created, could that run see the first invoice, the timed-out attempt, or the other run's claim? If the answer is no for most of them, the problem is not the billing tool or the schedule. The problem is that the agent's memory stops at the end of each run, and the billing state lives somewhere the next run never looks.

Fix that one read, and the second invoice stops appearing. The agent still bills every order that is genuinely unbilled. It just stops billing the ones it already billed.

Get Started for Free

Persistent memory across ChatGPT, Claude, and the AI tools you already use in Vilix AI.

Get Started for Free

Free forever, no credit card.

Keep reading
Does Base44 Remember Between Sessions? Two Different Memories, Two Different Answers

Does Base44 Remember Between Sessions? Two Different Memories, Two Different Answers Short answer: yes, in two separate places, and neither one is the memory most people mean when they ask the question. The AI chat that builds your app keeps its conversation, its plans, and the instructions you wrote for that app. The AI agents you build inside your app have their own memory, on by default, that carries preferences and facts across conversations with your app's users. Both are real. Both stop a

Does v0 Remember Between Sessions? Chat Context, Knowledge, and Where It Stops

Does v0 Remember Between Sessions? Chat Context, Knowledge, and Where It Stops Short answer: inside one chat, yes. Across chats, projects, and the rest of your tools, mostly no, unless you wrote the context down yourself in the places v0 calls Knowledge and custom instructions. That distinction matters because v0 feels continuous while you work in it. You return to a chat, the conversation is still there, the generated app is still there, and iteration picks up where it left off. It is easy to

Does Bolt Remember Between Sessions? Chat Threads, Knowledge, and Short-Term Memory, Explained

Does Bolt Remember Between Sessions? Chat Threads, Knowledge, and Short-Term Memory, Explained Short answer: the project remembers, because the project never goes away. Your code, your chat thread, your version history, and your backups are all still there when you come back tomorrow, so picking the work back up feels continuous. But Bolt does not build a learned memory of you or your decisions the way a memory product does. What carries between sessions is the work itself, plus whatever contex