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

Your Customer Got the Same Message Three Times. Your Scheduled Agent Sent It on Every Channel at Once.

A customer gets a reminder at 9:00 in the morning. It arrives by email. Two minutes later, the same reminder arrives by text message. Two minutes after that, it shows up in chat. Same wording, same appointment, same request to confirm. From the customer's side, this does not look like thorough follow-up. It looks like nobody is keeping track. Nobody told the agent to send the message three times. Each channel did its own job correctly, and that is exactly the problem. The email workflow sent th

A customer gets a reminder at 9:00 in the morning. It arrives by email. Two minutes later, the same reminder arrives by text message. Two minutes after that, it shows up in chat. Same wording, same appointment, same request to confirm. From the customer's side, this does not look like thorough follow-up. It looks like nobody is keeping track.

Nobody told the agent to send the message three times. Each channel did its own job correctly, and that is exactly the problem. The email workflow sent the reminder. The text workflow sent the reminder. The chat workflow sent the reminder. None of them knew the others had already sent it.

One message, three senders

A scheduled agent often looks like one agent from the outside. On the inside, it is usually several workflows that happen to share a schedule. One workflow owns email. Another owns SMS. A third owns chat. Each one pulls its own list, checks its own conditions, and sends. They were built at different times and tested one channel at a time. Tested that way, each workflow passes. Run together, they triple-send.

The customer does not experience three workflows. The customer experiences one business that cannot remember what it just said. A repeated message makes the next message less believable: when a real change arrives later, the customer may ignore it, assuming it is another copy of something already seen.

Where the duplicate comes from

The first source is the separate list. Each channel workflow builds its own send list. The email list says this customer needs a reminder. The SMS list says the same thing. The chat list says the same thing. There is no step where the three lists are compared, because no workflow owns the comparison. Three lists saying the same thing should produce one send, not three.

The second source is the missing send record. A send is an event that should be recorded once, in one place, where every channel can see it. In many setups, each channel records its own send in its own log. The email tool knows it sent the email. The SMS tool knows it sent the text. Neither record is visible to the other workflow, so the next workflow in line has no reason to stop. A send recorded only inside the channel that sent it is not a shared fact. It is a private note.

The third source is the reply that only reaches one channel. A customer confirms on chat, and the chat workflow marks the reminder as answered. The email and SMS workflows, which already built their lists, never see that confirmation. They send anyway, after the customer already answered. The confirmation existed. It just never travelled to the workflows that needed it.

The fourth source is overlapping runs. A reminder workflow that runs every hour, plus a daily digest, plus a follow-up triggered by an event, can all decide the same customer needs the same message. Each run is reasonable on its own. Together they produce a burst. Without a shared record of what was already sent, for this customer, about this appointment, in this window, every run starts from zero and reaches the same conclusion.

All four failures share one root cause. The decision to send is made per channel, from a per-channel picture, with no shared memory of what has already been sent. The agent does not have a sending history. It has three sending histories that never meet.

The check that has to happen before every send

The fix is a habit that sits in front of every channel, not inside any one of them. Before any message goes out, the agent should check one shared record and ask three questions. Has this message, for this customer, about this appointment or order, already been sent, on any channel, within this window? Has the customer already answered it, on any channel? If a send is still needed, which channel should carry it?

That record needs a few specific parts. It needs the customer, identified the same way on every channel, so an email address, a phone number, and a chat handle for one person resolve to one person. It needs the message itself, named by what it is about, so a reminder about Tuesday at 10 is recognizably the same reminder on every channel. And it needs the time sent, the channel used, and the outcome: delivered, answered, ignored, or superseded.

With that record in place, the channel decision changes. The agent no longer asks each channel whether it should send. It asks the shared record whether a send is still needed, and then it picks one channel for it. The other channels stand down, not because they are broken, but because the job is already done. When the customer replies on any channel, that reply lands in the same record, and every channel sees it before its next send.

This is where a shared memory layer changes the problem. Vilix AI is cloud-hosted, so there is no infrastructure to set up or maintain. A scheduled agent connects over MCP and reads the same memory every run. It stores full conversation history, not just extracted facts, so the actual thread is there to check, including what was already sent, where it was sent, and what the customer already answered. Because the same memory follows the agent across tools and devices, a confirmation that arrived by chat is visible to the workflow that sends email, and a decision made in one run is visible to the next. The plan is free forever, with a 7-day Pro trial that needs no credit card, and everything can be exported or deleted at any time.

What to change this week

Start with one message type, not every message at once. Appointment reminders are a good first candidate, because the duplicates are easy to spot. Give that message a single send record that every channel workflow reads before sending.

Next, resolve customer identity across channels. An email address, a phone number, and a chat handle for the same person must map to one customer in the record. Until they do, the shared record cannot work, because each channel will keep describing the same person as a stranger.

Then add the reply rule. A reply on any channel marks the message as answered everywhere, and a send that is already answered never goes out again. Test it with the case that breaks most setups: the customer confirms on chat, and the email workflow runs ten minutes later. If the email still goes out, the reply did not travel.

Finally, pick a default channel per message type, and let the other channels act as backup only when the first channel fails or goes unanswered for a defined window. A backup channel is useful. Three simultaneous channels are not backup. They are the same message wearing three outfits.

A customer who gets one clear message trusts the next message more. A customer who gets the same message three times learns to ignore all three. The difference is a memory of what was already sent, shared across every channel before the next send.

Vilix AI

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