What an AI agent actually is
Tool calling is a small mechanism you can write in forty lines. Every hard problem left over is a stop condition, a state model or a permission, and none of them is something the model will handle for you.

Kingsley Ijomah
Founder, Codehance
Almost every team I work with arrives at the same place. They have shipped something that produces text, it works well enough that people use it, and now somebody wants it to do a thing rather than describe one. Book the slot, update the record, open the pull request. That request sounds like a small extension of what already exists, and it is not. It is the point where the software stops writing and starts acting, and where a wrong answer stops being embarrassing and starts being expensive.
The word for what they are about to build is agent. It is used so loosely that plenty of experienced engineers have quietly decided it means nothing, a fair response to the marketing and a poor one to the engineering. The mechanism underneath is real, and small enough to read in a page.
This is the orchestration slot from the map at the start of this category. Mechanism first, because once you have seen how little there is to the loop, your attention is free for the part that decides whether this goes well: what you allow the thing to do.
The loop is about forty lines
Start with the piece that makes any of this possible, which is called tool calling.
You send the model your conversation as usual, and alongside it a list of function descriptions: a name, a sentence about what the function does, and a schema for its arguments. The model can then reply with something other than prose. It can reply with a structured request that says, in effect, call create_booking with these arguments. The model cannot call anything. It emits a request, and your code decides what to do with it.
That is the entire authority model, and almost nobody says it out loud. The decision to execute is a line in your own codebase, running under credentials you chose.
An agent is that exchange in a loop. The model asks for a tool, your code runs it, the result goes back into the conversation, and the model gets another turn with the new information in front of it. It keeps going until it stops asking, or until you stop it.
messages = [{"role": "user", "content": task}]
for step in range(MAX_STEPS):
reply = model.respond(messages=messages, tools=TOOL_SCHEMAS)
messages.append(reply)
calls = [b for b in reply.content if b.type == "tool_use"]
if not calls:
return reply # it stopped asking. done.
results = []
for call in calls:
if call.name not in ALLOWED: # your code decides
results.append(refuse(call, "not permitted"))
elif call.name in NEEDS_APPROVAL and not ask_human(call):
results.append(refuse(call, "declined by operator"))
else:
try:
results.append(run(call.name, call.input))
except Exception as e:
results.append(refuse(call, f"failed: {e}")) # tell it, don't crash
messages.append({"role": "user", "content": results})
raise StepLimitExceeded(step) # the loop needs a floor
That is it. Two independent sources have sized the same thing and landed in the same place. Zep, writing in June 2026, put a production-shaped loop at roughly forty lines of Go given goroutines, context cancellation and an official SDK, while conceding that third-party support outside Python and TypeScript is thin. Hugging Face made the same point from the other end when they released smolagents in December 2024, whose pitch was that the logic for agents fits in about a thousand lines of Python. Different languages, different agendas, same order of magnitude.
Two lines in there carry more weight than they look like they do. The ALLOWED list is a permission model, and I have seen it left as an empty check in shipped code. The tool descriptions are documentation, read by the only consumer that cannot ask a follow-up question, and vague ones cause more misbehaviour than anything else I encounter. Consolidated tools beat granular ones, real words beat cryptic identifiers, and an error that says what to do next beats a stack trace. Ordinary API design for an unusually literal reader, and it deserves its own article.
Once the loop is this small the framework question changes shape. You are not deciding whether to buy the loop. You are deciding who maintains the parts around it. The four vendor SDKs, OpenAI's Agents SDK, the Claude Agent SDK, Google's ADK and AWS Strands, are each a model provider's own harness for its own model, used internally before it was offered to anyone else. A structural argument rather than a popularity one: the risk is API churn and renaming, not the thing vanishing while you ship on it.
Most of what you want is a workflow
Anthropic drew the distinction the field then adopted, and the exact wording carries the argument. Workflows are "systems where LLMs and tools are orchestrated through predefined code paths". Agents are "systems where LLMs dynamically direct their own processes and tool usage." The difference is who chooses what happens next.
The five workflow patterns they set out are prompt chaining, routing, parallelisation, orchestrator-workers and evaluator-optimiser. Read those again as a backend engineer rather than as an AI person. They are a pipeline, a switch statement, a fan-out, a fan-out with a coordinator, and a retry loop with a checker. Ordinary control flow, with a model in one slot of it. A model lab publishing that list is the strongest support available for the idea that most of this work is software engineering, and their advice on the same page is to find the simplest thing that works and add complexity only when something forces you to.
The field is behaving accordingly, on numbers that come with a caveat because they are self-selected. Stack Overflow's pulse survey, fielded to about 1,100 people in late April 2026, found agent usage had nearly doubled year on year, from 31% to 59%. Among those users, 69% run a single agent rather than a coordinated crew, 63% rarely or never let one run entirely unsupervised, and 60% block agents from making unapproved system changes. A profession adopting the thing quickly and keeping a hand on it.
The default should be a workflow, and the burden of proof should sit with the agent. You reach for a loop when you genuinely cannot enumerate the steps in advance, which is rarer than the demos suggest.
Nothing stops it, and nothing remembers
The trouble is not in the loop.
Nothing inside the model enforces a stopping condition. It does not know it has been running for forty minutes, it has no view of your bill, and its sense of having finished comes from the same process that produces everything else it says. Every limit is yours to impose: a step cap, a wall-clock timeout, a token budget, and a spend ceiling.
Then there is error that accumulates. Chip Huyen puts it as arithmetic rather than measurement, and that is what it is: at 95% accuracy per step, ten steps comes out around 60%, because 0.95 to the tenth is 0.60. Nothing was measured to produce that number. The shape of it is still enough to change how you design.
The failure she describes next matters more, and it is the one I put in front of anyone about to ship. An agent assigns forty of fifty people to rooms and reports that it has finished. The run does not fail. It succeeds, incorrectly, and tells you so in the same tone it would use if it had been right. A crash you will find. A confident partial completion travels downstream and is found by a person, usually one of the ten who has no room.
Now state, which is the part that turns an interesting prototype into an infrastructure project. Anthropic, writing about their own multi-agent research system, put the problem cleanly: agents "can run for long periods of time, maintaining state across many tool calls. This means we need to durably execute code and handle errors along the way," and "without effective mitigations, minor system failures can be catastrophic for agents." Their answer was systems that resume from where the agent was when the error hit, plus rainbow deployments so that shipping code does not kill runs already in flight. Cognition reported the same wall from a different angle in April 2026: containers "cannot survive the async gaps that define most real engineering work", so they snapshot memory, process trees and filesystem at the hypervisor level instead.
Look at what those two are describing. A process that runs for an hour, holds real state, has to survive your deploy, and cannot be retried from the top because half its steps have already touched the outside world. That is a distributed systems problem and has been one for decades, and it is the actual reason to reach for a framework. LangGraph's checkpointers exist to give you conversation continuity, human-in-the-loop pauses, time travel and fault tolerance. Temporal predates all of this by years, and OpenAI publicly credits it as a critical part of the infrastructure powering Codex, responsible for executing their core control flows.
Anything it reads can instruct it
A team can wire a database tool to an agent on a Tuesday and leak a table by Thursday, which is why this belongs at the on-ramp. The documented cases involve shipped enterprise products, not toy demos.
The model has no separate channel for instructions and data. Your system prompt, the user's message, the support ticket it just read, the web page it fetched, the PDF a customer uploaded, the comment in a file it opened: all of it arrives as one stream of text, and any of it can carry a sentence addressed to the model. Nothing marks which parts are trusted. Engineers reach for the parameterised query as the analogy, and it misleads them, because the entire defence in the SQL case is a separation this system does not have.
Simon Willison named the dangerous combination in June 2025, and the field adopted the name because it makes the decision easy. He calls it the lethal trifecta: access to private data, exposure to untrusted content, and the ability to communicate outward. Any two of those are usually survivable. All three together means an attacker who can get text in front of your agent can get your data out. His own summary of the state of the art is worth carrying around: we still do not know how to prevent this reliably.
EchoLeak, CVE-2025-32711, was disclosed against Microsoft 365 Copilot in June 2025, rated 9.3, and patched server-side with no exploitation observed in the wild. A single crafted email, no user interaction. It got past a classifier built specifically to catch cross-prompt injection. It got around link redaction by using reference-style Markdown. It used an auto-fetched image to move data outward, and it routed through a permitted proxy to satisfy the content security policy. Four defences, chained through, by an email. Every layer that failed was a filter. The layer that would have held was a permission.
The second is closer to what a small team would actually build. General Analysis showed an agent being asked to work through a support queue, where one ticket contained instructions telling the model to read the integration_tokens table and post the contents back into the ticket as a reply. The agent did. The interesting part is not the injection, it is the credential: the MCP server was running with Supabase's service_role, which bypasses row-level security entirely. The database had correct access rules. The connector was standing outside them.
Supabase's guidance has moved on since. Their current documentation opens by warning that connecting a model to your projects carries security risks, and every recommendation under it is a permission rather than a filter: do not connect to production, use read-only mode if you must touch real data, scope the server to a single project, restrict which tool groups are exposed, and keep manual approval of tool calls switched on. Read-only alone would have broken this attack, because the exfiltration needed a write, and it is still not the whole answer because a different path would not have needed one.
The design rules are least privilege, applied to a component that follows instructions found in its input. Read-only by default, with write access as a deliberate exception per tool. A separate, narrowly scoped credential per tool rather than one powerful connection shared by all of them. A confirmation gate in front of anything irreversible or outbound. Allowlists rather than denylists, because you can enumerate what you want and cannot enumerate what an attacker will try. And model output treated as untrusted input by whatever consumes it next, including your own rendering layer.
One consequence: be sceptical of any product advertising that it blocks 95% of attacks. Willison's line on this is right. In web application security 95% is a failing grade, and an attacker who can retry does not care about your other 95%.
Publishing an MCP server is an OAuth problem
The Model Context Protocol is the standard way to expose a set of tools to any model client. You have probably installed one by pasting a block of JSON into a config file. That is configuration, and this site treats it as Layer 1.
Publishing one is a different job entirely. In the current specification, revision 2026-07-28, a protected MCP server "acts as an OAuth 2.1 resource server". It MUST implement OAuth 2.0 Protected Resource Metadata, RFC 9728. Clients MUST implement Resource Indicators, RFC 8707, so that a token names the server it is meant for. The server MUST validate that access tokens were issued specifically for it as the intended audience, and it MUST NOT accept or transit any other tokens, which is the defence against being turned into a confused deputy that passes a borrowed credential along. Add PKCE, issuer validation under RFC 9207, discovery under RFC 8414 or OpenID Connect, and a step-up flow for requesting extra scopes at runtime.
That gap, between pasting JSON and standing up a resource server, is a fair description of what this whole category costs.
Learn the resource-server problem rather than the revision. The wire format churns hard: the July 2026 revision removed protocol-level sessions, removed the initialisation handshake so MCP is now stateless, and deprecated Roots, Sampling and Logging outright. Anything I told you about message shapes would have a short life. The authorisation model is the part converging, and it is converging on standards older than any of this.
The one habit that does not carry over from the rest of your career is the assumption that a component only ever does what you wrote it to do.
See it for yourself
You almost certainly have an MCP server configured already, from Layer 1. Open the config file and read it as a security review rather than as a settings screen.
Take each server in turn and write down three things. What credential is it holding, and what can that credential reach if every check above it fails? Can it write, or only read? And where can data it touches end up: a file, a reply, a request to a host you do not control?
Then run the trifecta over the whole set together, not server by server, because the model sees them as one toolbox. Does the combination give it private data, untrusted content, and a way outward?
Most people find one of two things. Either a credential is broader than the job needs, usually because the setup instructions offered a single powerful key and no narrower option, or the third leg arrives from a server they added for something unrelated. The dangerous configuration is rarely one careless install. It is the accumulation, and nothing in your tooling shows it to you as a set.
Ten minutes. Bring the list to whoever owns the credentials.
Sources
Linked so you can check them, with the weak ones labelled as weak.
- Anthropic, Building effective agents, 19 December 2024. The workflow and agent definitions quoted verbatim, the five workflow patterns, and the advice to start with the simplest thing. Vendor engineering writing, but the definitions have been adopted field-wide. Note the framework list on that page has been edited since publication; the definitions have not.
- Zep, Building Agents in Go Without a Framework, 18 June 2026, and Hugging Face, smolagents, 31 December 2024. The "~40 lines of Go" and "~1,000 lines of code" figures. Both are vendor or practitioner posts sizing their own work, which is why the pair matters more than either alone. smolagents' internal "30% fewer steps" benchmark is unaudited and is not used here.
- Stack Overflow, 2025 Developer Survey (n=49,009) and Agents on a leash, 27 May 2026 (n=1,100, fielded late April 2026). The 10% and 52% are 2025 figures. The 31% to 59%, 69%, 63% and 60% figures are from the pulse survey. Both are self-selected samples of Stack Overflow's own audience, so read them as direction rather than measurement. The 2026 annual survey had not published results when I checked on 1 September 2026.
- Chip Huyen, Agents, 7 January 2025. The 95%-per-step to 60%-over-ten-steps figure is illustrative arithmetic, not a measurement of any system, and I have presented it as such. The room-assignment failure is the more valuable half.
- Anthropic, How we built our multi-agent research system, 13 June 2025, and Cognition, What We Learned Building Cloud Agents, 23 April 2026. Used for the durable-execution problem statement only. Anthropic's 90.2% multi-agent performance figure from the same post is an internal unpublished evaluation on roughly twenty queries and is not cited here as a benchmark.
- Temporal, customer engineering post, 17 May 2025, quoting Will Wang, Software Engineer on Codex at OpenAI. Vendor testimonial, but a named engineer on a named product. The scale figures attached to it are Temporal's own characterisation and are unverified.
- Simon Willison, The lethal trifecta for AI agents, 16 June 2025. The three-condition framing and the line about 95% being a failing grade. This is a framing the field adopted, not a measurement, and the coinage is his.
- Reddy and Gujral, EchoLeak, arXiv:2509.10540, on CVE-2025-32711, disclosed by Aim Security against Microsoft 365 Copilot in June 2025, CVSS 9.3, patched server-side with no exploitation observed in the wild. The arXiv paper is third-party analysis after the fact.
- General Analysis, Supabase MCP can leak your entire SQL database, 2025, and Supabase's current MCP documentation, checked 1 September 2026. Supabase's guidance has changed since the research was published, and the current page leads with the security warning and the do-not-connect-to-production rule. Treat the incident as a description of how this shape of mistake happens, not as a live vulnerability.
- Model Context Protocol, Authorization, specification revision 2026-07-28, confirmed as the current revision on 1 September 2026. All the MUST requirements above are quoted from that page. MCP changes fast: check the versioning page before relying on any wire-format detail here.
Want to build this, not just read about it?
The free 3-day Codehance challenge teaches the architecture-first method hands-on. No coding background needed.
Start the free challenge