# What is an 'agent'? A class/instance definition, updated with the 2026-07-28 MCP spec
## Industry standards
In the Gen AI / LLM space, two standards have emerged as the de facto choice in their domains:
* **A2A** (v1.0, Linux Foundation) defines how agents integrate and communicate with their peers. It defines the *interface* of an agent, but not the agent itself.<br>* **MCP** (2026-07-28 spec, finalizes today) defines how an agent uses tools. It defines the *internal plumbing* of an agent, but not the agent itself.
One nuance to be fair to both: MCP can also act as an agent's public interface, when an agent is exposed as an MCP server inside a single trust domain. So A2A covers the cross-organization contract, and MCP covers everything inside it. Either way, the conclusion stands: neither protocol defines what an agent *is*.
To me it seems the terms 'agent' and 'agentic' are still not well defined, and this article is my attempt at an operational definition: one precise enough that you could build a host around it. That claim is not hypothetical — I am building an MCP host, and this definition is what fell out of that work.
## Prior art (and why it is not enough)
"An agent is an LLM using tools in a loop" (Anthropic's framing) is directionally right, but it is not operational: it does not tell you what belongs in your `agents.json`. The academic definitions (rational agents, BDI, FIPA) predate LLMs and do not map to context windows, token budgets or MCP servers. I want something in between: a definition you can serialize.
Scope: this is a definition for agents that live in an MCP host. Frameworks like LangGraph organize things differently, but I believe the same components show up under different names.
## The definitions
I split the concept in two parts, like a class and its instances. Both live in the MCP host. From here on: an **agent definition** is the class, an **agent** is the instance.
The agent definition consists of:
* **the host loop** — the core. The LLM deciding actions, observing results and iterating. Without a loop you have a chatbot with tools, not an agent.<br>* **system context** — persona, instructions. Static and authored.<br>* **MCP server set**<br>* **capability boundary / tool policy** — which servers and tools this agent *may* use, and what needs approval. This is a role, not a login.<br>* **LLM** — the actual model we are using<br>* **termination limits** — max iterations, token budget, stop conditions<br>* **task contract** — the schema of what this agent accepts and what it must return<br>* **context-size strategy** — compaction vs top-x<br>```csharp<br>record AgentDefinition(<br>HostLoop Loop,<br>SystemContext Context,<br>McpServerSet Servers,<br>CapabilityBoundary Capabilities,<br>Model Llm,<br>TerminationLimits Limits,<br>TaskContract Contract,<br>ContextStrategy Strategy);<br>```
An agent is an instance of that class. In C# terms:<br>* **goal** — what the user actually asked<br>* **working context window** — conversation history, tool results<br>* **credentials** — the principal: whose OAuth tokens, on whose behalf. Two instances of the same definition, running for two different users, differ only here.<br>* **consumed budget** — iterations elapsed, tokens spent<br>```csharp<br>record Agent(<br>AgentDefinition Definition,<br>AgentTask Goal,<br>ContextWindow WorkingContext,<br>Principal Credentials,<br>Budget Consumed);<br>```
Note the symmetry: the definition holds limits, contracts and capabilities; the instance holds counters, goals and credentials. Static in the class, dynamic in the instance.
## Enter the 2026-07-28 spec, or more precisely: the stateless core
The new MCP spec removes protocol sessions entirely. A server no longer remembers you between calls. All state now travels in explicit handles that the model itself can see: task handles for long-running work, workflow ids, and the `requestState` blob a paused call hands back.
This breaks my 'working context window' as defined above. Those handles land in the context window, which means compacting — or worse, top-x-ing — becomes a *correctness* concern instead of a cost concern. Summarize away a task handle and the agent has orphaned remote work it can never resume, because the stateless server has no session through which to remind it.
So the instance needs a split:
* **compressible context** — conversation history, safe to compact<br>* **load-bearing context** — outstanding handles and request state, never compacted
The host loop also stops being free-form. It must now support:
* the multi-round-trip pause — a tool call returns input-required plus request state; the loop surfaces the question and re-issues the call with the answer<br>* task polling (`tasks/get`)<br>* unsolicited task handles arriving in results
## Serializable Agents
Here is where the stateless core points. If instance state is exactly {goal, context, handles, credentials, consumed budget}, and the protocol holds no hidden session on your behalf, then an agent is a *serializable value*. You can suspend it, persist it, and...