Every codon in a run pays for its context twice: once in tokens, and again in the risk that a long, stale conversation steers the model wrong. This page is about controlling both. It covers how to hand results from one codon to the next without passing session history, when accumulating context is the right call instead, how to structure work that is bigger than one context window, and how to keep loop iterations from contaminating each other's workspaces.
The running example is the anchor hank, a seven-codon supplier-evaluation pipeline whose codons all start fresh and communicate entirely through files.
When long contexts rot#
As a conversation grows, we need to keep asking what the next task actually needs from it. Worldline rot is the slow erosion of meaning across a long context window: prompts bloat, tool output piles up uncollapsed, and the model that compacts the session carries the longest history without a useful anchor. For the full failure-mode framing, see Why Hankweave.
Treat context as a run resource. A hank is the configured sequence of codons a run executes; a codon is one sealed agent task in that sequence. Every token an agent has seen is paid for again on each later call, so cutting context is a correctness decision as well as a cost decision. No numeric cost estimate is implied.
The usual response is the goldfish doctrine: make most codons fresh, so each task starts without its predecessor's session and runs from files instead. Keep a long horizon only for the reporting codon, and make it re-read settled files from disk. Files are ground truth; conversation history is a probabilistic summary of files already written down. "Worldline rot" and "goldfish doctrine" are names for these rules, not runtime objects.
The sections below apply the doctrine in order of increasing scope: a single handoff between two codons, the cases where accumulation beats freshness, work too large for any one window, and loops that must not leak state between iterations.
Passing understanding without passing history#
When the next codon needs the previous result, write a focused handoff file instead of passing the conversation. A context bridge states who reads it, what that reader will and will not see, decisions and their reasons, constraints, open questions, and confidence. Mark uncertainty as [UNCERTAIN: reason]; leave out exploration logs, failed attempts, and dead ends. The file carries the understanding; the session that produced it is discarded.
Choose the bridge's format separately from its content. Summary Markdown suits broad human-readable context, structured JSON suits a downstream codon that needs specific fields, and a file list suits directing attention at relevant code. All three are legitimate; none is a runtime schema.
Building a bridge takes three steps:
- Write the handoff from codon 1 into
agentRoot/, the shared workspace. - List it in codon 1's
checkpointedFiles. This causes the file to be watched, streamed to the client, tracked in the git-based checkpoint system (a saved rollback record), and sealed into the checkpoint for rollback. - Start codon 2 as
freshand read the file directly fromagentRoot/. Execution setup createsagentRoot/once and uses it as the working directory for every agent process in the run. Afreshcodon shares no session with codon 1, but the file remains at the same relative path.
One mechanism does not work here: do not add a copy rig for a prior codon's output. A rig is setup work that executes before a codon starts. Its copy.from path resolves inside the hank directory, not in agentRoot/, so it can reach a shipped hank file but not the previous codon's workspace output. Portable relative paths are accepted; absolute paths, .. escapes, and symlinks are rejected. If the source path does not exist, the hank fails when it loads: validation records rig setup item N: source path "…" does not exist and throws Codon configuration validation failed, so --validate and startup refuse the whole hank and no rig runs. allowFailure does not apply to this load-time check; runtime rig failure policy is a rigs topic. See the hank JSON path contract.
Read the diagram as text
+-- codon 1 ---------------------------------------+ +-- codon 2 (fresh) ------+
| | | |
| +-----------+ discarded +-----------------+ | | |
| | session 1 |-------------->| session history | | | |
| +-----+-----+ +-----------------+ | | |
| | the handoff, listed in checkpointedFiles | | |
| v | | |
| +---------------------------+ read directly | | +-----------+ |
| | handoff file in agentRoot/ |------------------+-------->| session 2 | |
| +---------------------------+ | | +-----------+ |
+--------------------------------------------------+ +-------------------------+
Because a fresh codon shares no session with its predecessor, the bridge also works across model switches. continue-previous with a different model is a hard load error; use the file bridge instead. For accumulation rules, see codon concepts.
The anchor hank shows the pattern end to end. All seven codons use fresh, and no copy rig carries a prior codon's output. The hank fragment below shows two of them: each declares continuationMode: "fresh" and seals its handoff files with checkpointedFiles.
"id": "normalize-aster",
"name": "Normalize Aster (Datalab dialect)",
"continuationMode": "fresh",
…
"checkpointedFiles": [
"envelope-aster.json"
],
…
"id": "validate-and-repair",
"name": "Validate & Repair Envelopes",
"continuationMode": "fresh",
…
"checkpointedFiles": [
"validated-records.json",
"exception-ledger.json"
],
The downstream side of the bridge is an ordinary file read. The validation codon's prompt points it at the normalized files in the current directory, which is the workspace path used by the run:
…
From the current directory (written by the three normalize codons and survey-and-extracts):
- `envelope-aster.json` — a JSON array of **two** envelope objects (Aster's original submission and its rev2 re-submission).
- `envelope-beacon.json` — a JSON array of **one** envelope object.
- `envelope-cedar.json` — a JSON array of **one** envelope object.
- `envelope-dover.json`, `envelope-embar.json`, `envelope-fjord.json`, `envelope-harbor.json`, `envelope-iris.json` — one envelope array each (native extracts, normalized).
- `survey-notes.json` — the raw-intake survey; carry every `quarantined` entry into the exception ledger as type `UNKNOWN_TEMPLATE` (quarantine is a success path — zero rows, onboarding note).
The same rule holds for a codon whose job is reporting: stay fresh and re-read settled files instead of carrying a long conversation. In the anchor, award-brief makes no new judgment calls and reads unified-records.csv and exception-ledger.json from the current directory:
Complete only the qualitative assessment in the generated `award-brief.md`. Every claim must already be settled by `unified-records.csv` or `exception-ledger.json`; make no new judgment calls. Setup has rendered the financial section with `pipeline/render-award.ts` and rendered `exceptions.csv` losslessly from the ledger. Do not edit the generated financial section, CSV files, ledger, reconciled records, or rig scripts.
…
From the current directory:
- `unified-records.csv` — 40 data rows (8 suppliers × 5 BOM parts; 41 CSV rows including the header).
- `exception-ledger.json` — the full exception ledger from `validate-and-repair` and `reconcile`.
Check-it: After running the anchor hank, verify that validate-and-repair produces validated-records.json and exception-ledger.json. The captured expected outputs cover those two files; the check is about the files produced by the codon, not a sentinel completion-event log.
When to accumulate instead#
continuationMode is a required field with no default, so every codon states its choice explicitly. Most codons should be fresh; write continue-previous when the next codon refines the same artifact, needs intermediate attempts for multi-step reasoning, or answers a conversational follow-up such as "now fix what you wrote." A continue-previous codon must use the same model as the codon it continues.
Continuation has load constraints too: which predecessors a continue-previous codon may continue, and the bars on continuing after a contextExceeded loop or an exhaustWithPrompt codon. Codon concepts owns those rules. A conversational sentinel is a configured observer, not a third way to carry codon context; see sentinels and sentinel configuration.
There is a cost dimension as well. Keeping a stable prompt prefix with a changing suffix, and choosing continue-previous only when the later work actually needs the history, are levers worth pulling, but provider cache hits and savings are not guaranteed: measure them. The mechanism lives in budgets.
When the work is bigger than the window#
Some jobs do not fit in one context window no matter how the context is managed. Do not rely on silent compaction (the automatic shortening of a conversation) to rescue them. Compaction is off by default: a codon that overruns the context window fails with the provider's context-overflow error. Design the hank around the window.
Three patterns cover most of these jobs:
- Chunked processing with aggregation: Have an inventory codon list the work in a file. An
iterationLimitloop processes the next batch on each iteration and appends findings to an accumulation file. A synthesis codon reads the aggregated findings, never the raw corpus. Track processed items durably in the inventory file; an iteration limit alone does not prove every item was processed. UseiterationLimit, not acontextExceededloop with afreshbody codon: that pairing fails at load time; see loop concepts. - Map-reduce: Put each item in a
freshcodon inside aniterationLimitloop. Have each codon write a small summary and archive it witharchiveOnSuccess. A reduce codon reads those summaries fromrigArchive/(each lands atrigArchive/<loopId>-<iteration>/<runtime-codon-id>/…, the shape described below) rather than the raw documents. Each item is isolated, unlike the accumulating chunked loop. - Hierarchical summarization: For a very large corpus, summarize in layers: file summaries, section summaries, then an executive synthesis. The layers run as two sequential loops followed by a final codon; each layer compresses the material before the next reads it.
These patterns compose. A rig can pre-compile many files into one input before processing begins. Pointers plus agent search are a more thorough but costlier alternative to chunking. A research codon followed by a work codon has the map-then-reduce shape.
Model choice is part of the design too. Use cheaper model tiers for mechanical per-chunk work and a more capable tier for synthesis; see hank concepts. In the anchor, five haiku codons handle mechanical extraction or rendering, while validate-and-repair and reconcile use pi/baseten/deepseek-ai/DeepSeek-V4-Pro for judgment work.
When using the anchor's fixture counts as checks rather than as pattern requirements, distinguish the full run from the smaller ch4 checkpoint: the full anchor processes eight suppliers × five BOM parts, or 40 data rows, and its CSV has 41 lines including the header. The ch4 checkpoint intentionally emits 15 data rows. GRN is quarantined in the exception ledger, not counted as a ninth quoting supplier.
Check-it: Validate a loop pairing terminateOn: contextExceeded with a fresh codon. Validation fails at load with the captured diagnostic; the continue-previous variant validates as good to run. The two captures below show both outcomes.
Validation failed: Loop 1 (bad-loop): Loop with contextExceeded termination cannot contain codons with continuationMode "fresh". Codon "step" (step) has continuationMode "fresh", which would prevent context from building up and cause an infinite loop. Change to "continue-previous" to allow context to accumulate.
✓ Configuration is valid!
…
╭─ GOOD TO RUN! ─────────────────────────────────────────────────────╮
│ 1 codons • 0 prompts • 0 system prompts • 0 rigs • 0 checkpoints │
╰────────────────────────────────────────────────────────────────────╯
Archiving loop workspaces between iterations#
Loops raise a related problem: each iteration should start from a clean workspace, and its completed work should be put somewhere the next iteration will not trip over it. archiveOnSuccess is the mechanism. It is a codon-level list of file globs relative to agentRoot/; absolute paths and .. spellings are rejected at load. On successful completion, matching files move to rigArchive/ by being copied and then deleted from the workspace.
Before each iteration runs, use rigSetup to copy a template into the clean workspace. This is different from the bridge: it creates a clean loop workspace instead of importing a prior codon's output. Archive a completed iteration when its codon succeeds, so an iteration does not see another iteration's intermediate files. A loop-level archiveOnSuccess (on the loop itself) behaves differently: the runtime runs it after each completed codon of an iteration except the last, as well as at the loop's real termination, so with a multi-codon body the later codons of an iteration can find their paths already archived. It runs once per termination only when the loop body has a single codon; loop concepts owns the timing.
The full three-variant archive path table (non-loop, loop-codon, and loop-level) is in execution directory. The shorthand is:
- a non-loop codon:
rigArchive/<codonId>/<path>; - a codon inside a loop:
rigArchive/<loopId>-<iteration>/<runtime-codon-id>/<path>, where<runtime-codon-id>is the codon's runtime ID<codonId>#<iteration>with#replaced by-(iteration 0 of codoneditruns asedit#0and archives toedit-0); - a loop-level archive:
rigArchive/<loopId>-loop/<path>.
The archive is a sibling of agentRoot. From an agentRoot shell command, a copy-back source therefore starts with ../rigArchive/; this shell path is not a copy.from rig path and is not subject to that rig-path validation. The hank fragment below puts the pieces together: the edit codon's setup restores the previous iteration's archive into a clean current-project/ directory, and archiveOnSuccess: ["current-project/**"] moves the finished work out again. The result is rigArchive/revise-0/edit-0/current-project/ and rigArchive/revise-1/edit-1/current-project/, with agentRoot/current-project/ absent after each successful archive.
"id": "edit",
"name": "Edit current-project",
"model": "deepseek-v4-flash",
"continuationMode": "fresh",
…
"run": "mkdir -p current-project && if [ -d ../rigArchive/revise-0/edit-0/current-project ]; then cp -R ../rigArchive/revise-0/edit-0/current-project/. current-project/; fi"
…
"archiveOnSuccess": [
"current-project/**"
]
A mistyped or non-matching glob resolves zero files: patterns are expanded against existing files, the only log line is Resolved 0 files to archive from patterns, and the archive is silently empty. (Archive source not found (skipping): <path> appears only when a file matched and then disappeared before the move.) Inspect rigArchive/ or .hankweave/archive-manifest.json before treating success as proof.
The archive manifest records each entry's sourcePath, archivePath, codonId, optional loopContext, checkpointSha, and timestamp. Rollback restores archives by git reachability, not by the manifest's list order: it selects the entries archived after the rollback target on the abandoned line of history (plus orphaned entries), removes the entries it restores successfully, and never overwrites a path the target tree already contains. Execution directory and resume, rollback and retry own the mechanics.
Check-it: After the two-iteration loop, verify that rigArchive/revise-0/edit-0/current-project/history.txt and rigArchive/revise-1/edit-1/current-project/history.txt exist, while agentRoot/current-project/ is gone. The expected archive tree:
rigArchive/revise-0/edit-0/current-project/history.txt
rigArchive/revise-1/edit-1/current-project/history.txt