Agent Foundations
What an agent is, ReAct, and the anatomy of the agent loop.
Prerequisites
- How LLMs Work — the model only predicts tokens; the loop and tools live outside it.
- LLM APIs — chat messages, tool blocks, and multi-turn request shapes are the wire format of the loop.
- Structured Output — tool arguments are structured generation; constrained decoding is what makes them reliable.
The intuition
Think of a junior analyst with a phone and a list of systems they can call. You hand them a goal — "find why order 48291 is stuck" — not a script. They think ("I need the order status"), call the order API, read the result ("payment failed"), decide the next call (billing logs), and stop when they can write a useful answer. That is an agent: goal + tools + a loop where the model chooses the next step from what it just observed.
A chatbot is the same analyst waiting for your next email. A workflow is you writing their day as a flowchart beforehand — same tools, fixed path. The agent is powerful because the path is not fixed; it is fragile for the same reason.
Key insight
An agent is not "an LLM with tools." Tools can sit inside a fixed workflow. The defining move is that the model owns control flow at runtime — which tool, in what order, whether to stop — and the only memory between turns is the transcript you resend.
Why it exists
Single-shot prompts and fixed pipelines break when you cannot name the path at design time. "Summarize this ticket" is one call. "Investigate this production incident" might need logs, then a deploy history, then a config diff — or those same steps in another order. Hardcoding every branch becomes a brittle expert system. Agents exist for that residual class of work: the path must be discovered at runtime, and the environment can push back with real signals.
Pure chain-of-thought invents facts when it never touches ground truth; pure acting without a plan is myopic. Interleaving reasoning with observations keeps multi-step work honest. By roughly 2023–2024 the stack stopped fighting the idea — native structured tool calling, models trained on tool trajectories, and large context windows. ReAct (Yao et al., 2022) is older than that stack; what changed was the product surface, not the insight.
The alternative that still wins most of the time is a workflow: fixed paths, fixed cost, testable stages. Reach for an agent only when the path cannot be enumerated and the environment can steer the model.
The core idea
An agent is an LLM in a loop with tools, where the model decides control flow: next tool, whether to continue, when to stop. You supply the goal, the toolset, and an environment that returns feedback.
Anthropic's line is still the cleanest: workflows orchestrate LLMs and tools through predefined code paths; agents let the model dynamically direct its own process and tool use. The short form the field has largely settled on: an LLM agent runs tools in a loop to achieve a goal. Who picks the sequence at runtime is the distinction — not whether tools exist.
The intellectual origin is ReAct (Yao et al., ICLR 2023): interleave reasoning traces with
actions. Thought plans; action hits the world; observation grounds the next thought. That cut
hallucination versus pure chain-of-thought and improved planning versus act-only baselines. The
failure mode still bites: a wrong early observation derails later reasoning — silent error
propagation (agent reliability). Modern APIs internalized the pattern: the
model emits structured tool_use blocks; your runtime owns execution. No more regex-parsing
Thought: / Action: text.
How it actually works
One iteration at the API level (Claude's shape; OpenAI is equivalent under different field names):
- Request — system prompt, tool definitions (name + description + JSON Schema), message history.
- Model turn — plain text (
stop_reasonsuch asend_turn) or one or moretool_useblocks{id, name, input}withstop_reason: "tool_use". Multiple blocks mean independent concurrent calls. - Execute — your runtime runs the named function. The model only produces structured intent; every side effect lives in your code.
- Observe — append each output as a
tool_result(keyed by callid), including instructive errors. Resend the grown transcript. - Terminate — model answers in text, or the harness stops: max iterations, cost budget, timeout, or no-progress detection.
The loop is keyed on stop reason: while the model asks for tools, execute and continue. The model is stateless between iterations. The transcript is the state. Three consequences: context grows every step (cumulative input without caching is roughly quadratic in steps); you checkpoint by persisting messages; anything not written into the next request never happened for the model.
Key insight
The model never "remembers" the last tool result unless you put it back in the next request. Persistence, audit, and resume all reduce to owning the transcript — see orchestration for checkpointers and the agent harness for compaction, dispatch, and caps around this loop.
The loop earns its keep when the environment gives verifiable feedback and tools are designed for the model (tool calling). In the governed enterprise platform, agent mode is this loop over MCP tools, with write tools behind human approval — governance lives in the harness, not the model.
The flows
| Flow | Sequence | When it applies | What breaks it |
|---|---|---|---|
| Happy path | Goal → tool call(s) → observe → … → final text | Open-ended task, working tools, clear stop | Vague goal, overlapping tools, no success signal |
| Tool-error recovery | Fail → error as tool_result → retry, switch, or explain | Recoverable failures (bad args, 429, empty search) | Unactionable "failed"; no iteration cap |
| Parallel tool turn | N independent tool_use → concurrent execute → all results | Independent reads | Side-effect ordering; args that depend on another call |
| Harness stop | Cap trips → summary / escalate | Long or looping runs | Only model-initiated stop; silent kill |
| Human gate mid-loop | Write tool → pause → approve → resume same transcript | Irreversible or high-blast actions | Prompt-only "please ask first"; no durable pause |
A worked example
On the governed enterprise platform, an employee asks:
"Why is purchase order PO-99102 still pending approval, and who needs to act?"
Setup (illustrative): ops assistant; tools search_orders, get_approval_chain, lookup_user,
and draft_nudge_email (write, gated). First request often ~800–1 200 tokens of system + schemas.
| Step | Actor | What happens | Approx. context |
|---|---|---|---|
| 1 | Model | search_orders({query: "PO-99102"}) | ~1.5k |
| 2 | Runtime | pending, amount, requester id | +0.4k |
| 3 | Model | get_approval_chain({po_id: "PO-99102"}) | ~2.2k |
| 4 | Runtime | L1 done; L2 waiting on user:mchen | +0.5k |
| 5 | Model | lookup_user({id: "user:mchen"}) | ~3k |
| 6 | Runtime | name, team, OOO until Monday | +0.3k |
| 7 | Model | Final text: stuck at L2; owner OOO | — |
4 model turns, 3 tool round-trips, often 15–40 s. No write tool → no human gate. "Nudge them"
may emit draft_nudge_email; the harness checkpoints and waits for approval. Same loop; only the
tool tier changed.
What omitted stages look like in production
- No max-iteration cap — same empty
search_ordersforever. - Error not returned as observation — 429 throws; loop dies instead of recovering.
- No transcript persistence — restart mid-run re-fires non-idempotent tools.
- Vague tool descriptions — hallucinated names; recovery needs instructive harness errors.
- No cost budget — a 40-step wander can burn a power user's monthly allowance.
Production concerns
Cost grows with the transcript. Each turn resends history, so cumulative input without caching scales roughly as O(n²) in steps. Cache the stable prefix (system + tools + early history); new tool results still pay full price. Single-agent runs often land several times a one-shot chat's tokens (~4× appears as a multi-agent-paper baseline — order of magnitude, not a guarantee). See cost.
Latency is a sum of model turns. Ten steps at a few seconds each, plus tools, is tens of seconds. Parallel independent tool calls, a faster model for simple steps, and streaming for perceived progress matter more than micro-optimizing one call (latency).
Non-determinism kills path-based tests. Same input class, different trajectories. Use multi-run outcome metrics — success rate, steps, cost — plus targeted checks such as approval before write (evals and testing).
Errors compound. Design for recovery (errors as observations, verification after identity lookups) rather than hoping each step is correct — catalog in agent reliability. Coding agents often look more reliable on the same model because compilers and tests refute bad steps cheaply; soft enterprise APIs do not.
Guardrails and observability are product features. Max iterations, cost ceilings, permission tiers, and sandboxes are mandatory — shell tools are RCE by design (security). Log every iteration under one trace id (observability). Long runs need context engineering: compaction, notes outside the window, pruning stale tool results — the transcript is a finite attention budget, not a free dump.
Common drill-downs
Does the LLM execute the tools?
No. It emits structured intent; your runtime validates, authorizes, executes, and returns a
tool_result. Side effects and safety live there.
How do you stop an agent that will not finish?
Layer model-initiated stop (final text or a task_complete tool) with harness caps: max iterations,
token/cost budget, wall-clock timeout, no-progress detection (identical repeated calls). Never rely
on the model alone.
How would you evaluate an agent? Outcome-based evals over many runs: verifiable success, pass rate, cost, latency, step count. Add trajectory checks for must-not-skip behaviors. Single-run path assertions are not meaningful under non-determinism.
Test yourself
A product team says: 'We already have tools — so we have an agent.' How do you respond?
You log a 12-step run where step 3 returned a wrong but plausible order id, and every later step looked confident. What failed first?
Why is 'the transcript is the state' both a gift and a tax?
Coding agents often look more reliable than research or ops agents on the same model. Why?
When would you refuse to ship an agent and insist on a three-step workflow instead?
Go deeper
- Building effective agents — Anthropic — workflows vs agents; when agency is worth it.
- ReAct — Yao et al. — thought → action → observation.
- How tool use works — Claude docs —
stop_reason,tool_use,tool_resultloop. - Effective context engineering for AI agents — Anthropic — compaction, note-taking, long-run transcript management.
- Agents are models using tools in a loop — Simon Willison — the short definition the field has largely settled on.
- How We Build Effective Agents — Barry Zhang, Anthropic — when (not) to build agents.
Where this connects
- Tool calling — schemas, parallel calls, error-as-result recovery.
- Agents vs workflows — when not to hand the model control flow.
- Agent reliability — compounding error, HITL, fragile long trajectories.
- The agent harness — context assembly, dispatch, compaction, sandbox, caps.
- Orchestration — graphs, checkpointing, and memory around the while-loop.