An idea about how machines should hand work to each other

Context is
infrastructure,
not conversation.

Five independent language models worked one continuous task. None of them saw another one's conversation.

An AI model forgets everything the moment its session ends. So when a long job has to pass between several of them, the usual answer is to replay the entire conversation to the next one, which gets slower, more expensive and less useful at every step. The idea here is to stop passing the conversation at all, and keep the work itself in a record that no model owns.

Further down, five models take one job and finish it that way, live, while you watch. You can read what each of them was told, and check for yourself that none of them ever saw another's conversation.

Start The idea, in plain words Two minutes. Then you can watch it happen: no sign-up, no key, nothing to install.
5workers, 4 model families
0raw conversation transfers
1,199peak tokens per handoff
140tests passing
The idea

Workers are temporary. The record is not.

Every section here opens in plain words followed immediately by the engineering mechanics, formal invariants, and types behind it.

In plain words

Imagine five people take turns building one big Lego castle, but each person completely forgets everything the moment they hand over. How does the fifth person know not to rebuild the front gate that the second person already finished?

One answer is to tell every new person the entire story of the whole day. That gets very long very fast, and the few important bits end up buried in the middle of it.

The idea is to stop retelling the story. Instead, keep a notebook that belongs to the table rather than to any of the builders. The notebook holds what is finished, what was decided and why, what was tried and did not work, and what to do next.

Before each new person starts, a helper reads the notebook and writes them one short briefing that fits on a single sheet. That sheet is all they get. No story, no chat. Just the sheet. And crucially, nobody may quietly cross something out of the notebook: if you claim you fixed a problem and nobody checked, the problem stays written down.

It works. Five different AI models, from four different companies, each with its own separate password, finished one job together, and not one of them ever read another one's conversation.

In engineering terms: a model's working context dies with its session, and both usual ways of continuing a task in a new session fail. Replaying the transcript grows without bound. Summarising it loses exactly the things that matter: why a decision was made, what already failed, and what the precise next action is.

So the state of work is held outside every model. Each worker returns a result and a report for its successor; those are treated as claims and merged into the record by something that stamps the attribution itself and refuses to close anything unverified; then the record plus the next assignment is compiled into one bounded briefing. The next worker gets that briefing and nothing else.

The same thing, precisely types, invariants and cost

Continuity across heterogeneous LLM sessions is modelled as an externalised, typed, append-biased execution state rather than as message history. ExecutionState is a Pydantic aggregate: objective, completed and pending tasks, decisions with reasons, versioned artifacts, issues, append-only failed attempts, assumptions, progress, last and next action, worker and handoff history. It is owned by the orchestrator; no worker holds a reference that outlives its turn.

Each turn is stateless in the way that matters: compile(state, assignment, budget) is deterministic, and the message array handed to the provider is rebuilt from scratch every turn and always has length two. There is no accumulator into which a prior transcript could leak, which is why raw_conversation_transfers == 0 is an assertable structural invariant rather than a convention someone has to remember.

Transcript replay costs O(n²) tokens across n handoffs. A compiled package costs O(n·B) for a fixed budget B, and the interesting engineering is entirely in how the compiler spends B: relevance scoring against the pending assignment, a recency blend, per-category caps, and an anchoring rule that pins founding decisions so recent detail cannot outrank them.

The second axis is trust. Model output is treated as a claim from an untrusted origin, and StateReconciler is the only component permitted to write canonical state. Its four invariants, the compile algorithm and the failure semantics are all in Internals.

Stuck on a word Every term on this page is defined twice Once in plain words, once precisely. Terms with a dotted underline show their definition when you hover or focus them.
The objective

Can several independent models finish one task without sharing a transcript?

That is the whole experiment. Everything in this project exists to answer it honestly.

A language model's working context dies with its session. When one worker stops and another takes over, the obvious fix is to replay the entire conversation into the next model. That fails predictably: context windows fill, token cost climbs with every handoff, irrelevant history accumulates, and the details that actually matter get buried in transcript.

Summarising is the usual second attempt, and it is lossy in exactly the places that hurt. A summary drops the reasons behind decisions, the approaches that already failed, the dependencies between pieces of work, the precise execution state, and the exact next action.

So this project takes a different position. The state of work is treated as infrastructure that exists independently of whichever model happens to be doing the work. Models are interchangeable execution engines. The record of the work is not.

In plain words

An AI assistant only remembers things while you are talking to it. Close the window and its memory is gone. Not hidden somewhere, actually gone.

So if one AI does half a job and a different one has to finish it, how does the second one find out what happened? There are two obvious ideas, and both have a problem.

  • Tell it the whole story. Every word of every conversation so far. But that story keeps growing. By the fifth handover it is enormous, most of it no longer matters, and the few sentences that really do matter are lost in the middle. It also costs more every single time, because these models charge by how much you send them.
  • Tell it a short summary. Shorter, yes, but summaries throw away exactly the wrong things. A summary keeps "we built the door" and drops "we tried a sliding door first and it jammed". So the next person builds a sliding door, and it jams again.

This project stops trying to pass the memory along at all. The important facts live in a notebook the system owns, and each new worker gets a fresh, short briefing written from that notebook. The workers come and go. The notebook stays.

Why both naive approaches fail complexity and loss bias

Transcript replay is quadratic and degrades

Replaying history into worker n sends roughly the sum of all prior turns, so cumulative tokens across a run grow as O(n²) while per-call latency grows linearly. Worse, the prompt's signal-to-noise ratio falls monotonically: the fraction of the window occupied by material relevant to the current assignment shrinks with every turn, which is the mechanism behind the familiar "lost in the middle" degradation. It is also model-bound: a transcript carries one provider's message roles, tool-call encodings and formatting conventions, so switching families mid-task means translating a growing artifact you did not design.

Summarisation is lossy in a biased direction

A summariser optimises for narrative compression, and the material it discards first is precisely what a successor needs: the reason attached to a decision (which is what lets a later worker judge whether the decision still applies), negative results, and exact cursor position. Negative results are the sharpest case (low narrative salience, high operational value), so they are systematically the first casualties, and re-deriving one costs a full wasted turn.

The position taken here

Model context is treated as a cache; the system of record is a typed aggregate with explicit categories. That distinction is what lets the compiler make a category-aware budgeting decision rather than a token-level one. It is the reason failed_attempts exists as a first-class field with its own priority slot and its own append-only rule, instead of being a sentence inside a summary that the next compression pass can quietly delete.

Verification

What is being tested

The claim
N independent workers can complete one continuous task with zero conversation passed between them.
The mechanism
Persistent execution state, mandatory handoff reports, state reconciliation, and context compilation.
The rule
Each worker receives its assigned task and a compiled context package. Nothing else. Never a transcript.
How it would fail
If continuity were fake, a later worker would redesign something that already exists, or repeat an approach that already failed. Both are visible in the playground below.
FULL CONVERSATION TRANSFER grows without bound STRUCTURED EXECUTION HANDOFF bounded by an explicit token budget
Each bar is one worker's inbound context. The lower series is measured from a live five model run. The upper series is what the same run would send if the transcript were replayed each time.
Next Meet the eight parts that make this work All eight are named again during the live run, so three minutes here saves confusion later.
The parts

Eight components, each with one job.

You will see every one of these named in the playground, so it is worth knowing what they are. Each is one file, and each has exactly one responsibility.

The eight parts, as a school project

Picture a group project where only one person may work at a time, and each person forgets everything when their turn ends. Here is who does what.

  • The notebook: Execution State. The one true record of the project. What is done, what was decided and why, what broke, what to do next. The teacher keeps it, not the students.
  • The student: Universal Worker. Any student, any subject. They walk in, read their briefing sheet, do their bit, and walk out. They remember nothing afterwards, and there is only one kind of student.
  • The homework sheet: Worker Result. What the student hands in: what they did, decided, made and broke. Just what they say happened, mind you. Nobody has checked it yet.
  • The note to the next student: Handoff Report. A second thing every student must write, addressed to whoever comes next: where I stopped, what to watch out for, what not to assume is finished.
  • The teacher: State Reconciler. Reads both, copies the true parts into the notebook, crosses out repeats, and writes down anything that looked doubtful. If a student says "I fixed it" and nobody checked, the teacher leaves the problem in the notebook as still broken.
  • The briefing writer: Context Compiler. Reads the whole notebook and writes the next student a one-page sheet. Only one page. So it has to decide what matters most and leave the rest out on purpose.
  • The sheet itself: Handoff Package. The one page that gets handed over, with a note at the bottom saying what had to be left off to make it fit.
  • The phone and the filing cabinet: LLM Gateway and Store. The phone is the only thing allowed to call the AI companies. The filing cabinet saves the notebook after every single turn, so if the lights go out, nothing is lost.
Execution State
The canonical record of the work. Objective, completed and pending tasks, decisions with reasons, artifacts, issues, failed attempts, assumptions, progress, last action, next action, and the full worker and handoff history. The engine owns this. No model does.
Universal Worker
One class, for every model. A worker is a configuration plus a gateway, with no memory between turns. It does not know whether it is the first worker or the hundredth.
Worker Result
The structured output a worker returns after doing its work. Validated by Pydantic. Treated as a claim, never as fact.
Handoff Report
A second, separate output every worker must produce, addressed to its successor. What was completed, what state things are in, what was decided and why, what failed, what is assumed, where it stopped, and what the next worker absolutely needs to know.
State Reconciler
The trust boundary. Merges the worker's claims into canonical state, deduplicates, stamps provenance itself, and records every discrepancy it noticed. This is the component that refuses to close an issue on an unverified assertion.
Context Compiler
Turns the full canonical state plus the next assigned task into a bounded, prioritized package. Scores every item for relevance, anchors the founding decisions, and fills a configurable token budget in strict priority order.
Handoff Package
What the compiler produces and the next worker actually receives. Plain structured text with an explicit record of what was included, what was omitted, and how many tokens it cost.
LLM Gateway
The only module allowed to know providers exist, and even it delegates to LiteLLM. Ships with a live gateway and a deterministic offline mock so the whole architecture runs with no keys at all.
Store
Written to disk after every worker turn, not at the end of a run. Holds state snapshots, worker executions, handoff reports, compiled packages, and an append-only event log. This is what makes a task resumable after a crash.
How the eight are wired dependency rule, claims vs records

The dependency rule

Dependencies point one way: orchestrator → {worker, reconciler, compiler, store}, and only worker → gateway. Nothing above the gateway imports a provider SDK or names a provider, and the gateway itself delegates to LiteLLM rather than branching per vendor. That is not a style preference. It is what makes "swap the model family mid-run" a configuration change instead of a code change.

Claims versus records

Two contract families sit side by side, and the split is deliberate. WorkerResult and HandoffReport are claim types: they are whatever a model produced, validated for shape only. Decision, Artifact, Issue and friends inside ExecutionState are record types, and they carry fields a worker structurally cannot populate: recorded_by, recorded_at, verified. Because provenance lives only on the record side, a model cannot assert its own authorship or its own verification status.

Why exactly one worker class

A per-model worker subclass is the obvious design and it is a trap: capability drift creeps into the class hierarchy, and within a few months "which worker can do X" is decided by inheritance instead of configuration. Here a worker is WorkerConfig + Gateway, and everything that varies (model string, credential, temperature, token ceiling, role label) is configuration read at runtime.

Two model calls per turn, not one

The result and the handoff report are separate calls with separate prompts. Merging them into one schema is cheaper and measurably worse: asked in the same breath to report success and to warn its successor, a model biases both toward the same tone. Asking separately, after telling the model its turn is over, is what surfaces "do not assume the refresh-token issue is solved". The cost is one extra call per turn, and on a rate-limited free tier that cost is the binding constraint, which is why max_tokens defaults to 2,200 rather than something larger.

Next See what crosses the boundary between two workers Then step through a single turn, one stage at a time, with the real objects the engine produced.
How it works

What crosses the boundary, and what never does.

A worker finishes, writes a report for its successor, and disappears. The engine reconciles what it claimed, updates canonical state, and compiles a fresh package for whoever runs next.

In plain words

Think of a relay race. The runners never merge into one person; they just pass a baton. What matters is what is on the baton.

Here the baton carries: what has been finished, what was decided and the reason for it, what was tried and failed, what is still broken, and what to do next. Short, useful, checked.

What the baton never carries: the previous runner's conversation, their thinking, who they were, or their password. Not because someone remembered to strip it out, but because the engine never wrote it down in the first place. There is nothing there to leak.

That is the dotted red line in the picture below. Everything above it simply does not exist as far as the next worker is concerned.

The boundary, mechanically message construction and the audit record

Every model call is constructed as exactly [{role: "system", ...}, {role: "user", package.rendered_text}]. The list is built fresh inside the worker on each turn; there is no instance-level message buffer, no session id, no thread handle, and no provider-side conversation object. Isolation here is structural rather than procedural: there is no code path that could append a prior turn, so it cannot be forgotten or regressed by a later change.

Each handoff also emits a TransferAudit record carrying raw_conversation_transferred, canonical_state_transferred, handoff_report_included, the included and omitted section lists, and the package's token cost against its budget. It is persisted, not merely logged, so the claim "no conversation crossed" is auditable after the fact from the database rather than trusted from a run's stdout. The run summary aggregates it, and across a full multi-worker run that count is zero.

The credential boundary is separate and narrower still. A key resolves inside the gateway from api_key_env or an in-memory WorkerConfig field; it is never a parameter of state, never serialised into a package, and never written to any of the six tables. Keys pasted into the playground live for the duration of one run.

WORKER N any model HANDOFF REPORT RECONCILER claims are not taken as facts CANONICAL EXECUTION STATE written to disk after every turn COMPILER budget enforced WORKER N+1 BLOCKED AT THE BOUNDARY conversation history, message arrays, model reasoning, session identity, API keys
Every model call carries exactly one system message and one compiled package, which is the mechanical reason no transcript can leak forward.
Step by Step

One turn, step by step

Below is a single worker's turn taken apart. The numbers, the package text, the JSON and the reconciler verdict are all from a real run of the demo task in the playground: worker three, picking up a design it has never seen, from two models it has never met.

The engine compiles state into a package, a worker executes it, and the reconciler merges the result back into state NEVER CROSSES: CONVERSATION, MESSAGE ARRAYS, MODEL REASONING, SESSION IDENTITY, KEYS CANONICAL STATE COMPILER scores, ranks, fits PACKAGE 631 of 1600 tok WORKER 3 no memory RESULT + HANDOFF REPORT RECONCILER trust boundary THE RECORD written every turn WORKER 4
Stage 1 of 7


        
Use the arrow keys, or click a stage. Every payload shown is the object the engine actually produced on that turn.
Budgeting

What the budget actually drops

The package above cost 631 tokens because the budget allowed 1600. Squeeze it and the compiler starts giving things up, but never in an arbitrary order: it fills strictly by priority, trims a section line by line before abandoning it, and refuses to drop the two sections a worker cannot function without.

In plain words

Packing a suitcase with a weight limit. You cannot take everything, so you have to decide what matters most, and you decide before you start packing, not by grabbing whatever is nearest.

The order here is fixed: your job first, then the goal, then what has been done, then the decisions and why, and so on down to notes from the last person. Two things are never left behind at any weight: your job and the goal. If they will not fit, they get shortened, never dropped, because a worker who does not know what it is doing is worse than useless.

Now drag the slider down to about 300 and watch failed attempts get struck out. That is the interesting one. The next worker now has no idea that the sliding door already jammed, so it will happily try a sliding door. Preventing exactly that is why this whole project exists.

The fill algorithm priority order, trimming, anchoring, estimation

Sections are built in a fixed priority order (1 assigned task, 2 objective, 3 current progress, 4 current task state, 5 decisions, 6 completed work, 7 artifacts, 8 unresolved issues, 9 failed attempts, 10 assumptions, 11 last action, 12 next action, 13 previous worker's notes), then filled greedily in that order. Three details make it behave:

  • Cost is measured against the rendered package, not a sum of section estimates. Section-wise estimation drifts from the real prompt by the joining whitespace and headers, and that drift is what produces "it fit locally but overflowed the window". Each candidate section is re-rendered with everything already accepted and the whole string is measured.
  • Trim before abandon. A section that does not fit whole is retried line by line, keeping the prefix that fits. A partially useful FAILED ATTEMPTS beats an absent one, and the package records that it was truncated rather than silently shortening.
  • Two sections are never dropped. assigned_task and objective are truncated character-wise as a last resort instead. Everything else that does not fit is reported in omitted_sections and dropped_items, so omission is observable rather than invisible.

Anchoring, and the bug it fixes

Item selection within a section blends relevance against the assigned task with a recency bias, under per-category caps. Pure relevance-plus-recency has a failure mode that showed up in a real five-model run: by worker five, the founding decisions ("use FastAPI", "use UUID primary keys") had been outranked by a flood of recent detail, and the review worker was auditing an architecture whose foundations it could not see. Anchoring pins the earliest decisions and failed attempts regardless of score. Flood the record with thirty later decisions and the founding ones still reach the final briefing.

Token estimation

Uses tiktoken when installed, otherwise the heuristic max(words, chars // 4). TokenEstimator is a protocol, so a per-provider tokenizer drops in without touching the compiler. The slider above runs the heuristic path, which is why its numbers match a tiktoken-less run exactly.

Cost is O(s²) in section count from the re-render-and-measure loop, with s = 13 fixed. Line-level trimming adds a factor of the lines in one section. At these sizes the whole compile is microseconds and is not on any hot path: a single model call is five to six orders of magnitude slower.

Token budget
Worker three's real state, run through the same priority order, the same greedy fill and the same token estimate the compiler uses when tiktoken is not installed. Verified against ContextCompiler at every budget on this slider. Drag it down to 300 and watch a later worker lose the failed attempts it needs in order not to repeat them.
Security & Trust

The trust model

A worker's report is a claim, not a fact. Generated text can exaggerate, invent an artifact, quietly drop an open issue, or declare a problem solved that nobody verified.

In plain words

"I did my homework" is not the same as homework. A teacher who writes done in the register every time a student says so ends up with a register full of nonsense.

So this engine believes almost nothing on the word of the worker. Four house rules:

  • If a worker says it fixed a problem and nobody checked, the problem stays on the list, with a note saying who claimed to have fixed it.
  • If a worker mentions a file it made, but did not list it properly, the file is written down and stamped unverified. It keeps that stamp as it travels forward.
  • Things that failed can be added but never removed. No later worker can quietly delete the record of a dead end.
  • The engine, not the worker, decides who goes next and what they do. A worker may suggest; it does not choose.

And the engine writes the name and time on every entry itself. A worker cannot sign someone else's name, because it never holds the pen.

The invariants and where they live merge semantics, and what is still thin

StateReconciler.reconcile(state, result, report, worker_id) → ReconcileOutcome is the only write path into canonical state. It is a pure merge over the aggregate, returning accepted counts, suppressed duplicates, warnings, unverified artifacts and rejected resolutions, all of which are persisted next to the execution record, so the verdict on any turn is queryable long after the run.

  • Issue resolution is never accepted from a claim. A worker asserting resolution sets resolution_claimed_by on the issue; resolved stays false. In the shipped demo, worker five claims the refresh-token rotation issue is fixed, the engine records the claim, keeps the issue open, and forwards it as open.
  • Artifacts named only in the handoff report (present in prose, absent from the structured result) are stored with verified=False and raise a warning. They travel forward labelled unverified, so the successor treats them as unconfirmed rather than as ground truth.
  • Failed attempts are append-only. Nothing a later worker says removes one. This is the single most load-bearing rule in the trust model, because a removable negative result is a negative result that will be rediscovered at full cost.
  • Provenance is stamped by the engine. recorded_by, recorded_at and verified are written by the reconciler from the worker id and the server clock. They are not fields a model can populate.

Merge semantics

Completed tasks and decisions dedupe on normalised text, so a restated decision does not inflate the record. Artifacts are versioned rather than overwritten: architecture.md v3 keeps that worker-1 created it and workers 2 and 5 modified it. Discrepancies between result and report (a last_action that disagrees, a decision with no reason, missing handoff notes, a completion claim for an unplanned task) are recorded as warnings rather than swallowed or thrown.

Where this is deliberately thin

verified is currently only ever false. Real verification (file existence, content hashing, a tool result) is the next layer, and verified is precisely the seam it plugs into: nothing above the reconciler reads the flag as anything other than a boolean, so a validator can begin setting it true without a change anywhere else. Claiming more than that today would be dishonest, so the page and the README both say so.

Observed in a live run

Worker five reported that the refresh token rotation issue was resolved. Nothing had verified it. The engine recorded the claim, kept the issue open, and passed it forward as still unresolved. You can watch this exact behaviour happen in the playground below.

See it work

Different vendors. Different models. Nothing lost between them.

Give it a job and a key, or borrow one of ours. Every worker runs on a separate credential and answers to a different model, and none of them ever sees another one’s conversation. Watch what crosses instead.

1

Bring a key

Any vendor. The key tells us who issued it, we ask them what it can run, and you pick from what comes back.

2

The job

What do you want done
Who decides the steps

Total the whole job may be told
9000 tok

Split across the workers, with later ones given more because they inherit more. Each share is a ceiling, not a cost.

The steps
3

Who does it

One worker per step, in order. Change any model you like: the engine never learns which company is behind which worker, so nothing below is load-bearing.

Two things are worth watching for. A green line between two workers is the handover, and it says in writing that no conversation crossed. A red box is a worker claiming something the record would not accept.

5

Turn by turn

Nothing running yet

Each worker will appear here with the exact briefing it was handed, what it claimed afterwards, which of those claims were refused, and the document that went on to whoever runs next.

4

What is happening

not started
Nothing running yet
    6

    What the record holds

    idle
    Next Read how it does all that The contracts, the way context is chosen, and what happens when a worker fails. Or jump to the glossary if a word here was unfamiliar.
    Use cases

    Where externalised execution state actually pays.

    Continuous tasks, heterogeneous teams, crash recovery, and auditable pipelines without conversation bloat.

    01

    Work that outlives a context window

    A long refactor, a migration, or a research task runs past what any single session can hold. Instead of compacting a transcript and losing the reasoning, the work continues in a fresh session with the decisions, the dead ends, and the exact next action intact.

    The failed attempts list is the part summarisation always loses.
    02

    Mixed model pipelines and cost routing

    Put a small fast model on bulk drafting and a strong one on review, inside one continuous task. Because no worker inherits a transcript, the expensive model pays only for the compiled state it actually needs, not for everything said before it arrived.

    Verified across four model families in a single run.
    03

    Provider outages and rate limits

    A provider throttles or fails mid task. The engine records the failure, keeps canonical state intact, and the next worker picks the work up from disk. Nothing in flight is lost, and the switch requires no code change.

    Rate limit backoff honours the delay the provider itself reports.
    04

    Work that has to be auditable

    Every decision carries who made it and why. Every artifact carries a version and whether anything verified it. Every claim the engine declined to accept is written down next to the execution that made it. You can answer what was decided, by which model, on what basis, and what was never actually checked.

    Useful anywhere a human has to sign off on model output.
    05

    Overnight and batch runs

    Long unattended jobs crash. When the process dies between worker three and worker four, a new process compiles worker four's package from what is on disk and finishes the task. State is written after every turn, not at the end.

    Tested by killing a run mid execution and resuming it in a fresh process.
    06

    Comparing models on identical footing

    Because context is compiled rather than inherited, two models can be given byte identical inputs at the same point in a task. Differences in output are attributable to the model instead of to accumulated conversational drift.

    Every model call carries one system message and one package.
    Inside the machinery

    The rules that make the record trustworthy.

    Everything below is true of the working code behind the run you just watched, including the parts that are deliberately unfinished.

    One turn, as a sequence

    The loop, condensed
    # state is loaded from the record, never held only in memory
    for seq, (worker, task) in enumerate(assignments):
        package  = compiler.compile(state, task, worker.id, budget)   # deterministic
        result   = worker.execute(package)                            # call 1 -> WorkerResult
        report   = worker.handoff(package, result)                    # call 2 -> HandoffReport
        outcome  = reconciler.reconcile(state, result, report, worker.id)
        store.write_turn(state, package, result, report, outcome)     # before the next turn
        audit    = handoff.audit(worker, next_worker, package)        # persisted, not logged

    Two model calls per turn, one write per turn, and no shared mutable object between iterations except state, which only the reconciler writes.

    Contracts

    TypeTrustWhat it holds
    ExecutionStatecanonicalObjective, completed and pending tasks, decisions, versioned artifacts, issues, failed attempts, assumptions, progress, last and next action, worker and handoff history.
    WorkerResultclaimWhat the worker says it did this turn. Shape-validated by Pydantic, believed by nothing.
    HandoffReportclaimA second, separate output addressed to the successor: state at handoff, what is unfinished, what must not be assumed.
    HandoffPackagederivedThe compiled context a worker receives, plus included_sections, omitted_sections, dropped_items and estimated_tokens.
    ReconcileOutcomeverdictAccepted counts, suppressed duplicates, warnings, unverified artifacts, rejected resolutions. Persisted beside the execution.
    TransferAuditevidencePer-handoff record of what crossed and what did not, with token cost against budget.
    WorkerConfigconfigid, model, credential source, api_base, temperature, max_tokens, max_retries, role, enabled, provider_config. Read from JSON at runtime.

    Design decisions worth arguing with

    State is a typed aggregate, not an event log

    An event-sourced design would give free history and replay. It was rejected because the compiler's job is category-aware budgeting, and folding an event stream into categories on every compile is work the aggregate does once. History is kept anyway as per-turn snapshots plus an append-only event table, so replay is available without paying for it on the read path.

    Sequential turns, not a DAG

    Only one worker runs at a time. Parallel branches would need conflict resolution in the reconciler (two workers versioning the same artifact from the same base), and that is a different, larger problem. SwitchPolicy is the interface a scheduler would implement; the loop itself would not change shape.

    Budget measured on rendered text

    Summing per-section estimates drifts from the real prompt by headers and joining whitespace, and that drift is exactly what produces a context overflow that unit tests never see. Re-rendering costs O(s²) with s = 13 fixed: microseconds against a model call.

    Write after every turn, not at the end

    Persisting per-turn is what makes resume real rather than aspirational: kill the process between worker three and worker four and a new process compiles worker four's package from disk.

    Rate limits are scheduling, not failure

    The gateway parses the delay the provider itself suggests ("try again in 8.4s") and honours it, falling back to exponential backoff. The same worker simply waits; state is untouched, so nothing needs unwinding.

    Provider blindness is tested, not documented

    tests/

    Failure semantics

    What failsWhat happensWhat is lost
    A single worker callThe failure is recorded on the execution row; the run continues from canonical state with the next worker.that turn only
    Provider rate limitRetried inside the gateway, honouring the provider's own suggested delay.nothing
    The process is killed mid-runState up to the last completed turn is on disk. A fresh process recompiles the next briefing from it and finishes the job.the in-flight turn
    A model returns unparseable outputPydantic validation rejects it; the turn is recorded as failed rather than merged half-formed.that turn only
    A worker lies about what it didThe reconciler's four invariants contain it: the issue stays open, the artifact is stamped unverified, the failed attempt cannot be deleted.nothing structural
    The budget is set too lowSections are trimmed then dropped in priority order, and every omission is reported in the package.context, visibly

    Seams built for extension

    SwitchPolicy
    Decides which worker takes which step. SequentialSwitchPolicy is one implementation; cost-aware, capability-aware, context-limit and availability routing are all alternate implementations of the same interface. The loop does not change.
    TokenEstimator
    A protocol. tiktoken when present, a character and word heuristic otherwise, a per-provider tokenizer if you write one.
    Gateway
    Live (LiteLLM) and deterministic mock implementations of one interface. A gateway that records and replays answers is the same shape.
    Artifact verification
    The verified flag is currently only ever false. File existence, content hashing or a verification step would set it true, and nothing above the reconciler needs to change; it already reads the flag as a boolean and forwards the label.
    Store
    A narrow interface over a handful of tables. Swapping the database underneath is a swap, not a rewrite: the engine only needs write-a-turn and read-a-task.

    What this is not

    Honest limits

    Not a parallel agent framework: turns are strictly sequential. Not a tool-use or code-execution runtime: workers produce structured descriptions of work, and artifact content is never validated, which is why every artifact carries unverified. Not a scheduler, a queue, or a service. And not a claim that this beats a single long-context model on a task that comfortably fits in one window: it earns its place when the work outlives a context window, crosses model families, or has to be auditable afterwards.

    Next Every word on this page, defined twice Plain words in one column, the precise meaning in the other.
    Glossary

    Every word this page uses, defined twice.

    Once the way you would explain it to someone who has never written code, and once the way you would write it in a design document. Both columns describe the same thing.

    TermIn plain wordsPrecisely
    Tokenthe unit of cost Roughly a word-and-a-bit. AI models charge by how many you send them, so "how many tokens" really means "how much does this cost and will it even fit". The unit a model's tokenizer splits text into. Here estimated with tiktoken when available, otherwise max(words, chars // 4).
    Context windowthe size limit How much a model can hold in its head at once. Go over it and the oldest parts fall out the back. The maximum token span a model attends over in one call. Exceeding it truncates or errors depending on the provider.
    Worker One AI doing one turn of the job. It walks in knowing nothing, reads its briefing, does its bit, and forgets everything. WorkerConfig + Gateway. One class for every model; no memory between turns and no reference to state that outlives the turn.
    Canonical state The notebook. The one true record of the job, owned by the system and not by any of the AIs. ExecutionState, a typed Pydantic aggregate. The single source of truth; only the reconciler may write to it.
    Context packagethe briefing The one-page sheet a worker is handed. Written fresh for that worker, for that step, with a note saying what had to be left off. HandoffPackage: rendered text plus included_sections, omitted_sections, dropped_items and estimated_tokens.
    Handoffthe pass The moment one worker stops and the next starts. What crosses is the notebook, never the conversation. A turn boundary producing a HandoffReport, a reconcile, a persisted write and a TransferAudit record.
    Handoff reportthe note A note every worker must write to whoever comes next: where I stopped, what to look out for, what not to assume is done. A second, separate model call with its own schema, so warnings are not biased by the same breath that reports success.
    Reconciler The teacher who checks the homework before writing anything in the notebook. Believes almost nothing on the worker's word alone. StateReconciler, the sole write path into canonical state. Dedupes, stamps provenance, and enforces four invariants.
    Claim vs. factthe trust split "I did my homework" is not homework. Everything a worker says is a claim until the engine has a reason to accept it. Claim types (WorkerResult, HandoffReport) are shape-validated only. Record types carry engine-written recorded_by, recorded_at and verified.
    Provenancethe signature Who wrote this down, and when. The engine signs every entry itself, so no worker can sign someone else's name. Engine-stamped attribution fields on every canonical record. Structurally unpopulatable by a model.
    Unverifiedthe stamp "Someone said this exists, but nobody checked." The stamp travels forward so the next worker knows not to rely on it. verified=False on an artifact. Currently always false: the seam where real validation plugs in.
    Token budgetthe weight limit The size limit on a briefing sheet. It forces the engine to decide what matters most instead of dumping everything. A per-package ceiling enforced against the rendered package, filled greedily in priority order. Default 1,600.
    Anchoringcompiler rule Always keep the very first big decisions, even when newer stuff looks more urgent. Otherwise the last worker cannot see the foundations it is judging. Pinning earliest decisions and failed attempts regardless of relevance score. Added after a real run where founding choices were outranked by recent detail.
    Failed attemptthe dead end Something already tried that did not work. The most valuable thing in the notebook, and the first thing a summary would throw away. An append-only category. No later worker can remove one, because a removable negative result will be rediscovered at full cost.
    Gateway The only part allowed to phone the AI companies. Everything above it has no idea which company it is talking to. The single provider-aware module, delegating to LiteLLM. Ships live and deterministic mock implementations of one interface.
    Mock gatewayoffline mode A stand-in that answers instantly without calling anyone, so you can run the whole thing with no key and no cost. Deterministic offline implementation. Compilation, reconciliation, persistence and audit all execute for real; only the model call is simulated.
    Orchestrator The organiser. Decides who goes next, hands out briefings, and keeps the notebook safe. Owns the turn loop, the worker registry and the SwitchPolicy. Owns the plan cursor; a worker's suggested next action is advisory.
    Resumecrash recovery If the power goes out halfway, you can pick up where it stopped, because the notebook was saved after every turn. Rebuilding the next package from persisted state in a fresh process.
    Next The questions people actually ask Including the sceptical ones: is this not just RAG, and why not use a long-context model?
    Questions

    The things people ask, including the sceptical ones.

    Direct answers on models, security, RAG vs. state, rate limits, and framework comparisons.

    Next What is built and what is verified Including the one part that is deliberately minimal, and why.
    Status

    What is built and what is verified.

    Current test coverage, verified behaviors, and architectural invariants.

    The machinery
    The record, the interchangeable worker, the reconciler, the briefing compiler, the model gateway and the persistent store. All built and working.
    Live execution
    Five workers, four model families, five separate credentials, roughly ninety seconds per run.
    Provider independence
    No part of the engine above the gateway names any provider, and there is exactly one worker class.
    Crash recovery
    Verified by killing a run after three workers and resuming to completion in a new process.
    Scale
    Runs identically with one, three, five, twenty, and one hundred workers.
    Artifact validation
    Deliberately minimal. Workers name artifacts and the engine grades them unverified. Real content validation is the next layer, and the seam for it already exists.