How LLM Instructions Work: Tokens, Messages, Roles, and Context
You tighten the system prompt. You add the word "always." You move the rule to the top. The model still ignores it, and you have no idea which part of the…

Key topics
You tighten the system prompt. You add the word "always." You move the rule to the top. The model still ignores it, and you have no idea which part of the request actually won.
The problem is usually not your wording. It is the mental model behind the wording. Most of us carry a quiet assumption that we are sending a message to a reader who understands roles, priorities, and intent. That assumption is wrong in a specific, useful way. Once you replace it, most instruction failures stop looking mysterious and start looking mechanical.
Here is the invariant this article will prove: the model consumes one serialized, ordered sequence of tokens, and it predicts the next token over all of it. Your message list is an abstraction that gets flattened before the model ever runs. Instructions are not commands. They are context that shifts a probability distribution.
The Model Never Sees Your Messages
When you call a chat API, you send a structured list:
[
{"role": "system", "content": "You are a terse assistant."},
{"role": "user", "content": "Summarize this contract."}
]
That list is a developer-facing abstraction. It is not what the model consumes.
Between your list and the model sits a chat template: a translation layer that flattens the message objects into one contiguous string using model-specific special tokens and delimiters. A template for one model family might render the above as something close to:
<|im_start|>system
You are a terse assistant.<|im_end|>
<|im_start|>user
Summarize this contract.<|im_end|>
<|im_start|>assistant
The exact tokens differ by model. The structure does not: role markers become tokens in the sequence, and the model reads the whole thing as text.
This is where the base-model versus instruct-model distinction earns its keep. A base model trained on raw text predicts the next token and will happily continue your conversation formatting instead of answering. An instruct model has been fine-tuned on conversation-formatted data, so it learned to treat the role delimiters as a signal to respond rather than continue. The role structure is not a permission system. It is a pattern the model was trained to recognize.
Now the qualification that keeps this model honest. The serialized sequence is what the model reads, but the serialization itself is a learned signal, and the surrounding application can enforce things the model cannot. A framework may reject a malformed tool call before it reaches your handler. A provider may apply its own instruction treatment. Your own code may validate a schema and retry. So the correct statement is not "roles are meaningless." It is: the model's behavior toward roles is learned, not guaranteed, and any guarantee you need has to live outside the model.
Swap models or templates and the same message list can produce different behavior, because the delimiters, ordering conventions, and formatting changed underneath you.
Knowledge check
Check your understanding
Answer this question before you continue.
Tokens Are the Unit of Everything
Text does not reach the model as text. A tokenizer splits it into sub-word units from a fixed vocabulary. A token might be a whole word, a fragment, a single character, or punctuation. Spaces often attach to the front of the following token, so tokenization is not word-aligned.
The model operates on token IDs. It never sees characters. This matters more than it sounds.
Tokenization boundaries can split a word, an identifier, or a delimiter. If you instruct a model to emit an exact JSON key, an exact format string, or an unusual identifier, the tokenizer may carve that string into pieces that do not match your intuition about "one thing." Exact-match instructions are where tokenization stops being trivia and starts being a bug source.
Token count is also the real currency. It sets cost, and it consumes the context window before generation even begins. A short instruction is not automatically cheap, and a long instruction is not automatically precise. Measure tokens, not characters. If you have ever wondered why a "simple" prompt costs more than expected, the answer is usually in the rendered sequence, not the source text you typed.
Knowledge check
Check your understanding
Answer this question before you continue.
Roles, Delimiters, and the Instruction Hierarchy
System, user, and assistant are conventions encoded by special tokens during fine-tuning. They are not hard-coded permissions. What they produce is an instruction hierarchy: a trained tendency to weight system-level content more heavily than user content, and user content more heavily than stray text.
That tendency is real and useful. It is also a bias, not a guarantee. Treating the system prompt as a security boundary is the classic mistake here. It is a strong prior, not an access control list. If your threat model depends on the model refusing something because the system prompt said so, you do not have a threat model. You have a hope.
Two more mechanics deserve attention.
First, assistant turns in the history are model output replayed as context. They shape the next prediction as strongly as user text does. A bad earlier answer does not just sit in the log; it becomes evidence the model builds on.
Second, tool results, retrieved documents, and injected chunks usually arrive as additional roles or delimited blocks. That extends the same mechanism rather than replacing it. A retrieved document is not "knowledge the model has." It is more tokens in the sequence, competing for weight with everything else.
Knowledge check
Check your understanding
Answer this question before you continue.
Ordering and Recency: Why Position Changes Behavior
The model attends across the whole sequence, but training and formatting conventions create position-sensitive weighting. In practice, content near the end of the sequence tends to influence the next token more strongly. This is why late-injected context often overrides earlier instructions, and why appending a constraint at the end frequently beats burying it at the top.
The deeper problem is not position alone. It is competing text. Two instructions that conflict do not merge into a compromise. They compete, and the winner depends on position, specificity, and phrasing. If your system prompt says "be concise" and a late user message says "explain in full detail," you have not given the model a rule. You have given it a fight.
A practical pattern that holds up:
- Put stable behavioral rules early.
- Put task-specific and high-salience context late.
- Do not duplicate conflicting instructions in both places.
Ordering tricks are not enforcement. If a constraint must hold, validate the output. Do not rely on the model's position bias to protect you.
Knowledge check
Check your understanding
Answer this question before you continue.
The Context Window Is a Budget, Not Memory
Everything competes for the same window: system instructions, conversation history, retrieved documents, tool output, and the tokens being generated. It is one finite pool, and every token spends from it.
Longer context is not strictly better. Attention is spread across more tokens, and marginal returns diminish. Irrelevant tokens are not neutral. They consume budget and dilute the signal the model needs. This is the "attention budget" framing, and it is the right one: context is a finite resource with diminishing returns, not free storage.
Keep one distinction sharp. Transient context is what the model sees on this call. Persistent state is what your application stores across turns. They are different systems with different failure modes. Confusing them is how you end up debugging the model when the real bug is in your message assembly.
Once you are programmatically choosing and trimming what enters the window per call, you have crossed from prompt engineering into context assembly. That is the next thing worth learning.
Debugging Instruction Failures with This Model
The mental model becomes useful when it turns into a procedure. When an instruction fails, work the steps in order.
- Dump the rendered prompt. Not the message list you wrote. The exact string or token sequence your template produces. Debug the artifact, not your intention.
- Locate the competing text. Find every instruction that touches the same behavior and check whether they conflict.
- Check position. Is the instruction you care about early, late, or buried under retrieved content?
- Check tokenization on anything exact: keys, formats, identifiers, delimiters.
- Change one variable at a time. Treat each failure as evidence about what the model actually weighted.
The most common misdiagnosis is blaming model capability when the real cause is a template that silently dropped, reordered, or reformatted a message. I have watched that happen more than once, and it always looks like a model problem until you print the sequence.
What to Do Next
Before you rewrite a single word of your prompt, inspect the rendered sequence. Find the competing text. Check position and tokenization. Most instruction failures are not wording failures. They are context-assembly failures wearing a wording costume.
Your next move: take one prompt that has been misbehaving, dump its fully rendered form, and read it as the model reads it — one ordered sequence, no roles, no privileges, just tokens competing for weight. Then decide what actually needs to change.
Knowledge check
Final check
Finish the article by checking the ideas you just learned.
References
Research updated Sep 11, 2026


