Agents and Tool UseThe shape of an agent

STOP 01 / 14~6 MIN

A loop, not a brain

One question separates an agent from a script, and most production systems should stay on the boring side of it.

The word "agent" has been stretched to cover a chatbot, a cron job and a research system in the same week. That is a problem for you specifically, because the label decides what you have to build around it.

The four moving parts

Take the label off and look at what is actually running. There are four things and no fifth.

  • A model. Stateless. It reads everything you send and produces tokens.
  • Tool definitions. A name, a description and a JSON Schema, sent in the tools array on every single request.
  • An executor. Your code. It reads the model's request, runs the real function, hands back the output.
  • A loop. Something that decides whether to go round again.

Nothing in that list runs itself. When the model wants a tool it emits a tool_use block — a tool name and a JSON object of arguments — and sets stop_reason to tool_use. That is a request, not a call. Your process executes it and returns the output as a tool_result block on the next request. The model never touches your database. Provider-hosted tools such as web search are the exception: those run on the provider's servers and the results are already in the response when it reaches you.

Here is the entire loop, with nothing hidden:

import anthropic

client = anthropic.Anthropic()
TOOLS = [...]          # your tool definitions - *Designing a tool a model can actually use* is about writing these
messages = [{"role": "user", "content": "How many open bugs are assigned to me?"}]

for step in range(10):                       # a step budget, not optimism
    resp = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=1024,
        tools=TOOLS,
        messages=messages,
    )
    messages.append({"role": "assistant", "content": resp.content})

    if resp.stop_reason != "tool_use":       # the model decided it is finished
        break

    results = []
    for block in resp.content:
        if block.type == "tool_use":
            results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": run_tool(block.name, block.input),   # your code, not the model's
            })
    messages.append({"role": "user", "content": results})
else:
    raise RuntimeError("step budget exhausted")  # the harness decided it is finished

Read the two comments on the terminations. One is the model saying it is done. One is you saying it is done whether or not the model agrees. Both belong in every real loop, and Planning a run, and knowing when to stop is about the awkward fact that only the second one is dependable.

That is the whole machine. No planner object, no state machine, no memory system. Those are things people bolt on afterwards, and each of them is worth understanding on its own — which is what the rest of this course is.

The one test

Anthropic's framing is the clearest one going, and it is a distinction about control rather than capability. A workflow is a system where models and tools are orchestrated through predefined code paths. An agent is one where the model directs its own process, deciding for itself how to accomplish the task.

WorkflowAgent
Picks the next stepYour codeThe model, every turn
Path through the systemDrawable before the runOnly knowable afterwards
Number of model callsKnownBounded at best
Cost of one runPredictableA range
When it goes wrongA branch you can point atA trace you have to read
How you fix itEdit the codeEdit descriptions and prompt, then re-run and hope

The test fits in one question. Before the run starts, can you draw the sequence of steps it will take? If yes, it is a workflow, whatever the design doc says.

A model making a decision does not make something an agent. Classifying a ticket and sending it down one of three branches is a decision, made by a model, inside a path you wrote. You enumerated the branches; the model picked an index. Adding an if on a model's answer is still your code choosing.

The middle ground is real and underrated: a fixed pipeline with one genuinely agentic step inside it. Five steps you control, and step three is a small loop with three tools and a budget of four calls. You keep the predictable outer shape, you keep the ability to point at the step that broke, and you pay for flexibility only in the one place that needs it. Most systems that work in production look like this rather than like either extreme.

Agent is not a compliment and not an architecture. It is the answer to one question: who picks the next step, your code or the model?

Most of what you want is a workflow

Before you give the model the wheel, check whether one of these covers you. All five are workflows. All five are in production somewhere doing work people are paying for.

PatternShapeReach for it when
Prompt chainingOutput of call one feeds call twoThe task splits into fixed stages
RoutingClassify, then send to one of N specialised promptsInputs fall into known categories
ParallelisationRun several calls at once, then combineSubtasks are independent, or you want a vote
Orchestrator–workersOne call breaks the task into subtasks, others do themThe subtask list varies, the moves do not
Evaluator–optimiserOne call produces, another critiques, repeatYou have a quality bar you can check

Look at orchestrator–workers, because that is the one people mislabel. A model decides how many subtasks there are and what each one says. It is still a workflow: the set of things that can happen is yours, the loop runs a known shape, and you can draw it. The model is filling in a form you designed, not choosing what form to fill in.

What you give up the moment the model picks the path:

  • A known step count. A run can take three steps or thirty on inputs that look the same to you.
  • A cost ceiling. Every step re-sends the whole growing transcript. Why the bill exploded is entirely about the bill this produces.
  • A latency ceiling. Each step is a full round trip, and they are serial by nature.
  • A reproducible failure. Two runs of the same input can fail in two different places.
  • Easy tests. You can assert on a branch. Asserting on a trajectory is a much harder problem.

An agent earns that when you genuinely cannot write the paths down in advance — when the number of steps depends on what gets found halfway through. A coding agent does not know how many files it needs to read until it has read some. A research task does not know its third query until it has seen the second result. That is the honest case, and it is narrower than the marketing suggests.

So: start with the simplest thing that works and let a real requirement push you up. Being blunt about it — a while loop around a chat completion with no tools is not an agent. It is a chat completion in a loop, and the loop is a bug waiting for a step budget.

Next: given a set of tools, how does the model actually pick one?

WHAT YOU TAKE AWAY

  1. Name the four moving parts: a model, tool definitions, your executor, a loop.
  2. Apply the one test — does your code pick the next step, or does the model?
  3. Recognise the five workflow patterns before reaching for an agent.
  4. Say out loud what you give up when the model picks the path.
  5. Default to a workflow, and let a real requirement push you off it.

RECALL NO SCROLLING BACK

00 / 05 answered

  1. QUESTION 01

    What separates an agent from a workflow?

  2. QUESTION 02

    In a loop over your own tools, what actually executes a tool call?

  3. QUESTION 03

    Your loop should exit when...

  4. QUESTION 04

    A pipeline that classifies a ticket, then sends it to one of three fixed prompts, is...

  5. QUESTION 05

    The honest cost of moving from a workflow to an agent is...