Abilities unlocks 20 years of functionality, and does so while planning for the next 20.
That line sounds like marketing copy, but it’s actually the most accurate way I’ve found to describe what the Abilities API is meant to do for WordPress. When WordPress 6.9 ships, tens of millions of sites will get a new, first-class API that essentially answers the question:
“What can this site do, in a way that software can reliably understand and safely trigger?”
That’s a big statement. It’s also not something that appeared out of nowhere.
In its current nomenclature, the Abilities API was conceived at WordCamp Europe 2025, sitting in the back of a restaurant in Basel, Switzerland, on a rainy evening. Matías, Nikolai and I were there, going back and forth on a list of ideas and names, trying to define what we actually wanted from a “WordPress abilities API.”
That moment feels recent. But the truth is that there’s a much longer history behind it – startup years, internal experiments, failed attempts at unification inside WordPress, a lot of things that didn’t quite land. Abilities is the product of all of that.
This post is the story of how it came about.
The moment in Switzerland
It’s exciting that Abilities API is coming to WordPress with version 6.9. This is a major version release, and there are tens of millions of sites that will update almost immediately. Suddenly they’ll have this new primitive baked into core: a shared registry of abilities and a standard way to run them.

In its current shape, Abilities was really defined at WordCamp Europe, earlier in 2025. It was early evening. We were in Basel, in the old town, in one of those restaurants that feels tucked away even though it’s not that far from the conference. It had rained lightly; the city was in that in-between state where everything feels a little quieter than it should be.

Matías and I had a literal list of names and concepts. We were talking through, and building on ideas from Automattic’s explorations: what would an “abilities API” need to do for WordPress? How far should it go? What should it not do? How do we keep it primitive/smart enough that it still makes sense a decade from now?
By the time we got up from that table, we had the basic shape of what became the Abilities API. But that conversation in Switzerland was the midpoint, not the starting point. To understand why we needed Abilities … and why it looks the way it does, you have to go back a few years.
Before Automattic: trying to build agents on top of chaos
Abilities actually started life as something else entirely: an API called the Feature API.
The Feature API came out of a problem my co-founder Greg Hunt and I ran into when we were not working at Automattic, not in any sort of “Core AI” role, but running a recently funded startup whose entire job was to bring agents to WordPress.
This was roughly threeish years ago. It was GPT-3, not GPT-5+. “Agentic workflows” weren’t a buzzword yet. MCP didn’t exist. Tool calling and function calling were just starting to become real concepts in the APIs from model providers. Structured decoding and “JSON mode” were early, unreliable, and honestly a little weird.
What we wanted to do was pretty straightforward conceptually: take LLMs, take WordPress, and make the model actually do things for the user.

In the beginning, that meant single-shot actions. Ask the system to do one thing – “create a draft post from this outline,” “translate this content into Spanish,” “swap out this hero image,” whatever – and then have the agent figure out which action to take, run it, and return the result.
Over time, we wanted to grow into what we now think of as agents: buckets or boxes of actions that can be taken, with a model that has agency to pick and chain those tools together to accomplish goals.
The problem was WordPress itself.
WordPress is twenty-plus years of people building whatever they want, in whatever way made sense at the time. That’s its strength. But when you try to put an agent on top of it, you immediately feel the downside: there is no real unification.
The best standards we had to draw from were:
- The way fields were registered in PHP and classic settings pages,
- Menu registration for the admin navigation,
- And the REST API.
That gave us (some) pieces. It did not give us a single place to say: “Here is a normalized list of everything this site can do, with structured input and output, and here’s how to run it.”
So as we tried to build this agent, we found ourselves grasping at straws. We could see what needed to exist, a registry of capabilities, but the reality was:
- Either we built direct, hardcoded support for every plugin we wanted to integrate with, or
- We had to convince plugin developers to unify around a standard that didn’t exist yet.
And we were just a small startup. Yes, we were moving quickly and had hundreds of thousands of users. But in the grand scheme of the WordPress ecosystem, we were early, experimental, and didn’t have enough sway to define a standard and have people rally around it.
We ended up building custom adapters. We pulled on the bits of unification that did exist (REST endpoints, some shared patterns, a few internal conventions) and we accepted that huge parts of our coverage would be dependent on future unification or future investment – either on our side or on the plugin developers’ side.
In other words: we hit the limits of what you can do with agents on top of a system that doesn’t didn’t have a shared capabilities layer.
Joining Automattic: the Feature API
When we came to Automattic, none of that magically went away.
We still hadn’t solved the underlying problem at the startup. We’d just built around it. And as we integrated our team and our work into Automattic, we saw that other AI efforts inside the company were running straight into the same thing:
- Tool registration was fragmented.
- Context management was gnarly.
- Each project had its own approach to “features” or “tools” that didn’t translate well to the others.
The big realization was that it wasn’t just a “startup trying to convince plugin authors” problem. Even inside a single company, with shared infrastructure, the lack of a unified way to describe capabilities was slowing us down.
The first serious answer to that inside Automattic was the Feature API.
The idea of the Feature API was:
- Automattic and core plugins would register features they wanted AI agents to use.
- We’d have a unified registry of those features.
- Internal agents could then consume this registry, rather than relying on one-off integrations and bespoke schemas.
Crucially, the Feature API was never really intended to go into WordPress core. It was an (experimental and) internal API, installed on WordPress.com and other Automattic-owned properties. The assumption was: Automattic has a big enough footprint that if we define this protocol, others may use it, but we’re not going to push it into the core project.
If you look at the history of the Feature API code, you can see Greg’s (and my) fingerprints all over it. The design was directly shaped by the pain we experienced trying to build an AI agent for WordPress as an independent company. The Feature API grew and grew, with help of others from within A8C, Jorge, Hector and Em come to mind. We built proof-of-concept agents on top of it. We effectively built version 0.0.0.0.0.0.0.0.1 – the alpha of the alpha – of what later became Abilities.
And it worked. It proved something important:
You can create a unified registry of logic and capabilities and actions in WordPress, and that concept works very well for AI agents.
But as it matured, we also started to see its limitations.
The Feature API:
- Was designed purely for AI from day one.
- Was designed purely for Automattic’s context.
- Made assumptions that didn’t line up cleanly with how WordPress core is built and governed.
- Was never meant to be a core API, and that showed up in the details.
At the same time, the industry around us was changing.
Tool calling and function calling were settling into stable, predictable patterns across providers. MCP (the Model Context Protocol) appeared. It wasn’t clear yet whether MCP would be the protocol ten years from now, but it was clear that the problem space around tools and context was stabilizing.
Which meant we could start thinking less in terms of “we need to defend against chaos forever” and more in terms of “we can design a primitive that survives protocol churn.”
That set the stage for the next step.
The Core AI group and pulling things back to primitives
As the Feature API kept evolving inside Automattic, there was a parallel effort inside the WordPress project to formalize AI as something the project should care about directly.
WordPress had been publicly discussing AI in various ways since around 2023. There were companies like WPAI (ours, originally) and others building on top of frontier models and research. But there was no unification, no standardization, and everything at the model/API layer was changing constantly until basically the middle of 2025.
Around that time, as MCP started to look like it might stick – or at least might influence everything else – there was momentum to create a Core AI group in WordPress. And, with the backing of the project, I pulled together the best team in the industry; Jeff Paul, Felix Arnz, and Pascal Birchler.
The Core AI group had a simple brief: identify the minimum set of building blocks that WordPress needs in order for AI to be a first-class citizen in the software.
When we started pulling on that thread, I kept peeling layers away from the “AI product” surface, down towards the most primitive questions:
- What is the simplest thing we can add to WordPress that makes it possible to build agents, assistants, and AI features in a sane way?
- How do we do that without locking the project into one provider, one protocol, or one architectural style?
We kept going until we got to two fundamental primitives.
- A discoverable, uniform list of abilities. A way for WordPress core and plugins to register “things that can be done” in a machine-readable way, and for software to discover and trigger them safely. This is what became the Abilities API.
- An easy, first-class way to call LLMs from within WordPress. This is what became the PHP Client AI API (and its adjacent tooling) – which itself was inspired by Felix’s AI Services plugin that I came to know when building WPAI.
With those two pieces in place, the rest becomes compositional:
- You can define abilities that do static, non-AI things.
- You can define abilities that wrap LLM calls.
- You can create orchestrators that feed ability descriptions and schemas into models and let them choose what to call.
- You can expose the same abilities to external systems via REST, MCP, WebMCP, UTCP, A2A, whatever comes next.
There was also a third, important offshoot:
If we’re going to build a generalized abilities layer, we should demonstrate how it can be adapted to the current AI protocol landscape without locking core to any one protocol.
That’s where the MCP adapter came from: a canonical plugin that takes Abilities and projects them out as MCP tools and resources. It’s close to Abilities, but deliberately not part of core. It’s allowed to move faster. It’s allowed to track protocol changes. And it can be replaced if the ecosystem shifts.
That pattern is important. WordPress has a 20-year legacy. Backwards compatibility and non-breaking changes are not just nice-to-haves; they are core values. That means:
- You can’t casually add protocols to core that might be irrelevant in five years.
- You can’t casually deprecate deep APIs without causing massive pain.
- If you bet wrong, you either carry legacy forever or force people through a bad migration.
So the Building Blocks approach matters. Abilities and the WP/PHP Client AI API are primitives. MCP, WebMCP, UTCP, and whatever comes next are adapters that sit on top.
Deep-auditing the Feature API and deciding to start again
As the Core AI group was getting up and running, we did a deep audit of the Feature API.
It was clear that the Feature API was “cool” in the sense that it worked and had actual usage. There was an AI agent bundled into the repository as an example. People were excited about it. Internal Automattic products were actively using it.
But it was just as clear that it wasn’t built for core.
The assumptions baked into the Feature API were:
- Automattic controls the environment.
- The primary (and almost exclusive) consumer is AI, not non-AI features like workflows or command palettes.
- The governance model is one company, not an open source project with many equal stakeholders.
- The naming and architecture didn’t fully line up with how WordPress historically structures its APIs.
We could have tried to “clean it up” and push it into core. Instead, we chose a harder route:
- Deprecate the Feature API as an internal implementation.
- Take the lessons from it… what worked, what didn’t.
- Bootstrap a new Abilities API inside the Core AI group, designed for the WordPress project, not for Automattic.
That decision is important. It’s always tempting to promote an internal project into “the official thing,” but doing that when it isn’t actually the right shape just pushes complexity down the road. You end up carrying legacy decisions for a decade.
By starting again, we gave ourselves room to be more primitive, more general, and more honest about how deep we wanted this to go.
Designing Abilities as a WordPress core API
Back to Basel 🇨🇭
At that dinner, when we were sketching out what became the Abilities API, we weren’t starting from a blank page. We had:
- Years of experience from trying to build agents at a startup.
- A fully working internal Feature API with real usage.
- A clear brief from the Core AI group about primitive building blocks.
- A WordPress project that was ready to move, but still extremely cautious about core changes.
The design goals for Abilities looked something like this:
- WordPress-first, not Automattic-first. The API needed to feel like it belonged in WordPress core. That means: hooks, filters, data structures, and naming conventions that fit naturally into the existing architecture and the way people think about building plugins.
- Primitive, not framework. Abilities shouldn’t try to be an entire agent framework, workflow engine, or orchestration layer. It should be a simple, cross-context capabilities registry that everything else can sit on top of.
- Cross-context from day one. It had to work for both server-side and client-side abilities. It had to be usable from PHP, REST, and JavaScript. It had to make sense whether you were building a button in the editor, a CLI command, or a remote automation.
- AI-friendly, but not AI-only. It needed to be designed with AI in mind – input/output schemas, descriptions that models can read, clear permissions – but it also needed to be useful without any AI at all. Workflows, command palette, admin actions, and non-AI automations should all benefit from it.
- Protocol-agnostic in core. No MCP in core. No WebMCP in core. No UTCP or A2A in core. Those should live in adapters and canonical plugins, so we can evolve them as the ecosystem shifts without forcing migrations at the core level.

With those constraints, Abilities settled into a simple mental model:
- An ability has:
- A stable name.
- A human- and model-readable label and description.
- A structured input schema.
- A structured output schema.
- A permission callback.
- An execution callback that actually performs the work.
- Abilities live in a registry that:
- Can be queried from PHP.
- Can be exposed via REST.
- Can be bridged into client-side code.
- Can be adapted into other protocols like MCP.
That’s it. Everything else happens outside of the core API.
Naming it “Abilities”
Naming sounds cosmetic. It wasn’t.
WordPress already has “actions” and “capabilities.” Those words are deeply loaded inside the project. They mean specific things. Using them for a new core API would have been confusing at best and dangerous at worst.
We walked through a bunch of options:
- Actions API – makes sense conceptually, but actions already exist.
- Capabilities API – again, makes sense, but capabilities already exist.
- Features API – we liked the name. I still like the name. But it was tied to an internal Automattic API we were explicitly not promoting to core.
- There were many more that I can’t remember right now.
“Abilities” hit the right balance. Good call Matias.
It’s not used anywhere else in the project. It maps nicely to what we care about: the things WordPress is able to do. It works well in conversation:
- “What Abilities does this plugin expose?”
- “This workflow chains three Abilities.”
- “This agent has access to these Abilities.”
There’s also a subtle promise hidden in the word: if you write a plugin, you should be able to describe what it can do as a set of abilities. And once you’ve done that, everything from AI agents to workflows to REST clients can make use of it.
We left that restaurant with a name, a direction, and the expectation that the Abilities API would go into WordPress 6.9.
And even then, we knew that was fast. From the outside, it looks like a half-year project. From the inside, it’s the end of a much longer story.
From canonical package to WordPress 6.9
After Basel, we did the thing WordPress increasingly likes to do for big new features: we started Abilities as a canonical project.
We created a new repository. We treated it as a composer package first, a plugin second, and a core candidate third. That allowed us to:
- Iterate quickly.
- Get real usage from plugin authors who were willing to experiment.
- Refine the API surface before it was locked into a core release.
Over the next several months, a lot happened in a relatively short period:
- Greg Ziółkowski, a long time contributor to WordPress Core, took over as the technical lead for the project and a collection of incredible contributors shaped up alongside him.
- The server-side implementation solidified: registering abilities in PHP, querying them, running them.
- REST routes were added so abilities could be discovered and triggered externally.
- Plugin developers started to experiment with using Abilities for both AI and non-AI use cases.
- The MCP adapter took shape, projecting abilities out as MCP tools and resources.
By the time we proposed merging Abilities into WordPress core for 6.9, it wasn’t an abstract idea. It was a working API with a real repository, real usage, and a path forward.
From a calendar perspective, the repository was started on July 13, 2025, and as I write this, it’s November 20ish, 2025. About half a year.
From a history perspective, though, this is the culmination of:
- Years of startup experiments trying to build agents on top of an unstructured ecosystem.
- An internal Feature API that did the wrong thing in the right way long enough to teach us what the right thing needed to be.
- A project-wide shift towards treating AI as something that requires core primitives, not just plugins.
Beyond AI: why Abilities matters even if you never touch an LLM
It’s tempting to think of the Abilities API as “the AI API.” That’s not how I (we) see it.
Yes, Abilities is designed with AI in mind. It’s designed to work well when you’re feeding ability descriptions into a model and letting it decide what to call. It’s designed to make it easy to build agents, orchestrators, and AI-driven workflows.
But the reason it’s going into WordPress core is that it’s useful even if you never call an LLM.
If you ignore AI entirely, Abilities still gives you:
- A unified way for plugins and core to register what they can do.
- A consistent surface for human interfaces like the command palette to draw from.
- A way to build deterministic workflows by chaining abilities together.
- A better story for REST and WP-CLI, because both can sit on top of the same primitives instead of duplicating logic (something I’d really like to explore as Abilities API matures further).
In many ways, the best version of this story is:
It would have been great if Abilities had existed before LLMs, because a lot of non-AI tooling could have been built on top of it. The fact that it also powers AI is a bonus.
That’s also why we were careful not to bake protocols into core. MCP, WebMCP, UTCP, A2A – these are all important parts of the current ecosystem. They might be the dominant protocols ten years from now. Or something else might replace them.
Abilities is meant to survive that churn. It’s the WordPress-native answer to “what can this site do?” … Protocols and adapters can come and go on top of it.
What’s next
Abilities started as a problem at a small startup trying to build AI agents on top of WordPress before the rest of the world cared about “agents.” It turned into an internal Feature API at Automattic that worked but wasn’t right for core. It became one of the core building blocks of a newly formalized WordPress Core AI group. And it was finally named, scoped, and pushed towards WordPress 6.9 after a rainy evening in a Swiss restaurant this summer.
Along the way, the concept shifted:
- From “how do we get our startup to talk to popular plugins?”
- To “how do we get Automattic’s AI projects to talk to our own products?”
- To “how does the CMS that powers half the internet express what it can do, in a way that works for humans, machines, and whatever comes after MCP?”
Abilities unlocks 20 years of functionality, and does so while planning for the next 20. It gives AI agents a sane way to work inside WordPress. It gives non-AI tooling a single, stable place to discover capabilities. And it does all of that without forcing the project to bet its future on any one protocol.
In the next post, I’ll go into the practical side: how to actually use the Abilities API to build single-shot actions, agentic workflows, deterministic workflows, and how all of that ties into MCP, WebMCP, and the rest of the agentic stack.
For now, the takeaway is simple: after two decades of improvisation, WordPress finally has a native capabilities layer. That’s what Abilities is.