Skip to content
Harness Engineering2026-09-109 min readRev. 2026-09-30

Write a Handoff the Next Engineer or Agent Can Verify

A handoff for a half-finished sweep or eval should let the receiver check every claim, not trust it. Attach a check to each claim, separate claimed sends from receipts, and see why spot-checking is not enough.

Key takeaways

  • A handoff holds claims and evidence; a claim without a way to check it asks to be trusted rather than verified.
  • If each of 40 claims is independently right with probability 0.98, the whole handoff is right only about 45% of the time.
  • Checking 10 of 40 claims at random catches a handoff with two wrong claims only 44% of the time; making every claim machine-checkable lets the receiver check all of them.
  • A status of claimed_sent with no receipt reference means the external outcome is unknown; reconcile before resending anything.
  • Schema validation, artifact resolution, recomputation and external reconciliation answer different questions; passing one does not pass the others.

Rod Rivera

Author

Write a Handoff the Next Engineer or Agent Can Verify

Rod's note: read with a pencil; the margins are for you.

The note says "posted," but where is the receipt?

It is the end of your day, and an eval of a new checkpoint across 16 shards is half done. You write a handoff for a teammate in another time zone, or for the next agent session: shards 1 to 12 are scored and written, shards 13 to 16 are submitted, and the summary has been posted to the team channel. The note is tidy and every field is filled in. The one thing missing is anything the receiver can check. There is no hash of the results file, no scheduler job IDs, and no message ID for the post.

Your teammate picks it up cold, without your terminal history. Should they trust that the summary went out and move on? Or treat "posted" as a claim to check? If they repost to be safe, the channel gets two summaries, perhaps with different numbers. If they wait for shards that were never submitted, the eval sits "in progress" for a day.

A useful handoff lets the receiver tell three things apart: what was planned, what was attempted, and what is confirmed. This matters most when the previous worker is gone and repeating an action creates a duplicate. Chapter 13 of the book shows that a replacement must recover from records rather than ask a model what happened. This article is about writing those records for a person or an agent to receive. It adds a check for every claim, and the arithmetic of why spot-checking is not enough.

Separate claims from evidence

A handoff needs six kinds of information: the goal, the exact current state, evidence, the next permitted action, known failures, and what the receiver may and may not do. Most trouble comes from mixing up two of them. State is a claim: "shards 1 to 12 scored." Evidence lets someone check it: the path of the results file and its SHA-256, or the query that counts the rows. A handoff that reports state without evidence asks to be trusted.

Prithvi Rajasekaran's account of long-running application development describes planner, generator and evaluator roles, with structured artifacts carrying context between sessions. The principle to take from it is to keep state inspectable and acceptance criteria explicit. LangGraph's persistence documentation describes checkpoints that preserve a graph's execution state so a run can resume (LangGraph, "Persistence"). A checkpoint can faithfully record that the agent called the post tool without that call corresponding to a message anyone received. Persistence preserves beliefs. It does not make them true.

Why a long handoff needs checks, in numbers

Suppose a handoff contains 40 claims, and each is independently right with probability 0.98. The chance that all of them are right is

text
0.98^40 ≈ 0.446

More often than not, at least one claim is wrong. These numbers are illustrative, but the structure holds for any long handoff: reliability over many claims multiplies, just as it does over many agent steps.

Can the receiver spot-check? Suppose 2 of the 40 claims are wrong, and the receiver checks k of them chosen at random. The chance of catching at least one wrong claim is

text
P(catch) = 1 − C(40 − 2, k) / C(40, k)
Claims checkedP(catch at least one wrong claim)
101 − (30 × 29)/(40 × 39) ≈ 0.442
201 − (20 × 19)/(40 × 39) ≈ 0.756
401.0

Checking a quarter of the claims catches the problem less than half the time. Checking by hand is slow, so people check a few. The fix is to make every claim checkable by a machine, so the receiver can check all 40 in seconds.

A handoff whose claims carry their own checks

Here is the handoff above, with a check attached to each claim. It uses only Python's standard library and runs on Colab's Python 3.12. The artifacts live in a dictionary so the example runs anywhere; in practice they are files, table rows and scheduler records.

python
import hashlib

# Artifacts the receiver can read. In a real handoff these are files, rows or scheduler records.
artifacts = {
    "results/shards_01_12.jsonl": b'{"item": 1, "correct": true}\n',
}


def sha256(data: bytes) -> str:
    return hashlib.sha256(data).hexdigest()


handoff = {
    "run_id": "run-0930",
    "status": "in_progress",
    "next_action": "Wait for shards 13-16, then write the summary",
    "claims": [
        {"text": "Shards 1-12 scored and written",
         "check": {"path": "results/shards_01_12.jsonl",
                   "sha256": sha256(artifacts["results/shards_01_12.jsonl"])}},
        {"text": "Shards 13-16 submitted",
         "check": {"path": "scheduler/run-0930-shards-13-16.json", "sha256": "unknown"}},
    ],
    "external_actions": [
        {"type": "post_summary", "status": "claimed_sent"},
    ],
}


def verify(doc, artifacts):
    problems = []
    for field in ("run_id", "status", "next_action", "claims"):
        if field not in doc:
            problems.append(f"missing field: {field}")
    for claim in doc.get("claims", []):
        check = claim.get("check") or {}
        data = artifacts.get(check.get("path"))
        if data is None:
            problems.append(f"evidence_missing: {claim['text']}")
        elif sha256(data) != check.get("sha256"):
            problems.append(f"evidence_mismatch: {claim['text']}")
    for action in doc.get("external_actions", []):
        ref = action.get("receipt_ref")
        if action.get("status") in {"claimed_sent", "confirmed_sent"}:
            if not isinstance(ref, str) or not ref.strip():
                problems.append(f"no_receipt_ref: {action.get('type')}")
            elif ref not in artifacts:
                problems.append(f"receipt_missing: {ref}")
    return problems


for problem in verify(handoff, artifacts):
    print(problem)

It prints two problems:

text
evidence_missing: Shards 13-16 submitted
no_receipt_ref: post_summary

The first claim passes: the file exists and its hash matches. The second has no scheduler record behind it, so the receiver should look up the jobs by their operation IDs before submitting anything. The third is the case this article opened with: a claimed post with nothing to check it against.

An empty problem list from this function is not permission to act. It shows the references resolve and the hashes match. It does not show that a scheduler record says the jobs are running, or that a message record names the right channel and text. That requires reading what the external system recorded.

Reconciling a claimed external action before resuming. Handoff claims an action; Look for a receipt reference; Reference resolves?; Reconcile with the external system; Record the confirmed scope or the unresolved outcome
Reconciling a claimed external action before resuming

What each check can and cannot tell you

"The handoff validated" gets used loosely. Be precise about which layer passed.

CheckWhat it confirmsWhat it cannot confirm
Schema validationThe document is well formedWhether referenced files exist
Artifact resolution and hashThe evidence exists and is the file the writer sawWhether it belongs to this run and commit
RecomputationA number follows from the evidence, such as accuracy from the results fileWhether an external action tied to it happened
External reconciliationWhat the scheduler or messaging system recorded for a matching operationWhether "accepted" means delivered, running or read; interpret the stated status

Recomputing an accuracy from the results file and getting the number in the handoff tells you the arithmetic was right. It says nothing about whether the posted summary contains that number, or whether it was posted at all. "The numbers check out" is not "the handoff checks out."

An in-memory success flag is not a receipt

A variable set to True shows only that an assignment ran. It may have been set before the call, after an error, or with no call at all. A receipt comes from the system that performed the action: a job ID from the scheduler, a message ID from the chat service, a row the results store returned.

Receipt verification proceeds from path presence to artifact resolution, operation matching and authoritative status interpretation.. Receipt reference present; Artifact resolves; Match operation and payload; Interpret authoritative status; Permit only next supported action
Receipt verification proceeds from path presence to artifact resolution, operation matching and authoritative status interpretation.

Test your handoff format on a stranger

You can find out whether your format supports verification without any production system.

Attach a check to every claim

Rewrite your last real handoff so each claim carries a path and hash, a query and its expected count, or an external ID to look up. List each external action with its status and receipt reference.

Break one piece of evidence

In a copy, keep a receipt reference but remove the artifact it points to. Give the copy to a colleague, or a fresh agent session, who did not write it, and ask for the next permitted action.

Watch what the receiver does

A receiver who reports the missing evidence, leaves the run in its current state and takes no external action is behaving correctly. One who proceeds, or invents plausible values, has shown you a gap in the format or in the habit of checking it.

Run the same test with an agent as the receiver. Chapter 13 found that, handed a transcript and asked to continue, one small local model re-placed an order in 14 of 20 samples without looking it up. Structured claims with checks give an agent receiver something to verify instead of a story to continue.

Quick check — A handoff says the results summary was posted to the team channel, with status claimed_sent and no receipt_ref. What should the receiver do first?

Check the decision

What would prove this wrong

If receivers still act without resolving references that are present, the format is not driving the behavior; you may need a required verification step that runs before the receiver is allowed to act. If breaking a piece of evidence changes nothing in what receivers do, either they always check the underlying systems regardless of the document, or they never check anything. Both are useful results, and the stranger test above finds them cheaply.

Why this matters in a lab

Research work is handed off constantly: across time zones, between an engineer and an agent, between agent sessions whose context was compacted, and to whoever picks up a paper's experiments six months later. A handoff full of unverifiable claims is how a team ends up rerunning a week of evals, or reporting a number nobody can trace.

An interviewer might ask: "You're taking over a half-finished eval from a colleague who has left for the day. What do you need from their handoff, and what do you check before you touch anything?" A strong answer separates claims from evidence and expects a check per claim. It uses the arithmetic to explain why spot-checks are not enough, treats claimed sends as unknown until reconciled, and names which layer each check covers. The companion article on resuming a crashed job uses the same records when the previous worker is a process rather than a person.

Read Chapter 8: durable work, inbox and outbox

Give each piece of work and each report its own identity, finish and report together, and keep an outbox that says what was sent.

Learn the mechanism. Test the claim.

Join the Prof Rod newsletter for one educational lesson a week, with worked examples attached. It is free to register for and separate from the Zero Employee community.