Your coding agent has been running for eight hours. It edited twelve files, started a dev server, attempted a migration, hit two failing tests, and then lost its session.
The transcript is still there. It might even fit inside the model's context window. But a fresh process still cannot answer the questions that matter:
- Which changes were successfully applied?
- Is the migration safe to run again?
- Is that dev server still alive?
- Which failing test blocked the last step?
- Should the next process resume, roll back, or stop for review?
The transcript survived. The job did not.
Long-running agent work needs a resume protocol. More context can help a model continue a conversation, but it cannot turn chat history into durable job state.
Context is not a checkpoint
Conversation context preserves messages, tool calls, and explanations. That is useful. It can remind a model what the user asked and how the session reasoned about the task.
A checkpoint has a different job. It records what is true about the work now.
That distinction gets expensive when a run is interrupted. A transcript might say, "I'll update the schema and rerun the tests." It does not necessarily prove that the schema changed, identify which command ran, or preserve its exit code. If the session disappeared between the tool call and the final response, the prose may describe an intention rather than the repository's actual state.
A replacement process needs a compact operational record:
- the run's contract
- the last completed step
- changes and external side effects already made
- exact validation results
- the next safe decision
Without that record, recovery starts with archaeology.
Give the run a bounded contract
"Keep working until it is done" sounds productive, but it is a terrible recovery contract. Done is undefined, authority is open-ended, and a replacement process cannot tell whether the run stopped normally or simply ran out of road.
A useful contract names the boundary before execution begins:
- a run ID and owner
- repository and worktree
- the goal and stop condition
- time, tool, and authority limits
- the expected artifact
- the checks that decide whether the artifact is acceptable
Nightshift's author describes this shift explicitly: long agent runs become disk-backed, time-bounded jobs with contracts, recovery paths, receipts, and archives. That is a project-authored design, not independent evidence that every run will recover correctly. Still, the operating model is the interesting part. A shift has an end, and its state exists somewhere other than the active chat.
The stop condition deserves special attention. "Implement authentication" leaves too much room for interpretation. "Prepare a reviewable patch for the login callback, stop before deployment, and record the named test results" gives the next operator something they can inspect.
Persist facts at step boundaries
Do not wait until the final response to save state. By then, the process may already be gone.
Checkpoint after meaningful steps: dependency installation, migration generation, code modification, test execution, browser validation, or any external mutation. The record should stay small. Its purpose is fast re-entry, not a polished diary of everything the agent thought about.
Mivia's documented workflow offers a useful implementation signal here. Its README describes isolated workflows, per-step run records, lifecycle hooks, and local files. Those features create places where a harness can persist facts before moving forward.
The word "facts" matters. Save the command and its real result, not "tests look good." Save the files changed, not "updated the frontend." If a check failed, keep the failure visible instead of smoothing it into a progress summary.
A good checkpoint might say:
last_completed_step: generated migration 0042_add_job_receipts
changed_files:
- db/migrations/0042_add_job_receipts.sql
- src/jobs/receipt.ts
checks:
- command: pnpm test --filter job-receipts
exit_code: 1
outcome: 2 tests failed in receipt-retry.test.ts
pending_action: inspect whether retries duplicate an existing receipt
That is far more useful than another page of confident narration.
Track side effects separately
File changes are only part of an agent run. The process may have started services, modified a database, opened a pull request, published an artifact, sent a message, or changed remote configuration.
Those effects need their own ledger because replaying the original prompt can repeat them.
A blind retry might apply the same migration twice. It might create a second deployment while the first one is still running. It might overwrite uncertainty with a new sequence of actions that happens to produce cleaner logs.
A side-effect ledger should answer three questions:
- What changed outside the transcript?
- Can the operation be checked safely?
- Is it repeatable, reversible, or neither?
This does not make every action idempotent. It makes the uncertainty visible before another process acts on it.
Recovery must live outside the failed session
A stalled process cannot be the sole owner of its recovery plan. The plan needs to be readable by a fresh process or a human operator with no access to the original model state.
Recovery should begin with inspection, followed by an explicit decision:
- Resume when the recorded state matches the environment and the pending action is still valid.
- Roll back when a known reversible change should be removed before work continues.
- Escalate when the evidence is incomplete, the environment drifted, or another action could compound an unknown side effect.
This is why recovery is not the same as retry. Retry repeats an operation. Recovery first establishes what already happened.
PI-Desktop's project documentation points at the operator-facing side of this problem through project sessions, message-scoped diffs, approvals, and guarded rollback. Those controls do not guarantee safe recovery, and local-first software is not automatically isolated or secure. They do make the unit of change more inspectable than one opaque stream of agent activity.
A resume protocol can be simple. Here is an operating pattern, not a standard or a security guarantee:
run:
id: auth-callback-2026-09-04-01
owner: overnight-agent
repository: web-app
worktree: ../worktrees/auth-callback
contract:
goal: prepare a reviewable login-callback patch
stop_when: named tests pass or a migration needs approval
time_budget_minutes: 90
allowed_effects:
- edit_worktree
- run_local_tests
forbidden_effects:
- deploy
- modify_production_data
expected_artifact: git_diff
checkpoint:
last_completed_step: add receipt persistence
pending_action: inspect two retry test failures
changed_files:
- src/jobs/receipt.ts
- db/migrations/0042_add_job_receipts.sql
side_effects:
services_started:
- name: web-dev-server
port: 3102
external_mutations: []
evidence:
checks:
- command: pnpm test --filter job-receipts
exit_code: 1
outcome: 2 retry tests failed
recovery:
inspect_first:
- git diff --stat
- pnpm test --filter job-receipts
resume_when: migration is unchanged and failures reproduce
rollback: discard the isolated worktree
escalate_when: database state differs from the checkpoint
receipt:
status: blocked
reviewer_action: decide whether receipt creation must be idempotent
The schema is deliberately boring. Boring is good when a process wakes up at 3 a.m. and needs to decide whether a migration already ran.
Finish with a receipt, not "done"
A completion message is not evidence. The final receipt should contain the artifacts produced, the exact checks and outcomes, known failures, assumptions, and the next reviewer action.
This also gives review tools a clean handoff. R3's launch describes a local interface that turns scattered comments into explicit feedback for a coding agent. It is a small, low-engagement project signal rather than adoption evidence, but the shape of the loop is useful: review state becomes an artifact that can follow the job into another session.
A receipt does not prove correctness. It tells the next reviewer what was checked and what was not. That is enough to replace a vague claim of completion with a reviewable boundary.
Let old runs improve new contracts
An archive earns its keep when it changes the next run.
The ZeroShot launch describes local capture of agent sessions, clustering repeated friction, and drafting reusable workflow improvements. Those are author claims, not measured productivity results. The useful idea is narrower: repeated interruptions can reveal missing fields in the contract.
If three runs stall because nobody recorded which browser profile owns port 3102, add that ownership to the template. If retries keep duplicating external actions, require idempotency keys or an escalation rule. If reviewers repeatedly ask which checks actually ran, make command outcomes mandatory in the receipt.
The loop is practical: archive the run, find recurring ambiguity, then remove that ambiguity from the next contract.
Apply the replacement-process test
Before letting an agent run unattended for hours, imagine the current session vanishes halfway through.
Can a different process inspect durable artifacts and determine the contract, current state, side effects, evidence, and next safe action? Can it choose resume, rollback, or escalation without treating the old transcript as ground truth?
If the answer is no, a larger context window will only preserve more material to reread. Make the job resumable before making it longer.
Source notes
Top comments (0)