Oh My Learning

Continuous Agent Execution: Pausing, Resuming, and Operating Without a Session Boundary

tool-use-agentic-loop/11 staff drafted · 23 min read

Anthropic, Effective harnesses for long-running agents (Nov 2025); Microsoft Agent Framework, Handling long-running operations with background responses (devblogs.microsoft.com, 2026); OpenAI, Background mode - OpenAI API docs (2026); Google Developers Blog, Build long-running AI agents that pause, resume, and never lose context with ADK (2026); Google ADK Docs, Resume Agents (2026); LangChain, Introducing ambient agents (Jan 2025); Diagrid, Checkpoints Are Not Durable Execution: why LangGraph, CrewAI, Google ADK and others fall short for production agent workflows (2026); Zylos Research, Durable Execution for AI Agent Runtimes: Checkpointing, Replay, and Recovery (Apr 2026); Zylos Research, Agent Observability and Debugging: Tracing Autonomous AI Systems in Production (May 2026); DEV Community, How Much Does It Actually Cost to Run an AI Agent 24/7 in 2026? I Tracked Every Dollar for Three Months (2026)

Prerequisites tool-use-agentic-loop/08 prompting-context-engineering/10

Continuous Agent Execution: Pausing, Resuming, and Operating Without a Session Boundary#

TL;DR#

Most agent loops are designed around an implicit assumption: the process that started the task is the process that finishes it, in one uninterrupted run. Continuous agents break that assumption on purpose - they watch for events, wait days for a human to sign a document or a third-party API to finish a job, and must survive a process restart, a deploy, or a dropped connection without losing their place. That requires three things a request-response loop never needed: state durable enough to outlive the process, an explicit mechanism to resume exactly where execution stopped, and an idle-time cost model, because the meter keeps running even while nothing visible is happening.

The idea#

Lesson 08 answered "when should this loop stop." This lesson is about loops that are not designed to stop at all in the ordinary sense - they are designed to run indefinitely, punctuated by long, unpredictable pauses, and the engineering problem is not deciding to end but surviving the gap. A customer-support agent that answers one ticket and returns is a request-response loop with a session boundary a human can see: the human sent a message, the agent replied, the interaction is over. An onboarding agent that sends a new hire's welcome packet, then needs to wait three days for HR to confirm the signed paperwork before it can provision hardware, is a fundamentally different shape - the "session" spans days, the process that started the task is very likely not the process that finishes it, and nothing about that multi-day gap is a failure. It is the expected steady state.

prompting-context-engineering/10 already covered a related but distinct problem: a context window filling up within one continuous run, and the choice between compacting it in place or handing the remaining work to a fresh context. That lesson's failure mode is context-window pressure while the process is still alive and reasoning continuously. This lesson's failure mode is different in kind: the process itself goes away - crashes, gets redeployed, the container scales to zero, the user closes their laptop mid-stream - and comes back later, possibly on different hardware, with no memory of anything unless something outside the process's own runtime remembers for it. Compaction and handoff assume you get to choose when the transition happens and control what crosses it. A process restart offers no such choice: it can happen at any point in the loop, including mid-tool-call, and the agent has to be built to tolerate that from the start rather than to gracefully wind down when told to.

The reason this is a staff-level concern rather than an implementation detail: getting it wrong doesn't produce a crash you notice immediately. It produces silent duplicate work (an agent that re-sends a welcome email because it forgot it already sent one), an agent that appears "stuck" forever because nothing is polling for the event it's waiting on, or a support burden nobody budgeted for because the agent's cost accrues around the clock rather than per completed task. None of that shows up in a demo where the process never restarts and the whole interaction happens in one sitting.

How it works#

Three requirements a continuous agent has that a single-session loop does not#

  1. Durable state, not just accumulated context. The state that matters - what step the agent is on, what it is waiting for, what side effects it has already caused - has to be written somewhere that survives the process dying, not held only in an in-memory conversation object. This is a stronger requirement than context management: a context window can be huge and still evaporate completely the instant the process is killed, unless it is also persisted.
  2. A resumption mechanism, so a new process invocation (possibly on different hardware, possibly hours or days later) can pick up exactly where the last one left off instead of starting over or, worse, half-repeating work. Concretely this takes the shape of a continuation token, a checkpoint plus a stable identifier to resume against, or an equivalent handle - the specific vendor primitive varies, but the shape (a durable pointer into a durable execution history) is the same everywhere.
  3. Idle-time handling for the gaps themselves - deciding whether the agent polls, waits for a webhook, or sits truly dormant while nothing is happening, because each of those choices has a different cost and latency profile, and getting it wrong (aggressive polling during a three-day wait) is a specific, avoidable expense that a single-session loop never has to think about.

Worked example: continuation tokens for resuming an interrupted stream#

Microsoft's Agent Framework exposes background responses for exactly this problem: instead of a client blocking on a synchronous call until a long-running agent task finishes, the call returns a continuation token immediately. The token "captures the current state of the operation," and stays non-null until the operation has completed, failed, or needs external input; a client (or a fresh process, after a restart) resumes by passing that same token back in, either polling for completion or resuming a dropped stream from the exact sequence number it was interrupted at. The documented pattern starts polling at a 2-second interval and recommends exponential backoff as the wait stretches from seconds into minutes - a small but concrete illustration of the idle-time-handling requirement above: naive fixed-interval polling for a multi-minute operation wastes calls, so the resumption mechanism and the polling cadence are tuned together. OpenAI's Responses API exposes the analogous shape under a different name: each response carries an id, and passing it as previous_response_id on the next call tells the API to treat that call as a continuation of the same logical task, with response objects retained server-side (30 days by default) so a client that comes back later can still resume against them.

Example (2026): these are swappable boxed examples of the same underlying pattern - a durable pointer that lets a different process invocation resume a task without replaying it from scratch. The exact object (a continuation token, a previous_response_id, a checkpoint ID) and its retention window are vendor-specific and will keep changing; the requirement they satisfy - "give me a durable handle I can hand to any future process, not just this one, to pick this exact task back up" - is the durable part.

Worked example: pausing for days, resuming from a webhook, scaling to zero#

Google's Agent Development Kit (ADK) documents a new-hire onboarding agent that runs across weeks, not minutes, to make the durable-state requirement concrete. The agent's state lives in three pieces written to a DatabaseSessionService (SQLite locally, Cloud SQL in production): a current_step field tracking position in an explicit state machine (START, WELCOME_SENT, DOCUMENTS_SIGNED, ...), a data payload for the specific new hire, and a list of external events the agent is waiting on. The flow: 1. The agent sends a welcome packet, and the moment that tool call succeeds, current_step is durably written as WELCOME_SENT - before the process does anything else. 2. The agent is instructed, in its own prompt, not to call any further tools while current_step is WELCOME_SENT - it reports to the user that it is paused, waiting for document signatures, and stops. There is no loop spinning waiting for the signature; the container can scale to zero for the entire multi-day gap, because nothing about the wait depends on the process staying alive. 3. Days later, a webhook fires when the documents are actually signed. That webhook invokes run_async() with a state_delta that atomically flips current_step to DOCUMENTS_SIGNED before the agent's next inference call runs - so the very first thing the resumed agent sees is a state that already reflects the event that woke it up, not a stale snapshot it has to reconcile itself. 4. The agent resumes, delegates IT provisioning to a sub-agent, and the same pause-webhook-resume cycle repeats for hardware delivery.

The load-bearing design choice here is that the pause itself is a first-class, checkable state, not an absence of activity the system has to infer. An agent that is merely "not currently running" looks identical, from the outside, to an agent that crashed - the explicit current_step/pending_signals state is what lets a monitoring system, or a human, tell the difference between "correctly waiting" and "silently broken."

Worked example: durable state as files and commits, not a database#

Not every continuous agent needs a purpose-built session service. Anthropic's own documented harness for long-running coding agents persists state as ordinary artifacts a git repository already understands: a claude-progress.txt log of what was done in each prior session, a feature-list JSON with several hundred individually testable requirements each carrying a passes: false/true flag (so the agent cannot declare victory by narrative alone - a concrete tie-in to the explicit stop-condition discipline from tool-use-agentic-loop/08), and the git commit history itself as the append-only record of what actually happened. A new session, which may be an entirely new process with zero memory of the previous one, is prompted to re-ground itself deterministically before doing anything else: run pwd, read the git log and the progress file to see what the last session did, pick the highest-priority still-failing feature, run a smoke test, and only then resume work. Nothing here depends on a specially engineered checkpoint format - the durability comes from writing state to a filesystem and a version-control history that were already going to persist independently of the agent process, and the resumption mechanism is simply a fixed, scripted re-grounding sequence run at the start of every session rather than a token handed between calls.

Checkpoints are not automatically durable execution#

It is tempting to treat "the agent writes its state to disk periodically" as equivalent to the guarantees above, and it is not automatically true. A widely cited practitioner critique of framework-level checkpointing (as opposed to a purpose-built durable-execution runtime) points out three gaps that a plain checkpoint, by itself, does not close: nothing detects that a process crashed in the first place (no heartbeat, no watchdog - a crashed agent looks exactly like an idle one from the outside unless something is explicitly checking); resuming after a detected crash is a manual step someone or something has to trigger correctly, with the right identifier, rather than something that happens automatically; and nothing prevents two different processes from both deciding to resume the same paused task at once, duplicating whatever side effects that task causes. That last failure is the same idempotent-retry problem tool-use-agentic-loop/07 already covers for a single tool call, one level up: a resumed task that re-sends an email, re-charges a card, or re-runs a non-idempotent tool call because two workers both grabbed the same resumption token is not a theoretical edge case, it is the default outcome of adding resumability without also adding exactly-once discipline around every side-effecting step. Purpose-built durable-execution runtimes (Temporal, Restate, and comparable systems; Azure's Durable Task Extension for Microsoft Agent Framework is the same idea applied specifically to agents) address this by making step-level idempotency keys, event history, and automatic crash detection part of the platform rather than something the agent author has to bolt on - which is a real trade-off in build complexity against reliability, not a strictly-better option in every case.

The idle-cost problem: a different economic shape than a completed-task budget#

The ordinary way to budget an agent loop is to model cost as a function of one completed task: how many steps a loop takes, how much context each step re-sends, and which model tier handles each step - a shape that assumes the meter starts and stops with the task (agent-security-and-operations/05 covers this per-task model in depth; if you've already read it, the contrast below will be more concrete, but nothing here depends on it). A continuous agent's cost does not have that shape, because the agent is, by design, never "done" in the sense that would let a per-task budget reset. One practitioner's three-month account of running a self-hosted agent 24/7 to handle recurring business tasks (checking a CRM, pulling and formatting a report, sending it via Slack, several LLM calls per completed task) makes the difference concrete:

Month 1: $187   (unoptimized - default model tier for every call, including idle checks)
Month 2:  $94   (routine steps moved off the frontier model)
Month 3:  $78   (classification-type steps routed to the cheapest model tier)
------------------------------------------------------------------------------
3-month total: $560, cost breakdown at month 3 steady state:
  Token costs (LLM calls)         64%
  Compute infrastructure          13%
  Memory / vector database        13%
  Monitoring                       8%
  Miscellaneous                    2%

The specific dollar figures are one operator's self-reported numbers for one workload, not a benchmark to extrapolate from - but the shape of the finding generalizes: roughly a third of the steady-state bill was not "the model doing the task" at all, it was infrastructure, memory storage, and monitoring that exist purely because the agent is always on, plus - per the same account - "heartbeat polling" burning tokens during idle stretches when nothing was actually happening. A per-task budget cap of the kind described above bounds the cost of any one completed task; it does nothing to bound the cost of a hundred idle heartbeat checks a day, because none of those checks is a "task" in the sense that budget was designed around. Budgeting a continuous agent means adding a second axis entirely: a steady-state monthly ceiling and an idle-polling cost cap, on top of (not instead of) the per-task budget for whatever work the agent actually does when triggered. (If you've read agent-security-and-operations/05, this is the same per-task cap it recommends - still necessary here, just no longer sufficient on its own.)

Testing, debugging, and monitoring a continuous agent#

A request-response agent's test suite can run the loop start-to-finish and check the output. A continuous agent's correctness depends on behavior a single end-to-end run cannot exercise at all: what happens if the process is killed between the tool call succeeding and the state write that records it succeeded? Does resuming twice on the same token cause the same email to send twice? 2026 practitioner guidance on durable agent runtimes recommends deliberately injecting crashes at exactly those seams - after an LLM call but before the tool executes, after a tool call succeeds externally but before the local state write confirming it - specifically because those are the windows where a resumed agent can duplicate or lose a step, and they are invisible to any test that only runs the happy path uninterrupted.

Monitoring shifts correspondingly. Where a request-response agent is monitored per-call (latency, error rate, cost per completed task), a continuous agent needs monitoring for the gaps themselves: heartbeat trace health confirming the loop is still alive and not silently dead, and session-length token budgeting tracking cumulative spend against the steady-state ceiling described above rather than a single task's cap. Reported anomaly signals worth alerting on specifically because they surface before a quality metric degrades: a context window growing well above its historical baseline, or the rate of tool invocations spiking within an hour - both patterns consistent with an agent stuck replanning or re-querying in a loop that a short request-response session would never live long enough to exhibit.

Pros#

  • Enables genuinely event-driven, long-horizon work that a request-response agent cannot do at all - waiting days for a human approval or a third-party process to finish, without a human keeping a session window open the whole time.
  • Scales to zero during idle periods when built on durable state plus an external trigger (webhook, event stream) rather than an in-process wait loop, so idle time costs infrastructure dollars, not a live, reasoning process.
  • Survives real infrastructure churn (deploys, crashes, autoscaling events) that would silently destroy an in-memory-only agent's progress, once durable state and a resumption mechanism are actually in place.
  • Makes "correctly waiting" observable and distinguishable from "silently broken" when the pause itself is a first-class, checkable state, rather than an absence of activity a human has to guess about.

Cons#

  • Every extra piece of durable machinery is a new failure surface. Session-storage schemas, continuation tokens, and webhook wiring can each break in ways a single in-memory session simply cannot - documented incidents include background agent tasks that kept "running" indefinitely after their triggering session ended, consumed roughly a million tokens over 34+ hours, and could not be stopped through any available control, precisely because the resumption/keep-alive machinery outlived the intent that started it.
  • A checkpoint is not automatically exactly-once. Without deliberate idempotency design at every side-effecting step, resuming after a crash or a race between two workers can duplicate a real-world action (a second welcome email, a second charge) rather than safely continuing.
  • The idle-cost tail is easy to miss in initial budgeting, because it does not show up in any single task's cost and only becomes visible in an aggregate monthly bill - by which point it may already represent a meaningful fraction of total spend, as the heartbeat-polling and monitoring-overhead figures above illustrate.
  • Debugging is structurally harder. A bug that only manifests when a crash lands in a specific narrow window between a tool call and its state write will not reproduce in any test that runs the happy path start to finish; finding it requires the deliberate fault-injection testing described above, which most teams don't build until after they've been bitten by exactly this class of bug.

Alternatives#

  • A conventional request-response session, possibly with compaction or handoff (prompting-context-engineering/10) for length. The right default whenever the whole task genuinely completes within one continuous run and no external event outside the agent's control needs to be waited on - building durable state and resumption machinery for a task that never actually needs to survive a restart is unjustified complexity.
  • Scheduled batch runs (a cron-triggered agent that runs once an hour, does whatever work is currently available, and exits cleanly) instead of a genuinely continuous, always-listening process. This gets most of the "handles work I'm not watching" benefit with none of the idle-process cost or crash-mid-task complexity, at the cost of up-to-an-interval latency between an event happening and the agent noticing it - fine for many operational tasks, wrong for anything that needs to react within seconds.
  • A human-staffed on-call rotation instead of an always-on agent for tasks whose trigger events are rare enough, or whose stakes are high enough, that the engineering cost of durable pause/resume infrastructure isn't justified by the volume of work it would offload.
  • A purpose-built durable-execution runtime (Temporal, Restate, Azure's Durable Task Extension, or comparable systems) instead of hand-rolled checkpointing. Preferable once the checkpointing gaps described above (crash detection, exactly-once resumption, distributed coordination across workers) are load-bearing for the task's stakes; overkill for a single-instance agent where a simpler file- or database-backed state (per the ADK and Anthropic examples above) is sufficient and a dedicated workflow engine would just be extra infrastructure to operate.

When to use it#

Reach for continuous execution when the task is genuinely event-driven and open-ended - waiting on a human action, a third-party process, or an external signal that can arrive hours or days after the agent last acted - and when a human is not expected to keep a session open for the duration of that wait. It earns its complexity specifically when the alternative (a human manually re-triggering the agent once the event has happened) is the actual bottleneck you're trying to remove.

When NOT to use it#

Do not reach for continuous execution, durable state, and resumption machinery for a task that completes in one sitting - that is what session compaction and handoff (prompting-context-engineering/10) are for, and building pause/resume infrastructure for a task that never needs to survive a restart adds real failure surface (per the Cons above) for no corresponding benefit. Also avoid it when the trigger events are rare enough, or consequential enough, that a scheduled batch check or a human on-call rotation is simpler and safer than an always-listening process - the idle-cost tail and the exactly-once discipline this pattern demands are only worth paying for when the volume or urgency of events genuinely requires an agent that's always ready to react, not merely convenient to have.

Key takeaways / mental model#

A continuous agent is not a longer session - it is a different contract with the process boundary. A session-boundary agent can assume the process that starts a task finishes it; a continuous agent cannot assume that at all, and has to treat "the process might die between any two steps" as the normal case to design for, not an edge case to handle if it comes up. That contract requires three things together, not any one alone: state durable enough to survive the process dying (a session-storage entry, a progress file plus git history - the storage mechanism is swappable, the durability requirement is not); an explicit resumption handle a different process invocation can use to pick up precisely where the last one stopped, with exactly-once discipline around every side-effecting step it might replay; and a deliberate answer for what happens, and what it costs, during the gaps - because idle time is not free time once heartbeats, monitoring, and standing infrastructure are all billed continuously rather than per finished task.

Self-check questions#

  1. An engineer proposes making an existing single-session coding agent "always-on" by simply wrapping its main loop in a while True and having it poll for new work every 30 seconds, with all state held in the running process's memory. Using the three requirements in this lesson, explain specifically what breaks the first time this process is redeployed mid-task, and what's still missing even if you fix that.
  2. The ADK onboarding-agent example treats "paused, waiting for document signatures" as a first-class, checkable state rather than an absence of activity. Explain why that distinction matters operationally - what would a monitoring system (or a human checking on the agent) be unable to tell apart without it?
  3. A continuous agent's resumption token gets picked up by two worker processes at once after a brief network partition, and both resume the same paused task. Which of this lesson's failure modes does this illustrate, and what would you add to prevent the duplicate side effect specifically (not just detect it after the fact)?
  4. Contrast a per-task budget cap with this lesson's idle-cost problem: give a concrete scenario where an agent stays comfortably under every per-task budget cap and still runs up an unexpectedly large monthly bill, and explain in your own words what budgeting change would catch it. (If you've read agent-security-and-operations/05, frame this as its per-task cap specifically.)
  5. A team wants to add crash-resilience testing to their continuous agent's test suite. Their current tests all run the agent's full task end-to-end and check the final output. What specific gap does this leave, and where (in terms of when in the loop) should a fault-injection test actually interrupt execution to be useful?
  6. Given the "checkpoints are not durable execution" critique in this lesson, when would you judge that a hand-rolled, file-or-database-backed state mechanism (like the Anthropic git-based coding harness) is sufficient, versus when the gap to a purpose-built durable-execution runtime is worth closing? What about the task changes your answer?

References#