Why a Scheduled AI Agent Kept Reporting Success While Doing Nothing

Published

A scheduled agent job I was running kept reporting success while doing nothing at all. Not once, twice, for two different underlying reasons, both invisible from the outside until I went and reproduced the exact command by hand. That's the actual subject of this post: not a framework tutorial, a specific failure mode that's easy to build into any automation that runs a Claude Code agent headlessly on a schedule, and the fix that removed it entirely.

The Setup That Looked Obviously Right

The straightforward way to run a recurring agent job is a scheduled task that spawns a headless CLI process, authenticated with an API key, at a fixed time. That's what I built first. It's the pattern every tutorial suggests, and it worked in initial testing.

The problem showed up later, in production, in a way that looked exactly like success.

Where It Actually Broke

Twice, on two separate days, the scheduled process exited with code 0, the standard "everything worked" signal, having done nothing at all.

The first time, a stale authentication credential was silently blocking the API key from ever being used as a fallback. The process attempted to authenticate, failed against expired credentials, and gave up cleanly, no error surfaced anywhere the scheduler could see.

The second time, the API balance had simply run out. The process checked its credit, found none, and exited. Also code 0. Also invisible.

The Real Problem Underneath

Neither of these was a one-off bug. They're the same underlying issue: a headless process has no way to recover from, or even clearly report, a class of failure that happens before real work starts. The exit code is supposed to mean "this succeeded." For both of these failures, it didn't mean that, and there was no automated way to tell the difference from outside the process.

That's a reliability problem baked into the architecture, not something a retry loop fixes. Retrying a process that reports false success just gets you the same false success again.

What Fixed It

The fix wasn't a better error handler. It was running the same agent logic somewhere with a fundamentally different failure mode: inside a live, resident session instead of a fresh headless process spawned by an OS-level scheduler.

A resident session stays open and schedules its own work internally instead of relying on the operating system to spawn a new process each time. Two things change as a result. Failures become visible, because there's an actual running context to report back into, not a process that exits before anyone's watching. And billing changes too: work done inside a live session runs as normal usage instead of metered per-token API calls, which was the second problem this setup was quietly causing alongside the reliability issue.

The tradeoff is real and worth naming directly: a resident session has to actually stay running for its scheduled jobs to fire. There's no equivalent of a machine waking itself from sleep to run a one-off script. That's a genuine constraint, not a free upgrade, and it's worth deciding on purpose rather than discovering by accident.

A Second, Unrelated Discovery From The Same Project

While debugging this, a second failure showed up in a completely different part of the same system: automating a browser action through a standard headless automation library got blocked by the target site's bot detection, every time, even with a real human clicking in the same visible window.

The same action, driven through a real, already-logged-in browser session instead, worked cleanly, no detection at all. The lesson generalizes past this one case: the "automated" version of something and the "actually working" version aren't always the same implementation, and it's worth testing that assumption directly instead of assuming automation-in-general behaves the same way regardless of how it's driven.

What This Actually Costs You

Running agents inside a resident session instead of headless scheduled processes isn't strictly better in every dimension. It trades OS-level reliability (a scheduled task survives a reboot on its own) for a different kind of reliability (failures are visible and billing is predictable). Which tradeoff is right depends on what's actually being automated and how much it matters if a single cycle gets missed because a session wasn't open.

For a job where silent, costly, undetected failure is worse than an occasional missed cycle, this tradeoff is the right one. It won't be the right call for everything.

Debugging a scheduled automation that looks fine but isn't?

I build and fix exactly this kind of agent infrastructure, using real scripts and direct API access, not off-the-shelf no-code platforms.