← All agentafk.si Blog Posts · Post 01 of 04 · 2026-10-18 · Overnight Execution · 7 min read · Raw Markdown (.md) · Subdomain Permalink

Why Overnight Coding Runs Stop After 15 Minutes: How Checkpoint Leases Fix It

Unattended agents usually stop prematurely after 12 minutes due to conversational politeness bias or stall indefinitely on a hung subprocess. Here is how AgentAFK checkpoint leases solve both.


When developers try to run a coding agent overnight in an ordinary chat window, one of two failures almost always happens by 2:00 AM. Either the model completes the first sub-step after 12 minutes and stops to ask "Would you like me to proceed with Step 2?", or a single test subprocess hangs on stdin/network I/O and blocks the entire night's queue. agentafk.si eliminates both failure modes using explicit completion predicates and heartbeat checkpoint leases.

Why chat-tuned models bail out early on long assignments

Instruction-tuned models are heavily rewarded during RLHF for short, conversational turns that defer to the user after producing a partial summary. In an interactive session, asking for confirmation is polite; in an unattended 6-hour overnight queue, it wastes the entire night.

In agentafk.si, a discrete cognitive or act step Loop node does not decide when the queue is finished by emitting conversational prose. Instead, the Loop controller evaluates an external, machine-checkable exit_condition after every turn:

# AgentAFK Loop Supervisor: Enforces Verifier Exit Conditions & Lease Deadlines
def supervise_overnight_task(task_spec: dict, runner, verifier) -> dict:
    calls_used = 0
    max_calls = task_spec["max_calls"]
    while calls_used < max_calls:
        calls_used += 1
        step_out = runner.run_step_with_lease(
            assignment=task_spec["assignment"],
            lease_seconds=task_spec.get("lease_seconds", 300)
        )
        if step_out["status"] == "unknown_external_outcome":
            return {"state": "paused_for_reconciliation", "calls_used": calls_used}

        verdict = verifier.check(task_spec["invariants"])
        if verdict["all_passed"]:
            return {"state": "finished_verified", "calls_used": calls_used, "verdict": verdict}

        runner.update_counterexample_memory(verdict["minimal_counterexample"])
    return {"state": "halted_at_call_ceiling", "calls_used": calls_used}

Navigation Post Title Routes
Previous Post Overnight Proof Runs with Cheap Models: How Verification Gates Beat Raw Model Price
Next Post Running Unattended Overnight Solves on Ollama Cloud Without Runaway Spend or Lost Work
Domain Blog Index Return to agentafk.si/blog Index