Skip to content

A Short History of Agents: From ReAct to 2026

16 min read

If you squint at four years of agent research, the headline result is simple: we figured out how to get the model to stop talking and actually do something. Everything on top of that (ReAct, Toolformer, function calling, MCP, Devin, Claude Code) is a variation on the same tune.

I want to walk through that history, because knowing why each thing happened is half of how I reason about where the stack is headed. And there's one mental model I keep coming back to that makes the whole arc easier to hold in your head: the loop hasn't changed; the substrate has. Every era since 2022 has been a different answer to "which part of the loop are we upgrading this year?"


The problem this layer solves

The core problem is small when you write it down: an LLM, taken as a pure next-token predictor, can only do what is expressible in tokens. It can talk about the weather, but it can't check the weather. It can describe how to run a test suite, but it can't run one. It can claim an answer with great confidence, and you have no independent evidence it's right.

So from the moment anyone had a usable LLM, there was an obvious gap: how do we give this thing hands?

"Agents" is the name we've collectively landed on for whatever answers that question. An agent is a system that runs an LLM in a loop with the outside world. The model produces output, something in the environment reacts, the model sees the reaction, and the cycle continues until the task is done. The loop is the agent. Everything else is substrate.

The history of the last four years is the history of that loop getting better tools, better training, and better runtime around it. Not a different loop.


Prerequisites

This post sits near the end of the series. To follow the trajectory, it helps to already have a feel for a few earlier layers:

  • What a tokenizer does and why chat templates matter. Agent protocols live inside the transcript format.
  • The difference between training a behavior into a model and prompting it at inference time. Most of the history here is a swing between the two.
  • What function calling looks like at the API level. We'll cover the history, but I'll lean on the mechanics from the dedicated function calling post.

If any of those feel shaky, the earlier posts in Arcs 3, 7, and 10 are the on-ramps.


The minimal formalism

This is a history post, so the "math" is honestly more like a definition I want to fix in place before we start. If you write down what an agent does at the most skeletal level, you get four pieces:

  • A model π\pi that produces tokens.
  • An action space A\mathcal{A} — the set of things the model is allowed to ask the world to do.
  • A tool (or environment) τ\tau that executes an action and returns an observation.
  • An observation oo that gets pasted back into the context for the next model step.

One step of the loop is just:

atπ(ct),ot=τ(at),ct+1=ctatota_t \sim \pi(\cdot \mid c_t), \quad o_t = \tau(a_t), \quad c_{t+1} = c_t \oplus a_t \oplus o_t

The model samples an action from its context, the tool produces an observation, the context grows by one action-observation pair, and you loop until the model emits a final answer or a stop condition fires.

Every era we're about to walk through is an upgrade to one of those four pieces. That's the handle I want you to carry through the rest of the post.

THE LOOP HASN'T CHANGED. THE SUBSTRATE HAS.modelgenerates tokensactiontool call + argstoolruntime executesobservationresult fed back2022 · CHAIN-OF-THOUGHT
Reasoning moves into the generation stream. The model step gets richer.

The same four-node loop across every era of agent research. Each highlight shows which piece of the substrate the era upgraded. The loop itself never changes: model, action, tool, observation, repeat.


Chain-of-thought: reasoning moves into the generation stream

January 2022. Wei et al. publish Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. The paper is short and the finding is straightforward: if you ask a large enough model to "think step by step" before answering a math word problem, accuracy jumps dramatically. For PaLM-540B on GSM8K, it went from about 18% to about 57%.

No new architecture, no fine-tuning. Just more tokens before the answer token.

Why does this matter for agents? Because it's the first time we clearly see that the generation stream is doing computation, not just narration. If the model can think in tokens, then thought is addressable, editable, and inspectable. You can prompt for it, log it, compare it across runs. It's not quite an "action," but it's the thing that, a few months later, will get interleaved with actions to make the whole loop legible.

This is also the last moment where "agents" is mostly a prompting story. Everything after this starts involving the outside world.


ReAct: the loop gets a name

October 2022. Yao et al. publish ReAct: Synergizing Reasoning and Acting in Language Models. This is the one that puts the loop on paper.

The move is small. You take chain-of-thought and interleave Thought tokens with Action tokens (like search("Arthur's Magazine")) and Observation tokens (the tool's response), and you train or prompt the model to keep alternating until it emits a final answer.

REACT TRACE · HOTPOTQA-STYLEstep 1 / 7QUESTION
Which magazine was founded first, Arthur's Magazine or First for Women?
THOUGHT
I need to look up both magazines' founding dates, then compare.
ACTION
search("Arthur's Magazine")
OBSERVATION
Arthur's Magazine was an American literary periodical published in Philadelphia in the 19th century, founded in 1844.
ACTION
search("First for Women magazine")
OBSERVATION
First for Women is a woman's magazine launched in 1989 by Bauer Media Group.
THOUGHT
1844 is earlier than 1989, so Arthur's Magazine was founded first.
ANSWER
Arthur's Magazine

A ReAct-style trace on a HotpotQA question. The model thinks, acts, reads the observation, thinks again, acts again, and finally answers. The structure in the transcript is the loop.

This is where the word "agent" starts to mean something concrete. Before ReAct, "agent" could mean almost anything. After ReAct, an agent is a model whose transcript looks like this: thought, action, observation, thought, action, observation, answer. The trace is the agent.

A few things about ReAct:

  • It works just as prompting, not only with fine-tuning. The format is simple enough that a big model can follow it from a few in-context examples. That meant anyone with API access could ship an agent.
  • It makes the loop legible. You can read a ReAct trace and see exactly what the model was thinking when it called a tool. That property is still what makes modern agent traces debuggable.
  • It's model-agnostic. The exact same format works on GPT-3.5, Claude 1, Llama 2, whatever. The protocol is in the prompt, not the weights.

If you only remember one paper from the history of agents, remember this one. The loop you read about in any 2026 agent framework is a descendant of this.


Toolformer: training the behavior into the weights

February 2023. Schick et al. publish Toolformer: Language Models Can Teach Themselves to Use Tools.

The pitch is that instead of relying on prompting to get the model to call tools, bake tool use into the weights. The clever bit is the self-supervised dataset. They let a pretrained LM propose tool calls inside text, execute them, and keep the annotations that actually reduced perplexity on the next token. Then fine-tune on the winners.

MILESTONES IN AGENT HISTORY1 / 8JAN 2022Chain-of-Thoughtlet's think step by stepWHAT CHANGED
Showed that asking the model to emit its reasoning before the answer dramatically improves accuracy on multi-step problems.
CORE IDEA
Reasoning can live inside the generation stream. No tools yet, no actions, just more tokens.
2022202320242025Chain-of-Thought

The scrubbable version of the same story, milestone by milestone. Each panel names what that paper or release actually changed about the substrate around the loop. Pause on any one to sit with it.

Why does this matter? Two reasons.

The first is obvious: if the behavior is in the weights, the model doesn't need a giant prompt template to know when to call a tool. It just does the right thing.

The second is less obvious and more important for where things went: Toolformer is the ancestor of every modern tool-use SFT recipe. Post-training data for Claude, GPT-4, and Gemini all contain tool-use trajectories. The pipeline is fancier now (verifier models, rejection sampling, reinforcement learning from tool-use rewards), but the shape is the same. You generate trajectories, you filter, you train on what works.

From Toolformer onward, "the model knows how to use tools" stops being a prompting claim and becomes a capability claim you can measure on held-out tool-use benchmarks.


Function calling: the action gets a schema

June 2023. OpenAI ships function calling in the Chat Completions API. The API now accepts a list of function definitions in JSON Schema, and the model can return a structured function_call object alongside (or instead of) the text.

This is not a new research idea. It's a productization move. But it matters because it standardizes the action piece of the loop in a way that a free-form prompt never could.

  • The action is typed. The arguments have a schema the model is expected to fill.
  • The action is parseable. You get a JSON object, not "the model said it wanted to call search and here's a regex to extract the arg."
  • The action is enforceable. Under the hood, providers use constrained decoding (grammar-guided sampling) so that the model physically cannot emit syntactically invalid JSON for a declared function.

Anthropic shipped their version a few months later, Google followed with Gemini function calling, and by the end of 2023 every serious LLM provider had a version of this. The action space had moved from "whatever the prompt template asks the model to emit" to "whatever the provider's API says is a legal tool call."

This is the moment "agents" starts showing up in production systems that aren't research demos. Not because any single capability got better, but because the protocol around the action became reliable.


Voyager and Reflexion: memory and self-critique

Summer 2023. Two papers land in quick succession that push on pieces of the loop that function calling didn't touch.

Reflexion (Shinn et al., March 2023) adds a verbal self-critique step. After a failed trajectory, the agent writes a short natural-language reflection and stores it as memory for the next attempt. Performance on HotpotQA and AlfWorld climbs significantly. The move is simple and, like ReAct, works just with prompting. The implication is bigger: the observation piece of the loop can include the agent's reflection on its own past behavior. Memory enters the picture as just more tokens.

Voyager (Wang et al., May 2023) takes this further in a Minecraft environment. The agent writes executable code, stores working skills in a library keyed by natural-language description, and retrieves them later when a relevant situation arises. It makes open-ended, lifelong progress without retraining the underlying model.

The Voyager idea that stuck: memory can be learned code, not just text. Skills are programs you've already gotten to work. The agent grows by accreting capability rather than just accumulating facts. Most of what modern coding agents do with "remembered" bash invocations, test-runners, scratchpads, and project-specific tools is a descendant of this.

Tree-of-Thoughts, also 2023, pushes on the model-step piece by letting the agent search over multiple reasoning branches before committing. I won't linger on it, but it's another era-specific upgrade to the "model" node of the loop.


2024: the substrate productionizes

2024 is the year where agents stopped being a research story and started being a product category. The papers don't matter as much as the ship dates.

SWE-agent (Yang et al., 2024) showed that a general-purpose language model, wrapped in an "agent-computer interface" (a careful curation of shell commands, file views, and edit operations exposed as tools), could solve real GitHub issues. SWE-bench went from a humbling benchmark to a credible target. This is the research precursor to every 2025 coding agent.

Anthropic Computer Use (October 2024) gave a model a screenshot and a mouse, and asked it to do things. The action space is now "anything a human can do at a desktop." The failure modes are spectacular and the loop is exactly the same.

MCP (Model Context Protocol, November 2024) took the function-calling idea and cut it loose from any one provider. A single MCP server exposes tools, resources, and prompts, and any MCP-capable client can use them. This is when the tool node of the loop started behaving like an operating system interface instead of a per-API blob.

OpenAI Responses API and the Harmony transcript format (March 2025 and August 2025 respectively) tightened the model-side contract: explicit channels for user, assistant, tool calls, and tool results, baked into the training distribution. The protocol and the implementation met in the middle.

None of these are new research ideas in the ReAct or Toolformer sense. They're infrastructure. The loop hasn't changed. But 2024 is the year the loop got the substrate it needed to run reliably in production.


2025–26: agents that ship

By 2025, "agent" in practice means one of a small number of things.

Coding agents — Claude Code, Cursor's agent mode, GitHub Copilot Workspace, Devin, Codex CLI. The agent edits files, runs tests, reads the output, keeps going. The loop is still ReAct; the tools are a curated set of file and shell operations; the memory is a combination of the open editor state, a running scratchpad, and (often) a sub-agent whose only job is to manage what stays in the context window.

Computer-use agents — Anthropic's Computer Use, OpenAI's Operator, various browser-pilot products. The action space is "the screen," which turns out to be both much more general and much harder to get right.

Retrieval-and-answer agents — the ones living inside Perplexity-style products, enterprise search, and most "chat with your docs" deployments. They look boring next to Devin but they're where the majority of deployed agent traffic runs.

What's striking looking across all of them is how little has changed in the shape of the loop. A 2026 coding agent's inner loop, if you zoom in, looks strikingly similar to a 2022 ReAct trace.

SAME LOOP, DIFFERENT SUBSTRATE2022 · REACT PROMPTfree-form text, parsed by regex2026 · STRUCTURED AGENTtyped tool calls, constrained decodeBEAT
I need to look up the repo's test command.
I need to look up the repo's test command.
THOUGHT
search[query="package.json test script"]
{ "name": "bash", "input": { "cmd": "cat package.json" } }
ACTION
Obs: "scripts": { "test": "vitest run" }
{ "type": "tool_result", "content": "\"test\": \"vitest run\"" }
OBSERVATION
Now run the tests and see what fails.
Now run the tests and see what fails.
THOUGHT
run[cmd="npm test"]
{ "name": "bash", "input": { "cmd": "npm test" } }
ACTION
Obs: 1 failing test in auth.spec.ts, line 42.
{ "type": "tool_result", "content": "FAIL auth.spec.ts line 42" }
OBSERVATION
The test on line 42 is failing because…
The test on line 42 is failing because…
ANSWER

Same seven beats on both sides: thought, action, observation, thought, action, observation, answer. The 2022 side is free-form text a regex has to parse. The 2026 side is typed JSON under constrained decoding. The shape of the loop is identical, and only the substrate underneath is different.

The differences are elsewhere:

  • The model is better at the thought step (post-trained hard on tool-use and coding data).
  • The action space is richer and more reliably enforced.
  • The tools are real and standardized (MCP, Responses, etc.).
  • The context window has its own sub-system (compaction, summarization, sub-agents) so the observation piece doesn't drown the loop in 50-file diffs.
  • The runtime around it is production-grade, with retries, logging, eval harnesses, and human approval gates.

The loop hasn't changed. The substrate has.


A minimal agent loop

Here's the smallest version of the loop I can write that captures what's going on. It's maybe 25 lines, uses the Anthropic SDK, and exposes one tool.

import json
from anthropic import Anthropic
 
client = Anthropic()
 
# One tool: a toy "search" that pretends to hit a knowledge base.
def run_tool(name: str, args: dict) -> str:
    if name == "search":
        q = args.get("query", "")
        return f"(pretend result for: {q})"
    return f"unknown tool: {name}"
 
tools = [{
    "name": "search",
    "description": "Look something up.",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string"}},
        "required": ["query"],
    },
}]
 
messages = [{"role": "user", "content": "Which magazine was founded first, Arthur's Magazine or First for Women?"}]
 
while True:
    resp = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )
    messages.append({"role": "assistant", "content": resp.content})
 
    if resp.stop_reason != "tool_use":
        # The model emitted a final answer. We're done.
        print(resp.content[-1].text)
        break
 
    # Run every tool the model asked for and feed results back.
    tool_results = []
    for block in resp.content:
        if block.type == "tool_use":
            out = run_tool(block.name, block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": out,
            })
    messages.append({"role": "user", "content": tool_results})

Four things worth noticing about this loop.

One, the while True is the agent. Everything else is bookkeeping. The loop is what makes this an agent rather than a single-turn assistant.

Two, stop_reason is how the model tells the runtime "I'm done for this turn." If it's tool_use, keep going. If it's anything else (usually end_turn), the agent terminates. This tiny bit of protocol is doing enormous work: it's how the model, from inside the token stream, communicates with the runtime that wraps it.

Three, the tool result goes back in as a user message with tool_result blocks. That shape is not arbitrary. It matches the Harmony-style transcript the model was post-trained on, so the model sees something that looks like its training distribution when it reads back the observation.

Four, this loop is identical, structurally, to a 2022 ReAct prompt. Same thought → action → observation → thought pattern. The API has just made every piece of it first-class.


Misconceptions

"Agents are a new kind of architecture." They're not. An agent is a control-flow pattern around an LLM. The model itself is the same transformer you've been reading about for eight arcs. What's new is the loop, the tool protocol, and the post-training recipes that make the model good inside that loop. If you hear "agent model architecture," it usually means one of two things: a tool-use post-training recipe, or a runtime. Both matter. Neither is a new architecture.

"ReAct is obsolete, we have function calling now." Function calling is ReAct's action token, plus a schema, plus constrained decoding. The loop is the same loop. A 2026 agent trace with structured tool calls is a ReAct trace in a prettier coat. Reading the ReAct paper is still the fastest way to build the mental model for what's going on inside a modern agent.

"Chain-of-thought is the same as reasoning models." They're related but distinct. Chain-of-thought is a prompting technique that was demonstrated to work on a pretrained model. Reasoning models (o1, the Claude thinking-block variants, DeepSeek-R1) are post-trained to produce long internal reasoning before their answer, often with RL against verifiable rewards. The inference-time picture looks similar (more tokens before the answer) but the training-time story is completely different. A chain-of-thought prompt is free; a reasoning model required real training budget. Don't conflate them.

"Agents will replace function calling / prompting / RAG." Agents are the outer loop that those things live inside. A modern coding agent uses retrieval to grab relevant code (RAG), runs tools with structured schemas (function calling), and sometimes even prompts itself with specific personas for sub-tasks. The layers don't compete; they stack.

What's next

I wanted this post to leave you with one handle: the loop is the invariant; everything else is substrate. When you hear about the next agent framework, the next coding agent, the next protocol, that's the question to ask. Which piece of the substrate did it upgrade? The model step? The action schema? The tool interface? The memory? Usually it's one of those four, and knowing which makes the rest easy to reason about.

The next post covers Function Calling as Structured Generation, how structured tool calls actually work under the hood, what constrained decoding is doing, and why the "tool schema" is doing more work than it looks.


Additional reading (and watching)