Skip to content

The Reasoning Core

LLMs as the engine

Tokens, context window, sampling

Every agent you will ever build wraps one component: a large language model. Strip away the tools, memory, and orchestration and what remains is a next-token predictor, a function from text to text. Build that engine from first principles and its two hard constraints - it is stateless and context-bounded - stop surprising you when you design agents.

The whole model in one sentence

Given a sequence of tokens, an LLM outputs a probability distribution over the next token, samples one, appends it, and runs again. Chat, reasoning, and tool use are all emergent behaviour layered on top of this single mechanism.[1]

The whole engine: predict the next token

A decoder-only Transformer does exactly one thing. It reads a list of token IDs and emits one raw score (a logit) for every entry in its vocabulary - typically 50,000 to 200,000+ possible tokens. A softmax turns those scores into probabilities that sum to 1. The model draws one token from that distribution, appends it to the sequence, and runs the whole network again on the longer sequence. That loop, called , is generation.

Tap a node to see what it does.

One step of autoregression. The same network runs once per generated token; the output feeds back in as the next input.

Three consequences fall straight out of this design, and every one of them shapes how agents behave:

  1. No plan exists. The model commits one token at a time. When it "reasons," it is literally emitting reasoning tokens that then condition later tokens. The scratchpad is the computation.
  2. Compute per token is fixed. Each token costs roughly 2x the parameter count in FLOPs.[1] A model cannot think harder on one token, only longer, by emitting more of them.
  3. Everything is conditioning. System prompt, retrieved docs, prior turns, tool outputs, and the model's own words are all just tokens in context that shift the next-token distribution.

"More tokens equals more serial computation" is the mechanical reason chain-of-thought and reasoning models work - you buy accuracy with tokens. That is the subject of the next lesson, Reasoning and test-time compute.

Tokens: the model never sees your text

Transformers operate on integers, not characters. A tokenizer encodes your string into token IDs before the model sees anything, and decodes IDs back into text afterward. Nearly every modern model - GPT, Llama, Mistral, Claude, Gemini - builds its tokenizer with (BPE): start from raw bytes, then repeatedly merge the most frequent adjacent pair into a new token until you hit a target vocabulary size. The saved merge rules are the tokenizer.[2] Tokens are sub-word chunks - usually bigger than a letter, smaller than a word. A rough rule for English: about 4 characters is 1 token, and 100 tokens is about 75 words. The leading space is part of the token, so " France" is a different token from "France".

Feed the five tokens of "The capital of France is" into the network and it returns a probability for every possible next token. For this prompt the distribution is sharply peaked:

Next tokenProbability
" Paris"0.86
" the"0.04
" a"0.03
" located"0.02
" home"0.01
~50,000 more tokens in the taileach about 0.00
The next-token distribution for The capital of France is. Sampling settings decide which row becomes the output; they never change the numbers themselves.

Why how many r's in strawberry is hard

The word may tokenize as str, aw, berry - three opaque chunks, not ten letters. Asked to count r's, the model never sees the letters, so it guesses. The same root cause makes spelling, string reversal, rhyming, and digit-level arithmetic unreliable: numbers tokenize inconsistently ("327" may be one token, "328" two).[2] Reasoning models often get it right only because they first spell the word out token-by-token in their chain of thought, converting a character task into one the model can read.

Non-English text and code learn fewer merges, so they cost more tokens per word - inflating both price and how fast you burn through the context window.[2]

Sampling: turning a distribution into a choice

The network gives you a distribution. Sampling parameters decide how a single token is drawn from it. Crucially, they do not change what the model knows or predicts - they only reshape or truncate the bars before the draw.[3]

  1. Temperature. Divides the logits by T before softmax. T < 1 sharpens the distribution (more confident); T > 1 flattens it (more random). T = 0 disables sampling entirely, giving greedy decoding, always the argmax.
  2. Top-k. Keep only the k highest-probability tokens, renormalize, then sample. A fixed cutoff - it ignores how confident the model actually is on this particular step.
  3. Top-p (nucleus). Keep the smallest set of tokens whose cumulative probability is at least p (for example 0.9), renormalize, sample. Adaptive: few tokens when confident, many when uncertain. For the France prompt above, top-p 0.9 keeps just " Paris" plus " the".

Here is the required intuition made concrete: the same prompt run five times at two temperatures. Notice two things: at T = 0 the output is identical every run, and temperature only matters when the distribution is not already peaked:

PromptTemperature 0, five runsTemperature 1, five runs
Peaked: "The capital of France is __"Paris, Paris, Paris, Paris, ParisParis, Paris, Paris, Paris, Paris (0.86 of the mass, hard to move)
Flat: "A name for a new coffee shop: __"The Daily Grind (times 5, identical)Brew and Co, Bean There, Kettle and Cup, Morning Ritual, Roast House
Temperature only changes the output when the distribution is flat. On a peaked prompt even T=1 barely moves.

Low temperature (0 to 0.3)

Extraction, classification, code, math, tool-call arguments - anything where you want the correct and reproducible answer. Reach for greedy T = 0.

High temperature (0.7 to 1.0)

Brainstorming, drafting, creative variety - usually paired with top_p about 0.9. Tune one knob at a time; cranking both invites low-probability nonsense.

Determinism has an asterisk

T = 0 is deterministic in principle, but outputs can still vary run-to-run because of floating-point non-determinism, request batching, and mixture-of-experts routing on shared server hardware. Do not rely on it for bit-exact reproducibility.

The context window: a hard token budget

The is the maximum number of tokens the model can attend to at once - and it must hold everything: system prompt, tool definitions, conversation history, retrieved documents, and the generated output (including any hidden reasoning tokens).[6] When it fills up, the earliest tokens must be dropped or summarized. There is no memory beyond it. In an agent, tool schemas, history, and retrieved docs compete for the same fixed space as the answer you still need to generate.

Windows grew from about 2k tokens (GPT-3) to 128k to 1M+ on frontier models - but bigger is not reliably usable. The lost in the middle effect shows retrieval accuracy follows a U-shaped curve over position: highest when the needed fact sits at the start or end of context, degrading by more than 30% when it is buried in the middle.[4]

Design implication for agents

Do not dump everything into the window. Retrieve narrowly, and place the most important instructions or data at the top or bottom of the context. Simon Willison's rule for reasoning models inverts the usual RAG instinct: give the model the most relevant context, not the most context.[6] We turn this into a discipline in Context engineering.

In-context learning: teach it in the prompt

(ICL) is the ability to perform a new task purely from instructions or examples placed in the prompt - with no gradient updates and no fine-tuning. Zero-shot describes the task; few-shot adds a handful of input-to-output demonstrations and the model infers the pattern. This is the property that made prompt engineering viable at all, and it is widely considered an ability that emerges sharply above a scale threshold.[5]

# Two demonstrations teach the task, no retraining involved.
Review: "Loved it, would buy again."    Sentiment: positive
Review: "Broke on day two. Avoid."      Sentiment: negative
Review: "Arrived late but works fine."  Sentiment:   # model completes: neutral
Few-shot in-context learning: two demonstrations teach the task with no retraining.

Chain-of-thought - prompting for intermediate steps before the answer - is ICL's most famous trick, and it too emerges only at scale.[5] We put ICL to work in Prompting for agents.

Two properties that shape every agent

Everything above collapses into two constraints you must design around. Miss them and your agent architecture will fight the engine instead of using it.

1 - Stateless between calls

The model keeps nothing after a call returns - no session, no scratch memory, no recollection of turn 1. The illusion of a chatbot that "remembers" exists only because the framework resends the entire prior transcript as tokens every single turn.

2 - Context-bounded

That resent transcript, plus tools, retrieved docs, and the answer, must all fit inside one finite window. Long conversations do not grow the model's memory - they consume the budget until something has to be dropped or summarized.
# The model is stateless. YOU carry the state, and resend it all every turn.
history = [system, user_1, assistant_1, user_2]   # just a growing list of tokens
reply   = model.generate(history)                 # one stateless call, remembers nothing
history = history + [reply, user_3]               # you append the new turn...
model.generate(history)                           # ...and the model re-reads the WHOLE thing
The model is stateless: you hold the transcript and resend it in full on every call.

These two facts are why the rest of this course exists. Statelessness is why agents need external memory and a persistent agent loop. Context-boundedness is why retrieval and context engineering exist: you are constantly deciding which tokens earn a place in a budget that is always too small.

Check yourself

Match each engine concept to what it governs.

drop here

the unit of cost, latency, and vocabulary

drop here

the ceiling on tokens per call

drop here

how random the token choice is

drop here

trims the unlikely tail before sampling

You need a model to return byte-identical JSON for identical input on every run. Which decoding setting gives you the best shot?

A model is stateless between calls. So how does a chat agent appear to remember what you said three turns ago?

Why can an LLM count the words in a sentence but fail to count the letter r in strawberry?

What does the model actually see? Try to state it, then check.

Lock it in

  • An LLM is a next-token predictor: text, then a distribution over the vocabulary, then sample, append, repeat. Everything else is emergent.
  • Models read tokens, not characters (BPE sub-word chunks). That single fact explains spelling, counting, and arithmetic failures, and why non-English text costs more.
  • Sampling (temperature, top-p, top-k) only decides which token is drawn, never what the model knows. T = 0 is greedy and, in principle, deterministic.
  • The context window is one finite budget holding prompt plus history plus tools plus docs plus output; facts in the middle get lost.
  • The engine is stateless and context-bounded - the two constraints that drive memory, retrieval, and the agent loop.

Primary source

Andrej Karpathy, Let's build the GPT Tokenizer / minbpe

Build a BPE tokenizer from scratch (bytes, then iterative merges, then vocabulary). It is the fastest way to feel the core truth of this lesson: the model sees tokens, not your text, and that explains a startling number of its quirks.

Sources

  1. 1.Lilian Weng, Why We Think (2025)
  2. 2.Andrej Karpathy, minbpe / Let's build the GPT Tokenizer
  3. 3.Sebastian Raschka, Temperature, top-k, and top-p sampling
  4. 4.Lost in the Middle and long-context evaluation (arXiv 2412.10079)
  5. 5.Wei et al., Chain-of-Thought Prompting Elicits Reasoning (2022)
  6. 6.Simon Willison, Notes on OpenAI o1 (2024)