Target query: how to stop scheduled ai agent redoing the same work
Slug: scheduled-agent-memory-of-done-completion-ledger
Published: 2026-09-23
Surface: dev.to (this version)
Companion piece (vilix.ai blog, full rewrite): agent-completion-ledger-stop-redoing-work.md
- dev.to: TBD
- vilix.ai blog: TBD
Your Scheduled Agent Keeps Re-Doing Finished Work. Teach It What "Done" Means.
Your ticket-triage agent diligently triages the same 40 support tickets every morning. Your lead-scoring agent re-scores the same leads. Your reporting agent files Tuesday's report, then generates it again Wednesday as if Tuesday never happened.
The agent is not lazy or broken. It is diligent with a blank slate: every scheduled run starts with zero knowledge of what previous runs finished, so it repeats work that, as far as it can tell, nobody did.
The fix is not a better prompt or a bigger context window. It is a specific kind of memory most automation setups never build: a record of what is already done.
The problem: runs that remember nothing finished
An n8n workflow, a Make scenario, or a scheduled script is stateless by default. Each execution starts fresh: it pulls the inputs, hands them to the agent, the agent acts. When the run ends, whatever the agent did evaporates. Tomorrow's run repeats the same pull and acts on the same items again.
The symptom is duplication, not confusion: the agent does real work and then loses all evidence it happened. The same ticket answered twice, the same lead enriched twice, the same report filed twice.
Stored rules do not fix this: "always tag billing tickets urgent" survives between runs but says nothing about which tickets were handled. Fresh state checks do not either: a ticket can be "open" right now and still have a reply drafted by Tuesday's run.
What the agent is missing is a memory of completed work.
The completion ledger
The working pattern is a completion ledger: a small, durable record of what the agent already did, checked before every action and updated at the end of every run:
1. Stable identities for work items. The agent can only remember "done" if it can recognize the same item twice. That means identifying each work item by something stable: a ticket ID, an email thread ID, a lead record ID, a content hash of the row. "The email from Sarah about the refund" is not stable. ticket_8841 is.
2. Check-before-act. Before the agent does anything with side effects, it looks the item up in the ledger. Already there with a matching action? Skip it. Not there? Proceed. This check has to be a hard step in the workflow, not a polite suggestion in the prompt. Prompts get skimmed; a lookup step gets executed.
3. Write the outcome at the end of the run. Record what was done, to which item, when, and the outcome: not "handled ticket 8841" but "replied to ticket 8841 at 09:04, reply sent, awaiting customer response." The next run needs enough detail to tell whether "done" is still done.
"Done" expires
Here is the part most first versions get wrong: done is not forever. A lead contacted in January may be fair game again in April, a "resolved" ticket can reopen, and last week's report is stale by Friday.
So completion records need expiry, and the expiry should match the task:
- Contact actions (emails, follow-ups, outreach): expire after weeks or months, depending on your cadence. A 90-day window on "already emailed" is a common starting point.
- Triage and classification: expire when the underlying item changes. A re-tagged ticket is a new triage decision.
- Data enrichment: expire when the source data is refreshed.
- One-way sends (reports filed, webhooks fired): the scariest to get wrong, because re-doing them has visible side effects. Give them the longest memory and the strictest identity checks.
Without expiry, a completion ledger turns into a different failure: the agent refusing to act on things it legitimately should act on again. "I already emailed them" is wrong if the email bounced, a reply arrived, or six months passed. The ledger must record enough context to separate "done and still done" from "done but circumstances changed."
Where the ledger lives matters more than what is in it
A completion ledger only works if every agent that could repeat the work reads the same one. This is where per-workflow storage quietly fails.
Your n8n workflow keeps its own "processed" list, your Make scenario keeps another, and a contractor's scheduled script keeps a third in a local file. The n8n agent has no idea the Make scenario already contacted the lead, so it contacts them again. Each ledger is correct about its own workflow and blind to the others.
The fix is one shared ledger every agent and tool reads before acting. That is what a shared memory layer is for. Vilix AI is built for this shape: cloud-hosted, so there is no database to run, and connected to agents over MCP, so the same memory follows the work across Claude, Codex, Cursor, OpenClaw, Hermes, or any MCP-compatible AI. A completion record written by the n8n agent is visible to the Make scenario's agent and the scheduled script, because they all read the same store. Last write wins and retrieval is recency-aware, so the next run sees the newest version of every record.
It stores full conversation history, not just extracted facts, so a ledger entry carries the actual context, not just a "done" flag. Low risk to try: a free plan forever, a 7-day Pro trial with no credit card, and your data stays yours, exportable or deletable anytime in a portable format.
The guardrails a ledger does not replace
A completion ledger stops duplicate work. It does not make the agent trustworthy on its own.
First, destructive actions still need a human gate. "Did I already send it" is a different question from "should I send it." A ledger that perfectly tracks sends can still perfectly track a send that should never have gone out. Refunds, deletions, outbound messages to customers: keep a human approval step before those, ledger or not.
Second, the ledger is only as honest as the agent's reporting. If the agent records "email sent" when the API call failed, the ledger becomes a machine for skipping work that was never done. Record outcomes from tool results, not intentions: the write happens after the tool confirms success.
Third, partial work needs partial records. An agent that enriched 8 of 10 lead fields and crashed must not record "lead enriched." Record per-item, per-action granularity, so the next run picks up exactly where the last one stopped.
The cheapest reliability upgrade in your stack
Most scheduled-agent reliability work goes to prompts: sharper instructions, longer context, more examples. Prompts do not remember Tuesday. A completion ledger does.
Teach your agents what "done" means, store it somewhere every run can see, and let expiry rules keep it honest. The duplicate emails stop, the re-triaged tickets stop, and the agent finally spends its runs on new work.
Top comments (0)