PMaker home
Define done first, then design recoveryWrite the goal contractOutcome, constraints, verificationAdvance in stepsOne small, named task at a timeLeave artifactsPlan, implement, documentationReach an end stateBlocked or out of budget, stopArtifacts decide whether work survives a session

A goal with no stop condition and no budget ceiling is still an infinite loop.

Long Tasks Need Handoffs and End States

A goal is an executable contract: it must state the outcome, the constraints, and the verification, and it must define explicit end states. Without them it is an infinite loop.

Long tasks fail by not finishing more often than by doing the wrong thing. The context window runs out, the agent forgets early decisions, drifts off plan, and retries approaches it already rejected. A larger window is not what saves you; handoff artifacts on disk and end states defined before you start are. A goal with no stop condition and no resource ceiling is an infinite loop.

A goal is an executable contract

A real goal states three things: the outcome, the constraints, and the verification. "Keep going until it is done" is not a goal, it is a wish.

Constraints and verification are the two that get dropped. Without constraints the agent reaches the outcome by a route you would never accept; deleting the tests so the suite goes green is also a form of done. Without verification, your definition of done and the agent's diverge mid-run.

Only external evidence confirms completion

Completion has to rest on tests, measurable metrics, a diff, a screenshot, external state, or human acceptance, never on the model saying "done". The reason is structural: language models are lenient toward language model output. When Anthropic had an agent assess its own work, it praised itself confidently where a human found the result plainly mediocre. Subjective work is worst, but even verifiable tasks suffer from the agent's judgment getting in the way anthropic-long-running.

Separate the agent that does the work from the agent that judges it. Tuning one independent evaluator to be skeptical is more tractable than asking a generator to criticize itself.

Four end states, and do not let the loop decide

A continuously running system needs explicit end states: blocked, needs-input, cancelled, and budget-exhausted. What triggers them is an unreachable verifier, an exhausted budget, missing permissions, or an external dependency that has failed permanently.

Blocked is not a retryable failure: something outside the system has to change first, so it stops with evidence instead of spinning and burning budget.

Three files carried a 25-hour run

OpenAI ran GPT-5.3-Codex continuously for 25 hours, 13M tokens, and roughly 30,000 lines of code. What held it together was a durable project memory in three files: plan.md with the milestones, the acceptance command for each, and a stop-and-fix rule (if verification fails, fix before advancing, never push forward while broken); implement.md as the execution runbook, keeping the diff bounded and the docs current; documentation.md as a live audit log of status and decisions a human can read hours later openai-long-horizon.

Anthropic hit the same principle with sixteen agents writing a C compiler: README and progress files told each agent where it was. They also found agents suffer from time blindness: they do not know how long something should take and will run tests for hours. The harness response was to print less progress, because a progress bar invites the agent to keep waiting, and to offer a --fast sampling mode for cheap probing anthropic-c-compiler. The enemy in long work is not only forgetting, it is not knowing when to stop.

Show the agent where it is, every turn

Three files carry state across sessions. Inside a single run you still need a status bar, and the book's experiment implements five techniques that can each be switched off independently. Two come with measurements ai-agent-book:

  • Detailed errors, four layers deep: type and description, the full arguments as JSON, the stack, and a targeted fix suggestion (for FileNotFoundError: check the path, check the working directory, try an absolute path). In error scenarios the rate of finding a working alternative went from 60% to 95%, and behavior changed from blind retry to diagnosis.
  • A TODO list, each item with an ID, a status, and a timestamp, acting as external memory. With it enabled the agent finished in 15 iterations on average; without it, 21, often missing subtasks.

The other three each cover a different blind spot. A tool-call counter puts "Tool call #3 for read_file" in context, which lets the model keep its own rhythm — check the path on the first failure, list the directory on the second, change approach on the third — and gives it implicit cost awareness. Timestamp prefixes belong on user messages and tool responses, never on the system prompt; put them in the wrong place and you have destroyed the cache, which Layered Loading and Handoffs prices out. And of the environment facts injected each turn, the working directory matters most: after the agent runs cd, it must update, or the next command executes somewhere else and the agent has no idea.

All five do the same job. They turn "how many times have I tried, where am I, what is left" from something the model has to remember into something it can read. Models are poor at counting their own steps and excellent at reading a counter.

Advance in steps and hand off structurally

Move one or a small number of named tasks at a time, leave a structured handoff before the session ends, and keep the workspace buildable and resumable.

Complex changes refine in three layers: proposal, then design, then tasks, each reviewed and versioned on its own. The proposal answers why and what, plus the acceptance criteria, reviewed by product; the design answers how, reviewed by the engineering lead; tasks carry the breakdown, priorities, and dependencies. When an upstream layer changes, update downstream and record the blast radius instead of jumping into code. Anthropic's AI-native SDLC calls this chain intent, spec, plan: every artifact versioned and treated as a stage handoff contract, not a one-off prompt. When the bottleneck is planning, review, and handoff, that chain is the lever for compressing the wait anthropic-sdlc.

Summarize turn by turn like git log, not like git squash: keep one structured record per turn rather than folding history into a sentence. The fold is what deletes "which path did we abandon at turn nine," and that is the only part the next step can use. Production harnesses pair full compaction with a consecutive-failure circuit breaker for the same reason — plenty of sessions get stuck in a loop of failed compactions, and the breaker stops the spend, not the error ai-agent-book.

Four rules for anything resumable

Recovery works by replay, so the rules all serve replayability:

  • Wrap non-deterministic operations and side effects as separate tasks.
  • Task inputs and outputs must be serializable.
  • Any task that can be retried must be idempotent.
  • Assume code that ran before the interruption may run again.

That last one is counterintuitive: you are not saving a breakpoint, you are replaying history, so assume everything before the interrupt point executes a second time. Which means no unprotected external side effects before an interruption point.

The cost is real: three files and an artifact chain are overhead a task inside one session should not pay. Three questions audit you. Does your goal state a verification? Does it have an end state and a budget ceiling? If you kill and restart the process, does it know where it is?

References

  1. Run long horizon tasks with Codex
  2. Harness design for long-running application development
  3. Building a C compiler with a team of parallel Claudes
  4. The AI-Native SDLC playbook
  5. AI Agents in Depth, Chapter 2: Context Engineering