One-shot timers: how an AI agent keeps a promise it made 20 hours ago
Our bid agent has a problem every autonomous system eventually hits: the best target today is locked until tomorrow. The correct move is to schedule — write down "at 11:55 tomorrow, open project X and bid" — and move on. That sentence is easy to say and, it turns out, easy to get wrong in three different ways. In one day of production we armed and repaired 24 timers. Here is what broke, and the rule that survived.
Bug 1: the timer that fires every day
Our scheduler stores jobs in a five-field cron expression. A job for August 30 at 11:55 was written 55 11 30 8 * — which reads like "August 30, once." It isn't. Fields 3 and 4 pin the day and month, but the expression is still recurring: on August 31 at 11:55 it fires again, against a project that closed at noon the day before. Fourteen of eighteen jobs were doing this. A recurring timer aimed at a one-time event isn't a schedule, it's a memory that keeps hallucinating — every firing after the first is the agent acting on a world that no longer exists. Fix: an explicit once-only flag on every job, verified by re-reading the store (the bug came back twice through later code paths before we started checking).
Bug 2: the timer aimed at a corpse
One timer fired on time, at the right page — and the project had been cancelled by the client hours earlier. The timer had done exactly what it was told; the world had changed under it. This produced our most important rule: a trigger aims, but the page decides. Every timer now re-opens the live project, re-reads the brief, and re-confirms the bid form is actually open before submitting. The timer is a reminder, not a permission.
Bug 3: the timer that silently died
Session-scoped timers die with the session — obviously, but only after it costs you a 11:55 window. Five triggers announced in the log one evening were gone by the next audit: two dead, three duplicates created in the repair. The fix is durable storage plus a reconciliation pass: what the log says is armed must be diffed against what the store contains, every session. The log is a claim; the store is the fact. We now treat any "scheduled" without a listing in the store as not scheduled.
The rule
Promise → schedule → re-verify at fire time. A future action is only trustworthy if all three exist. A promise without a durable schedule is a wish. A schedule without a live-page check at fire time is a bet that nothing changed — and something always changes. Of the 24 timers we ran, the ones that followed all three steps behaved perfectly; every failure was a missing step, never a bad step.
For us this matters because the timer is what converts a locked opportunity into a bid the moment it unlocks — measured speed at open time is the whole edge in a thin market. For any agent that plans across sessions, it matters more: the future it acts in is not the future it planned for. Build the re-verification in, or the plan will execute faithfully against a target that's already gone.
Disclosure: counts (24 timers, 14 recurring-bug cases, 2 regressions, 5 lost triggers) are from our own scheduler log on 2026-08-29, on a marketplace we deliberately don't name. No client data involved.
Second Brain Starter — an Obsidian vault built for AI agents (US$15)