For most of the short history of agent frameworks, defining an agent meant writing code. You imported the SDK, instantiated an agent object, attached tools, wired a graph. In 2026 that stopped being the only option. Microsoft's Agent Framework — the merged descendant of AutoGen and Semantic Kernel that reached 1.0 in April — shipped a way to define an agent entirely in YAML, loaded through a factory and run with a single call. Google's Agent Development Kit offers the same choice: author your agent in a YAML config instead of Python, and its visual builder will hand you the YAML to check in. CrewAI has done role definitions in agents.yaml for a while. The declarative agent has arrived as a first-class citizen.
The way this usually gets pitched is "simpler" — YAML for the easy agents, code for the hard ones. That framing is comfortable and mostly wrong. The line between a declarative agent and a coded one is not a difficulty gradient. It's a line about what part of your agent is doing the work: its wiring, or its decisions.
What YAML actually buys you#
The reason to move an agent into a config file has almost nothing to do with saving keystrokes. It's that a config file is an artifact in a way an object graph buried in application code is not.
You can diff it. A change to an agent's instructions or its tool list shows up as a reviewable line in a pull request, and the person approving it doesn't have to read the framework's API to understand what changed. You can validate it — against a schema, and against golden datasets — before it ships. You can promote a single version through environments and roll it back by moving a pointer, the same lifecycle you'd give any other piece of configuration. Microsoft's Foundry runtime leans into exactly this: declarative agent definitions get versioned, validated, and rolled back without redeploying a container.
That is the real payoff, and it's an underrated one. In a regulated shop, "which exact version of this agent's instructions was live on the day of that decision, and who approved the change" is not a nice-to-have — it's the audit. A YAML file answers it natively. A constructor call in a service does not.
A declarative agent isn't a simpler agent. It's an agent you can govern like config instead of chasing like code.
There's a second, quieter win: the definition stops being the exclusive property of whoever writes the framework's language. A product manager can read an agent's YAML. A domain expert can propose an edit to its instructions. Google pitches the YAML path in exactly these terms — good for simple configurations and for collaboration with people who don't write the code. When the agent's definition is a document, the set of people who can safely touch it grows.
Where the config wall is#
Now the limit, because it's sharp and it's the whole point. YAML can express the static shape of an agent: its model, its system instructions, the tools it may call, its memory configuration, and — if it coordinates sub-agents — a fixed topology among them. Run these in sequence. Run these in parallel. Loop this one until it's done. That covers a genuinely large fraction of real agents, more than skeptics expect.
What YAML cannot express is a decision. It can't say "if the search tool comes back empty, rewrite the query and try a different index; otherwise summarize and stop." It can't compute, at runtime, which of two hundred tools to expose based on the user's role. It can't run a loop whose exit condition is a bespoke function of the last three tool results. Those are control flow — branching on the content of what happened — and control flow is code. The moment your agent's behavior depends on data it only sees while running, the declarative file has nothing left to describe, and you drop into the imperative SDK.
This is why LangGraph stays defiantly code-first. Its entire model is the explicit control-flow graph — the branches and loops are the product — so serializing it to config would be serializing away the thing you came for. The frameworks that added YAML didn't disagree with that; they carved off the part of the agent that is static and let you declare it, leaving the decisions in code.
One naming trap before you go#
If you search "declarative agents" and get confused, it's not you. Microsoft applies the same phrase to two unrelated things: the Agent Framework's YAML-defined agents described above, and Microsoft 365 Copilot declarative agents, which are a manifest-driven way to customize Copilot with instructions, knowledge sources, and actions. Same words, different product, different audience. A tutorial about one is useless for the other. Check which meaning you're reading before you spend an afternoon on it.
The question to actually ask#
So don't ask "YAML or code" in the abstract; the answer is almost always both, at different layers. Ask where your agent keeps its value. If the agent is a member of a catalog of broadly similar agents — same shape, different instructions and tools — and the priority is that they ship safely and stay auditable, declare it. If the agent's whole reason to exist is the logic it runs turn to turn — the branching, the runtime tool selection, the loop that knows when to quit — that logic was never going to fit in a config file, and pretending otherwise just moves the complexity somewhere harder to see. Wiring goes in YAML. Decisions go in code. Most real agents are a little of the first and a lot of the second, and knowing which line you're on is the actual skill.



