← back
00 · opening
Last updated August 4, 2026

From token predictor to agent.

A language model does only one thing: it guesses the next token. This page shows how special tokens, a parser, and a small Python loop turn that guess into an agent that reads files and runs commands.

TOKENS IN the whole transcript MODEL next-token guess TOKENS OUT prose · or a tool call HARNESS runs the tool · appends result
The model never runs anything. It only writes text. A loop around it runs the tools and feeds each result back to the model, and that repeated cycle is what looks like agency.
scroll
01 · the predictor

All the model does is guess the next token.

Take away the chat window, the tools, and the personality, and what is left is a function. Each call is one forward pass. You give it a sequence of tokens, and it returns one score for every entry in its vocabulary (the logits). Then a sampler picks one token. You add that token to the end of the sequence and call the function again. There is nothing else. The model has no memory outside the prompt, no way to act on anything, and no goals.

one forward pass at a time
candidates for the next token
in essence
# the whole model, seen from outside
def generate(tokens):
    while True:
        logits = model(tokens)            # one forward pass
        tok = sample(softmax(logits))     # pick one token
        if tok == END_OF_TURN:            # stopping is a token too
            return tokens
        tokens.append(tok)                # append, repeat
the constraint: Everything an "agent" ever does has to be produced this way: one token at a time, chosen by probability. Even the decision to stop talking is one more token.
02 · the transcript

You see a chat. The model sees one long string.

There is no "user" object and no "assistant" object inside the weights. Before every call, a chat template joins the whole conversation into one long string, and special tokens mark where each turn begins and ends. The model learned this layout in post-training. So when the string ends at the start of an assistant turn, the most probable continuation is a helpful reply, followed by the end-of-turn token, which tells the server to stop.

the same conversation, two ways
user
What's the weather in Tokyo?
assistant
It's 22°C and sunny in Tokyo right now.
in essence
# a chat template is string formatting, nothing more
def render(messages):
    out = ""
    for m in messages:
        out += f"<|im_start|>{m.role}\n{m.content}<|im_end|>\n"
    return out + "<|im_start|>assistant\n"  # cue: your turn
the trick: Roles, turns, and even "stopping" are conventions written in tokens. The model learned them in training, and the server enforces them by watching for the closing special token. The chat bubbles you see are one way of displaying that string.
03 · learning to act

A tool call is text the model learned to write.

Two things turn a chat model into one that "uses tools". First, the tool definitions are sent as text. The JSON Schemas you pass to the API are written into the prompt next to the system prompt, so the model can read what each tool does. Second, post-training teaches a strict output format. The model sees thousands of example conversations where the correct assistant turn is a machine-readable block, wrapped in special tags, that names a tool and its arguments. The idea goes back to ReAct prompting and Toolformer. In today's models, the format is trained into the weights.

watch the model emit a tool call, token by token

      
Press play. The model is partway through its turn, and the tool schemas are already in its context.
in essence · what the training data looks like
# one of thousands of supervised examples
prompt = render(system + tool_schemas + "user: weather in Tokyo?")
target = "<tool_call>{\"name\": \"get_weather\", " \
         "\"arguments\": {\"city\": \"Tokyo\"}}</tool_call>"
# training makes this exact shape the most probable reply
the key idea: The model runs nothing. "Calling a tool" means predicting the tokens of a tool call. The model gets the format right with high confidence because so many training examples looked like this one. It is writing down an intention, and something else has to carry it out.
04 · the api contract

The server turns the tool call into structured data.

The inference server watches the token stream. When the model opens a tool-call block, the server lets it finish, then stops the turn, parses the JSON, and returns it as a structured object with a stop_reason of tool_use. You never see the raw special tokens. Because sampling picks one token at a time, the server can also force the output to fit the schema. With constrained decoding, it blocks any token that would break the schema. That is what "strict" tool modes promise.

three dialects, one idea
open weights · raw stream

Special tokens

The raw output of a Qwen- or Hermes-style model. The tags are reserved tokens.

<tool_call>
{"name": "get_weather",
 "arguments":
   {"city": "Tokyo"}}
</tool_call>
anthropic · parsed block

tool_use block

The same tool call, parsed by the server into a content block, with stop_reason: "tool_use".

{"type": "tool_use",
 "id": "toolu_01A...",
 "name": "get_weather",
 "input":
   {"city": "Tokyo"}}
openai · parsed array

tool_calls

The same again, but the arguments stay a JSON string and the stop reason has a different name: finish_reason: "tool_calls".

{"id": "call_x9q",
 "type": "function",
 "function": {
   "name": "get_weather",
   "arguments":
     "{\"city\":\"Tokyo\"}"}}
the contract: Each provider uses a different format, but the arrangement is the same: the model writes formatted text, and the server parses it into JSON. Your code gets a field it can switch on, instead of having to dig answers out of free-form prose.
05 · the loop

The agent is a while loop.

The core of every coding agent is much smaller than most people expect. A harness sends the transcript and the tool schemas, checks stop_reason, runs the requested function, adds the result to the transcript as a new message, and calls the API again. The model reads the tool result as new tokens and predicts what to do next. Step through one task below.

one turn of an agent · read a file, then answer
01 SEND transcript 02 PREDICT tokens 03 BRANCH stop_reason 04 EXECUTE for real 05 APPEND result · loop while stop_reason == "tool_use" · END_TURN
01 / send
Every call sends the full transcript.
Press play, or step through one full task.
in essence · the whole agent
TOOLS = {"read_file": read_file, "run_bash": run_bash}

def agent(task):
    messages = [{"role": "user", "content": task}]
    while True:
        r = api.messages.create(model="...",
                                tools=SCHEMAS, messages=messages)
        messages.append({"role": "assistant", "content": r.content})
        if r.stop_reason != "tool_use":
            return r                      # done: plain text answer
        results = []
        for call in r.content:            # may be several in one turn
            if call.type == "tool_use":
                out = TOOLS[call.name](**call.input)   # the real world
                results.append({"type": "tool_result",
                                "tool_use_id": call.id,
                                "content": out})
        messages.append({"role": "user", "content": results})
the surprise: Nothing is kept between calls. The API is stateless, so the "agent" is rebuilt from the transcript on every pass through the loop. Its memory, its progress, and its personality all live in the messages array that your loop keeps adding to.
06 · the composition

Three limited parts add up to an agent.

None of the pieces can do much alone. The predictor has judgment but no way to act. The tools can act but have no judgment. The loop has neither. It only passes tokens back and forth. Put together, they form a feedback cycle. The model perceives the world through tool results, which arrive as tokens. It decides by predicting the next token. It acts through the harness. Run that cycle enough times and you get what we call agency.

two halves of an agent
from the weights

What the model brings

judgment
Which tool to call, with which arguments, and when to stop. Each of these is a next-token prediction shaped by training.
the format
Writing tool calls that a parser can read is a habit the model learned in post-training.
recovery
An error message comes back as tokens too. After a failure, the most probable continuation is a retry or a new plan.
from the harness

What the loop brings

hands
The real read_file, bash, and browser. The model only ever names them.
time
The while loop keeps going for as many turns as the task needs. One call is a chat. Many calls in a loop are an agent.
guardrails
Permissions, sandboxes, context compaction, sub-agents. This is where harnesses differ, so the same model can make a very different agent.

This is why the harness matters so much. Claude Code, a CI bot, and a chat app can run the same weights and still behave very differently, because the harness decides which tools exist, what the system prompt says, and how the context window is managed. I took two production harnesses apart in the agent harness explainer. This page covers the mechanics underneath that one.

the frame: An agent is a token predictor, a parser, and a while loop. The weights decide what to do, and the loop makes it happen.
07 · fin

The model only ever reads and writes text.

The model guesses tokens one at a time, and they add up to a sentence. When the sentence is in the learned tool-call format, it states an intention. A parser turns the intention into structured data, the loop carries it out, and the result comes back as more tokens for the next guess. At no point does anything except text go into or come out of the model.

Where to go next: the agent harness shows what production loops add on top, api, mcp & the two acps covers how tools are discovered and shared, and pre-training vs post-training covers how the model learns the tool-call format from section 03.