The one test for what an agent is, and the loop every agent is made of.
Is it an agent?
- An agent lets the model decide the control flow (which step, when to stop) in a loop; a workflow hard-codes that control flow. If the path is fixed, it is a workflow, not an agent.
- Default to a workflow and reach for an agent only when the steps cannot be known in advance.
The agent loop
flowchart LR
A[Assemble context] --> C[Call model]
C --> P[Parse + stop_reason]
P --> AU{Authorize}
AU --> D[Dispatch tools]
D --> M[Manage context]
M --> A
style AU fill:#2d6a4f,color:#fff
- Assemble context → call model → parse response and read
stop_reason→ authorize → dispatch tools → manage context → repeat. stop_reasondrives the loop:tool_useruns tools and loops;end_turnmeans done but is weak evidence, so verify against the goal;max_tokensmeans the reply was truncated and must be handled.
The harness (code, not prompt)
Most agent quality lives here, because these cannot live in a prompt:
- Authorization is the one hard boundary — a prompt rule is advisory, and 1% non-compliance on a destructive action is unacceptable.
- Context assembly and order set the cache hit rate, a mechanical property.
- Retry policy, budget accounting, loop detection, and tracing all need state the model cannot see or reliably track.
- The loop guard attaches to authorize, so a repeated
(tool, args)is caught before you pay for the tool.
Stop conditions
- Always cap iterations and cost.
end_turnalone is not “done” — confirm the task is actually satisfied before ending.
Reactive vs proactive
- A trigger delivered at-least-once plus a non-idempotent agent produces duplicate side effects; make tool actions idempotent or dedupe them.
When not to build an agent
- Fixed, known steps mean a workflow. The common trap is a disguised workflow — a fixed pipeline described as an agent. Agents cost more tokens and add failure modes, so use one only for genuine open-ended control.