HOW AI ACTUALLY WORKS · TOP TO BOTTOM

THE DESCENT

How AI actually works — from the chat box to the silicon, and back up to your business.

L0 · 10⁰The Conversationwhat pressing Enter actually sends L1 · 10⁻¹Text Becomes Numberstokenization, BPE, embeddings L2 · 10⁻³The Transformer Blockattention — how the model decides what mattersQ·Kᵀ, softmax, MLP, residual L3 · 10⁻²Generationhow the next word gets picked, one at a timelogits → sampling → the loop, KV cache L4 · 10⁻⁹Silicon and WattsGPUs, memory-bound inference, batching L5 · 10¹The Agent Looptools, MCP, context and memory L6 · 10²Orchestrationmulti-agent, verification, tradeoffs L7 · 10³Building It For Youhow this becomes delivered systems

The depth on each card is the physical scale of that level's subject — from your sentence at arm's length down to nanometer silicon, then back up through agents and fleets to the business. The gauge tracks the size of the thing, not the reading order — which is why L2's matrix cells sit deeper than L3's words.

Everything on this page is public science about the architecture class. Where a specific product's internals aren't published, this page says so — that's the difference between knowing the field and guessing.

begin the descent ↓

LEVEL 0 · 10⁰ — THE SENTENCE public science

The Conversation

You are not talking to a mind — you are sending a document that gets continued, and the server forgets you the moment it finishes answering. One stateless HTTPS POST per turn: system prompt plus full message history serialized to JSON in; a stream of tokens out; zero session state retained on the server.

Here is the one fact that reorganizes everything below it. Every time you press Enter, your app mails the entire conversation so far — hidden instructions, every earlier turn from both sides, and your new sentence — to a server. The server reads all of it, writes the next chunk, sends it back, and keeps nothing. There is no "session" living somewhere with your name on it. (Providers do cache and log as optimizations and policy — but correctness never depends on the server remembering you.) Each turn is one stateless HTTPS POST. The client serializes the system prompt plus every prior turn into a JSON messages array; the server tokenizes it, runs the model, streams the reply back, and retains no conversational state for the next call. "Memory" is client-side replay. Caching and logging exist server-side as optimizations and policy — but correctness never depends on the server remembering you.

That single fact explains most of what people find mysterious: why the model knows nothing about your other chats (they were never in the envelope), why long conversations get slower and pricier (the envelope grows every turn), and why "it remembered me" always means "software on the client side put that back into the envelope." Statelessness is a deliberate architecture choice, the same one behind every scalable REST service: a request that carries all its own context can be served by any replica, so the provider gets horizontal scale and the client inherits the memory problem — transcripts, summaries, retrieval are all client-side responsibilities.

C++ The conversation is a std::vector<Message> — roughly struct Message { Role role; std::string content; } — serialized to JSON and re-sent whole on every call: push_back, never mutate.

The request, literally

This is not a metaphor — below is essentially the whole thing your chat app sends. An ordinary web request, the same kind your browser makes for any page, carrying one JSON body. Step through it. The wire shape below follows the published Anthropic Messages API — every field shown is in the public docs; other providers differ in field names, not in kind. Step through it.

POST /v1/messages HTTP/1.1
Host: api.anthropic.com
x-api-key: sk-ant-…   (secret — lives server-side, never in a browser)
content-type: application/json
 
{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 1024,
  "stream": true,
  "system": "You answer plainly and admit what you cannot see.",
  "messages": [
    { "role": "user",      "content": "What limits your memory?" },
    { "role": "assistant", "content": "A fixed token budget shared by all I can see." },
    { "role": "user",      "content": "So what happens in long chats?" }
  ]
}
  1. It starts as an ordinary web request — the same kind your browser fires for any page. No open line to the model, no special channel, no standing connection with your name on it. One HTTPS POST to a published REST endpoint, authenticated by an API-key header, body in plain JSON. Anything that can make a web request can drive a frontier model — that is the whole integration surface.
  2. The system prompt is the part of the envelope you never see in a chat app: instructions the developer prepends that set the persona and the rules. It is not magic — it is a field in the request. system is a top-level request field in this API's shape. It occupies the same token budget as everything else and reaches the model as tokens in the same linear sequence — authority is trained in, not enforced by the wire.
  3. Here is the conversation itself — all of it, every turn from both sides, replayed in full on every single request. This array IS the model's memory of you. The messages array alternates user/assistant roles and is append-only: the client re-sends the whole transcript each turn because the server holds no session.
  4. Only this last entry is new — the sentence you just typed. Everything above it is history your own app is mailing back so the model can see it again. The newest user turn is one more element pushed onto the array. Nothing marks it as special at the wire level; recency matters only because of its position in the sequence.
  5. Two practical dials: a cap on how long the reply may get, and a flag asking for the answer to be delivered word-by-word as it is written instead of all at once at the end. max_tokens reserves output room inside the same shared budget; stream: true keeps the HTTP response open and delivers tokens as server-sent events the moment each one is sampled.

One honest caveat about that hidden field: the system prompt mechanism is public science, but any given product's exact production text is only known if its vendor chooses to publish it not public. Roles are just special marker tokens in one linear sequence — there is no hard channel separating "instructions" from "input" at the wire level. The model is trained to weight system-role text more heavily, which is why prompt injection (untrusted text impersonating instructions) is a structural risk to engineer around, not a bug to patch. The mechanism is public; a specific product's deployed system-prompt text is the vendor's to publish or not not public.

The round trip

YOUR CLIENT system user assistant user (new) append-only the whole transcript API SERVER MODEL predict → append → repeat state kept between calls: none one HTTPS POST carries the ENTIRE transcript, every turn tok tok tok reply streams back one token at a time (SSE) next turn: client appends the reply, mails an even bigger transcript, and the cycle repeats
client the whole convo API + model POST everything → ← tokens drip back append & repeat
"Every turn, the client mails the entire conversation to a server that remembers nothing, the reply drips back token by token, and the client appends it so next turn's mailing is one turn bigger."

The reply "typing itself" across your screen is not theater. The model genuinely produces one token at a time, and the server forwards each one the instant it exists — waiting for the whole answer before showing anything would be the same computation with worse manners. With stream: true the response arrives as SSE deltas — in the Anthropic shape, content_block_delta events — which the client concatenates into the visible reply. Same tokens, same order; the win is time-to-first-token, not total time.

YOUR CLIENT API SERVER system user assistant user (new) one JSON body POST — full transcript TLS, one request, no session MODEL predict → append → repeat tok tok tok SSE — each token forwarded the moment it is sampled + assistant (new) state kept for next call: none next turn starts at step 1 — with a bigger transcript
  1. You press Enter. Your app does not send your sentence — it assembles the whole conversation so far into one package, with your new sentence appended at the end. The client serializes system prompt + full messages history + the new user turn into one JSON body. Nothing has touched the network yet.
  2. One sealed envelope crosses the wire. However long you have been chatting, each turn is a single self-contained delivery. A single HTTPS POST over TLS. The request is self-describing; no cookie or server session is required for the model to have "context" — the context is the payload.
  3. The server reads the entire conversation from the top and starts writing the continuation, one small piece at a time. The payload is tokenized and run through the model: predict a distribution over the next token, sample one, append it, repeat — the autoregressive loop that Levels 1–3 open up.
  4. Pieces of the answer come back the moment they are written — that is the "typing" effect you watch in every chat app. Each sampled token is flushed down the open response as an SSE event; the client appends deltas to the visible reply as they land.
  5. Your app files the finished reply into its local copy of the conversation. The server keeps nothing at all — next turn, the whole, now-bigger conversation gets mailed again. Client appends the assistant turn to its transcript; server-side session state after the response: none. Turn k+1 re-sends all k prior turns — remember that shape for the arithmetic below.

The context window — an append-only log with a hard ceiling

The envelope has a hard size limit. Hidden instructions, tool descriptions, every turn either of you has ever sent in this chat, plus room reserved for the reply — all of it shares one fixed budget. When the budget fills, something must be thrown away or compressed, and that is the moment a long chat starts "forgetting" its own beginning. The context window is one budget with four tenants: system prompt, tool definitions, full history, reserved output. Published frontier limits run from 128K to roughly 1M tokens public science — the numbers are in each vendor's API docs. Overflow means truncation, compaction (summarize old turns), or a hard error; the model cannot attend to what was never sent.

C++ The context window is a fixed stack-frame budget, not a heap — everything the call needs must fit in one frame. Overflow errors at the API; the silent fall-off of the oldest data happens in the client's truncation policy, not on the server.

ONE SHARED BUDGET — everything the model can see, in a single bar SYSTEM TOOLS HISTORY — every prior turn grows every turn → HEADROOM reserved for the reply total = the model's published limit, e.g. 200,000 tokens — one budget, not per-message when system + tools + history + headroom would exceed it: truncate, summarize, or fail
The context window as an append-only log inside a fixed budget. Segment sizes are illustrative; the limits themselves are published per model public science.

Run the numbers once and long-chat behavior stops being mysterious. Take a 200,000-token budget, subtract fixed overhead and reply room, and divide by the cost of a typical turn: Worked with round numbers — a 200,000-token budget, 3,000 tokens of fixed system + tool overhead, 4,000 reserved for output, and an average of 1,200 tokens per full turn (user message + assistant reply):

history budget = 200,000 3,000 4,000 = 193,000 tokens
turns that fit 193,000 ÷ 1,200 160 turns

But the sharper insight is the total bill. Because the whole conversation is re-mailed every turn, you pay for the early turns again and again — over that 160-turn chat you are billed for about eighty times more tokens than the final transcript actually contains. Append-only replay has a quadratic cost curve: turn k re-sends all k−1 prior turns, so a T-turn chat bills O(T²) input tokens in total, not O(T). Summing the arithmetic series for T = 160:

total billed = 1,200 × (1 + 2 ++ 160) = 1,200 × 12,880 15.5M tokens
final transcript 195,000 tokens you pay ~80× the transcript

That one calculation is why every serious AI system summarizes old turns, retrieves only what is relevant, or starts fresh — and why "just make the window bigger" changes what is affordable, never the mechanism. Hold that thought: the descent now follows the envelope inside the machine, starting with what a token actually is. Quadratic replay is the root cause behind three optimizations you will meet on the way down and back up: KV caching inside one generation (Level 3), prompt caching across turns (published, priced API features public science), and context compaction in agent loops (Level 5). Next: what a "token" actually is.

LEVEL 1 · 10⁻¹ — THE TOKEN public science

Text Becomes Numbers

Before the model reads a word of your sentence, the sentence is gone — replaced by a list of integers, and each integer by a point in space where distance is meaning. A BPE tokenizer maps text to ids over a fixed vocabulary; each id indexes a row of W_E ∈ ℝ^{V×d_model}, and the sequence enters the stack as one positions × d_model float matrix.

The model never sees letters. A tokenizer chops your text into reusable fragments — whole common words, pieces of rare ones — and hands the model only the fragment numbers. Everything the model will ever know about your sentence has to survive that conversion. Input is segmented by BPE (or a close relative): a merge table learned offline by greedily fusing the most frequent adjacent pair, applied at runtime as a deterministic merge-replay encode. Output: a sequence of integer ids.

A rough napkin figure for English prose: ~4 characters ≈ 1 token — it drifts for code, dense JSON, and non-Latin scripts, which tokenize less efficiently. Vocabularies typically run tens of thousands to a few hundred thousand entries architecture class · publicly inferred

  1. Start from the raw sentence — just a stream of characters, including the spaces. Encoding starts at the byte level: every input is representable, so there is no out-of-vocabulary failure mode — worst case, a word falls apart into bytes.
  2. Offline, before the model ever ships, the tokenizer learned which letter-pairs occur together most often — and glued the winners into single units. BPE training: count all adjacent pairs in the corpus, merge the most frequent, repeat. Each merge appends one rule to an ordered merge table.
  3. Repeat that gluing tens of thousands of times and frequent words become one unit each, while rare words stay in pieces. The stop condition is the vocabulary budget V — merges run until the table reaches V entries. Frequency decides granularity; nothing linguistic does.
  4. Encoding replays those glue rules on your sentence: six fragments, six id numbers. This list of integers is all the model receives. Runtime encode applies the learned merges deterministically — same text, same ids, every time. The ids here are toy; real vocabularies index into the tens or hundreds of thousands architecture class · publicly inferred
  5. Here is why models famously stumble counting the letters in "strawberry": the model never gets letters. It gets three opaque ids — asking it to count the r's is asking about characters it cannot see. This split — str·aw·berry — is one plausible BPE-family segmentation; exact pieces vary by tokenizer — some vendors publish theirs (OpenAI's tiktoken is open source); Anthropic's is not published not public The failure is representational, not a reasoning bug.
  6. Tokens are also the billing unit — every provider prices per million tokens, and Level 0 showed the whole history is resent every turn. Token count is the cost model of this entire industry. Published API pricing is per-token in and out public science — the $3/M figure here is illustrative arithmetic, not a quote. Replayed history re-bills as input each turn; prompt caching exists precisely to discount that repeated prefix.

The vocab table — the first data structure

The tokenizer's whole worldview fits in one two-column table: a fragment of text on one side, its id number on the other. That file ships with the model and never changes after training. Concretely, a string→int map serialized to disk (open models ship it as a JSON vocab plus an ordered merges list), inverted at decode time to an id-indexed array of strings.

{ "the": 12, "str": 901, "aw": 33, "berry": 17, "␣tastes": 2044, … }  // vocab: string → id
[ "t h", "th e", "s t", "st r", "a w", … ]                            // merges: ordered rules

C++ Tokens ≈ indices into a vocab array: decode is const char* s = vocab[id]; — encode is the only interesting direction, and it is a replay of the learned merges over the merge table.

From id to vector — the embedding lookup

An id number carries no meaning by itself — 17 is not "berry-ish". So the model keeps a giant learned table with one row per vocabulary entry, and a token's meaning is its entire row: a long list of numbers positioning it in a space where words used alike sit close together. The embedding matrix W_E has shape V × d_model; lookup is a bare array index, no hashing, no search. Directions in that space are discovered during training, not designed — nothing labels them.

xt = WE[idt],   WE V×dmodel

Internal width d_model is commonly a few thousand for frontier-class models architecture class · publicly inferred — worked examples on this page use toy sizes (d_model = 4, V = 8) so every number fits on screen.

C++ Embedding lookup ≈ &weights[token_id * d_model] — a float* lookup table: one strided read per token, then billions of multiply-accumulates; tokenization cost is noise next to the forward pass.

berry id 17 ← d_model columns → W_E — V rows: the whole vocabulary row 0 row V−1 0.31 −1.20 0.07 2.41 row 17 0.31 −1.20 0.07 2.41 the vector (toy d = 4) meaning-space — a 2-D shadow of d_model dimensions sweet fruit jam strawberry engine gasket berry
  1. The tokenizer hands over id 17 — a bare integer, no meaning attached yet. Input to the embedding stage is the id sequence from the encoder; each id is just an index, and 17 here is a toy value.
  2. The model owns a giant table with one row per word-fragment it knows. Id 17 selects row 17 — that is the entire "lookup". W_E is V × d_model learned floats; row selection is array indexing — no hash, no search, no branch, one strided read.
  3. That row is a list of numbers — the token's coordinates. The numbers were learned from data; nobody wrote them, and nobody can point at one and say what it means. x = W_E[17] ∈ ℝ^d_model (toy d = 4 shown). Dimensions are unlabeled directions the optimizer found useful for next-token prediction — discovered, not designed.
  4. Plotted, the coordinates drop "berry" into a neighbourhood: near sweet, fruit, jam — far from engine and gasket. Meaning became distance, and distance is something the machine can compute with. Any 2-D view is a projection of d_model dimensions, so neighbourhoods are illustrative — but similarity in the full space is exactly what the next level's Q·K dot products measure.
W_E [V × d] id 17 → meaning-space berry engine
“A word is just a row number: look up that row in one giant table of learned numbers, and you get a point in a space where words used alike sit close together.”
// W_E: [V][d_model] learned floats — one contiguous block on disk and in RAM
const float* W_E = weights;
for (int t = 0; t < n_tokens; t++) {
    const float* row = &W_E[(size_t)ids[t] * d_model];   // the entire lookup
    memcpy(&X[(size_t)t * d_model], row, d_model * sizeof(float));
}   // X: positions × d_model — the matrix every later layer transforms
  1. The model's entire word-knowledge at this layer is one flat block of numbers, loaded once. Real loop, toy names — this is the shape production inference code takes. V·d_model floats, row-major, contiguous — mmap-friendly, cache-line-aligned, and streamed through, never searched.
  2. "Looking up a word" is one multiplication and one addition to compute an address — there is no dictionary search anywhere in the hot path. &W_E[id·d_model] is pure pointer arithmetic; the (size_t) cast matters, since id·d_model overflows int at real vocabulary and width scales.
  3. Each token's row is copied into place, and the sentence is now a grid of numbers — the object every deeper level of this page operates on. X ∈ ℝ^{positions×d_model} leaves this stage and keeps that exact shape through every transformer block: attention mixes across rows, the MLP transforms within them.

The dot product — similarity as alignment

Once words are points, one question drives everything downstream: how alike are two of them? The machine's answer is a single number — big when two directions agree, zero when they have nothing in common. Every "which words matter here?" decision at Level 2 is built from exactly this. The dot product is the primitive under attention scores: multiply component-wise, sum. Level 2's Q·Kᵀ is this operation done for every token pair at once.

a · b = Σi aibi
  1. Three toy words as three short coordinate lists. Sweet and tart lean the same way; engine points somewhere else entirely. Three vectors in ℝ³ — real embeddings do the same thing in thousands of dimensions, where "leaning the same way" means correlated components.
  2. Line the two lists up and multiply matching positions: agreement in a position produces a big product, indifference produces zero. Component-wise products: 2·1, 1·2, 0·0 — each term is one dimension's vote on how much the two vectors co-point.
  3. Add the votes: sweet·tart scores 4, sweet·engine scores 0. One number now says how related two words are — computed, not looked up. Nonzero overlap in shared components sums to 4; disjoint support gives exactly 0. Sign matters too: negative components can make dot products negative — actively opposed directions.
  4. That is the whole trick this page descends through: meaning became geometry, and geometry became arithmetic a chip can do billions of times a second. Normalizing by the magnitudes gives cosine similarity: 4/(√5·√5) = 0.8. Level 2 skips the normalize and instead scales by √d_k before softmax — same primitive, different hygiene.

C++ A dot product is the tightest loop in computing: float s = 0; for (int i = 0; i < d; i++) s += a[i] * b[i]; — attention is billions of these, batched into GEMM calls.

One honest caveat before descending: this whole stage is order-blind. "The dog bit the man" and "the man bit the dog" produce the same set of points — so position has to be injected explicitly, which is part of what the next level's machinery handles. Embedding lookup is per-token and attention is permutation-equivariant, so positional information is added to the embeddings or folded into attention itself; several schemes exist, with rotary embeddings widely used in open models — which one a given frontier product uses is unpublished not public

Carry two things down to Level 2: your sentence is now a grid of numbers, and similarity between any two words is one cheap multiplication away. X ∈ ℝ^{positions×d_model} is the residual stream's initial state, and the dot product you just computed by hand is the exact operation inside softmax(QKᵀ/√d_k)V.

LEVEL 2 · 10⁻³ — THE MATRIX public science

The Transformer Block

Every layer asks one question: which earlier words matter for predicting the next one — and by how much? Each block computes softmax(QKᵀ/√d_k)·V, adds it back to the residual stream, then pushes it through a two-layer MLP.

If you have ever written a neural network's forward pass in C++ — allocate the buffers, loop over layers, multiply, add, apply a nonlinearity — nothing on this level is foreign. A transformer block is that same forward pass, industrialised: This level is where the reading actually happens — and it is not magic, it is arithmetic on an industrial scale: bigger matrices, one genuinely new operation, and a strict discipline about how information flows. The new operation is self-attention, and it is the machinery behind every moment a model seems to "remember" what you said.

Attention is how the model reads. When an answer depends on something said three pages earlier, attention is what reaches back and pulls exactly that forward — not by keyword search, but by learned relevance. It is the single idea that made this generation of AI work. Self-attention computes, for each position, a similarity-weighted average over the value vectors of all visible positions — weights recomputed from the data on every forward pass. Content-addressed, not address-addressed: nothing is looked up in a table.

Three roles for every token

Each token's vector is projected — by three learned weight matrices — into three new vectors. Same input, three different lenses:

Q — Query

what this token is looking for

K — Key

what this token advertises to anything looking

V — Value

what this token actually contributes if chosen

C++ A hash map is address-addressed: one key, one bucket, one value. Attention is a content-addressed gather-reduce — score q against every stored k (in practice, GEMM calls), softmax the scores, return the blend Σ wᵢ·vᵢ. That is also the cost story: a map lookup is O(1); attention is O(n) per position, O(n²) per sequence.

The formula

The whole mechanism is one line of math: compare, weigh, blend. Everything else on this level is that line, unpacked. Dot every query against every key, scale by √d_k so the softmax stays in a well-behaved range, normalize each row into weights, and take the weighted sum of the values. One expression — the engine of the whole architecture.

Attention(Q, K, V) = softmax( QK dk ) V

The load-bearing word is softmax. It turns raw scores — any real numbers — into weights that are all positive and sum to exactly 1:

softmax(x)i = exi Σj exj

Softmax, by hand

Numbers are the proof. Here is one attention step small enough to do on paper: one question, three candidates, and watch how the votes get cast and counted. One query against three 2-D keys, no scaling — every arithmetic step shown. This is the worked example to reproduce on a whiteboard from memory.

setup q = [1, 0] · k₁ = [1, 0]   k₂ = [0, 1]   k₃ = [1, 0] · v₁ = [4, 0]   v₂ = [0, 8]   v₃ = [2, 0] scores s₁ = q·k₁ = 1·1 + 0·0 = 1    s₂ = q·k₂ = 1·0 + 0·1 = 0    s₃ = q·k₃ = 1 exponentiate e¹ = 2.718    e⁰ = 1.000    e¹ = 2.718   →  Σ = 6.436 weights 2.718/6.436 = 0.42    1.000/6.436 = 0.16    2.718/6.436 = 0.42   Σ ≈ 1.00 output 0.42·v₁ + 0.16·v₂ + 0.42·v₃ = [0.42·4 + 0.42·2,  0.16·8] = [2.53, 1.24]
  1. First, the question meets each candidate: how aligned are we? Candidates 1 and 3 point the same way as the question; candidate 2 points somewhere else entirely. Raw scores are plain dot products — q·k₁ = 1, q·k₂ = 0, q·k₃ = 1. Identical keys get identical scores; similarity is all that matters, position contributes nothing here.
  2. Every score gets amplified the same way — but the amplifier rewards leaders disproportionately. Exponentiate: e¹ ≈ 2.718, e⁰ = 1. The exponential is why softmax sharpens — equal gaps in score become ratios in weight.
  3. Divide by the total and the scores become vote shares: 42%, 16%, 42%. Note the loser still gets 16% — attention never fully ignores anything it can see. Normalize by Σ = 6.436 → weights [0.42, 0.16, 0.42], summing to 1. The orthogonal key still gets 0.16: softmax never emits an exact zero. That non-zero floor is a mechanical reason irrelevant context still nudges output — the honest argument for keeping prompts clean.
  4. The final answer is a blend of what the candidates carry, in proportion to their votes — mostly candidates 1 and 3, a little of 2. Weighted sum of values: 0.42·[4,0] + 0.16·[0,8] + 0.42·[2,0] = [2.53, 1.24]. That vector is this position's attention output.

Two guards on the scores

Before the votes are counted, two rules apply: keep the scores in a calm range, and never let a word see the future. A model that could peek ahead while learning to predict would be cheating on its own exam. Scale by 1/√d_k — in high dimensions raw dot products grow with √d, and large scores push softmax into near-one-hot saturation where gradients vanish. Then apply the causal mask before the softmax.

That second rule is the causal mask: position n may attend to positions 1…n, never to n+1. Future scores are set to −∞ before the softmax, so e−∞ = 0 and the future gets exactly zero weight — the only exact zeros in the whole mechanism.

The full computation, with real numbers

Now the same story at full width: four words go in as four rows of numbers, and seven moves later they come out understanding each other. Every number on this screen is genuinely computed — nothing is decorative. Toy dimensions — 4 tokens, d_model = 4, single head — but real arithmetic end to end: X → Q,K,V → QKᵀ → ÷√d_k + mask → row softmax → ×V → residual add → MLP. Production models run exactly this with d in the thousands and many heads.

  1. Four words arrive as four rows of numbers — the raw material every layer works on and hands to the next. X ∈ ℝ4×4: one row per token, d_model = 4. This matrix is the residual stream — every sublayer reads it and writes back into it.
  2. Each word is handed three roles: what it seeks, what it advertises, what it carries. The lenses that assign the roles were learned in training, not written by hand. Q = XW_Q, K = XW_K, V = XW_V — three learned projections, three GEMMs into preallocated buffers. The W matrices here are toy but fixed; the products are computed, not invented.
  3. Every word scores every word: how relevant are you to me? Sixteen small comparisons, filled in one by one. S = QKᵀ — one dot product q_i·k_j per pair; as one operation, a single 4×4 GEMM. Aligned directions score high.
  4. The scores are calmed down, and the future is walled off — a word may only look backwards. Divide by √d_k = √4 = 2, then set j > i to −∞. After the softmax those cells will be exactly zero — the mask makes generation causal.
  5. Each row of scores becomes vote shares — positive, summing to exactly 1. The first word, alone at the start, votes 100% for itself. Row-wise softmax: w_ij = es_ij/Σ_j es_ij over the unmasked cells. Row 1 is the degenerate case — one visible token, weight 1.00.
  6. Each word's new meaning is a blend of everything it voted for, in proportion to the votes. This blending IS the model reading. Out = W·V — each output row is a weighted average of the visible V rows. Row 4 blends all four: 0.20·v₁ + 0.28·v₂ + 0.31·v₃ + 0.21·v₄.
  7. The result is added back onto what came in — the original meaning is never thrown away — then a small network refines each word on its own. Stack that block again and again and you have the model. Residual add H = X + Attn(X), normalization, then a two-layer MLP (expand ≈ 4×, nonlinearity, project back), added back again. That whole unit repeats × N layers.

Toy dimensions, real arithmetic: every value above is computed from the matrices shown, rounded to two decimals (weight rows are display-rounded so each sums to exactly 1.00). The architecture is public science; the numbers are a worked example, not any model's actual weights.

The same thing in twelve lines of C

Strip away the scale and the entire mechanism fits on an index card. The magic is not in the code — it is in the learned numbers the code multiplies. One head, one query position, no batching — the shape of every real implementation. Production engines fuse the loops into GEMMs and fused kernels, but compute the same thing.

// one attention head, one query position — real loop, toy dims
void attend(const float* q, const float* K, const float* V,
            float* out, int n, int d) {
  float w[MAX_CTX];                  // scores, then weights
  for (int i = 0; i < n; ++i)        // S = q · K[i]  (one QKᵀ row)
    w[i] = dotf(q, K + i*d, d) / sqrtf((float)d);
  softmax_inplace(w, n);             // eˣⁱ/Σeˣʲ — now sums to 1
  for (int j = 0; j < d; ++j) out[j] = 0.0f;
  for (int i = 0; i < n; ++i)        // out = Σ wᵢ · V[i]
    for (int j = 0; j < d; ++j)
      out[j] += w[i] * V[i*d + j];
}
  1. The whole mechanism, in a dozen lines. The scale of modern AI lives in the sizes of the arrays, not in cleverness of the logic. One head, one query. The weight buffer lives on the stack, sized to max context — no allocation anywhere in the hot path.
  2. Score every visible word against this one. n dot products of length d, scaled by 1/√d — this is one row of QKᵀ. Production code batches all positions into a single GEMM.
  3. Turn the scores into shares of attention that sum to one. In-place softmax: subtract the max, exponentiate, normalize. The max-subtraction changes nothing mathematically — it exists purely so ex cannot overflow a float.
  4. Blend the values by those shares — that blend is the output, this word's new meaning. Accumulate w[i]·V[i][j]: a weighted gather-reduce over the rows of V. dotf and softmax_inplace are the obvious five-line helpers.

C++ Attention at production scale ≈ GEMM calls: three projections, one QKᵀ, one weights-times-V — five big matrix multiplies per head per layer, all against preallocated buffers.

The block around the attention

Attention is half of a layer. Each block wraps two sub-blocks, and the wrapping is not plumbing — it is what makes depth possible. First, every sub-block sits on a residual connection: the output is added to the input, never replacing it, so information can ride an untouched highway from the first layer to the last. Second, each sub-block is paired with layer normalization — one line's worth of idea: rescale each vector to a calm mean and variance so dozens of stacked layers stay numerically sane.

The second sub-block is a small private network that each word passes through alone — no talking between words. Attention moves information between words; this refines what each word now knows. Much of what the model has memorized about the world appears to live here. The feed-forward network is two linear maps with a nonlinearity between, applied per position: expand to ~4×d_model, squash back. Empirically, much of the model's stored factual and procedural knowledge is localized in these weights.

Many heads, then many floors

The attention trick runs many times in parallel, each copy with its own learned lens — one may track grammar, another track who "she" refers to, another track facts. Then the whole two-part block is stacked, floor on floor, and the tower is the model. Multi-head: h independent sets of Q/K/V projections at d_k = d_model/h each, run in parallel, concatenated, projected back to d_model. Then the block stacks: output of layer i is input of layer i+1, shape n×d_model preserved the whole way down.

That parallel trick is multi-head attention; one detail worth saying aloud: attention itself is order-blind — shuffle the tokens and the same weights appear, shuffled. Word order only exists because position was injected into the vectors back on Level 1.

How deep do the towers go? Open models publish their configurations — GPT-2 small, published: 12 layers, d_model = 768, 12 heads. Frontier models of this architecture class are typically dozens of blocks deep with model widths in the thousands architecture class · publicly inferred. The exact layer count, width, and head count of Claude or GPT-class production models not public — treating that boundary precisely is the difference between knowing the field and guessing.

C++ A block ≈ a pure function float[n][d] → float[n][d]; the network is that one function composed N times — you could typedef it.

× N identical blocks x — the residual stream (n×d) norm MULTI-HEAD ATTENTION mixes BETWEEN positions Q K V + norm MLP d → 4d → d + mixes WITHIN a position · stores knowledge norm placement varies by family
x (n×d) Q K V softmax(QKᵀ/√d) weights · V → out
“Vectors come in, every token votes on every other token, the votes reshape the vectors, and a little network cleans them up — stack that thirty-plus times.”

LEVEL 3 · 10⁻² — THE LOOP public science

Generation

The model never writes a sentence. It places one bet, commits, and bets again — every reply you have ever read was built one token at a time, and the past is never redone, only remembered. The forward pass ends in logits over the vocabulary; softmax with temperature turns them into a distribution, one multinomial draw appends one token, and the stack runs again — with K,V cached per layer so each step computes only the new position, never the prefix.

The forward pass ends in a bet sheet

After all the matrix math of Level 2, the model's output is surprisingly plain: a raw score for every token it knows. Every word-piece in the vocabulary gets a number saying "how strongly I'd bet the next token is you." Nothing has been chosen yet — the model hands back the whole bet sheet. The final hidden state of the last position is multiplied by an unembedding matrix WU ∈ ℝd×V, yielding one raw score per vocabulary entry. These are unbounded reals — no probabilities yet, and only the last position's row matters for the next token.

That raw score vector has a name: logits — and everything sampling does downstream is a transformation of this one array.

C++ The logit vector is literally float logits[V] — one flat array, V = vocab size; the model's entire "decision" is an argmax-or-sample over one array of floats.

The bet sheet is long. GPT-2's published vocabulary is 50,257 entries; current open models publish vocabularies around 128,000. Every entry gets scored — every single token. Published tokenizers put V between ~5·10⁴ and ~2·10⁵ (GPT-2: 50,257; Llama 3: ~128k — both published). The unembedding is a [1×d]·[d×V] GEMM per decode step, so vocabulary size is a real serving cost, not a footnote. public science

Same softmax, new knob

The same softmax from Level 2 turns scores into a distribution — the formula doesn't change, the audience does: four attention scores there, the entire vocabulary here. The knob that reshapes it is temperature, and its cold limit has a name too: greedy decoding at T → 0.

pi = exi/T Σj exj/T

Temperature is the model's risk dial. Turn it down and the favorite wins almost every time — crisp, repeatable, a little boring. Turn it up and the long shots get real chances — varied, creative, occasionally weird. Same scores underneath; different appetite. Dividing logits by T before exponentiating scales the gaps between scores: T → 0 sends the max toward probability 1 (greedy in the limit); T > 1 compresses differences toward uniform. Crucially it is monotone — it reshapes the distribution without ever reordering the candidates.

Toy vocabulary, V = 5, at T = 1 — every number computed. (3-decimal rounding; the exact column sums to 1.)
tokenlogit xp = eˣ / 13.345
mat2.07.3890.554
floor1.02.7180.204
roof0.51.6490.124
dog0.21.2210.092
moon−1.00.3680.028
Σ13.3451.000

The API's sampling knobs — temperature, top_p — are published request parameters; the default a consumer chat product runs behind the curtain is not public, and this page won't guess. Saying "that isn't published" out loud is what separates knowing the field from guessing.

Two published cousins, top-p (nucleus) and top-k, trim the tail instead of rescaling it.

They exist because a 100,000-entry bet sheet has a very long tail of nonsense: keep only the most probable tokens whose bets add to, say, 90% (top-p), or keep a fixed top handful (top-k), and roll the dice inside that set. top-p keeps the smallest prefix of the sorted distribution with cumulative mass ≥ p, then renormalizes; top-k truncates to the k largest. Both apply to the post-temperature distribution, before the draw.

Watch one token get born

The whole cycle — predict, draw, append, repeat — is autoregressive generation.

Here is the pipeline on one screen, with real numbers: five candidate words fighting over what follows "The cat sat on the". Toy V = 5, real arithmetic end to end: logits → softmax(T) → CDF → multinomial draw → append. Every number matches the table above.

  1. The scores as they leave the model: five candidates, five raw numbers, one clear favorite — and nothing decided yet. Raw logits x = [2.0, 1.0, 0.5, 0.2, −1.0] over a toy V = 5. Unbounded, unnormalized — argmax would already say "mat", but we don't take argmax.
  2. Exponentiate and share out 100%: the scores become betting odds that add up to exactly one. softmax at T = 1: p = eˣⁱ/Σeˣʲ = [0.554, 0.204, 0.124, 0.092, 0.028], Σp = 1 — the same normalization attention used, now over the vocabulary.
  3. The risk dial, live: cold T = 0.1 crowns the favorite outright; warm T = 1.5 lets the outsiders into the race. Nobody's rank ever changes — only their share. p ∝ e^(x/T): T = 0.1 → [1.000, 0.000, …] (near-greedy); T = 0.7 → [0.691, 0.166, 0.081, 0.053, 0.010]; T = 1.5 → [0.431, 0.222, 0.159, 0.130, 0.058].
  4. One spin of a wheel whose slots match the odds: today r = 0.37 lands on "mat". Tomorrow, same prompt, it might not. Multinomial draw at T = 0.7: uniform r ∈ [0,1) against the CDF [0.691, 0.857, 0.938, 0.990, 1.000]; r = 0.370 < 0.691 → "mat".
  5. The winner is appended to the sentence — permanently. The model never reconsiders a committed token; it only bets on the next one. ctx.push_back(id("mat")). The committed token conditions every subsequent distribution; plain decoding has no lookahead and no backtracking.
  6. And the entire machine runs again from the top. A 500-word answer is this loop five hundred times — streaming isn't a progress bar, it's the loop itself, watched live. Autoregressive step: the new id re-enters the stack; one full forward pass — essentially every weight read once — per emitted token, until EOS or max_tokens.

Temperature lab — same five logits, live

0.1 cold · 2.0 hot

Drag the dial. The favorite never changes — only how much oxygen the alternatives get. That is all temperature is: a confidence dial, not a creativity engine. pi(T) = e^(xi/T) / Σ e^(xj/T), recomputed per input event over the fixed logits [2.0, 1.0, 0.5, 0.2, −1.0]; rank order is invariant for all T > 0.

The loop that writes everything

This loop is also the honest answer to "why did it say something different this time?" One line of it is a weighted dice roll — on purpose. Turn the temperature to zero and the dice go away, along with most of the spark. The multinomial draw is the designed-in nondeterminism of generation (greedy T → 0 removes it at this layer). It is also why fan-out — running the same prompt several times and reconciling — is a rational verification strategy, not superstition.

context t₁ … tₙ FORWARD PASS × N layers — every weight read logits float[V] ÷ T → softmax a distribution over V sample one draw → tₙ₊₁ append tₙ₊₁ — run again …until EOS or max_tokens
context model ×N softmax pick 1 append · repeat
"It bets on one word, appends it, and runs the entire machine again — streaming isn't a progress bar, it's the loop itself, live."
std::vector<int> ctx = tokenize(prompt);
KVCache cache(N_LAYERS, N_HEADS, MAX_CTX, D_HEAD); // preallocated once
prefill(model, cache, ctx);        // one parallel pass over the whole prompt
int tok = ctx.back();
while (tok != EOS && ctx.size() < MAX_CTX) {
  float* logits = decode(model, cache, tok);   // float[V] — appends K,V inside
  for (int i = 0; i < V; ++i) logits[i] /= T;  // temperature
  softmax_inplace(logits, V);                  // now sums to 1.0
  tok = multinomial(logits, V, rng);           // ONE weighted draw
  ctx.push_back(tok);                          // the "auto" in autoregressive
  emit(tok);                                   // the streaming you watch
}
  1. Setup happens once: the prompt becomes ids, and the cache is carved out of memory before the first word — sized for the worst case, so nothing ever has to grow mid-sentence. tokenize → ids; the KV cache is preallocated at [layers][heads][max_ctx][d_head] and appended via a cursor, never realloc'd; prefill computes K,V for every prompt position in one parallel pass.
  2. One full pass of the machine produces the entire bet sheet — a score for every token the model knows. decode() runs all N layers for the single new position, attending against cached K,V, appends this position's K,V, and returns the logit vector — float[V].
  3. Divide by the risk dial, then convert scores into shares of 100% — the same normalizing move the attention layers used. Logit scaling then in-place softmax over V entries: subtract the max for numerical stability, exponentiate, normalize — O(V) per token.
  4. One weighted coin flip picks the winner. This single line is why the same question can get different answers on different days. Multinomial draw: uniform r against the CDF. Generation's designed-in nondeterminism lives on this line; set T → 0 (greedy) and it vanishes.
  5. Append, show the user the word, jump back to the top. A long answer is just this loop refusing to stop. push_back conditions the next iteration; emit streams the token; loop until EOS or the context limit — one full forward pass per emitted token.

Real loop shape, toy dimensions — a production server batches many sequences through this same loop; error handling and stop-sequences omitted.

Never do the same work twice

There is an obvious scandal in that loop: to write token 501, the model conditions on tokens 1 through 500. Does it redo all that work every single time? No — it files the work away, and only ever reads the files. Under the causal mask, position i's key and value depend only on the fixed prefix — once computed they are immutable. So cache them, per layer, per head, per position, and each decode step computes Q, K, V for the new position only.

That filing cabinet is the KV cache.

C++ A preallocated append buffer (high-water mark): two big float tensors indexed [layer][head][position] plus a write cursor — append, never realloc, exactly like any high-water-mark buffer you'd carve out at startup.

cache[layer][head][position] — two preallocated tensors, a write cursor, no realloc layer 1 layer 2 layer N The cat sat on the mat . append K,V for "mat" — nothing left of it is recomputed one more column — attention now reads 7 each filled column = that token's K and V, in every layer and head memory ∝ tokens × 2 · layers · d_model — grows with every token …and the next token's attention must read all of it, every step, per concurrent conversation
  1. Reading your prompt: the model files two small records — a key and a value — for every word, in every layer, all in one parallel sweep. Prefill: one batched pass computes K,V for all 5 prompt positions across every layer and head — columns 1–5 land in cache[layer][head][pos] at once.
  2. Writing "mat": only the new word gets filed. Everything already in the cabinet is read, never redone. Decode: compute Q, K, V for position 6 only; append K₆,V₆; attention dots Q₆ against cached K₁…₆. Zero prefix recomputation — the causal mask made past K,V immutable.
  3. Each further word adds exactly one more file — and each new word must read every file before it. The cabinet, and the reading, both grow with the chat. One column per emitted token; step n's attention reads n cached entries — O(n) memory traffic per token, O(n²) summed over a long reply.
  4. The bill: the cabinet lives in the same scarce, ultra-fast memory as the model itself — one cabinet per open conversation. That rent is the real cost of a long chat. Cache bytes = tokens × 2 · n_layers · d_model · bytes, resident in HBM alongside the weights, per concurrent sequence — the mechanical link from context length to memory, latency, and price.
bytes/token = 2K,V × nlayers × dmodel × bytes/value
GPT-2 small: 2 × 12 × 768 × 2 B = 36,864 B ≈ 36 KB per token
1,000-token chat 37 MB — per concurrent conversation

GPT-2 small's shape is published (Radford et al., 2019): 12 layers, d_model = 768. fp16 (2 bytes/value) is an assumption made for the arithmetic. public science

Frontier-class models are far wider and deeper than GPT-2 small; the same arithmetic at class-typical dimensions lands in gigabytes of cache for one long conversation architecture class · publicly inferred — this page won't attach a number to any specific product. Published techniques like grouped-query attention (Ainslie et al., 2023) exist precisely to shrink this cache — evidence of how binding the constraint is. public science

positions → layers ↓ newest — only column computed this step K,V stored per (layer · head · position) 1,000 tokens ≈ 37 MB (GPT-2-small shape, fp16 — published) context length → cache bytes linear in tokens — and one of these lines per concurrent conversation
tokens → K,V × layers +1 per token chat length memory
"Every word files its two vectors in fast memory once per layer; new words only read the files — and that growing cabinet is why long chats slow down and cost more."

So a long chat gets slower and pricier as it grows for two plain reasons: every new word must consult the entire filing cabinet, and the cabinet occupies the same premium memory the model itself lives in — one cabinet per open conversation. Per-token attention reads the full cached K,V — O(n) memory traffic per step, growing linearly — and cache residency is per-sequence, in the same HBM as the weights. Context length therefore sets latency, the concurrency ceiling, and the price, mechanically.

LEVEL 4 · 10⁻⁹ — THE IRON public science

Silicon and Watts

The chips that run AI are mostly waiting. The math is nearly free — the bill is moving the model's memory, for every single word it writes. Almost everything about AI speed and cost follows from that one fact. Batch-1 decode delivers ~1 FLOP per byte streamed, on hardware balanced near ~300 — inference is memory-bandwidth-bound. Serving economics reduce to one ratio: arithmetic per byte moved, and every optimization below attacks it.

Two kinds of processor

A CPU is a few brilliant workers with a huge planning department: most of its silicon is spent deciding what to do next — predicting, reordering, caching. A GPU inverts that: thousands of simple workers, almost no planning, nearly all the silicon spent actually multiplying. A transformer is matrix multiplication all the way down, so the GPU's trade is exactly the right one. A CPU spends its transistor budget on latency-hiding for ONE instruction stream — branch prediction, out-of-order windows, deep caches. A GPU spends it on throughput: wide SIMD lanes executing in lockstep, latency hidden by oversubscription (swap in another warp while one waits on memory). Dense matmul has no branches and total data parallelism — the ideal tenant.

CPU — A FEW CLEVER CORES core core branch prediction · reorder buffer · L1/L2/L3 cache most silicon spent DECIDING what to do next GPU — THOUSANDS OF SIMPLE LANES ← one warp, lockstep tiny scheduler — swap warps to hide memory waits most silicon spent MULTIPLYING

C++ A GPU is your SIMD intuition made physical: the inner loop you would vectorize with AVX becomes thousands of hardware lanes running the same instruction on different data — warp after warp, no branches, pure throughput.

The bottleneck is the pipe, not the pump

Here is the single most useful hardware fact in AI, and it surprises almost everyone: to write ONE word, the chip must read essentially the entire model out of memory. Not the relevant part — all of it, every word. So the speed limit is not how fast the chip can think; it is how fast memory can pour. Generating one token at batch 1 touches every weight once: each parameter is loaded from HBM, used in one multiply-add, and discarded. That is an arithmetic intensity of ~1 FLOP/byte on machines built to sustain hundreds — the textbook memory-bound corner of the roofline model.

THE MEMORY WALL — WHY THE MATH UNITS WAIT HBM — stacked DRAM weights resident: ≈141 GB (Llama-3.1-70B, published: 70.6B params × 2 B fp16) 3,350 GB/s (H100 SXM, published) per token: essentially ALL of it, once tensor cores — ~990 TFLOP/s available ≈ 0.3% busy at batch 1 — the rest wait decode, batch 1 (~1 FLOP/B) prefill / big batch arithmetic intensity → (balance ≈ 295 FLOP/B at the corner) FLOP/s

The roofline, as arithmetic: on the slanted part of the roof you are paying for bytes, not math. Decode lives at the far left of the slant.

WEIGHTS 141 GB 3.35 TB/s per token: ALL of it MATH (mostly idle) ← we are here
“All the math on the right is basically free — the whole game is pumping the entire hundred-and-forty-gigabyte model through this pipe for every single token, so the pipe, not the math, sets the speed limit.”
  1. The model's knowledge is a warehouse of numbers — about 141 gigabytes for a 70-billion-parameter open model — parked in high-speed memory soldered right next to the chip. Weights sit resident in HBM. Llama-3.1-70B, published: 70.6B params × 2 bytes (fp16) ≈ 141 GB, sharded across the serving devices.
  2. To produce ONE word, the chip reads essentially the whole warehouse. Not the relevant shelf — the entire warehouse, every single word it writes. Batch-1 decode touches every weight once per token: ~141 GB streamed from HBM per forward pass; each fp16 value does one multiply-add and is gone.
  3. So the speed limit is plain division: how fast memory pours, divided by how much must pour per word. No cleverness on the chip beats that number. Ceiling = bandwidth ÷ bytes/token = 3,350 GB/s ÷ 141 GB ≈ 24 tokens/s per sequence (H100 SXM published bandwidth; KV-cache reads are extra, so reality is lower). That is per H100-worth of bandwidth — 141 GB exceeds one card's 80 GB of HBM, so the weights shard across k GPUs, which scales aggregate bandwidth and ceiling together: read ~24 tok/s as the per-GPU-equivalent ceiling.
  4. Meanwhile the actual math engine sits better than 99% idle — a firehose factory being fed through a drinking straw. Machine balance ≈ 990 TFLOP/s ÷ 3.35 TB/s ≈ 295 FLOP/byte. Decode delivers ~1 FLOP/byte → roughly 0.3% of peak math is used.
  5. The fix: serve many people from one pour. Read the warehouse once, answer eight users — each answer costs nearly eight times less. That single trick is the economics of every AI provider. Batch B sequences: weights stream once per pass, B tokens emitted → intensity ≈ B FLOP/byte; throughput scales ~linearly until you go compute-bound or run out of HBM for KV caches.
tokens/s bandwidthbytes / token = 3,350 GB/s141 GB 23.8 tokens/s
balance = 990 TFLOP/s3.35 TB/s 295 FLOP/byte;  decode supplies ≈ 1

Numbers used above are published: NVIDIA H100 SXM datasheet (3.35 TB/s HBM3, ~989 TFLOP/s dense BF16, 700 W TDP) and Meta's Llama-3.1-70B weight release (70.6B parameters). Ceilings on this level are quoted per H100-worth of bandwidth — a 141 GB model does not fit one 80 GB card, and sharding across k GPUs scales bandwidth and ceiling by k. The reasoning is general to any autoregressive transformer. public science

The same fact, in ten lines of C

/* one layer's decode-time matvec: y = W·x  (real loop, toy dims)   */
/* W: 8192 × 8192 fp16 ≈ 134 MB — one of dozens streamed per token  */
for (int i = 0; i < d_out; ++i) {
  float acc = 0.0f;
  const _Float16* row = W + (size_t)i * d_in; /* 2 B/weight, read once */
  for (int j = 0; j < d_in; ++j)
    acc += (float)row[j] * x[j];            /* 2 FLOPs per 2-byte load */
  y[i] = acc;
}
/* 2 FLOPs ÷ 2 bytes = 1 FLOP per byte. The machine wants ~295.     */
  1. This is the whole inner life of one layer: a grid of stored numbers times a list of incoming numbers. Everything the model knows is in the grid. One layer's y = W·x at decode time; W is 8192×8192 fp16 ≈ 134 MB, and a forward pass streams dozens of such matrices.
  2. Each stored number is fetched from memory, used once, and thrown away. The fetch is the expensive part — not the arithmetic. row = W + i·d_in: a 16 KB streaming read per row from HBM with zero reuse at batch 1 — the cache hierarchy can do nothing for you.
  3. The math itself is two tiny operations per number. The chip could do hundreds of times more math than this for every byte it reads. One fused multiply-add = 2 FLOPs per 2-byte load → arithmetic intensity of 1 FLOP/byte against a machine balance near 295.
  4. That ratio — math done per byte moved — is the one number that explains AI serving economics end to end. Raising FLOP/byte is the entire game: batching multiplies reuse of each loaded weight; quantization shrinks the bytes. Both attack the same ratio.

C++ Batching ≈ amortizing one weight-load across many requests — the same reason you restructure AoS to SoA: touch memory once, use it many times.

Shrinking the bytes: quantization

If the pipe is the limit, make the water denser. Store each number in half the space and the same pipe delivers words twice as fast — and the answers barely change. Squeeze too far, though, and the model's numbers get visibly wrong. Compression is a dial, not a free lunch. Quantization stores each weight as a small integer q with a shared scale s, reconstructing w ≈ s·q at compute time. Halving the bits halves the bytes streamed per token — which, in a bandwidth-bound regime, roughly doubles the throughput ceiling.

ONE WEIGHT, THREE SIZES — w = 0.7134 fp16 · 16 bits 0 01110 0110110101 stored: 0.71338 error: 0.00002 ≈141 GB · ceiling ≈24 tok/s int8 · 8 bits 00101101 scale s = 0.01575 q = 45 → 0.70866 error: 0.0047 ≈71 GB · ceiling ≈47 tok/s int4 · 4 bits 0010 scale s = 0.2857 q = 2 → 0.57143 error: 0.142 — visible damage ≈35 GB · ceiling ≈95 tok/s the fix: one ruler per small group group of 32 weights own scale s₁ next 32 weights own scale s₂ smaller range per group → smaller error, at ~half a bit of overhead per weight
  1. Full precision: every number stored generously. Accurate — but the warehouse is 141 gigabytes, and the pipe pays for every byte. fp16: 1 sign + 5 exponent + 10 mantissa bits; 0.7134 stores as 0.71338. 70.6B params ≈ 141 GB → ceiling ≈ 24 tok/s on the worked example.
  2. Squeeze each number into half the space and the same pipe delivers words twice as fast — and this number barely moved. int8: q = round(w/s) with s = max|w|/127 = 0.01575 here → q = 45, reconstructed 0.70866, error 0.005. ≈71 GB → ceiling ≈ 47 tok/s.
  3. Squeeze to a quarter and speed doubles again — but now the stored number is visibly wrong. This is the precision-versus-memory dial at its limit. Naive per-tensor int4: 15 usable levels, s = 0.2857 → q = 2, reconstructed 0.57143 — error 0.142 on a 0.71 weight, ~20% relative. ≈35 GB → ceiling ≈ 95 tok/s.
  4. Real systems keep most of the speed and avoid most of the damage by giving each small group of numbers its own ruler instead of one ruler for millions. Production int4 schemes use group-wise scales (one fp16 scale per ~32–128 weights), shrinking each group's range and its rounding error. Accuracy is then verified empirically per model — not assumed.

C++ int8 quantization is fixed-point DSP: store an int8_t q plus one float scale per block, reconstruct w ≈ s·q on the fly — precision traded for bytes, exactly like audio samples.

The triangle you will be asked about

Every serving decision is a three-way pull between how fast one user sees an answer, how many answers per second the fleet produces, and what each answer costs. You cannot win all three; batch size is the dial that slides you around the triangle. Latency, throughput, cost per token. Growing the batch raises intensity (throughput up, cost down) but adds queueing delay and, once compute-bound, longer passes — latency up. Chat products buy latency; batch APIs sell it back at a discount. Same iron, different corner.

LATENCY (time to first word) THROUGHPUT COST / TOKEN chat lives here — pay for snappiness overnight batch jobs live here batch size grows → one machine, one dial — the operating point is a business decision, not a hardware one
LATENCY THROUGHPUT COST/TOK batch ↑
“Latency, throughput, cost per token — one triangle; batch size slides you along the edges, and every serving decision is choosing which corner to give up.”

Watts, honestly

One AI chip draws about 700 watts — roughly half of what an average U.S. home draws around the clock. Stack chips into servers, servers into racks, racks into halls, and the electric bill becomes the second law of AI economics, right after memory bandwidth. H100 SXM TDP: 700 W (published). A DGX H100 node — 8 GPUs plus CPUs, NVLink, fans — peaks near 10.2 kW (published). Above that level the public record thins: rack densities and hall capacities below are class-typical figures, not any provider's spec sheet.

PIECEWISE TO SCALE — EACH ROW IS HONEST WITHIN ITSELF NODE — 8-GPU server ≈ 10.2 kW published (DGX H100) 8 × 700 W GPUs = 5.6 kW CPUs · NVLink · fans · PSU loss RACK — ≈ 40 kW class-typical, not a spec one node a few more nodes + networking HALL — tens of MW (30 MW illustrative) class-typical, not a spec ← your whole rack is this sliver (40 kW of 30,000 kW) A linear all-in-one chart would make the chip sub-pixel — that disproportion IS the point.
public science architecture class · publicly inferred

And here the honest map runs out: how many chips any given AI provider runs, where, and at what cost is simply not published. Anyone who quotes you those numbers as fact is guessing. Frontier weights exceed one accelerator's HBM, so models are sharded — tensor parallelism within layers, pipeline parallelism across them — making interconnect part of the performance envelope. That much is class-standard. Fleet sizes, chip mixes per request, and unit economics of specific providers are unpublished.

Anthropic has publicly stated it uses a mix of AWS Trainium, Google TPUs, and NVIDIA GPUs public science — but which hardware served any particular request, or in what proportion, is unknowable from outside not public.

C++ Sharding a matmul across chips is your threaded blocked-GEMM with the sync points made of network: partial results reduced across devices inside every forward pass.

This is the bottom of the shaft: sand, electricity, and one stubborn ratio of math to memory. Everything below your chat box is now accounted for. The climb back up starts with a question — what can a machine that predicts tokens actually DO? Bottom of the descent: every layer above the iron — sampling, attention, tokens — is software riding on FLOP/byte. Next level up, the output loop stops being text and starts being actions: the agent loop.

LEVEL 5 · 10¹ — THE AGENT public science

The Agent Loop

Up to here, the model only talked. An agent is that same model given hands — an intern with a phone: it can call for anything, but every single call goes through your switchboard. A while-loop around a stateless API: the model emits a structured tool call, the harness validates and executes it, the result is appended to context, and generation resumes — until the model stops asking.

An agent is a model wrapped in a loop by a harness — plus three more ingredients: tools it can request, accumulating context as memory, and a stopping condition.

Remove any one ingredient and the whole thing collapses back into something less. No tools — it's just chat. No memory — it re-decides from scratch every step, with no sense of progress. No stopping condition — it either runs forever or quits at random. The intern needs a phone, a notepad, and a quitting time. Degenerate cases: tools = ∅ → a chat model; memory dropped → a stateless policy re-deciding per step; no stop condition → unbounded iteration or arbitrary halting. The loop body is two calls: the model proposes an action from state; the harness executes it and folds the result back into state.

CONTEXT — WORKING MEMORY system prompt + history + every tool result so far MODEL reads everything, decides the next step TOOL CALL data: { name, input } HARNESS validates · permissions · executes for real RESULT stdout, API reply, file contents — the truth STOP? done / step cap / budget / human FINAL ANSWER emits yes no — result becomes context; loop
MODEL TOOL CALL { name, input } RUN only box that touches the world RESULT done → answer repeat until it stops asking
“The model proposes and my code disposes — it fills out a request, the harness is the only thing that ever executes, and the real result loops back in until the model stops asking.”

The stopping condition deserves more respect than it gets. The loop needs a reason to end: the model saying it's done, a cap on steps, a budget, or a human hand on the switch. “Just let it run until it's finished” is how you get a runaway intern — burning budget in a silent loop, taking twenty actions nobody asked for. In practice the stop check is a disjunction: the model returns no tool call (self-signaled completion) OR iteration cap OR token/cost budget exhausted OR explicit human interrupt. Production harnesses enforce all four; relying on self-signaled completion alone is the classic runaway failure.

C++ The agent loop is a while loop around an RPC: while (!stop(state)) { action = model(state); state += harness.execute(action); } — memory is just the state object growing each iteration, and the stop check is the sentinel that keeps it from becoming an infinite loop.

Tool calling — the request-form mechanism

Tool calling (also called function calling) is the single mechanism that turns a chat model into something that does things. Each tool is declared to the model as a name, a description of when to use it, and a JSON Schema for its input.

The critical fact: the model never runs anything. It emits a request to act, shaped like a function call — and something else, code you wrote, decides whether and how to actually run it. That pause between wanting and doing is the entire safety story: at that boundary you can validate, sandbox, log, or demand a human's approval. The model emits a tool_use block mid-generation — tokens like any other tokens. The harness parses it, validates the arguments against the schema with exactly the discipline you'd apply to any untrusted RPC caller, executes the real action, and appends a tool_result message. Everything downstream of the model is ordinary engineering: input validation, sandboxing, logging, approval gates.

// REQUEST → the model. Tools ride along as SCHEMAS — nothing is installed.
"tools": [{ "name": "run_shell",
  "description": "Run a shell command; returns stdout, stderr, exit code.",
  "input_schema": { "type": "object", "properties": { "cmd": { "type": "string" } } } }],
"messages": [{ "role": "user", "content": "Is the latest deploy green?" }]
// RESPONSE ← the model. Not an action — a structured REQUEST for one.
{ "type": "tool_use", "id": "toolu_01", "name": "run_shell",
  "input": { "cmd": "gh run list --branch main --limit 1" } }
// HARNESS: validate the input against the schema, run the real command,
// append the REAL result to the conversation — as data:
{ "role": "user", "content": [{ "type": "tool_result", "tool_use_id": "toolu_01",
    "content": "completed  success  main  ci.yml  3m ago" }] }
// NEXT TURN: the model reads the result as ordinary context and answers —
// or emits another tool_use. That repeat IS the agent loop.
{ "role": "assistant", "content": "Green — the last run on main succeeded 3 minutes ago." }
  1. You hand the model a menu, not the keys. Each tool is a card: a name, when to use it, and what the request form looks like. The model has read the menu — it has never touched the kitchen. Tool definitions ride in with every request: name, a prescriptive description (when to call, not just what it does), and a JSON Schema for the input. The model's entire knowledge of a tool is this text — no linking, no installation, no runtime binding.
  2. The model doesn't act — it fills out a request form. That gap between wanting and doing is the whole safety model, and it's why an agent can be trusted with a phone but not with the keys. Mid-generation the model emits a tool_use block — { name, input } conforming to the schema. It is emitted as tokens, exactly like prose; the model has no execution path of its own.
  3. Your switchboard answers. It checks the request, decides whether to allow it, does the real work, and files the actual outcome back into the conversation — the truth, not the model's guess about the truth. The harness validates against the schema, dispatches handlers[name](input), and appends a tool_result keyed by tool_use_id. The result enters context as data the model will condition on — never as instructions.
  4. The model reads what actually happened and either answers or asks for the next thing. Repeat until it stops asking — that, in full, is an agent. The next forward pass conditions on the result as ordinary tokens. Termination: the model returns no tool_use — backstopped by the harness's step cap, budget, and human interrupt.

Real Anthropic Messages-API shapes, abbreviated and annotated — the field names and block types are the published, public API surface. public science

C++ A tool call is a marshalled RPC: the model serializes a struct, the harness deserializes and dispatches through a vtable-style lookup — handlers[name](input) — and the JSON Schema is the interface contract, doing the same job a .proto file does.

The one security rule: whatever comes back through a tool is mail, not orders. The intern reads the mail; the mail does not get to command the intern. A web page, an email, a file — none of it gets to say “now transfer the money” and be obeyed. Tool results are DATA, not instructions. Role separation is a trained convention, not a hard wall — the wire is one token stream — so instruction-shaped text inside fetched content (prompt injection) must never be obeyed or allowed to authorize new permissions. The harness treats every tool result as untrusted input, structurally.

MCP — one port for every tool public science

The Model Context Protocol (MCP) exists to kill an integration tax.

MCP is USB for tools. Before USB, every device needed its own port and its own cable; after, one connector fits any machine. MCP does that for AI: any tool source can plug into any AI app, because both sides agreed on the plug — build the integration once, and everyone can use it. An open protocol — RPC-style JSON messages over two transports: stdio for a locally spawned child process, streamable HTTP for remote servers with their own auth — with standardized capability discovery: a client connects, asks “what do you offer?”, and receives typed lists of tools, resources, and prompts. The host runs one dedicated client per server: a stateful 1:1 session, never shared, never fanned out.

N × M N + M  ·  6 × 9 = 54 6 + 9 = 15
THE INTEGRATION PROBLEM App: Claude Code App: Claude Desktop App: your product Tool: GitHub Tool: filesystem Tool: Slack Tool: database 3 × 4 = 12 bespoke wires — each with its own auth, schema, quirks M C P — one protocol 3 clients + 4 servers = 7 — at 6 apps and 9 tools: 15, not 54 one client per server · 1:1 tools · resources · prompts stdio (local child process) streamable HTTP (remote)
  1. Before: every app that wants every tool writes its own custom wiring. Three apps and four tools is already twelve separate integrations to build, secure, and maintain — and at six apps and nine tools it's fifty-four. Point-to-point integration: N clients × M tool providers = N·M bespoke adapters, each with its own auth handling, schema conventions, and failure modes. The cost grows with the product, not the sum.
  2. After: everyone agrees to speak one language through one port. Each app learns the protocol once; each tool ships one server once. The wiring collapses from a web to a bus — seven connections instead of twelve, fifteen instead of fifty-four. One open protocol: each app implements one MCP client, each tool provider ships one MCP server — N + M implementations total. Any compliant client can then use any compliant server, the way any browser speaks to any web server.
  3. What flows through the port — three things, each owned by a different decision-maker: actions the model chooses to request, reference material your app attaches, and shortcuts the user explicitly picks. A server advertises three primitives via the discovery handshake: tools (model-invoked, may have side effects), resources (host-attached, read-only, URI-addressed), and prompts (user-selected templates). Cardinality is strict — one dedicated, stateful client per server, so each session's capability set and state machine stays independently reasoned about.
  4. And the plug works two ways: a tool can live on your own machine as a small local program, or across the network as a shared service with its own login — same protocol either way. Two transports, one message shape: stdio — the host spawns the server as a child process, messages over stdin/stdout, no network or auth handshake — versus streamable HTTP for remote, shared, or independently authenticated servers (OAuth, API keys).

C++ An MCP server is a plugin that exports a typed interface table the host queries at load time — dlopen plus a registry of function descriptors — capability discovery at run time instead of hardcoded linking at build time.

Working memory vs. writing things down

An agent's working memory is the conversation itself — sharp, complete, and temporary. Close the session and the agent wakes up tomorrow with no idea what it did today. So good agents do exactly what good engineers do: they write things down. The context window is finite, re-sent whole on every call, and volatile across sessions. Durable memory is artifacts on disk the agent deliberately writes — via the same tool-call mechanism as everything else — and re-reads at boot. When context nears its ceiling, compaction summarizes old turns to their essentials — exact wording traded for a bounded footprint.

This is not theory — my own fleet runs on it. Two Claude sessions share one repository and never speak directly: one designs, one implements. They pass the baton through a file called HANDOFF.md, keep distilled lessons in a MEMORY.md that outlives every session, and settle any disagreement by checking the git history — because a note can go stale, but the commit log can't. Real coordination pattern from my own multi-agent setup: shared, versioned artifacts instead of a live channel. HANDOFF.md is a baton with a one-writer-at-a-time rule; MEMORY.md persists doctrine across context resets; and on every session resume the agent reconciles against git log as ground truth, because either side's last written state may be stale.

WORKING MEMORY (volatile) SYSTEM TOOLS HISTORY + tool results grows every turn HEADROOM one finite budget · re-sent every call · wiped when the session ends DURABLE MEMORY (files) HANDOFF.md the baton between sessions MEMORY.md distilled lessons, survives resets git log ground truth when notes go stale write it down — itself a tool call read back at boot
CONTEXT RAM — wiped FILES disk — durable write it down read at boot
“Context is the agent's RAM — fast, finite, and wiped between sessions — so anything worth remembering tomorrow gets written to a file today.”

C++ The context window ≈ a fixed-size arena allocator torn down at process exit; anything that must survive gets fwrite'd to disk — an agent's files are its serialization format.

One intern with a phone is useful. The next level down the return climb is a staffed office: many agents, divided work, and someone whose whole job is checking the work — because the checking, it turns out, is the hard part. Next: orchestration — planner/worker/verifier topologies, isolated contexts per worker, and reliability bought with independent verification, trading time, memory, and compute against each other.

LEVEL 6 · 10² — THE FLEET public science

Orchestration

One mind checks its own work with the same blind spots that made the mistake. A fleet of minds — kept apart, then forced to argue — is how you buy certainty you can ship. Fan out N isolated contexts with different prompts, join them at a barrier, push every candidate through a fresh-context refuter, and let a deterministic script — never a model — own the merge and the write.

Level 3 showed that a model's output is a draw from a probability distribution — which means a fluent, confident, wrong answer is not a malfunction; it is the expected failure mode. You do not fix that with a better prompt. You fix it with architecture: more independent looks, and an adversary whose only job is to break the answer before you see it. Sampling means errors are stochastic. Stochastic errors across separately-seeded, separately-prompted contexts are (partially) uncorrelated — so fan-out buys coverage a single reroll cannot, and a refuter in a fresh context does not inherit the priors that produced the error.

A subagent is not a thread and not a function call. It is a separate conversation: its own system prompt, its own fresh context, its own loop. It cannot see its siblings, and the parent sees only the final structured text it returns. That informational isolation is not a limitation — it is the entire mechanism. It is what makes a second opinion a second opinion.

C++ Fan-out and join ≈ std::async futures: launch N workers, .get() every future before the reduce — Promise.all is the same join with different spelling.

The arithmetic of independent looks

If one reviewer catches a given bug six times out of ten, three reviewers working separately catch it nearly nineteen times out of twenty. The gain does not come from anyone being smarter — it comes from their misses not lining up. Model each finder as an independent Bernoulli trial with hit probability p. The only way the bug survives is if every finder misses:

P(caught) = 1 (1 p)n ;p = 0.6, n = 3 1 0.4³ = 1 0.064 = 0.936

public science Basic probability of independent trials — and the honesty clause: the independence assumption is the weak joint. Agents sharing one base model share failure tendencies, so their errors correlate; different prompts and different lanes reduce the correlation, they do not erase it. That gap is exactly why the fleet does not vote — it verifies. Voting averages correlated guesses; adversarial verification demands each claim survive an attack from a context that never saw the reasoning behind it.

The shape of the fleet: planner, workers, verifier

The manager of this fleet is not an AI. It is a short, boring, deterministic program: it hands out the jobs, waits for everyone, sends the results to a professional skeptic, and files what survives. Judgment lives in the workers; control lives in code you can read. The orchestrator is plain script: real loops, real conditionals, no model in the control path. Each agent() call is a concurrent request into an isolated context; returns are validated against a JSON Schema at the tool layer, so a non-conforming object is rejected and retried instead of parsed by hope.

PLAN WORK VERIFY MERGE ORCHESTRATOR deterministic script · no model in the control path FINDER 1 own context · own tool loop prompt: lane A FINDER 2 cannot see its siblings prompt: lane B FINDER 3 different prompt → different search region prompt: lane C BARRIER — the script blocks until every lane has returned ADVERSARIAL VERIFIER fresh context · never saw the finders’ reasoning instruction: REFUTE, not review CONFIRMED FINDINGS → FINDINGS.md schema-validated returns · one writer: the script
script (no AI) F1 F2 F3 barrier REFUTER fresh ctx confirmed only
“One plain script fans the job out to isolated workers, a barrier joins them, and a fresh-context skeptic kills every finding it can — only the survivors reach a human.”

Only confirmed findings survive

Self-review is weak for a structural reason, not a moral one: the same context that produced the error is still sitting in front of the model when it checks itself, quietly arguing for the error. The fix is a reviewer who never saw the reasoning — and who is told to attack, not to approve. In self-review, attention still weights the tokens of the flawed reasoning; the model’s own prior output conditions its next output. A refuter in a fresh context inherits none of those priors, and the imperative “refute” shifts the likely continuations from agreement toward attack. Findings that cannot survive refutation die before a human reads them.

FINDER A prompt: auth paths fresh context FINDER B prompt: input handling fresh context FINDER C prompt: state & sessions fresh context #1 · auth.js:41 #2 · auth.js:112 #3 · parse.js:9 #4 · parse.js:77 #5 · form.js:23 #6 · store.js:130 #7 · store.js:64 7 candidates — every one cites file:line BARRIER — all lanes joined, flat list assembled ADVERSARIAL VERIFIER fresh context, per finding instruction: refute it FINDINGS.md 3 confirmed shipped 4 killed before a human read them
  1. Three finders take the same codebase from three angles. They work at the same time, in separate rooms, and cannot copy each other’s answers. Fan-out: three isolated contexts, three different prompts — different prompts steer sampling into different regions of the search space, which is what decorrelates the misses.
  2. Every claim comes back with its receipt: the exact file and line. A finding without a receipt is not allowed to exist. Returns are schema-validated objects — file, line, claim — rejected and retried at the tool layer if malformed. Citations make each claim checkable outside the model.
  3. Nothing moves until every lane reports. A verdict issued before all the evidence is in is just a guess with a timestamp. The barrier: the script joins all lanes, flattens to one candidate list, dedupes. Downstream stages see a complete set or nothing.
  4. Now the skeptic goes to work — one fresh look per finding, with one instruction: prove it wrong. Four of seven don’t survive. Those four were fluent, confident, and false — and no one had to read them. One refuter call per finding, each in a fresh context that never saw the finder’s reasoning. It re-derives the claim from the cited file:line; non-reproducible findings get verdict REFUTED and are dropped.
  5. Only confirmed findings reach the report — and exactly one hand holds the pen that writes it. The deterministic script filters on the verdict and performs the single write. Model output never touches shared state directly — the one-writer rule, enforced by construction.
Toy counts for legibility. The same pattern at production scale, from my own fleet’s logs: 18 research lanes → 167 findings, every one URL-verified before it entered the tracker; the adversarial pass pushed three corrections back into the source of truth — including one claim about my own résumé that a refuter disproved by grepping the actual code.

The whole pattern in thirteen lines

const lanes = ['auth', 'payments', 'sessions'];

const findings = (await Promise.all(       // FAN-OUT: N isolated contexts
  lanes.map(l => agent(finderPrompt(l), findingSchema))
)).flat();                                 // BARRIER: all lanes or nothing

const verdicts = await Promise.all(findings.map(f =>
  agent(refutePrompt(f), verdictSchema)    // fresh context, told to REFUTE
));

const confirmed = findings.filter((f, i) => verdicts[i].confirmed);

write('FINDINGS.md', render(confirmed)); // ONE WRITER: the script
  1. The job list is plain data written by a plain program. No AI decides who does what — that part is boring on purpose. Control flow is deterministic script; the model is a callee. The lane list partitions the search space so coverage is by design, not luck.
  2. Everyone works at once in separate rooms, and nothing moves until every room reports back in a fixed, machine-checkable format. Promise.all is both the fan-out and the barrier. Each agent() spins up an isolated context; its return must validate against findingSchema or it is rejected and retried at the tool layer.
  3. Then every claim faces the skeptic — a reviewer who never saw the work, hired only to break it. One fresh context per finding. The refute instruction matters: sampling continues from the prompt, so “refute this” makes attack the likely continuation where “review this” invites agreement.
  4. Only what survives gets written down — by the program, not by any of the minds. One pen, one page, no crossed-out chaos. The filter and the write are deterministic. Model text never mutates shared state directly; the script is the single writer of record.
Real shape of my orchestration scripts — deterministic JavaScript around concurrent agent() calls with schema-validated returns; toy lane list, real control flow.

C++ The orchestrator ≈ plain main() calling remote workers over RPC — deterministic control flow with the model as a callee, the way you would never let a heuristic drive your scheduler.

Pipelines, barriers, and the one-writer rule

There are two ways to chain minds. An assembly line, where each station starts the moment a part arrives — fastest when the parts are independent. And a gate, where nobody moves until everyone reports — mandatory when the next decision needs the full picture. Verification is always a gate. A pipeline overlaps stages — stage k+1 consumes lane i’s return as it lands — maximizing throughput on independent items. A barrier synchronizes so the reduce sees the complete set. Use pipelines for per-item transforms; use barriers wherever correctness depends on completeness: dedupe, ranking, verification verdicts.

And shared documents die of too many authors. In my fleet every file has exactly one writer at any moment; everyone else reads. When two roles must share one workspace, they pass a baton — and the project history, not anyone’s memory, is the referee of who holds it. The one-writer rule: parallel lanes get disjoint working directories; the two roles that share one repo are serialized by a baton file, and git log — not the baton’s prose — is ground truth, because prose about repo state drifts and commits do not.

Why a hub with one manager instead of a team that all talk to each other? Because conversations multiply faster than people do. Peer-to-peer coordination scales quadratically; hub-and-spoke scales linearly. That asymmetry is the entire argument for an orchestrator:

channels(n) = n(n 1)2 ;n = 3 3 ;n = 8 28 ;  hub n

C++ The baton ≈ std::unique_ptr ownership — exactly one owner may mutate, a handoff is an explicit std::move, and shared mutation becomes an error you are never allowed to make.

The tradeoff triangle — and when not to orchestrate

Fanning out is not free. Every extra mind costs money, and every extra mind adds coordination. You are always trading between three pressures: the clock, the bill, and the size of the room where the results get combined. Three axes: wall-clock time, total compute (tokens ≈ dollars), and memory — each lane’s context budget plus, critically, the merge payload that must fit the parent’s context. Watch the marker: every fleet design is a point inside this triangle. Worked numbers below use a 200K-token context, a published API shape. public science

  1. One worker, nine jobs, one after another. Cheap to manage — but the clock runs nine times longer, and its memory fills up before the last job is even read. Serial baseline: 9 modules × ~40K tokens ≈ 360K tokens through one 200K context — wall-clock ≈ 9T, and truncation or lossy compaction is guaranteed before module nine. The time and memory vertices both pull hard.
  2. Nine workers at once: the clock collapses to roughly one job’s length — about nine times faster — while the bill rises only about ten percent, because the jobs were nine separate stacks of reading anyway; each worker just re-pays its own briefing. Fan out 9 lanes: wall-clock ≈ T + merge; total tokens ≈ 9 × 45K ≈ 405K vs 360K serial — ≈ 1.1×, because the modules are disjoint and each lane re-pays only its own prompt and overhead. Per-lane context sits at a comfortable 45K/200K. The honest pitch: ~9× faster for ~10% more tokens.
  3. The trap is the reunion: nine full stories cannot fit in one head. So workers hand back index cards, not diaries — and suddenly the whole fleet fits in the room. Merge budget: 9 raw transcripts ≈ 360K > 200K — the parent cannot hold them. 9 schema-bound returns ≈ 2K each = 18K — fits with room to think. This is why structured returns are non-negotiable: the merge payload IS the memory budget.
  4. And when the whole job fits in one head, use one head. Nine people can dig nine holes; nine people cannot dig one hole nine times faster — they just hold more meetings. Task ≈ 30K tokens < one context: orchestration adds N system prompts, merge code, and coordination overhead for zero coverage gain. Don’t. Orchestrate for independent-lane coverage or adversarial verification — never for ceremony.

When not to orchestrate — the checklist I actually apply before spawning anything:

This is not theory — the fleet exists

PRODUCTION PRACTICE — MY FLEET, FROM ITS OWN LOGS

48subagents, 4 orchestrated runs, ~2 days

~5.12Mtokens of subagent work

1,648tool calls

18 → 167research lanes → URL-verified findings

9 / 1packages cleared / blocked loudly, not shipped quietly

3corrections pushed back into the source of truth

The machinery is deliberately mundane: a terminal multiplexer holds seven worker lanes on one socket, each lane addressed by name; briefs are pasted in by the control plane, approvals come from a phone. Two roles that share one codebase pass an explicit baton and never write at the same time. Nothing exotic — which is the point. Reliability lives in the plumbing you can read. The substrate is tmux: one server on a named socket owns every lane; the control plane addresses sessions by name, pastes multi-line briefs via the paste buffer, and polls output with capture-pane. One writer per directory: two lanes sharing a repo are never concurrent; the DESIGN/IMPLEMENT pair serialize through a baton file, reconciled against git log before every pickup.

And the strongest proof of the pattern found its target at the level above the code: an audit lane read my fleet’s own rulebook cold and discovered two rules in live contradiction — one saying “stop after three failures,” another saying “never declare something impossible until other paths are tried.” That contradiction had already caused three logged failures in one night. No working session had ever seen it, because every working session read the rules mid-task, already leaning one way. The fresh, whole-system look saw what no single pass could. The 2026-07 standards audit: a dedicated fresh-context pass over the entire rule set found a live contradiction between the retry-budget rule and the capability-honesty rule — three logged failures traced to it — plus one rule that was cut for fighting behavior without preventing any real failure. Same mechanism as the refuter, applied to the system’s own configuration: independent verification at the level of the rules, not just the outputs.

That is the interview differentiator this level exists to earn: not “I know what orchestration is,” but “I run one — here are its logs, its one-writer rules, and the contradiction its own audit caught.”

LEVEL 7 · 10³ — THE COMPANY

Building It For You

Everything below this line is what I do with everything above it: find the expensive toil, wire the model to your data, and build the checks that make it safe to trust. Levels 0–6 as an engineering menu: one model call → workflow → agent fleet; RAG for grounding; evals, adversarial review, and human gates as the safety architecture — always the smallest shape that works.

The honest capability map

The fastest way to lose money on AI is to ask it to be something it isn't. Everything on this page tells you exactly what it is: a machine that continues text extremely well. Build on what that's genuinely good at, and put hard checks around everything else. The architecture (L2–L3) predicts the failure modes: it optimizes plausible-next-token, not verified-true-statement. So reliability clusters around transformation of supplied context, and falls off wherever ground truth must come from frozen weights instead of what's in the context.

Reliable — build on this

  • Transforming text you hand it: summarize, draft, translate, classify, extract — at any hour, at any volume. Conditioning on supplied context is the native operation — the answer is attention over tokens that are actually present (L2), not a memory lookup.
  • Reading a pile of documents and pulling out what matters — when the pile is in front of it. In-context retrieval and synthesis over the window; pair with RAG (below) when the pile exceeds the context limit.
  • Writing code — when tests sit behind it to catch what's wrong. Code is the best-instrumented output type we have: compilers, type checkers, and test suites are free deterministic verifiers.

Not reliable bare — needs architecture

  • Facts from memory. Its knowledge is frozen at training time, and it states guesses with the same confidence as facts. Hallucination is structural: sampling from a plausibility distribution (L3) has no truth term. Ground with retrieval or tool calls; require citations.
  • Arithmetic and precise lookups at scale — that's a calculator's job, and the fix is giving it a calculator. Digit-level manipulation through a token predictor is the wrong tool; route to tools (L5) — the model orchestrates, the tool computes.
  • Anything that must never be wrong, unsupervised. Those items don't get a smarter model — they get checks that don't guess. The never-wrong set gets deterministic verification and human gates. Model proposes; a checker disposes.

Verification is architecture, not hope

So the honest answer to "can we trust it?" is: you don't trust it — you verify it, the same way you don't trust a bridge, you load-test it. My builds ship with the checking built in: automated tests, an independent reviewer whose job is to prove the work wrong, and a replay that pins the model’s recorded answers in place and confirms everything built around them still produces the same result. Three gates, in order of cost: deterministic tests (exit codes, skipped counts as failed), adversarial review by a fresh context briefed to refute (self-review has self-preferential bias), and a determinism trace — replay the pipeline around the model against its recorded inputs and outputs and compare digests. This is the gate I actually run; here it is as code.

def ship_gate(change):
    r = run_tests(change.worktree)          # exit codes, not vibes
    if r.failed or r.skipped:
        return block("tests", r.log)        # skipped counts as failed
    review = adversarial_review(change)     # fresh context, told to refute
    if review.findings:
        return block("review", review)
    t = replay(change, io=r.recorded_io)    # pinned model I/O → same result?
    if t.digest != r.digest:
        return block("nondeterministic", diff(t, r))
    if change.irreversible:                 # deploy, delete, send, spend
        go = ask_human(change.summary)
        if go != "yes":                     # a hedged go is not a go
            return block("await an unhedged yes")
    return ship(change, evidence=[r, review, t])
  1. First gate: the tests actually run and actually pass. "Mostly passed" and "skipped a few" both count as failed — silence is not a pass. Deterministic exit codes; r.skipped promotes to failure. A gate that can be satisfied silently is not a gate.
  2. Second: a separate reviewer whose only job is to prove the work wrong. The author never grades their own homework. An independent context with an adversarial brief — "refute this" — because self-review is biased toward its own output. Any finding blocks.
  3. Third: run it again — with the model's recorded answers pinned in place — and confirm the rest of the machine produces the same thing. If the deterministic part gives a different answer, you don't have a system yet — you have a demo. Replay the pipeline against the recorded model I/O and compare digests — a determinism trace. Hosted inference is not bit-reproducible (batching and kernel nondeterminism, even at temperature 0), so model outputs are pinned by recording them; fixed seeds pin only local inference. Everything around the model must be exactly reproducible and diffable.
  4. Fourth: anything irreversible waits for a human — and a hedged yes is a no. A human-in-the-loop gate on the irreversible set: deploy, delete, send, spend. Approval parsing is strict by policy — "probably fine" returns block.
  5. Only then does it ship — and the evidence ships with it, so "it works" is a record, not a claim. The gate returns the artifact plus its trace: test log, review findings, replay digest. Auditable afterward, not reconstructed.

Real gate shape, toy API — the structure is the point: every arrow in it is a check the model cannot talk its way past.

Three build shapes — cheapest first, always

Most "AI projects" fail by starting too big. The discipline is a ladder: one model call if that solves it; a scripted workflow if the process needs steps; a self-directing agent only when the task is genuinely open-ended — and each step up has to earn its complexity. Tier ladder: single call → workflow (deterministic code sequences the model calls) → agent (the model picks its next step, L5). Going up a tier is justified against four checks — complexity, value, viability, cost-of-error — and a "no" on any check means stay a tier down.

Shape 1 · Assistant on your data L0L1

A model that answers from your documents — policies, contracts, tickets — and cites the exact source, instead of guessing from memory. RAG: chunk → embed → nearest-neighbour → stuff the context. Freshness lives in the index, not the weights — re-embed the changed document, not the corpus.

Shape 2 · Workflow automation L0L3

Your existing process, with the model doing the reading and drafting steps while your rules keep control of the order and the outcomes. A pipeline where deterministic code owns sequencing — classify, extract, draft — with schema validation between model steps. Not an agent: the model never chooses what happens next.

Shape 3 · Agent fleet L5L6

For genuinely open-ended work: the system plans its own next step — inside hard limits, with an independent checker watching every result. Model-directed loops with tools, budget and iteration caps as stopping conditions, and a verifier agent per Level 6 — the orchestration discipline I already run daily in my own shop.

C++ An agent loop ≈ a while loop around an RPC — the model call is the function; tools are the syscalls it is allowed to make.

Shape 1, opened up: RAG in five steps

The model's knowledge is frozen the day training ends, and your business changes daily. Retrieval fixes that without retraining anything: find the few passages that matter, put them in front of the model, and let it answer from what it can actually see. RAG composes three things this page already built: embeddings (L1) for both chunks and query, dot-product similarity (L2's math) for retrieval, and the messages array (L0) as the delivery vehicle. Nothing new is invented — it's the same machine, aimed at your corpus.

INDEX TIME — ONCE PER DOCUMENT, NOT PER QUESTION QUERY TIME — EVERY QUESTION YOUR DOCS policies · tickets chunk 1 chunk 2 chunk 3 EMBED text → vector VECTOR INDEX near = about the same thing QUERY "refund policy?" EMBED same space TOP-K CHUNKS the actual policy text MODEL CONTEXT [system, chunks, question] → grounded answer + citation answers from the retrieved text — not from frozen training memory
  1. First we cut your documents into passages small enough to point at — a paragraph, a policy clause, a table row. Chunking: split into passages of a few hundred tokens with overlap; every chunk keeps a pointer back to its source doc and offset — that pointer becomes the citation later.
  2. Each passage gets a coordinate. Passages about the same thing land near each other — closeness means aboutness. Each chunk → an embedding vector (L1's trick), stored in a vector index. Built once, offline; when a document changes you re-embed that document, not the corpus — freshness is an index update, not a training run.
  3. When a question arrives, it gets a coordinate in the same space, using the same measuring stick. Query-time: embed the question with the same embedding model — one vector, same dimensionality, directly comparable to every stored chunk.
  4. We grab the few passages sitting closest to the question. Out of gigabytes, only the handful that matter make the trip. Nearest-neighbour search: top-k by dot-product/cosine — the same similarity math as L1 and L2, aimed at your corpus. An approximate index makes it sub-linear instead of a full scan.
  5. The question and those passages go to the model together — so it answers from your documents, and can cite them, instead of guessing from memory. The chunks are literally concatenated into the L0 messages array ahead of the question; generation is conditioned on them, and the chunk pointers give you source citations for free.

C++ The vector index is a big float array plus an argmax over dot products — retrieval is the same inner-product math as attention, run over your documents instead of the live context.

Why retrieval and not the two obvious alternatives? Pasting everything into every request re-pays for the whole library on every question, and retraining the model to memorize your documents makes it stale the day a policy changes. Retrieval updates like a database and bills like a pamphlet. The three-way tradeoff, compressed: long context re-pays the full corpus token cost per call and caps at the window size; fine-tuning bakes facts into weights, so updates cost a training run and lag reality; RAG pays only for retrieved chunks and updates incrementally — and it's the only one of the three that hands you citations.

ApproachFreshnessCost to update knowledgeBest for
Long context (paste it all in) As fresh as what you paste, per call Zero setup — but every call re-pays the full corpus in tokens Small, bounded corpora; one-off analysis
RAG As fresh as the index — update the index, not the model Cheap and incremental: re-embed only changed documents Large or changing knowledge bases; answers that must cite sources
Fine-tuning Frozen at training time — stale when facts change Expensive: a training run per update Teaching a style, format, or narrow skill — not current facts

The three questions I ask a company first

Before any architecture gets drawn, three questions decide the whole project — and none of them are about AI. These three answers pick the tier, the grounding strategy, and the verification budget respectively — the entire design falls out of them.

  1. Where is the toil?

    Show me the work your best people do that doesn't need your best people — the reading, triage, drafting, and re-keying. That's where the return is, because it's measurable and it's already costing you money every week. Toil = high-volume, low-variance text and decision work → the single-call and workflow tiers. A measurable baseline (hours × rate) means the eval target and the ROI arithmetic both exist on day one, before any code.

  2. Where is the data, and who may see it?

    Grounded answers need your documents. Before any build I need to know where they live, how current they are, and which people — and which systems — are allowed to see each part. Corpus location, format, and update cadence drive the index design; access boundaries drive the architecture — per-tenant indexes, retrieval filtered by permissions before anything enters the context (never after), and an explicit list of what may leave the boundary in a model call.

  3. What must never be wrong?

    Every business has a short list — prices, legal wording, where money goes. That list doesn't get a smarter model. It gets checks that don't guess. The never-wrong set gets deterministic verification: values computed from source-of-truth systems, schema and range validation, and human sign-off gates. The model drafts around these fields; it does not decide them.

Tokens are metered compute public science

AI compute is billed like electricity: you pay per unit moved through the machine, and Level 4 showed you exactly which machine. That means the cost of a feature is a five-line calculation you can do before building anything — here's a real one. Published API price sheets bill per million tokens, input and output priced separately (output costs more — it's generated one memory-bound forward pass at a time, L3–L4). Rates below are an example mid-tier published rate; prices change, the method doesn't. Worked example: a support assistant reading 1,000 tickets a day, each call ~2,000 input tokens (system prompt + retrieved chunks + the ticket) and ~300 output tokens.

1,000 tickets/day × (2,000 in + 300 out) tokens in:  1,000 × 2,000 = 2.0M tok × $3.00/M = $6.00 out: 1,000 × 300 = 0.3M tok × $15.00/M = $4.50 total $10.50 / day ≈ $315 / month

Three hundred dollars a month to pre-read every support ticket — against what that reading costs in salaried hours today. When the arithmetic is that visible, the build decision stops being a leap of faith and becomes a line item. And the same arithmetic exposes the failure modes early: context length multiplies input cost linearly, naive full-history chat replays make per-turn cost grow with conversation length, and retrieval caps input at top-k chunks instead of the whole corpus — cost control and architecture are the same decision.

C++ A token budget ≈ a heap budget: profile it, cap it, alarm before the cap — the meter runs per-token instead of per-byte.

The risks, named — and where each one is stopped

The honest pitch names its own risks. There are three that matter, and none of them are handled by hoping the model behaves — each one is stopped by a piece of architecture. Threat model, in one pass: injection at the context boundary, exfiltration at the data boundary, and irreversible actions at the effect boundary. One enforcement mechanism per boundary, all outside the model.

Text that gives orders. A model reads instructions and documents through the same channel — so a document can try to impersonate an instruction. A retrieval assistant reads your files; a malicious file can say "ignore your rules." The defense isn't a smarter prompt — it's a harness that treats everything retrieved as evidence, never as authority. Prompt injection is structural (L0 showed why: roles are token markers, and the system-vs-user distinction is trained, not enforced). So enforcement lives outside the model: retrieved content is data, tool permissions are allowlisted in the harness, and nothing observed in content can grant a capability.

Data leaving the building. Every model call is data going somewhere. Before the first call, we decide exactly what may go — and everything else can't, by construction rather than by policy-memo. Data boundaries are enforced at the call site: an explicit allowlist of fields that may enter a prompt, permission-filtered retrieval so the index never serves a chunk the requesting user couldn't open, per-tenant index isolation, and secrets that never transit a context at all.

Actions you can't take back. Sending, deleting, paying, deploying — those wait for a human, every time. Not because the system usually fails, but because "usually" is not a governance policy. The HITL gate from the code above, as standing infrastructure: the irreversible set is enumerated, each member is behind an approval, and approvals are logged next to the determinism trace. Autonomy is granted per action class, never blanket.

How an engagement runs

Four phases, no mystery — and every phase maps to levels you've already descended through on this page. The level chips are literal: each phase is the practical application of the machinery those levels explained.

01 · INTAKE L0L5

The three questions, answered with your team: the toil, the data, the never-wrong list. Output: a one-page problem statement with the ROI arithmetic attached.

02 · SCOPED SYSTEM L1L2L3

The smallest shape that works — single call, workflow, or agent — grounded in your data where truth matters. Each step up the ladder justified, in writing.

03 · VERIFICATION L6

Evals, guardrails, and human gates designed alongside the feature — never bolted on after something breaks. The ship gate above is the template.

04 · DELIVERY L4L7

Metered costs known before launch, a runbook your team can operate, and the evidence trail that makes "it works" a record instead of a claim.

The whole descent, on one whiteboard

Everything on this page fits in one drawing and ninety seconds of talking. Here is the drawing; below it, the ninety seconds. One shaft down, one shaft up: L0→L4 is the mechanism, L5→L7 is the leverage. Every arrow in it was earned by a level above.

DOWN: THE MECHANISM UP: THE LEVERAGE L0 THE SENTENCE one JSON request, replayed each turn L1 THE TOKEN text → ids → vectors; meaning = distance L2 THE MATRIX attention: score, softmax, mix — stacked L3 THE LOOP logits → sample → append → again L4 THE IRON memory-bound; batching sets the price L5 THE AGENT the loop + tools: observe, think, act L6 THE FLEET planner, workers, independent verifier L7 THE COMPANY toil, data, never-wrong → shipped system
chat tokens matrix loop iron agent fleet you
“A sentence goes down — words become numbers, the numbers go through the matrix, the matrix runs on iron — and it comes back up as a loop with tools, a fleet with a checker, and a system your business runs.”

The ninety seconds, spoken

  1. L0When you press Enter, nothing mystical happens: the whole conversation is packed into one JSON request and replayed to a stateless server. The model sees text — nothing else.
  2. L1Text can't be multiplied, so it becomes numbers: the sentence splits into tokens, each token indexes a row of coordinates, and meaning becomes distance.
  3. L2The heart is one repeated block: every token scores every earlier token — a dot product — softmax turns the scores into weights, and the weights mix information forward. Stack that block many times.
  4. L3The output isn't an answer — it's a probability for every possible next token. Sample one, append it, run again: a while loop, one word per lap.
  5. L4That loop runs on iron, and moving the weights through memory — not the math — is the bottleneck. That's why batching, and the serving economics behind the price sheet, look the way they do.
  6. L5Wrap the loop in tools and it becomes an agent: observe, think, act — a while loop around an RPC.
  7. L6One agent can be wrong quietly. A fleet with an independent verifier is wrong loudly — and loudly is fixable. Verification is architecture, not hope.
  8. L7And this level is the point: find the toil, find the data, decide what must never be wrong — then build the smallest shape that works, with the gates built in. That's what I deliver.

You've now seen the whole machine — there is no magic anywhere in the stack, only layers you can inspect. So the question left isn't whether this works. It's where in your business we point it first. Softmax over a vocabulary, streamed off memory-bound iron, wrapped in a verified loop — inspectable at every layer, priced per token, gated where it must never be wrong. That's the machine. Let's point it at your business.