The agent loop

How an agent differs from a chatbot: a goal, a loop, tools, and a stopping condition — plus the failure modes of each.

Chatbot versus agent

A chatbot maps one message to one reply. An agent is given a goal and runs a loop: decide the next action, take it, look at the result, repeat until the goal is met or a limit is hit. The model is still the decision-maker; the loop and the tools are what you build.

goal ──▶ [ think ] ──▶ [ act: tool call ] ──▶ [ observe result ]
            ▲                                          │
            └────────────── not done yet ◀─────────────┘
                             │
                        done / limit → final answer
PieceYour responsibility
GoalWritten unambiguously, with the definition of done
PlannerPrompt + model choice; usually the least reliable part
ToolsReal functions with validated inputs and clear errors
Loop controlMax steps, timeouts, budget
TerminationHow you decide it is finished — and how you fail safely
💡
The single most valuable design decision is a crisp definition of "done". Agents without one do not stop; they wander until a step limit kills them.

A minimal loop you can reason about

def run_agent(goal, tools, max_steps=8):
    messages = [{"role": "user", "content": goal}]

    for step in range(max_steps):
        reply = model(messages, tools=tools)      # model may request a tool

        if reply.tool_calls:
            for call in reply.tool_calls:
                try:
                    result = tools[call.name](**call.args)
                except Exception as e:            # give failures back to the model
                    result = {"error": str(e)}
                messages.append(tool_result(call.id, result))
            continue                              # let the model see the result

        return reply.content                      # no tool call = it is answering

    return "Stopped: step limit reached without a final answer."
  • Always cap the loop. Steps, wall-clock time and tokens — all three.
  • Feed tool errors back as data. A well-described error often lets the model self-correct; a raised exception just ends the run.
  • Log every step with its inputs and outputs. Without a trace, an agent failure is unfixable.
  • Make tools idempotent where possible so a retry after a timeout cannot double-charge or double-send.

How agents fail

FailureSymptomMitigation
LoopingSame call repeatedDetect repeats, cap steps, vary the prompt
Tool misuseWrong argumentsValidate inputs; return precise errors
Over-broad actionDeletes or sends too muchDry-run mode, scoped credentials, confirmation
Hallucinated successClaims done, nothing happenedVerify with a real check, then report
Context overflowForgets the goalSummarise history, keep the goal pinned
⚠️
Give an agent the narrowest credentials that can do the job. An agent with production write access and a hallucination is an outage waiting for a trigger.

FAQ

Do I need a framework?
No. A loop, a tool dispatcher and a prompt are ~100 lines and you will understand every failure. Frameworks help when you need tracing, retries and many integrations — bring them in once the manual version works.
How many tools should one agent have?
As few as possible, with distinct names and descriptions. Ten overlapping tools confuse the model more than they extend it.

Tools and function calling Using a model API

Last refreshed 2026-09-18.