Skip to content
Pere Villega
Go back

The Night Shift Is a Bounded Handoff

9 min read

Starting an autonomous agent before leaving the desk is easy. The difficult part is deciding what you are willing to find in the morning.

A large patch with no trustworthy test record is not eight hours of progress. Nor is a branch that passed its checks by weakening them, a process still retrying the same failure, or a tidy report which omits the production credential it used. The operator was absent, so every ambiguous decision had more time to become code.

This is why I dislike the familiar “agents work while you sleep” pitch. Night-time is incidental. The useful pattern is a bounded hand-off: a human defines the work and its limits, an agent executes inside them, and a human reviews the evidence before anything consequential advances.

The previous chapter organised several agents across a work graph. A night shift adds another boundary. The two sides cannot rely on live conversation to repair the specification.

Absence removes steering, not responsibility

Interactive agent use hides a surprising amount of manual orchestration. We clarify a vague requirement, stop an irrelevant refactor, approve a command, explain a test failure and notice when the agent has mistaken “done” for “the compiler is quiet”.

When we leave, those small corrections disappear. Autonomy has not made the uncertainty go away. It has delegated the response to whatever instructions, permissions and checks remain.

That can be an advantage. Gaps which were routinely patched through conversation become visible. But only if the run stops or records a failure clearly. If it is allowed to guess indefinitely, absence turns weak documentation into a larger diff.

Jamon Holmgren describes a particularly committed version in his Night Shift workflow. He separates daytime specification and architecture from overnight implementation. The agent follows a repository workflow, writes tests, runs several review perspectives and the full test suite, then leaves commits and a report for manual review the next day. Holmgren is reporting his own evolving practice, not a controlled benchmark, but the shape is important: most of the system is preparation, validation and review rather than a long prompt followed by sleep.

I would start more modestly. Mitchell Hashimoto’s end-of-day pattern used agents for research, speculative exploration and read-only issue triage. He explicitly did not let triage agents respond to issues, and says most runs finished within half an hour. That is still asynchronous work. It produces a useful morning start without pretending that every unattended run should ship code.

Write the hand-off as an execution contract

An overnight task needs more than a feature description. It needs the information we would otherwise provide when interrupted.

I would include at least:

For example:

task: add CSV export for completed orders
base: 4d3c2b1
owns:
  - src/export/**
  - tests/export/**
must_not:
  - change the Order API
  - edit existing acceptance tests
  - push, merge, deploy, or contact users
acceptance:
  - exports the documented columns in order
  - rejects invalid date ranges without partial output
checks:
  - npm test -- tests/export
  - npm run build
budget:
  elapsed_hours: 2
  implementation_attempts: 3
stop_if:
  - the documented Order API cannot express a required field
  - baseline checks fail before any edit
  - a check requires an unavailable external service
handoff:
  - branch and commit SHAs
  - changed paths
  - check results and anything not run
  - assumptions, blockers, and residual risk

The exact syntax does not matter. The decisions do. An agent should not infer that a failed baseline belongs to this feature, that an acceptance test may be rewritten, or that a deployment is the natural last step.

The contract also separates a blocker from a failure. Discovering that the existing API cannot support the requirement is useful work. Changing the API without approval is a different task.

Begin from a recoverable state

Holmgren’s preparation step lets the agent stash or commit existing work and fix baseline failures. I would make those decisions before leaving the desk. The night shift should not start by deciding what to do with somebody’s uncommitted work.

Record the starting SHA and protect the current working tree before the run begins. Use an isolated worktree, clone or managed environment. Give the agent its own branch and task-specific credentials. If it needs a database, queue, port or test account, make that resource exclusive or safe to reset.

The baseline is part of the evidence:

  1. verify the intended revision;
  2. run the required checks before editing;
  3. record failures as pre-existing rather than silently fixing unrelated code;
  4. create a checkpoint before each change with a large blast radius.

Without a recorded baseline and an explanation of which failures the patch addresses, a green result cannot establish what the run fixed. It may spend the night repairing the wrong problem and still obscure the original feature.

Reversibility matters more than tidiness. Small commits or equivalent checkpoints provide inspectable recovery points. Do not squash away the only record of when a decision entered the branch before review. Do not automatically delete failed workspaces; a failure may contain the evidence needed to diagnose the harness.

Put deterministic gates between probabilistic steps

The agent can plan, implement and explain. It should not be the only authority deciding whether its explanation is true.

A useful execution loop alternates open-ended work with fixed gates:

select eligible task
        |
verify baseline
        |
implement a bounded change
        |
focused checks -> static checks -> broader tests
        |
independent review of the diff and specification
        |
checkpoint or stop

Run cheap, local checks first so a simple fault does not consume the rest of the night. Run broader regression checks only after the focused behaviour works. Preserve the exact command, exit status and relevant output for each gate.

An independent review agent can challenge missing cases, unsafe assumptions or scope drift. It is another probabilistic signal, not a substitute for tests or morning judgement. Give it the specification and diff, not the implementer’s claim that everything is fine. More review personas are worthwhile only when they represent genuinely different evidence or risk. Six agents agreeing from the same incomplete context remain one blind spot with a larger token bill.

Completion must be external to the acting agent. Protected tests, type checking, static analysis and policy checks should not be editable merely because they are inconvenient. Where a check is flaky or unavailable, the correct status is not PASS. It is FAIL or NOT-RUN, with the reason recorded.

Logs are part of the deliverable

A morning reviewer should not have to reconstruct the run from terminal scrollback. Nor should they receive an enormous transcript and be told the answer is somewhere inside.

Keep an append-only record of operational facts:

Store design decisions and assumptions in the hand-off or repository artefacts. Store raw tool output only where it helps reproduce a result. We need an audit trail, not private model reasoning or every token emitted.

The final report should be short because the evidence is addressable elsewhere. “Implemented export; focused tests and build pass; full end-to-end suite not run because the service was unavailable; API ambiguity remains” is useful. “Task completed successfully” is decoration.

Stopping well is successful autonomy

An overnight loop needs permission to stop before the clock runs out. Otherwise every problem becomes an invitation to spend more tokens.

Hard stop conditions should include:

Retries should be narrower than hope. A transient network timeout may deserve bounded backoff. A deterministic test failure after the same patch does not become transient because the fourth attempt happens at 03:00.

When stopping, preserve the workspace and report the smallest decision needed to continue. BLOCKED-NEEDS-HUMAN is a valid terminal state for the night. It is considerably better than an agent redesigning an interface to avoid asking.

The morning shift decides

The agent’s final state is “ready for review”, not “accepted”.

I would review in this order:

  1. confirm the task, starting revision and stop reason;
  2. inspect unexpected external effects and changed paths;
  3. read the concise hand-off and check record;
  4. review the diff against the specification and important invariants;
  5. rerun the proportionate gates in a trusted environment;
  6. manually exercise behaviour which automation cannot establish;
  7. accept, request a bounded correction, or discard the branch.

This order avoids being charmed by a polished summary before checking provenance. A passing focused test is not a passing repository. An agent reviewer approval is not a security decision. A screenshot is evidence of one rendered state, not proof of every interaction.

Morning review should also improve the system. An absent contract which forced the run to guess belongs in the documentation; unusable command output or a gate the agent could weaken belongs in the harness. Some tasks will simply prove to be poor fits for unattended work, and that class should remain interactive.

Do not turn every surprising result into permanent machinery. A rare harmless mistake may be cheaper to correct by hand. The point is to remove repeated ambiguity, not to construct a workflow engine around one awkward Tuesday.

Delegate only what can wait for judgement

Good night-shift tasks have bounded effects, executable acceptance criteria and useful partial results. Research, triage, dependency analysis, test generation in an isolated branch and well-specified maintenance work are sensible candidates. Ambiguous product design, emergency operations, irreversible migrations and work requiring live stakeholder decisions are not.

The clock is not the source of productivity. The hand-off is. We gain uninterrupted execution only by doing the specification, isolation, verification and recovery work in advance, then spending real attention on the morning decision.

Once several unattended runs must survive crashes, share capacity and resume safely, scripts begin to accumulate scheduling state. That is where a night-shift loop becomes an orchestration system, which is the subject of the next chapter.


Share this post on:

Previous Post
From Agent Scripts to Orchestration Systems
Next Post
How to Organise a Team of Agents