Buried in Pydantic's v2 announcement is a claim that reframes the entire declarative-agent conversation. Describing agent specs, the team notes that because capabilities are serializable, an agent can be loaded from a spec file — and that "the surface is small enough that an LLM can write one" [1].
Small enough that a model can write it. Not small enough that a human can read it, which was the old pitch. The audience for the config changed.
For two years the case for declarative agents was portability: define once, run anywhere, the ONNX argument applied to agents. That case is basically won and no longer interesting. Pydantic ships a YAML path, Microsoft's Agent Framework ships one, Google's ADK ships one. What is interesting now is the second-order consequence nobody was arguing for — when an agent's definition becomes a small, structured document, the agent can participate in writing it.
What a spec actually looks like
The shape is unremarkable, which is the point [2]:
model: anthropic:claude-opus-4-6
instructions: You are a helpful research assistant.
model_settings:
max_tokens: 8192
capabilities:
- WebSearch: local: duckduckgo
- Thinking: effort: high
Model, instructions, capabilities, settings. Loaded with Agent.from_file('agent.yaml') — one line, no Python agent-construction code [2]. (The model pin there is the documentation's example, not a recommendation.)
Compare that to what an equivalent agent looked like eighteen months ago: a class instantiation, a list of tool objects registered separately, hooks attached by decorator, retry behavior configured somewhere else, model settings passed as keyword arguments. Five concepts in four places, none of them serializable as a unit.
The abstraction that made it possible
The reason specs work now and did not before is a single design decision in v2, and it is worth understanding because it explains why earlier attempts at declarative agents were always partial.
Pydantic's central primitive is the capability, which "bundles an agent's instructions, tools, lifecycle hooks, and model settings into a single, composable unit" [1]. One concept reaches every layer of the agent.
That collapse is what makes serialization complete rather than partial. When instructions, tools, hooks, and settings are four unrelated mechanisms, a config file can only ever describe the subset that happens to be data — typically the model and the prompt — while the interesting behavior stays locked in code. Merge them into one serializable unit and the whole agent becomes representable.
The rest of the v2 architecture follows from the same instinct. The core shrank to the event loop, providers, and the capability and hooks APIs. Optional providers like bedrock, groq, and mistral became opt-in. Everything substantial — memory, guardrails, context management, filesystem access, code mode — moved into a separately-versioned first-party Harness, so the batteries can iterate quickly while the core stays stable [1].
A small stable core with composable, serializable units on top is precisely the shape you need if you want a machine-writable definition. The declarative capability was not bolted on; it fell out of the refactor.
The part that is genuinely new
Here is where it stops being a packaging improvement.
Pydantic ships Monty, a safe Python subset, and the example they give for it is an agent proposing its own declarative tweaks — specifically, "adding a hook that trims an oversized tool result before it fills the context window" [1].
Read that scenario carefully. An agent notices a recurring failure mode in its own operation — tool results are too large and they are consuming the context it needs — and responds by proposing a change to its own configuration. Not a change to its behavior within a run. A change to the document that defines what it is on the next run.
Two things have to be true for that to be possible, and both just became true. The configuration has to be small and structured enough for a model to produce validly, which the capability abstraction delivered. And the proposal has to be expressible in something safer than arbitrary code, which is what Monty is for.
The necessary caveat: this is described as an enabled possibility, not a shipped autonomous feature. Nothing in the announcement claims agents are editing their own production configs today. But the pieces are assembled, and the direction is explicit.
The versioning consequence nobody mentions
Splitting core from Harness does something to release cadence that matters more than it sounds [1].
A monolithic framework has one version number, and that number has to satisfy two incompatible constituencies: the people who want the event loop to never change, and the people who want memory and guardrails to improve every month. The usual outcome is that the stable constituency wins, improvements queue up behind compatibility concerns, and the framework calcifies.
Two artifacts, two cadences. Core changes rarely, because it is now small enough that there is little in it to change — the event loop, providers, and the capability and hooks APIs [1]. The Harness, holding memory, guardrails, context management, filesystem access, and code mode, can move fast because breaking it does not break the protocol between your agent and the model.
For anyone maintaining agents in production, that split is the practical benefit — bigger, in the near term, than declarative configuration itself. It means you can take context-management improvements without accepting an event-loop change, and pin the part you depend on being boring.
Everyone arrived at YAML
The convergence is worth noting because it means this is not one vendor's bet.
Microsoft's Agent Framework ships Microsoft.Agents.AI.Declarative, providing a ChatClientPromptAgentFactory type and a CreateFromYamlAsync extension method on PromptAgentFactory [3]. Different language, different stack, same conclusion: the agent definition belongs in a document, not in construction code.
This site has tracked the progression in three steps without naming it. Docker's cagent made a YAML file define a team of agents. Spec-driven development put specs in front of humans writing code. Agent specs are the third turn — the spec as an artifact the agent itself reads from and writes to.
Legible is not the same as safe
The obvious risk in a config an agent can edit is that an agent will edit it badly. That risk is real, and the mitigation is not technical sophistication — it is boring software process.
A YAML file has properties that a Python constructor does not. It diffs cleanly. It sits in version control. It can be code-reviewed by someone who does not know the framework. It can be gated behind an approval before it merges. An agent proposing a change to its own spec produces a pull request shaped object, and we already know how to handle those.
This is the same conclusion GitHub reached from the opposite direction this month, shipping confidence levels, rationales, and human approval for agent-driven changes. Two different problems — an agent editing an issue, an agent editing its own config — and the same answer: make the proposal inspectable, then put a human at the gate.
Declarative does not mean safe. It means legible, and legibility is the precondition for every control you might want to add afterward. A behavior locked in a Python class cannot be reviewed by your security team. A capability list in YAML can.
The obvious pushback
"Configuration as programming language" has a long and mostly unhappy history. Kubernetes manifests, Terraform modules, CI pipeline definitions — every one started as a clean declarative document and grew conditionals, loops, templating, and eventually a generator written in a real language. There is no reason to assume agent specs are immune, and a spec file with enough capability composition in it is just a program with worse tooling.
The counter-argument is scope. A Kubernetes manifest grew complex because it described an entire distributed system. An agent spec describes one agent: a model, instructions, a handful of capabilities, some settings. The surface stays small because the thing being described stays small — and if it stops being small, that is a signal to split the agent, not to add templating.
The weaker point in the whole story is that no performance or reliability figures exist for v2 at all [1]. The architectural argument is coherent; the evidence that it produces better agents is not yet published.
What to do with this
If you build agents in Python and your definitions live in code, try extracting one to a spec file. Not for portability — you probably do not need to run it on another runtime — but to find out how much of your agent's actual behavior refuses to serialize. Whatever will not fit in the YAML is the part of your agent that no reviewer outside your team can currently inspect. That inventory is worth having.
And if you are anywhere near letting an agent propose changes to its own configuration, put the gate in before the capability, not after. The proposal being readable is what makes review possible. Review being mandatory is what makes it safe.
The agent that writes its own config is not a novelty. It is the first version of an agent that can improve its own architecture — and the only reason we will be able to trust it is that the thing it writes will fit on one screen.
References
[1] Douwe Maan, Pydantic — Pydantic AI v2: capabilities, a leaner core, and the Harness — (2026-06-23). Blog
[2] Pydantic — Agent Specs — (2026-06-23). Documentation
[3] Microsoft Learn — Declarative Agents. Documentation