Vibe Engines
YouTube
AI System Design

Design an AI Agent

Learn AI system design by building an autonomous AI agent step by step.

The numbers to beatN toolsexposed to the model1 callper loop steptypedargs validated

The whole design, in writing

Learn AI system design by building an autonomous AI agent step by step. An interactive guide covering the plan-act-observe loop, tool calling with typed schemas, sandboxed execution, short- and long-term memory, error recovery and retries, and the cost/latency/safety controls that keep a multi-step agent from running away.

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

What makes it an "agent"?

A chatbot answers a question in one shot. An agent is handed a goal — "find the cheapest flight and book it" — and has to figure out the steps, take actions in the real world, react to what happens, and keep going until it’s done. How do you build something that acts, not just answers?

Usersets a goal
New in this step: User.

Wrap the model in a loop: ask it for the next action, run that action with real tools, feed the result back, and repeat. The model supplies the reasoning; the loop supplies the hands, the memory, and the brakes.

What the new pieces do

Userclient
A person who states a goal ("book me a flight under $400") rather than a single question.

Step 1 · The skeleton

A goal and a loop

The user gives a goal, not a question. A single model call can’t book a flight — it can only produce text. What structure turns "produce text" into "get something done"?

Usersets a goalAgent Loopplan · act · obs
New in this step: Agent Loop.

The user states a multi-step goal. What runs it?

  1. The model can’t check prices, call APIs, or run code on its own — it only emits tokens. Real tasks need actions between thoughts.

  2. The agent loop alternates thinking and doing: decide → act → observe → repeat, until the goal is met. This is the spine of every agent.

  3. A hardcoded script can’t adapt when a flight is sold out or a tool errors. The point of an agent is deciding the next step dynamically.

An Agent Loop (orchestrator) drives everything: it asks the model what to do next, executes that action, observes the result, and loops — until the model says the goal is complete. The model decides; the loop does.

What the new pieces do

Agent Loopbackend
The control loop. Calls the model to decide the next action, runs it, feeds the result back, and repeats until done.

Step 2 · Let it decide

The model picks the next action

Inside the loop, something has to choose what to do next — search? query a DB? finish? That judgment is exactly what the LLM is good at. But how does free-form text become a concrete, runnable action?

Agent Loopplan · act · obsLLM (Planner)decides actions
New in this step: LLM (Planner).

How does the agent turn the model’s reasoning into an actual action?

  1. Brittle and ambiguous — "I should probably search" isn’t a runnable call. You need structured output, not text mining.

  2. Powerful but dangerous and unbounded. You want the model to request specific tools, validated before they run — not a blank shell.

  3. The model outputs a function call — tool name and JSON arguments matching a schema — which the loop can validate and execute deterministically.

The LLM Planner is given the goal, the history so far, and the list of available tools (each with a typed schema). It responds with a structured tool call — a name and JSON arguments — or signals the task is done. Structured output is what makes the next step runnable.

  • N toolsexposed to the model
  • 1 callper loop step
  • typedargs validated

What the new pieces do

LLM (Planner)service
The reasoning model. Given the goal and history, it picks the next tool to call (or declares the task finished).

Step 3 · Give it hands

Execute tools — safely

The model asked to run a tool. But its arguments might be malformed, the tool might be dangerous (delete data, spend money), and it might hang. You can’t just blindly run whatever it emits. How do you execute safely?

Tool Executorsandbox + guardTools / APIssearch · code · db
New in this step: Tool Executor, Tools / APIs.

The model requests a tool call. How do you run it?

  1. The arguments may be invalid, the call destructive, or the tool may hang forever. Unchecked execution is how agents cause real damage.

  2. A Tool Executor checks the arguments, runs the tool in a sandbox with limits, and returns a structured result OR a structured error — both readable by the model.

  3. Approval matters for dangerous actions, but gating everything kills autonomy. Guard the risky calls (step 6); run the safe ones automatically.

A Tool Executor sits between the model and the world. It validates the requested arguments against the tool’s schema, runs the tool in a sandbox with a timeout, and returns a typed result — success or a structured error. The Tools/APIs are the agent’s hands: search, code, databases, third-party calls.

What the new pieces do

Tool Executorservice
Validates the model’s requested call against a schema, runs it in a sandbox with timeouts, and returns a typed result.
Tools / APIsservice
The agent’s hands: web search, code runner, database queries, third-party APIs — anything that touches the world.

Step 4 · Close the loop

Observe, then think again

The tool ran and returned something — a result, or an error. The model doesn’t know what happened yet. How does the outcome get back into its reasoning so it can decide the next move?

Agent LoopTool ExecutorTools / APIsTrace / Event Log
New in this step: Trace / Event Log. · swipe to pan the diagram

A tool returned a result (or failed). What happens next?

  1. If the agent ignores outcomes it can’t react — it’ll happily book a sold-out flight. The observation MUST feed the next decision.

  2. The result (or typed error) is appended to the agent’s history and handed back to the model, which reasons about it and picks the next action. That’s the "observe" in plan-act-observe.

  3. Blind infinite retries are exactly the death spiral guardrails exist to stop. Observe, adapt, and bound the attempts.

The observation — result or typed error — is appended to the run’s history and fed back to the model, which reasons over it and chooses the next action. Every loop iteration is also written to a Trace Log, so the whole chain of thought→action→result is replayable and debuggable.

What the new pieces do

Trace / Event Logbus
Records every thought, action and observation — for debugging, evals, cost tracking and replay.

Step 5 · Make it remember

Working memory vs long-term memory

Within one task the agent must remember what it has already tried. Across tasks, it’s wasteful to relearn the same facts every time. These are two different memory needs. How do you serve both?

Agent LoopTool ExecutorTools / APIsWorking MemoryLong-term Memory
New in this step: Working Memory, Long-term Memory. · swipe to pan the diagram

The agent needs to remember within a task AND across tasks. How?

  1. A long task overflows the context window, and nothing persists once the run ends. The prompt is working memory, not storage.

  2. That loses the reasoning the agent needs mid-task and the reusable knowledge it could recall later. You need both scopes, not just the output.

  3. A working-memory scratchpad holds the live task; a vector-backed long-term store lets the agent recall facts and past outcomes in future tasks.

Two memories. Working Memory is the scratchpad for the current run — goal, steps taken, observations — trimmed to fit the window. Long-term Memory is a vector store the agent can write durable facts and outcomes to and retrieve in later tasks (RAG, applied to the agent’s own experience).

What the new pieces do

Working Memorystore
The scratchpad for the current task: the goal, the steps taken so far, and their observations.
Long-term Memorystore
Vector-backed memory of facts and past outcomes the agent can recall in future tasks.

Step 6 · Don’t let it run away

Budgets, limits and approvals

A looping model can spin forever, rack up a huge bill, or take a destructive action. Autonomy without limits is a liability. How do you keep an agent on a leash without making it useless?

Agent LoopguardedBudget & Guardlimits · approval
New in this step: Budget & Guard.

What stops an agent from looping forever or doing something destructive?

  1. Models miscount steps, get stuck in loops, and underestimate consequences. Safety can’t depend on the thing you’re trying to constrain.

  2. Hard limits cap steps, tokens and cost; an approval gate pauses for human sign-off before destructive or expensive actions. Independent of the model’s judgment.

  3. Then it’s not an agent. The goal is bounded autonomy — let it loop, but inside guardrails that make runaway impossible.

A Budget & Guard layer wraps the loop: hard caps on steps, tokens and spend, plus approval gates that pause for human sign-off before destructive or costly actions (sending money, deleting data, emailing customers). Bounded autonomy — free to loop, impossible to run away.

What the new pieces do

Budget & Guardservice
Caps steps, tokens and spend; gates dangerous actions behind approval. The agent’s seatbelt.

Back of the envelope

max steps / run
hard stop on the loop — no infinite spinning
token + $ budget
cap spend per task; halt and report if exceeded
approval gate
human sign-off before irreversible/costly actions
allow-list tools
the agent can only call what you’ve granted

Step 7 · Finish cleanly

Done, or give up gracefully

Eventually the agent either achieves the goal or can’t. Both endings need to be deliberate — not "loop exhausted, returns garbage." How does a run actually end?

Usersets a goalAgent Loopguarded
New in this step: Agent Loop → User.

How should an agent run terminate?

  1. Dumping a half-finished buffer at the user is the worst ending. Termination should be a decision, not an accident.

  2. Some tasks are impossible (sold out, missing access). An agent that can’t admit defeat loops forever or lies. Graceful failure is a feature.

  3. The model signals completion with the final answer; if it’s blocked or hits a limit, the loop stops and reports what it tried and why it couldn’t finish.

A run ends two ways: the model emits a "task complete" with the final answer, or the agent hits a wall (blocked, out of budget, repeated failures) and stops cleanly — reporting what it attempted and why it couldn’t finish. Both are returned to the user deliberately. No silent garbage.

The payoff

You built an AI agent

From a one-shot chatbot to an autonomous agent: a plan-act-observe loop, structured tool calls, a guarded executor, two scopes of memory, full tracing, hard budgets, approval gates, and graceful endings.

UserAgent LoopLLM (Planner)Tool ExecutorTools / APIsWorking MemoryLong-term MemoryBudget & GuardTrace / Event Log
The finished design, end to end. · swipe to pan the diagram

Now break a tool and watch the agent hit an error mid-loop — and see why the executor’s typed errors, bounded retries and step budget are the difference between recovery and a runaway death spiral.

Everything you assembled, in order

  • Agent Loop — plan → act → observe → repeat until done
  • Tool calling — model emits typed, schema-checked function calls
  • Tool Executor — the airlock: validate, sandbox, timeout, typed result
  • Observe + Trace — feed results back; log every step for debug/eval
  • Two memories — working (this run) + long-term (across runs)
  • Budget & Guard — step/token/$ caps + approval on risky actions
  • Graceful end — "done", or stop cleanly and report when blocked
  • Error handling — typed errors + bounded retries beat death spirals

Deep cut · 25:41

It said booked. Nobody booked it.

The interactive build above lays out an AI agent: a plan-act-observe loop around the model, structured tool calls checked against a schema, one tool executor that validates, times out and returns a typed result or a typed error, every observation fed back, a trace of every step, working and long-term memory, and a budget, a step limit and an approval gate around it all. The film builds the same agent one fix at a time in a made-up travel app’s courtyard, then replays one Friday night lap by lap to find why an agent that read every result announced a booking nobody made.

  • See the wreck: the booking call timed out on a swamped airline, and the executor sent back whatever the airline had said — nothing — in the same envelope as a success. The model read a success after “book”, filled the gap with the flight, seat and price it already knew, and said done; the loop delivered it, because the model decides when it is done. Every brake held.
  • Take it into the interview: a timeout is an error, not an empty result, and for a write it means unknown — look before you retry; “done” is checked by the loop against ground truth from the world (a confirmation code), not trusted from the model.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. Why does the tool schema validation happen in the Tool Executor rather than just trusting the model to always emit well-formed arguments?

    Models are probabilistic text generators — even a well-trained one occasionally emits an argument of the wrong type, a missing required field, or a value outside a valid range, especially deep into a long agent run where context has accumulated and drifted. Validating against the schema BEFORE execution catches these malformed calls deterministically and returns a clear, typed error the model can actually reason about and correct — rather than either crashing on bad input or, worse, silently executing a tool with subtly wrong arguments that produces a plausible-looking but incorrect result.

  2. Why maintain two separate memory scopes (working memory and long-term memory) instead of just always writing everything to the long-term vector store?

    Working memory's value is being complete and immediately available for THIS run — every step and observation, in order, without needing a retrieval step, because reasoning about what just happened benefits from having it directly in context. Long-term memory's value is being selective and durable ACROSS runs — only facts and outcomes worth remembering later, retrieved by relevance rather than recency. Writing everything indiscriminately to long-term memory would flood it with run-specific noise (intermediate tool outputs, abandoned approaches) that pollutes future retrieval — the two scopes serve genuinely different purposes and mixing them degrades both.

  3. Could the step/token/cost budget alone (without a separate approval gate) sufficiently protect against a destructive action?

    No — a budget caps HOW MUCH the agent can do, but says nothing about WHETHER a specific action, even well within budget, should be allowed to happen without oversight. An agent could delete a customer's account or send a large payment in a single, cheap, fast tool call that consumes almost none of its budget — the action is destructive because of what it DOES, not because of how expensive it was to attempt. This is why approval gates are a separate mechanism scoped to action CONSEQUENCE, layered on top of budgets that are scoped to resource CONSUMPTION — the same two-axis distinction (how much vs. how risky) that shows up in several other agent designs in this series.

  4. Why does the agent write a trace of "thoughts" (the model's reasoning), not just the actions it took and their results?

    When an agent produces a wrong or surprising final outcome, the actions and results alone often don't explain WHY it chose that path — two runs could take the exact same sequence of tool calls for completely different (one sound, one flawed) reasons. Capturing the model's stated reasoning at each step lets a developer debugging a bad run see not just what happened but what the model THOUGHT was happening, which is usually where the actual bug or misunderstanding lived — a wrong action is often the symptom, and the reasoning trace is what reveals the actual cause.

  5. How would this design need to change to support multiple agents collaborating on one goal, rather than a single agent looping alone?

    The core loop (plan → act → observe) stays the same for each individual agent, but a multi-agent version needs an additional coordination layer above the single-agent orchestrator — deciding how sub-goals are divided, how one agent's output becomes another's input, and how the shared budget and approval gate apply across ALL the agents combined rather than just one. This is a genuinely different system design problem (see Multi-Agent Orchestration for the coordination-specific concerns) — this design is intentionally scoped to what one agent, alone, needs to act safely and effectively, which is itself a prerequisite for getting multi-agent coordination right.

Check yourself — the answers, and why

Eight steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. What turns a chatbot into an agent?

    • A bigger model
    • A loop that takes actions and reacts to their results
    • A longer context window

    Agents alternate thinking and doing — the plan-act-observe loop, with real tools — rather than answering in one shot.

  2. Why does the model emit a structured tool call instead of prose?

    • It’s shorter
    • So the loop can validate and execute it deterministically
    • To save tokens

    A typed tool name + JSON arguments can be schema-checked and run; free-form prose can’t be executed reliably.

  3. The Tool Executor exists mainly to…

    • Speed up tools
    • Be the one guarded boundary where calls are validated, sandboxed and timed out
    • Pick which tool to use

    Centralizing execution gives you one place to validate arguments, sandbox, time out, and return typed results/errors.

  4. Budgets and approval gates provide…

    • Faster answers
    • Bounded autonomy — freedom to loop without running away
    • Better reasoning

    Step/token/$ caps stop runaway loops; approval gates put a human in front of irreversible actions.

  5. The agent's trace log records the model's reasoning, not just its actions and results, because…

    • It makes the UI look more detailed
    • A wrong final outcome is often explained by flawed reasoning, which the actions and results alone don't reveal
    • It's required for billing

    Debugging a bad run needs to see WHY the model chose a path, not just what it did — the reasoning is usually where the actual cause lived.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Take a goal: accept a multi-step goal, not a single question, and figure out the steps.
  • Decide + act: the model emits a structured tool call; the loop runs it and feeds back the result.
  • Execute safely: validate arguments against a schema, run tools sandboxed with a timeout.
  • Remember: working memory for this run, long-term memory across runs.
  • End deliberately: finish with a "done", or stop cleanly and report when blocked.

The qualities that shape everything

Each one names the mechanism that buys it.

Handle tasks no single call could
An Agent Loop (orchestrator) plans, acts, observes and repeats until the model says the goal is met.
Turn reasoning into runnable actions
The model emits a structured tool call (name + typed args matching a schema) the loop can validate and execute deterministically.
Run tools without causing real damage
A Tool Executor validates arguments against a schema, sandboxes with a timeout, and returns a typed result or a typed error.
Debug a non-deterministic, multi-step run
Every thought/action/observation is written to a Trace Log, so the whole chain is replayable and auditable.
Remember within a task and across tasks
Working memory for the current run plus a vector long-term store the agent recalls in future tasks.
Free to loop, impossible to run away
A Budget & Guard layer caps steps/tokens/spend and gates destructive actions behind human approval.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

A loop that acts over one big model call

The model only emits tokens — it can’t check prices, call APIs, or run code. Real tasks need actions between thoughts, decided dynamically.

A structured tool call over parsing the model’s prose

Free-form text isn’t runnable and regex intent-mining is brittle. A typed name + JSON args can be schema-checked and executed deterministically.

Validate, sandbox, timeout over executing exactly what the model emitted

The arguments may be malformed, the call destructive, or the tool may hang. One guarded airlock is where limits, logging and safety live.

Two memory scopes over keeping everything in the prompt

A long task overflows the window and nothing persists once the run ends. Working memory holds this run; long-term memory carries knowledge across runs.

Budgets + approval gates over trusting the model to stop

Models miscount steps, get stuck in loops, and underestimate consequences. Safety can’t depend on the thing you’re trying to constrain.

The answer, out loud

What a strong answer to “Design an AI Agent System” sounds like, first question to last trade-off. It is about 7 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0–3 min

    Pin down what makes it an agent

    Before I draw anything, I want to agree on what we’re building. A chatbot answers one question in one shot. An agent is handed a goal — “book me a flight under $400” — and has to work out the steps, act in the world, react to what happens and keep going until it’s done. What the user feels is whether the task got done, and if it couldn’t be, an honest account of why. So the real question is: how do we let a model act on its own, over many steps, without it doing damage or running forever?

  2. 3–8 min

    The skeleton is a loop

    The skeleton is the user and an agent loop, or orchestrator. It asks the model for the next action, runs it, feeds the result back and repeats until the model says the goal is met: plan, act, observe. Not one big model call — a model only emits tokens; it can’t check a price or call an API. Not a fixed script either — a script can’t adapt when the flight is sold out or a tool errors. The cost: one task becomes many model calls, so I’ll need brakes later.

    Built in step 1: A goal and a loop
  3. 8–14 min

    Turn reasoning into a runnable action

    Inside the loop, the model plans. It gets the goal, the history so far and the tools it may use, each described as a typed function with a schema — a declared shape for its arguments. It answers with a structured tool call: a tool name plus JSON arguments, or a signal that it’s finished. Parsing its prose with regexes is brittle — “I should probably search” isn’t a runnable call — and letting it run arbitrary code is unbounded. A typed call is a checkable decision: which function, with what arguments.

    Built in step 2: The model picks the next action
  4. 14–20 min

    One guarded airlock for every action

    Between the model and the world — search, code, databases, APIs — sits a tool executor. I won’t run exactly what the model emitted: the arguments may be malformed, the call destructive, the tool may hang. The executor validates arguments against the schema, runs the tool in a sandbox — an isolated environment — with a timeout, and returns a typed result or a typed error the model can read. Even a good model occasionally emits a wrong type, especially deep into a long run. Nor does a human approve every call; that kills autonomy. One boundary means limits, logging and safety live in one place.

    Built in step 3: Execute tools — safely
  5. 20–25 min

    Close the loop, and trace everything

    The observation — result or typed error — goes into the run’s history and back to the model, which picks the next move. Assume each call worked and the agent books a sold-out flight; retry the same call forever and it’s a death spiral. Every iteration also goes to a trace log: every thought, action and observation. I log the reasoning because two runs can make identical calls for different reasons, one sound and one flawed. Agents are non-deterministic and multi-step, so the trace is how I debug, evaluate and bill.

    Built in step 4: Observe, then think again
  6. 25–31 min

    Two kinds of memory

    Memory has two scopes. Working memory is this run’s scratchpad — goal, steps, results — trimmed to fit the context window, the text the model can read at once. Long-term memory is a vector store, a database that looks things up by similarity of meaning, holding durable facts and past outcomes the agent retrieves in later tasks. Everything in the prompt overflows on a long task and vanishes when the run ends. Everything in long-term memory floods future retrieval with noise like abandoned approaches. The cost is deciding what’s worth keeping.

    Built in step 5: Working memory vs long-term memory
  7. 31–38 min

    Brakes, and a deliberate ending

    I can’t trust the model to stop — models miscount steps, get stuck in loops and underestimate consequences. So a budget-and-guard layer wraps the loop: hard caps on steps, tokens and spend, an allow-list of tools, and approval gates that pause for a human before irreversible actions like sending money or deleting data. Those are two axes: a budget limits how much the agent does, but one cheap call can still delete an account. And a run ends on purpose — “done” with the answer, or a clean stop when blocked or out of budget, reporting what it tried and why it couldn’t finish.

    Built in step 6: Budgets, limits and approvals
  8. 38–42 min

    What I’d watch, and how it fails

    On the dashboard, from the trace: steps, tokens and spend per run, tool errors, runs that end blocked rather than done, and actions waiting on approval. Two failures I’d plan for. A tool starts failing: the executor returns a typed error, retries are bounded and spaced further apart each time, the step budget backstops them, and the agent tries another path or stops cleanly and tells the user. Or the agent decides a destructive action is reasonable: the guard holds it for sign-off, however confident the reasoning looked. It can plan a risky action; it can’t take one alone.

  9. 42–45 min

    Close on the trade-off

    To close, in one breath: a plan-act-observe loop, typed tool calls, one guarded executor, a trace of every step, two scopes of memory, budgets with approval gates, and a deliberate ending. Every knob trades freedom against control — too loose and it runs away, too tight and it’s useless. With more time I’d go to several agents on one goal, which needs a coordination layer above this loop and one shared budget and approval gate.

What this teaches

Learn AI system design by building an autonomous AI agent step by step. An interactive guide covering the plan-act-observe loop, tool calling with typed schemas, sandboxed execution, short- and long-term memory, error recovery and retries, and the cost/latency/safety controls that keep a multi-step agent from running away.

Key takeaways

  • Agent Loop — plan → act → observe → repeat until done
  • Tool calling — model emits typed, schema-checked function calls
  • Tool Executor — the airlock: validate, sandbox, timeout, typed result
  • Observe + Trace — feed results back; log every step for debug/eval
  • Two memories — working (this run) + long-term (across runs)
  • Budget & Guard — step/token/$ caps + approval on risky actions
  • Graceful end — "done", or stop cleanly and report when blocked
  • Error handling — typed errors + bounded retries beat death spirals

Concepts covered

  • What makes it an "agent"?
  • A goal and a loop
  • The model picks the next action
  • Execute tools — safely
  • Observe, then think again
  • Working memory vs long-term memory
  • Budgets, limits and approvals
  • Done, or give up gracefully
built to be reasoned about, not memorized — make the calls, break a tool, run the quiz.
Finished this one? 0 / 61 AI System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More AI System Designs