Context Window Architecture — a context assembler spec (v2 draft)
CWA
GitHub
Context assembler spec · v2 draft

Context isn't a prompt. It's an assembled request.

CWA is a free specification for assembling everything a model call needs — instructions, state, evidence, history, the live turn — into one payload where every item has an owner, an authority, a lifecycle, a budget, and a place. Deterministic assembly. Inspectable behaviour.

Watch it assemble Copy the scaffold
Assembling · {{ mUcName }} {{ mProgress }}
{{ b.tag }}
{{ b.text }}
{{ mTokens }} profile · policy-first-chat/v1
Not a library
Nothing to install. A specification you apply to the payload you already send — and an assembler you can build against it.
Deterministic assembly
Same inputs, same source versions, same policy, same payload. The model's output stays probabilistic; the request never is.
Traceable
Every assembly run emits a trace: what got in, what was compressed, what was refused, and why.
Evaluating? Read to Why it works. Building? Start at the Spec.
The problem

What goes wrong when nobody owns the payload.

Every model call is assembled by a function. In most systems it has no name. It grew arguments for a year, it concatenates whatever the route happens to hold, and it knows nothing about who is allowed to direct the model, how old each piece is, what to shorten when the window is full, or what it sent last time. The failures this produces are not random. They repeat, they have shapes, and they can be named.

01 Authority inversion A protocol document outranks the never-diagnose rule, and the assistant names a condition. Reproduce · Clinical triage → 02 Instruction-shaped evidence A lint config or a runbook reads as a command, and the bot starts rewriting style or proposing failover. Reproduce · Code review bot → 03 Stale-as-current Last week’s brief is indistinguishable from this week’s data, so old numbers ship as current. Reproduce · Weekly brief → 04 Memory that never expires Corrections from weeks ago become live instructions. Reproduce · Language tutor → 05 Displacement under budget History is unbounded, so by turn thirty the price rule has been pushed out of the window. Reproduce · Support agent → 06 Redundant re-reading The whole menu is re-read on every turn; the reply lands late. Reproduce · Voice ordering → 07 Missing trigger The query is buried or absent, so the turn returns a summary, or nothing. Reproduce · Support agent, query removed →
These are assembly errors. Today they have no assembler.
Each card opens the demo on the system that reproduces it, shown as the unassembled blob.

Where an item sits in the window matters too. That question has evidence of its own: Why placement is a profile, not a rule.

Why it works

Prompt construction, promoted to assembly.

01

A shared vocabulary

"Evidence polluted governance" and "history displaced tool results" are sentences a team can act on. Named planes and slots turn vague prompt debates into specific bug reports.

02

Deterministic assembly

Same request state, same source versions, same selection rules, same budget: the assembler emits the same payload in the same order. That is a testable claim. "The model will answer the same way" is not, and CWA never makes it.

03

A budget with a policy

Tokens are finite. When every item is measured and tiered, the assembler knows what to protect, what to compress, what to drop, and when to stop and say the evidence didn't fit.

Live assembly

The slots aren't the point. The assembly is.

CWA gives you four planes and eleven typed slots. No request fills them all. The assembler admits the items each request actually needs, fits them to a finite budget by priority, and renders them in a tested order. Watch seven very different systems assemble — then pull a slot out, or squeeze the budget, and see what degrades first.

Input budget
Window fill {{ tokenLabel }}
{{ evictionLabel }}
Protected · instructions, task state, output contract, query Compressible · memory, history, knowledge, tool results Droppable · examples, user facts
Slots {{ usedLabel }}
Click a slot to remove it →
Nothing to click — the slots no longer exist
{{ ucName }} {{ progress }}
{{ line.tag }} {{ line.tokens }}
{{ line.text }}
↓ rendered by {{ profileName }} trace {{ traceId }}
Symptom you'll actually see

{{ ucSymptom }}

{{ n.text }}
What breaks without it
{{ r.tag }} {{ r.text }}
What this one teaches

{{ ucNote }}

Decisions it forces
? {{ q.text }}
The schema

Four planes. Eleven slots. Any number of items.

A plane says why a piece of context exists. A slot is a typed collection inside a plane, with its own admission rules. An item is one governed object in a slot — a policy, a retrieved passage, a tool observation. Newcomers learn the planes; implementers use the slots; the assembler moves the items.

{{ pl.name }}
{{ pl.answers }}

{{ pl.blurb }}

{{ s.name }} {{ s.id }}
{{ layer.meta }}
Holds

{{ layer.purpose }}

Admission rule

{{ layer.value }}

The unit

A slot holds items, not a paragraph.

Real systems put three retrieved passages, two tool observations, and a memory summary plus a task episode into the same request. Each one is a separate item with its own metadata. Without that metadata a clean slot order still produces unpredictable payloads.

{{ f.key }} {{ f.text }}
context_item.yaml evidence.knowledge · 1 of 3
id: "retrieval:refunds-eu:v17#p4" slot: evidence.knowledge type: evidence source: policy-corpus source_version: "2026-09-10" authority: reference_only trust: verified freshness: "2026-09-12T15:30:00Z" scope: refund_request eligibility: "similarity >= 0.82 AND jurisdiction == EU" token_budget: 420 compression: extractive_quote conflict_policy: defer_to_current_tool_result injection_risk: untrusted_content lineage: verbatim placement: evidence_near_query
placement is a hint the route’s profile consumes, not a position. Where items go is a profile decision with evidence behind it: Why placement is a profile, not a rule.
Go deeper

Order alone is not an architecture.

A fixed order reproduces a payload. It says nothing about who is allowed to direct the model, what wins when sources disagree, whether this order is right for this model, or how anyone would know. The normative rules, the producer contract and the placement evidence each have a page of their own.

Specification · v2 draft 23 numbered requirements. Conformance language, the authority hierarchy and resolution matrix, budget tiers, the profile shape, required trace fields. Pure text, permalinked per rule, mirrored to the repo. Read the spec → Producer contract What your tool has to emit. Eight minimum fields, slot defaults, the rules for retrievers, memory stores, state services and MCP servers. Paste an item into the linter and see whether an assembler would admit it. Read the contract → Placement evidence Why placement is a profile, not a rule. Serial-position research, provider guidance by model generation, the profile format and how to evaluate one. Five profiles to diff, one new. Read the evidence →
Evidence selection

RAG lands in Evidence. Admission is a pipeline.

"Retrieval goes in slot three" is memorable and too coarse. Between the vector store and the payload sit eight decisions. Each one is a deterministic rule the trace can point at. For high-stakes answers the slot holds evidence packets — source, passage, version, relevance, authority, binding or informative — not "knowledge."

{{ s.n }}
{{ s.name }}

{{ s.text }}

When nothing valid is retrieved
The assembler does not answer from nothing. It retrieves narrower, summarises with traceability, or routes the request for more context — and the trace records which.
When admission yields no valid evidence, an assembler MUST NOT answer from nothing. It MUST retrieve narrower, summarise with traceability, or route for more context, and the trace MUST record which.
Fresh beats retrieved
A tool observation from 0.4 seconds ago and a passage indexed in August are both evidence. For current facts, the observation governs; the passage cites.
In practice

What an assembled request looks like on the wire.

CWA doesn't dictate syntax. Tag slots however your stack prefers — XML-ish blocks, message roles, delimited sections. What matters: every item names its slot and authority, evidence arrives as packets with provenance, and the profile that ordered them is recorded.

payload.txtprofile · policy-first-chat/v1
<!-- governance.instructions · authority=governing · v12 -->
<system>You are Ada, a support agent for Northwind.
Never quote prices you cannot verify with a tool.</system>
<!-- state.user · authority=state · scope=session -->
<user_profile>plan=pro; region=EU; tone=concise</user_profile>
<!-- evidence.knowledge · authority=reference_only · 2 of 12 candidates -->
<evidence id="refunds-eu:v17#p4" trust="verified" as_of="2026-09-10">
Pro plans refund in full within 30 days of purchase.
</evidence>
<evidence id="billing-faq:v3#p1" trust="verified" as_of="2026-08-02">
Refunds return to the original payment method.
</evidence>
<!-- state.task · authority=state · canonical, app-owned -->
<task>refund_request: verify_eligibility=done, issue=pending</task>
<!-- interaction.memory · authority=generated · lineage=summary -->
<memory>User bought Pro in March, EU billing.</memory>
<!-- interaction.history · authority=user · verbatim, last 6 -->
<history>user: is my order refundable?</history>
<!-- governance.capabilities · authority=capability -->
<tools>lookup_order(id), issue_refund(id, amount)</tools>
<!-- evidence.tool_results · authority=observation · age=0.4s -->
<observation call="lookup_order(8821)">{"total": 240, "days": 12}</observation>
<!-- governance.output_contract · authority=governing -->
<format>Max 3 sentences. No bullet lists.</format>
<!-- interaction.query · authority=user · the trigger -->
<query>Can you just process it now?</query>
<!-- trace ctx_01J9K · 3 items excluded · 0 conflicts · policy-first-chat/v1 -->
Where it fits

It replaces nothing you already use.

Your tools supply the materials. CWA is the assembly step between them and the model.

RAG

Retrieval produces candidates for the Evidence plane. CWA decides which are admitted, how they're packetized, and what they may never overrule.

Read →
Model Context Protocol

MCP is the transport for tools and resources. CWA governs what it returns — capabilities in Governance, observations in Evidence, each with freshness and authority.

Read →
Agent frameworks

Frameworks orchestrate the loop. CWA assembles the payload each step of that loop actually sends, and emits the trace for it.

Read →
Prompt engineering

Prompting is craft at the sentence level. CWA is structure at the payload level. You need both.

Read →
Harness engineering

Already using a framework? The assembler goes inside it.

Your framework is the harness: it runs the loop, calls the tools, keeps the state, retries the failures. It is deliberately unopinionated about the one thing that decides answer quality — what actually lands in the window on each pass. That hole is where CWA lives. Pick your stack:

Runtime loop · {{ fwName }} Framework territory
01
Receive input
02
Plan / route
03
Resolve tools
04 · yours
{{ fwSeamStage }}
05
Call model
06
Parse & act ↻
Inside stage 04 Your territory · CWA specifies this
The framework hands you an empty array and a place to put a string. Everything below is a decision you are already making — usually implicitly, in one function, with no names for the parts.
{{ c.label }}
seam · {{ fwSeam }}
Your harness already owns
{{ o }}
It leaves you a blank
{{ b }}
What that costs you
{{ c }}
Should you use CWA with {{ fwName }}?
{{ fwVerdict }}
Skip it if
One fixed prompt, no retrieval, no history. An assembler for a single slot is bureaucracy.
Skip it if
You never use more than a fifth of the window. Nothing competes, so nothing needs priority.
Skip it if
It's a prototype you'll delete on Friday. Come back when someone asks why it answered that.
Take it with you

Copy the scaffold. Start today.

Six steps from your current prompt to a payload with owners, a migrator that proposes slots for it, and five files to copy: an assembly function, an empty payload, the item schema as YAML and JSON Schema, and a cwa.md for coding agents.

Getting started →

Adopt the spec. The assembler comes next.

Name the slots you already send, give every item an authority and a source, and see how much of your payload had no owner. A reference assembler that implements this spec — admission, fitting, profiles, traces — is in progress. Tell us what it must do. A future revision will describe request intent as a typed tree that items bind to.

View on GitHub Read the docs
{{ tourKicker }} {{ tourCount }}
{{ tourTitle }}
{{ tourBody }}