AI Engineering Playbook
Agents

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 checklist 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 on tasks whose shape you cannot enumerate at design time.

  1. Open-ended step graphs. "Summarize this ticket" is one call. "Investigate this production incident" might need logs, then a deploy history, then a config diff — or three of those in a different order. You cannot hardcode every branch without writing a brittle expert system.
  2. Grounding beats pure reasoning. Chain-of-thought alone invents plausible facts. Acting alone is myopic. Interleaving thought with tool observations is what keeps multi-step work honest.
  3. Feedback is available. Compilers, tests, APIs, and search return signals the model can use. When the environment talks back, a loop can recover; when it does not, the loop mostly wanders.
  4. APIs finally support the pattern. Native structured tool calling, models trained on multi-step trajectories, and large context windows made looped inference practical around 2023–2024 — not because the idea was new (ReAct is 2022), but because the stack stopped fighting it.

The alternative that still wins most of the time is a workflow: fixed paths, fixed cost, testable stages. Agents exist for the residual class of work where the path must be discovered at runtime and the environment can steer the model.

The core idea

An agent is an LLM running in a loop with tools, where the model decides its own control flow. You give it a goal, a set of tools, and an environment that returns feedback; the model chooses which tool to call next, observes the result, and keeps going until it decides the task is done or a stop condition fires. Anthropic's definition is the cleanest: workflows orchestrate LLMs through predefined code paths, while agents dynamically direct their own processes and tool usage. The distinguishing feature is not tools — a workflow can call tools — it's that the sequence of steps is chosen by the model at runtime, not by your code at design time.

The intellectual origin is ReAct (Yao et al., 2022): interleave reasoning traces with actions instead of doing either alone. Chain-of-thought reasoning alone hallucinates because it never touches ground truth; acting alone is myopic because the model never plans. Alternating thought → action → observation lets each ground the other. Modern tool-calling APIs internalized this pattern — you no longer prompt for Thought:/Action: text and parse it with regex; the model emits structured tool calls natively, and extended thinking covers the reasoning half.

Three things separate an agent from a chatbot: a chatbot's loop is human-driven (it acts only when the user sends a message), it typically has no tools or side effects, and it makes no autonomous decisions about next steps. And versus a workflow: a workflow's graph is fixed — same input class, same path — while an agent's trajectory varies per run, which is exactly what makes agents both powerful on open-ended tasks and harder to test.

How it actually works

One iteration of the loop, at the API level:

  1. Request — send: system prompt (role, constraints, stop criteria), tool definitions (name + description + JSON Schema per tool), and the message history so far.
  2. Model turn — the model either emits plain text (task done, or it needs user input) or one or more tool_use blocks: {id, name, input} with stop_reason: "tool_use".
  3. Executeyour runtime, not the model, runs the named function with the parsed arguments. The model only ever produces a structured request; all side effects happen in your code.
  4. Observe — append the output as a tool_result block (keyed by the tool call id) in a user-role message, and call the API again with the grown transcript.
  5. Terminate — loop exits when the model responds with text only, or your harness stops it: max-iteration cap, token/cost budget, timeout, or an explicit "done" tool.

Mechanistically the agent is stateless between iterations — the model has no memory beyond what you resend. The transcript is the state. This has two consequences: context grows every iteration (cost per step rises roughly linearly, so long runs need compaction), and you can checkpoint/replay an agent by persisting the message list.

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 that make that durable.

ReAct specifics worth knowing one level down: the paper (ICLR 2023) evaluated on HotpotQA and FEVER (knowledge tasks, Wikipedia API as the tool) and ALFWorld/WebShop (decision-making), showing ReAct beat both chain-of-thought-only (fewer hallucinations, because claims get checked against retrieved facts) and act-only baselines (better planning). Its failure mode was error propagation: a wrong early observation derails subsequent reasoning — the same compounding-error problem production agents still fight (agent reliability).

What makes a good agent beyond the loop: an environment with verifiable feedback (compiler errors, test results, API responses — signals the model can react to), tools designed for the model (clear descriptions, unambiguous parameters — tool calling), and a prompt that states when to stop. Anthropic's guidance: agents earn their cost only when the task is open-ended enough that you can't hardcode the path, and there's a feedback signal to steer by.

In the governed enterprise platform, agent mode is exactly this loop: the model may call internal tools over MCP, observations land as tool results, and write tools sit behind human approval. The loop is the same; the harness is where governance lives.

The flows

FlowSequenceWhen it appliesWhat breaks it
Happy pathGoal in → model plans → tool call(s) → observe → … → final textOpen-ended task with working tools and clear stop criteriaVague goal, overlapping tools, no success signal
Tool-error recoveryTool fails → error returned as tool_result → model retries, switches tool, or explainsRecoverable failures (bad args, rate limits, empty search)Unactionable errors ("failed"); harness with no retry cap
Parallel tool turnOne model turn emits N independent tool_use blocks → runtime runs them concurrently → all results in next messageIndependent reads (three lookups at once)Side-effect ordering; args that depend on another call's result
Harness stopCap trips (iterations, tokens, wall clock, no-progress) → graceful summary / escalateLong or looping runsOnly model-initiated stop; silent kill with no partial report
Human gate mid-loopModel requests a write tool → harness pauses → human approves/rejects → resume with same transcriptIrreversible or high-blast actionsPrompt-only "please ask first"; no durable pause state

A worked example

Consider the governed enterprise platform. An employee asks:

"Why is purchase order PO-99102 still pending approval, and who needs to act?"

Setup (illustrative): system prompt defines an internal ops assistant; tools include search_orders, get_approval_chain, lookup_user, and draft_nudge_email (write, gated). Typical first request: ~800–1 200 tokens of system + tool schemas, plus the user message.

StepActorWhat happensApprox. tokens in context
1ModelEmits search_orders({query: "PO-99102"})~1.5k
2RuntimeReturns status pending, amount, requester id+0.4k result
3ModelEmits get_approval_chain({po_id: "PO-99102"})~2.2k
4RuntimeReturns steps: L1 done, L2 waiting on user:mchen+0.5k
5ModelEmits lookup_user({id: "user:mchen"})~3k
6RuntimeReturns name, team, out-of-office until Monday+0.3k
7ModelFinal text: PO stuck at L2; owner OOO; suggests escalate or wait

End-to-end: 4 model turns, 3 tool round-trips, wall-clock often 15–40 s at 2–5 s per model turn plus tool latency. No write tool fired, so no human gate.

If the user then says "nudge them," the model may emit draft_nudge_email — the harness checkpoints and waits for approval before send. That is still the same agent loop; only the tool tier changed.

What omitted stages look like in production

  • No max-iteration cap — model retries search_orders with the same args forever after an empty result.
  • Error not returned as observation — runtime throws on 429; loop dies; user sees a blank failure instead of a corrected retry.
  • No transcript persistence — process restarts mid-run; work restarts from zero and may re-fire non-idempotent tools.
  • Tools without clear descriptions — model invents get_po_status (hallucinated name) or wrong field names; recovery only works if the harness returns instructive errors.
  • No cost budget — a confused 40-step run burns the monthly allowance for one power user.

Common drill-downs

These are the questions that naturally sit one level under the core idea — the ones a careful engineer asks before shipping a loop.

What's the difference between an agent and a workflow? Who owns control flow. Workflow: code decides the path at design time (LLM calls chained/routed by your logic). Agent: the model decides the next step at runtime based on observations. Anthropic's essay draws exactly this line, and most production "agentic" systems are actually workflows — deliberately, for predictability.

Explain ReAct in one minute. Yao et al., 2022: interleave reasoning and acting. Loop of thought ("I need X, so I'll search Y") → action (tool call) → observation (result), repeated until an answer. Reasoning grounds actions in a plan; observations ground reasoning in reality, cutting hallucination versus pure chain-of-thought. Modern tool-calling APIs are ReAct baked into the API contract.

Where does state live in an agent? In the message transcript — the model itself is stateless per call. You resend everything each iteration. That's why context management (compaction, summarization) and prompt caching matter, and why persisting the transcript gives you checkpointing for free.

Does the LLM execute the tools? No. The model emits a structured request (name + JSON args); your runtime executes it and returns the result as a message. All side effects, auth, and validation live in your code — which is also where you enforce permissions.

How do you stop an agent that won't finish? Layered stop conditions: model-initiated (final text answer or an explicit task_complete tool), and harness-enforced (max iterations, token/cost budget, wall-clock timeout, no-progress detection like identical repeated tool calls). Never rely on the model alone to terminate.

Why did agents only become practical around 2023–2024? Three capability jumps: native structured tool calling (no fragile text parsing), models actually trained on agentic/tool-use trajectories (following multi-step plans without derailing), and larger context windows (a 50-step transcript needs 100k+ tokens). Cost per token falling ~10x made looped inference economical.

How would you evaluate an agent? Outcome-based evals, not path-based: define tasks with verifiable success criteria, run each N times, report success rate, cost, latency, and step count. Add trajectory checks for specific behaviors (did it ask before deleting?). Single-run unit tests are meaningless under non-determinism.

Production concerns

  • Cost scales with iterations, superlinearly. Each turn resends the whole transcript, so an n-step run costs O(n²) in input tokens without caching. Prompt caching on the stable prefix (system prompt + tools + early history) is the single biggest lever — cached input is typically ~10x cheaper. Agents average ~4x the tokens of a chat interaction (Anthropic's measured figure). See cost.
  • Latency is a sum of model turns. A 10-step agent at 2–5 s per model turn plus tool execution is 30–60 s end to end. Mitigations: smaller/faster models for simple steps, parallel tool calls, streaming intermediate progress to the user so it feels alive. See latency.
  • Non-determinism breaks classical testing. Same input, different trajectory. You test agents with evals over many runs (task success rate, steps-to-completion, cost per task) rather than assertions on a single path. See evals and testing.
  • Compounding errors. 95% per-step reliability over 20 steps is ~36% end-to-end. Design for recovery (errors returned to the model as observations) rather than assuming step correctness — full catalog in agent-reliability.md.
  • Guardrails are mandatory: max iterations, cost ceilings, tool permission tiers, sandboxing for anything that executes code. An agent with a shell tool is remote code execution by design. See security.
  • Observability: log every iteration (prompt, tool call, result, tokens, latency) with a trace per run — debugging an agent without per-step traces is guesswork. See observability.

Test yourself

A product team says: 'We already have tools — so we have an agent.' How do you respond?

You log a 12-step agent run where step 3 returned a wrong but plausible order id, and every later step looked confident. What failed, and what would you change 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 might that be true even with identical harnesses?

When would you refuse to ship an agent and insist on a three-step workflow instead?

Go deeper

Where this connects

  • Tool calling — the wire format of every action in the loop: schemas, parallel calls, and error-as-result recovery.
  • Agents vs workflows — the decision framework for when not to hand the model control flow.
  • Agent reliability — loops, compounding error, HITL gates, and the arithmetic that makes long trajectories fragile.
  • The agent harness — the runtime this loop actually runs inside: context assembly, tool dispatch, compaction, sandbox, and the caps referenced throughout this page.
  • Orchestration — how graphs, checkpointing, and memory turn a while-loop into something you can pause, resume, and debug.
The Agent Harness

On this page