Your Scheduled Agent Sent the Same Email Twice. It Forgot It Already Sent It.
A customer opens their inbox and finds the same message twice: same subject, same reminder, minutes apart. Nothing looks broken on your side. The workflow ran, the logs show success, and the agent did exactly what it was told to do. It just did it twice, because the second run had no memory of the first. A double send feels small until it lands in front of a customer. One extra email looks sloppy, and two copies of an invoice reminder look aggressive. Customers do not think about retries or run
A customer opens their inbox and finds the same message twice: same subject, same reminder, minutes apart. Nothing looks broken on your side. The workflow ran, the logs show success, and the agent did exactly what it was told to do. It just did it twice, because the second run had no memory of the first.
A double send feels small until it lands in front of a customer. One extra email looks sloppy, and two copies of an invoice reminder look aggressive. Customers do not think about retries or run history when they see a duplicate. They think the business is careless.
A double send is rarely a bug in the message itself. What was missing was a record the next run could check before sending again.
Why a scheduled run sends twice
A scheduled agent usually starts each run by pulling a list and sending what the list says to send. That breaks in four common ways, all sharing one cause: the run cannot see what the previous run already did.
First, the retry problem. A run sends the email, then fails, times out, or crashes before it records the send. The platform retries the run, or the next scheduled run picks up the same list item, and the agent sends again. From the agent's point of view, this is the first time. From the customer's point of view, it is the second.
Second, the requalification problem. A customer meets the criteria for a message, receives it, and then meets the criteria again. If the automation re-enrolls people who meet the criteria again, the same customer can receive the same series a second time, starting from the first message. The agent followed a rule that never asked whether this person had already received this message.
Third, the double-trigger problem. The same customer enters the same automation through two triggers at once, or two workflows overlap and both decide to send. Each run is correct on its own. Together, they produce two copies, because neither run knows about the other.
Fourth, the partial-failure problem. The email provider accepts the message, but the workflow times out before the success is recorded. The run's record says the send is uncertain, so the safe-looking choice is to send again. The result is a duplicate, created by a system trying to be reliable.
The agent simply had no durable answer to the one question that prevents a duplicate: has this exact message already gone to this exact person?
A run log is not a send memory
Checking logs helps a person investigating a complaint, but it does not help the next run, because a run log records what happened without making it usable as a decision.
A log says a workflow ran at 7:00 and completed. It does not, by itself, answer whether a specific invoice reminder went to a specific address, which version went out, or whether the customer replied or paid in between. Finding that answer means searching across the scheduler, the workflow history, and the mail provider, each with its own identifiers. A scheduled agent that wakes up blank will not do that search.
Spreadsheets and workflow variables fail in a similar way. A column that tracks the last stage sent works until a run crashes between the send and the sheet update, or until a second workflow sends without updating the same sheet. A variable inside one run dies when the run ends. None give the next run a single, trustworthy place to ask: did this send already happen?
The check that stops the second copy
Start with a stable key for each send. A good key combines the recipient, the message, and the period it belongs to: the customer plus the invoice reminder stage, or the subscriber plus the weekly report date. If two runs generate the same key, they are talking about the same send, not two similar sends. Without a stable key, every check turns into a fuzzy search, and fuzzy searches are how duplicates slip through.
Next, check the key before sending, and write it as pending before the message goes out. If the record is written only after a successful send, a crash between the send and the write leaves the next run blind. If it is written as pending first, a crashed run leaves a marker the next run can see. That next run should not blindly resend. It should route the uncertain send to a review list, where a person can confirm whether the message actually went out.
Finally, record the outcome in the same place: sent, failed, or uncertain, with the date and the version that went out. That record makes the next run safe, and it makes the system explainable: when a customer asks why they received a message, the answer is one lookup away.
A send record must also live where every workflow that can send that message can read it. Shared sends need shared memory.
Give the agent a memory it cannot lose between runs
A shared memory layer changes the shape of the problem. Instead of each workflow keeping its own sheet and its own version of the truth, the agent reads from and writes to one memory that survives across runs, tools, and platforms.
Vilix AI is built for exactly that pattern. It is cloud-hosted, so there is nothing to install or maintain, and the same memory follows the agent across every tool over MCP. The agent can check its send record before it sends, write the pending marker before the message goes out, and update the outcome after, all in the same place the next run will look. Because Vilix AI stores full conversation history, not just isolated facts, the memory can also hold what happened after the send: a reply, a payment, or a cancellation that should stop the next message.
A duplicate is often only the visible half of the problem. The same blank run that sends twice also sends after a customer replied or paid, because the reply lives in a conversation the run never reads. Full history lets the run check the whole story, not just the last send.
Getting started does not require rebuilding the workflow: connect the agent to Vilix AI, give the send check a stable key, and make the check part of every run that sends. The free plan is free forever, and a 7-day Pro trial needs no credit card. Data stays portable and can be exported or deleted at any time.
Before the next run sends anything, it should be able to answer from memory: has this exact message already been sent to this person, is there a pending send that needs review instead of a resend, and has anything changed since the last send that should stop this message?
Customers forgive a late message far more easily than a duplicate one. A late message says the system was careful. A duplicate says nobody was watching. Give your scheduled agent the one thing that stops the second copy: a memory of the first.
Learn more about giving your agents a memory that survives between runs at Vilix AI.