#64098 closed feature request (fixed)
Introduce Abilities API
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 6.9 | Priority: | normal |
| Severity: | normal | Version: | 6.9 |
| Component: | AI | Keywords: | has-patch has-unit-tests needs-docs add-to-field-guide |
| Focuses: | Cc: |
Description (last modified by )
Part of AI Building Blocks for WordPress .
The Abilities API transforms WordPress from a collection of isolated functions into a unified, discoverable system. By creating a central registry of capabilities, it allows AI agents, automation tools, and developers to understand and interact with everything WordPress can do – from CLI commands and REST API endpoints to custom logic and plugin functions.
Full proposal at https://make.wordpress.org/ai/2025/07/17/abilities-api/.
Handbook page at https://make.wordpress.org/ai/handbook/projects/abilities-api/.
Documentation in https://github.com/WordPress/abilities-api/tree/trunk/docs.
Developed in https://github.com/WordPress/abilities-api.
Composer package: https://packagist.org/packages/wordpress/abilities-api.
Introduces a new Abilities API that allows WordPress plugins and themes to register and execute custom abilities with built-in permission checking, input/output validation via JSON Schema, and REST API integration.
Public Functions
Ability Management
wp_register_ability( string $name, array $args ): ?WP_Ability- Registers a new ability (must be called onwp_abilities_api_inithook)wp_unregister_ability( string $name ): ?WP_Ability- Unregisters an abilitywp_has_ability( string $name ): bool- Checks if an ability is registeredwp_get_ability( string $name ): ?WP_Ability- Retrieves a registered abilitywp_get_abilities(): array- Retrieves all registered abilities
Ability Category Management
wp_register_ability_category( string $slug, array $args ): ?WP_Ability_Category- Registers an ability category (must be called onwp_abilities_api_categories_inithook)wp_unregister_ability_category( string $slug ): ?WP_Ability_Category- Unregisters an ability categorywp_has_ability_category( string $slug ): bool- Checks if an ability category is registeredwp_get_ability_category( string $slug ): ?WP_Ability_Category- Retrieves a registered ability categorywp_get_ability_categories(): array- Retrieves all registered ability categories
Public Classes
WP_Ability- Encapsulates ability properties and methods (execute, check_permission, validate_input, etc.)WP_Ability_Category- Encapsulates ability category propertiesWP_Abilities_Registry- Manages ability registration and lookup (private, accessed via functions)WP_Ability_Categories_Registry- Manages ability category registration (private, accessed via functions)WP_REST_Abilities_V1_Categories_Controller- REST controller for listing category abilitiesWP_REST_Abilities_V1_List_Controller- REST controller for listing abilitiesWP_REST_Abilities_V1_Run_Controller- REST controller for executing abilities
REST API Endpoints
Namespace: wp-abilities/v1
List Ability Categories
GET /wp-abilities/v1/categories- Retrieve all registered ability categories- Query parameters:
page,per_page
- Query parameters:
Get Single Ability Category
GET /wp-abilities/v1/categories/(?P<slug>[a-z0-9]+(?:-[a-z0-9]+)*)- Retrieve a specific ability category by name
List Abilities
GET /wp-abilities/v1/abilities- Retrieve all registered abilities- Query parameters:
page,per_page,category
- Query parameters:
Get Single Ability
GET /wp-abilities/v1/abilities/(?P<name>[a-zA-Z0-9\-\/]+)- Retrieve a specific ability by name
Execute Ability
GET|POST|DELETE /wp-abilities/v1/abilities/(?P<name>[a-zA-Z0-9\-\/]+)/run- Execute an ability- Supports multiple HTTP methods based on ability annotations
- Validates input against ability's input schema
- Validates output against ability's output schema
- Performs permission checks via ability's permission callback
Hooks
Actions
wp_abilities_api_categories_init- Fired when ability categories registry is initialized (register categories here)wp_abilities_api_init- Fired when abilities registry is initialized (register abilities here)wp_before_execute_ability- Fired before an ability gets executed, after input validation and permissions check
wp_after_execute_ability- Fires immediately after an ability finished executing
Filters
wp_register_ability_category_args- Filters ability category arguments before registrationwp_register_ability_args- Filters ability arguments before registration
Change History (67)
This ticket was mentioned in PR #9410 on WordPress/wordpress-develop by @gziolo.
8 weeks ago
#1
8 weeks ago
#2
Yesterday, I synced changes from v0.3.0-rc in Abilities API repository with 9906821.
This ticket was mentioned in Slack in #core by jorbin. View the logs.
8 weeks ago
8 weeks ago
#5
First, thank you for the detailed review. I will
apply all the necessary changes as soon as possible. I hoped that having all CI checks passed in two different repositories with slightly different linting configuration would save us from that type of work, but apparently we are not there yet.
The biggest issue I see is with the therm Category being used since it's already a well known and documented term. I think we should find a better term for the grouping abilities.
I understand your concerns. However it didn’t occur to me previously it could be an issue because the name was proposed and picked based on the resemblance to the concept of Categories in WordPress. It’s being used in other places, like in the block editor for block types and for block patterns. There is even REST API endpoint for Block Pattern Categories. I guess it doesn’t fully justify we have to use the same term again if there are agreement there is better term that conveys the same meaning without the potential confusion. The immediate alternative would be “Group” or “Collection”. Let me tag a few AI contributors that are familiar with this choice for their perspective: @Jameswlepage, @felixarntz, @JasonTheAdams, @galatanovidiu and @emdashcodes. There would be a bit of work but fortunately the category concept is brand new and we only published v0.3.0-rc prerelease this week. Ideally, we keep it as is, but let’s gather more feedback how that translates also im the AI reality.
8 weeks ago
#6
the name was proposed and picked based on the resemblance to the concept of Categories in WordPress.
Do you happen to have a link to this conversation so that I can get a full sense of why Category was decided?
To me, “Collection" makes a lot of sense, but perhaps we use the specific "Abilities Collection" to start with in order to allow for more reuse of "Collection" in the future.
Tagging the 6.9 tech leads as well (both so they can way into this specific discussion, and since they may want to review one of the big features for 6.9) @dream-encode @ellatrix @priethor
@jason_the_adams commented on PR #9410:
8 weeks ago
#7
Do you happen to have a link to this conversation so that I can get a full sense of why Category was decided?
To me, “Collection" makes a lot of sense, but perhaps we use the specific "Abilities Collection" to start with in order to allow for more reuse of "Collection" in the future.
This conversation happened in a few places. I believe the origin of the conversation was here, by me: https://github.com/WordPress/ai/issues/21
Honestly, I didn't think too hard about the term. I was describing a taxonomy within abilities, and "category" is a pretty generic term. That said, I do also like "collection", and possibly even more. I think it does a better job of communicating what we're alluding to. I'd be open to the idea of swapping the terms!
8 weeks ago
#8
Another option to consider is Ability Set. For both, collections and sets, we face the challenge they are also technical programming concepts so we might need to use in user facing parts phrases like Ability Category Set.
@jason_the_adams commented on PR #9410:
8 weeks ago
#9
I think I like collection better, but I think set works as well. What I do like about "set" is that I think it's less likely to become a technical term within WordPress. In either case, I like that the terms denote a container of something, rather than a taxonomy.
@justlevine commented on PR #9410:
8 weeks ago
#10
Do you happen to have a link to this conversation so that I can get a full sense of why Category was decided?
I also wanted to surface these for completeness.
- https://github.com/WordPress/abilities-api/issues/101
- https://github.com/WordPress/abilities-api/pull/102
As noted, the current implementation uses Block Categories and Pattern Categories as a reference, but the shape - and more importantly the potential taxonomic reqs Abilities need long term - have not actually been fleshed out. The property exists primarily because we know we need _some form_ of categorization, but don't want to have a bunch of uncategorized Abilities by waiting until after 6.9 to introduce something(ref).
With future evolution in mind, I'm not sure whether it's overall better to stick with category and potentially deprecate the entire property in favor of ~collection~, ~set~, {something_else} or to start with {something_else} and then potentially evolve the shape, but I do think the first approach would allow for better future-compat.
Separately I have concerns with both Set and Collection. Putting aside the lexical/syntactic difficulties with both, generally I don't think it's a good idea to introduce any additional new concepts to 6.9 beyond what's essential, especially if the usage and holistic shape are still TBD.
Re "Collection": we also have Font Collection to contend with, where:
- Font Families has very different API / DX / semantics than Abilities
- Font Collections exist _alongside_
categories, and serve a similar function as thenamespace/prefix required by ability names.
so an (Ability) Collection wouldn't just be a new concept, but a competing one.
@karmatosed commented on PR #9410:
8 weeks ago
#11
I would add a +1 for collections. I don’t mind set but to me it’s just another term where collections would fit. Set is less explanatory.
@jason_the_adams commented on PR #9410:
8 weeks ago
#12
Reflecting on Category vs Collection a bit more, I think my biggest hesitation is that in my mind the connotation of a Collection is that it's a literal group of things, whereas Category is a taxonomy as more of a meta concept. That is, if I were to say I have a collection of apples, you'd assume I physically have them together. Whereas if I said there is fruit within the apple category, it's more of a meta conversation.
Things work more as a meta, now. That is, you define your category and then mark abilities as having that category, but when you get a category you don't have all the abilities; you simply have the category itself which they're associated to.
If we were to call them Ability Collections, then I would intuit that when I get the "User" Ability Collection, I _have_ all the "User" abilities. But, as I said, it doesn't work this way at the moment.
Interestingly enough, we were talking about introducing the ideas of collections, as that's really what the abilities are — an in-memory collection of Ability objects. We also talked about having ways of deriving a subset collection. So I like the idea of being able to have collections of abilities, as it's useful/necessary in multiple contexts including MCP. Still, it _would_ be confusing to mark an ability's collection, but then to say that you can have a collection of all abilities. The nomenclature starts to conflict, here. But it is fair to say "this is my collection of abilities in the 'User' category".
I may actually be talking myself back over to sticking with category! 😆
Still, very open to others' thoughts!
8 weeks ago
#13
I ran out of time to address coding style issues related to documenting arrays in PHPDoc. I will resume this task tomorrow.
@jason_the_adams commented on PR #9410:
8 weeks ago
#14
Amazing work today, @gziolo! You're awesome!
8 weeks ago
#15
Lots of amazing progress yesterday, thanks everyone! There is discussion happening all over this PR, so here is a quick summary of the open threads that I see right now:
- What is the best name for what is currently known as Categories? Discussion is happening in the main thread.
- adding a new
wp_has_ability()function so that the classes don't need to be used for anything _I am ok if we need to defer this in order to get the code merged for beta 1_ - Removing `has_permissions` so that already deprecated code isn't added when this is merged
- Where should the check for not registering abilities too early live (and what should that check look like)
- What should annotations be called and which ones should exist for v1.
- Updating the documentation for arrays to match the WordPress documentation standards (comments exist inline for these). _May be completed as I was writing this up._
- There are numerous smaller suggestions open that I'm not linking to as well.
Already deferred until after beta 1:
- The majority of the extender documentation should live in
src/wp-includes/abilities-api.phprather than pointing to the classes which only core should be using.
8 weeks ago
#16
Update:
has_permissionswas removed yesterday.- Updating the documentation for arrays is partially done, but there are a few more places to update which is going to be copy and paste.
I’ll continue addressing the feedback today, with the points that have clear resolution like documentation and adding additional public functions like wp_has_ability() and wp_has_ability_category() (or the final name we might agree upon). Then updating the default value for destructive annotation.
From the practical perspective it would be good to move the potential renaming from category term to something else into a follow-up PR and commit.
8 weeks ago
#17
Reflecting on Category vs Collection a bit more, I think my biggest hesitation is that in my mind the connotation of a Collection is that it's a literal group of things, whereas Category is a taxonomy as more of a meta concept. That is, if I were to say I have a collection of apples, you'd assume I physically have them together. Whereas if I said there is fruit within the apple category, it's more of a meta conversation.
While abilities aren't something you can hold (like apples), they are a literal grouping of things.
Things work more as a meta, now. That is, you define your category and then mark abilities as having that category, but when you get a category you don't have all the abilities; you simply have the category itself which they're associated to.
If we were to call them Ability Collections, then I would intuit that when I get the "User" Ability Collection, I _have_ all the "User" abilities. But, as I said, it doesn't work this way at the moment.
"I have a collection of apples" doesn't imply that I have all the apples, just that I have the collection that is called apples right now. It also doesn't mean that no one else can have apples.
I think the biggest thing is that it can't be the generic "category". If it's “Abilities Categories” that is better since that makes it a unique thing rather than the generic which is already well known. It should be as clear as possible that an Ability Category != Category (non-strict check intentional) which means adjusting some of the documentation and possibly the code such as in:
I still worry about the idea of an Abilities Category named Category to categorize all the category abilities and that getting confusing, but as long as the generic is avoided, I think this will be ok. (yo dawg for humor).
@jason_the_adams commented on PR #9410:
8 weeks ago
#18
Thanks for the thoughts, @aaronjorbin! You're right, a category Category would be real confusing. Hahah!
While my metaphor helped me process, I'm not sure it was so useful to others. Hahah! What I was really getting at there is that the way categories work _right now_ in Abilities is truly like a taxonomy. By grabbing a "User" Ability Category, you're not getting the associated abilities, you're just getting the Category object and its information, similar to how the category taxonomy works, otherwise. Instead, you can grab abilities and filter by category. Since Ability Categories work this way, I think it's best to keep with the more meta term.
While I can't promise no implementor will go maverick and make a category Abilities Category, I can say it hasn't even crossed our minds in the built-in abilities we've introduced.
I'm thinking we're good to stick with the category term on two conditions:
- We make a pact never to make an Ability Category called "category"
- We always refer to them as Ability Categories and not merely "category"
8 weeks ago
#19
I have personal obvious bias towards going with Abilities Category, but keep in mind that it’s largely because it would save me some hassle 😅
I’m also comfortable updating all docs and translated strings with that form to show it’s practical usage, even if the further decision will be with a different phrasing.
#20
@
8 weeks ago
I don't want to distract from the work happening on the pull request, so I'm raising this here so that this risk can be considered. I'm a bit concerned about adding a new API in 6.9 that core won't be using right away. This isn't to say it's not well-designed or well coded, but it's not really been through the paces. Where are the example abilities for extenders to learn from since they won't find them in core?
The public uses I can find are using a fairly old version which makes me wonder how battle tested this code is. Parts of it are very new with over 5k new lines of code in the last week.
Further, what is gained by shipping this in core for 6.9 without any abilities for people to take advantage of vs shipping this as a plugin earlier and then merging at a later time? Once it ships, it's a lot harder to change things.
Some of the things that I think could make good abilities for a v1 implementation in core are many of the uses of admin-ajax in core right now.
I wouldn't say that I'm -1 on merging, but I am somewhere between -0.25 and -0.5 for these reasons. Essentially, how well do we know if this API, in this design format, is going to solve the needs of people if we don't yet know if it's going to solve the needs of Core?
8 weeks ago
#21
In https://github.com/WordPress/wordpress-develop/pull/9410/commits/d4f77ef75245e36ef5ab1908a739d5124628cb0e, I attempted to update all the occurrences of category to use one of the forms discussed, "category ability" or "category abilities". As part of the effort, I also renamed the existing class to WP_Ability_Categories_Registry to follow the same pattern. Let me know how it feels with all the refinements.
I hope I reached the point where I addressed most of the coding style issues reported in other commits. There are a few remaining issues where some logic has to be added or refined, and I'm leaving that for another day. The current snapshot from the description for transparency:
8 weeks ago
#22
I addressed all the issues raised. The three most important topics that still need confirmation or further discussion are:
- Decide on the final name for the Ability Category / Ability Categories as discussed above. Fix attempted in https://github.com/WordPress/wordpress-develop/commit/6384be818256f5e85794f8b3384ca143ed95d3ef.
- Revisit the strategy for init hooks when registering abilities and category abilities (https://github.com/WordPress/wordpress-develop/pull/9410#discussion_r2435736550). Resolution proposed in https://github.com/WordPress/wordpress-develop/commit/d3e1cd72a9191426de510a8f225d898a07575e01.
- Adjustments to meta annotations (https://github.com/WordPress/wordpress-develop/pull/9410#discussion_r2437614400) (no defaults, remove instructions, handle DELETE). Fixed in https://github.com/WordPress/wordpress-develop/commit/61a06f492c7318683c47dd30ae3a5d6987dfadd1 and https://github.com/WordPress/wordpress-develop/commit/39396dce1baff378fa699fb7232973c1775a5c41.
#23
follow-up:
↓ 28
@
7 weeks ago
Thanks, @jorbin, for raising these points — they’re important considerations. I’d like to provide some additional context that may help clarify the current status and rationale behind proposing the Abilities API for 6.9.
From my perspective, I can say that I made sure Automattic began testing an exact copy of the Abilities API in internal systems to validate the design even before the first public Composer release (v0.1.0). This release coincided with WordCamp US and was covered in both the AI panel and Matt’s keynote demo. The subsequent v0.2.0 release, published two weeks ago, primarily incorporated enhancements to the public API based on feedback from production usage, early adopters testing, and core team reviews. This is also the version currently used by WordPress.com’s MCP on production. The latest v0.3.0 release introduced one significant change — a mandatory category for each ability — a collective decision by the Core AI team to ensure scalability across the WordPress ecosystem, considering ongoing implementations such as the core’s MCP Adapter and Woo agentic projects that are developed publicly.
This proposal follows a proven pattern established by past efforts like the REST API, HTML API, and Block Bindings. Each was introduced iteratively, with limited immediate integration in core but clear value for the wider community. The Abilities API similarly provides a stable, low-level interface that projects can build upon now, while allowing us to refine and extend it over time.
Strategically, the API also prepares WordPress for the growing importance of AI-driven and cross-system integrations. Transformer-based systems increasingly rely on structured, callable actions—“abilities”—to describe functionality in a machine-readable, executable form. Having a formal API for defining and exposing those interactions ensures WordPress remains relevant as part of the AI-native web, while simplifying the developer experience through a unified, self-authenticating interface accessible via PHP, REST, or MCP.
Merging the Abilities API in 6.9 gives plugin authors and extenders the opportunity to validate the approach during the release cycle, establishing a solid foundation for iterative improvements in future versions of core.
There is also an open PR https://github.com/WordPress/abilities-api/pull/108 that is almost ready to land which proposes 3 basic read-only core abilities that we can ship together with API in WordPress 6.9. This is going to be the most challenging process to identify what WP core should offer as built-in abilities, and leaving that to the ecosystem might be the best idea. Our intuition tells us based on the prototypes floating around, is that WordPress core should offer CRUD operations for handling content and it's tracked in https://github.com/WordPress/abilities-api/issues/84. However, that's much larger effort than the API itself, so this is something we would like to experiment with in the AI featured plugin.
#24
@
7 weeks ago
I think it's important we do try to get this into 6.9 so that plugin developers can ship without worrying about trying to ship copies of the feature plugin in their own code, because the abilities API seems to be the foundation AI exposure, and quite frankly, waiting another x months puts us all at a disadvantage.
I've been experimenting and building against this API code since it was the Features API, and I suspect many other plugin developers have been too, so can at least vouch for the "fit for purpose" of the code proposed here.
Given the importance of these APIs to end users, I suspect many other plugin developers are also far along in their preparation for this shipping in 6.9 too.
7 weeks ago
#25
There is also a new REST API endpoint for Ability Categories that I put into a separate PR:
It's based on this branch, so it's easier to review. I transferred it from the Abilities API repository, updating the code based on the feedback in this PR. Example paths:
GET /wp/v2/ability-categories - all ability categories
GET /wp/v2/ability-categories/test-data-retrieval - a single ability category
The name of the controller: WP_REST_Ability_Categories_Controller.
@TimothyBlynJacobs commented on PR #9410:
7 weeks ago
#26
Working on a full review of the REST API code. But I'd strongly suggest we use a namespace like wp-abilities/v1. It doesn't look like these endpoints are particularly RESTful and I think it could lead to some nicer named endpoints as well.
This matches what we did for Site Health and the less RESTy Gutenberg editor specific endpoints.
Given some of the concerns about API shape and stability, I also wonder if we want to actually name the PHP controllers accordingly (ie including V1 in the class name) to give us a better way to iterate if needed.
7 weeks ago
#27
@TimothyBJacobs, in this PR we have 3 more endpoints:
I'm happy to update all of them to wp-abilities/v1/. How do you envision all these routes to be structured exactly? Would it be:
wp-abilities/v1/abilitieswp-abilities/v1/ability-categorieswp-abilities/v1/ability-run
There is a bit of repetition in the naming, but it resolves the challenges with the dynamic parts of the URL (ability or ability category) in the URL for fetching or executing a single item. I'm also open to adjusting the controller name accordingly. That should be a relatively small change.
#28
in reply to:
↑ 23
;
follow-up:
↓ 33
@
7 weeks ago
Thank you @gziolo. The additional context is helpful and I'm glad we are having this discussion.
The comparison to the REST API feels off though since that was developed over a considerably longer amount of time. It went through multiple iterations before the proposal to merge in a multi step manor was shared a month before beta 1 wheras this never had a merge proposal published just a ticket opened a week before beta. One week ago initial abilities were still be discussed and considered.
Having a formal API for defining and exposing those interactions ensures WordPress remains relevant as part of the AI-native web, while simplifying the developer experience through a unified, self-authenticating interface accessible via PHP, REST, or MCP.>
Can you go a bit deeper on what you mean by "self-authenticating"? I'm not finding anything in the github repo or in slack that describes the API in such a way.
Merging the Abilities API in 6.9 gives plugin authors and extenders the opportunity to validate the approach during the release cycle, establishing a solid foundation for iterative improvements in future versions of core.
The iterative improvements are much more constrained once backwards compatibility needs to be paramount.
There is also an open PR https://github.com/WordPress/abilities-api/pull/108 that is almost ready to land which proposes 3 basic read-only core abilities that we can ship together with API in WordPress 6.9. This is going to be the most challenging process to identify what WP core should offer as built-in abilities, and leaving that to the ecosystem might be the best idea. Our intuition tells us based on the prototypes floating around, is that WordPress core should offer CRUD operations for handling content and it's tracked in https://github.com/WordPress/abilities-api/issues/84. However, that's much larger effort than the API itself, so this is something we would like to experiment with in the AI featured plugin.
Again, I very much agree that identifying what abilities to ship initially is a challenge, but those abilities also will help ensure that the API is flushed out for all of core's needs which also means that the API is much better for extenders needs.
I think it's important we do try to get this into 6.9 so that plugin developers can ship without worrying about trying to ship copies of the feature plugin in their own code, because the abilities API seems to be the foundation AI exposure, and quite frankly, waiting another x months puts us all at a disadvantage.
There is no featured plugin. There is a composer package which is supposed to make it esier to embed than trying to ship a copy of a feature plugin in your code (which also is something you should never do, but I digress)
Strategically, the API also prepares WordPress for the growing importance of AI-driven and cross-system integrations. Transformer-based systems increasingly rely on structured, callable actions—“abilities”—to describe functionality in a machine-readable, executable form.
I completely agree, and it's the biggest reason that I am in favor of merging despite the API not feeling as tested or mature as I think a new API of this importance should be. What I would like to find though is a way to ensure that what is shipped in 6.9 (and thus supported by Core for the long run) is something that is easily maintainable and isn't going to make future iterations harder.
A couple ideas to help with that:
- Come up with a big list of core abilities and do at least some psuedo-code to see if the API will work well for them.
- Before the final beta, have five (or more) plugins that are already in the repo ship abilities that use the version that gets committed to core.
- Implement abilities in WP-CLI and make sure that the API solves the needs there.
- Identify if there are other places that should use the abilities API (the command palate is one that stands out off the top of my head) and ask maintainers of those to also come up with an initial implementation.
@TimothyBlynJacobs commented on PR #9410:
7 weeks ago
#29
wp-abilities/v1/abilities
wp-abilities/v1/ability-categories
wp-abilities/v1/ability-run
I'd think perhaps like this. I like the /run being off of a name route, because it gives us the ability to dynamically serve their input and output schema.
/wp-abilities/v1/abilities
/wp-abilities/v1/abilities/{name}/run
/wp-abilities/v1/categories
By naming I'd mean something like WP_REST_Abilities_V1_Categories_Controller. Quite ugly without namespaces :D, but it gives us a clean way to implement a real V2 API.
7 weeks ago
#30
By naming I'd mean something like WP_REST_Abilities_V1_Categories_Controller. Quite ugly without namespaces :D, but it gives us a clean way to implement a real V2 API.
Can you elaborate on that? I don't understand why this API is not real? It fulfills all the needs that the Abilities API has. Why would there be a need to have another version of the REST API controller? We need exactly three things:
- fetch the list of abilities
- fetch a single ability
- execute a single ability
@TimothyBlynJacobs commented on PR #9410:
7 weeks ago
#31
I'm not trying to say the API is not real. What I'm referring to is the versioning. We have this problem with the Core Content REST API endpoints where they have a v2 version in the path, but all the PHP classes, functions, filters, and an used REST_API_VERSION constant mean that we can't really ever introduce a v3 with breaking changes.
If we include the version naming in the classes and filters, it'd give us the ability to introduce a breaking v2 abilities REST API that runs alongside the v1 endpoints.
I'm not a domain expert here, so if we think there isn't a chance we'd want that, that's fine with me. But given how quickly the "mcp" space seems to be moving, it seemed work raising as a possibility.
7 weeks ago
#32
Thank you for further clarification, @TimothyBJacobs. All clear now, and I’ll update the controller name, file names and URLs based your recommendations.
#33
in reply to:
↑ 28
@
7 weeks ago
Replying to jorbin:
Can you go a bit deeper on what you mean by "self-authenticating"? I'm not finding anything in the github repo or in slack that describes the API in such a way.
I think he means self-authorizing. That is, the Ability can do a permissions check prior to executing.
First-class Integrations API
Something that's been on my mind as I've helped build this comes from my experience building plugins like GiveWP, The Events Calendar, and so forth. Every plugin has 3rd party integration on its mind when building things out. Things like hooks and the REST API are often utilized to provide integration APIs, but there's also just PHP and JS functions/classes and the like meant to be used for integration. At this point, there is no first-class way to do this in WordPress; each plugin is left to determine how it wants to structure its APIs for discoverability and use.
The Ability API is, at its core, a formal public functions API for use in integrations. At this time, we're thinking of contexts such as REST, MCP, Command Palette, CLI, and so forth. But that's really because the Abilities API is already serving its purpose!
This is to say, that I think the Abilities API presents immediate value to the ecosystem, and folks will explore even further contexts for its use. If I was still working on GiveWP, I'd immediately provide a bunch of Abilities for interacting with campaigns, forms, and donations as a first-class way for 3rd parties to discover and use. The fact that these Abilities, with minimal configuration effort, can also be used in REST, MCP, and such is a cherry on top!
The more scenarios I've run through my head with the Abilties API as it is, the more I like it. I'm sure it will be (and should be) battle tested, at which point we'll iterate on it. I'm 100% with you, @jorbin, that I'd like to get this adopted as quickly as possible, and will personally put effort into making that happens during the beta. 👍
7 weeks ago
#34
@aaronjorbin, I can’t respond on my phone to https://github.com/WordPress/wordpress-develop/pull/9410#discussion_r2444533238 in the thread. I see s lot of value in adding check did_action( ‘init’ ) on attempts to instantiate the shared registry object. I’m also in favor of enforcing these registries can’t be used before init. On the technical level, the same effect can be achieved in the singleton get_instance method. Every public method calls it, so we strictly speaking we don’t need another method (that could also be bypassed by developers as you noted in another comment).
Regarding your point about what triggers do_action( ‘wp_abilities_api_init’ ). Every type of function call (wp_get_ability(), wp_has_ability(), wp_get_abilities()) that consumes something from the registry for the first time will create a shared instance and trigger the action. This would pair nicely with the additional restrictions proposed with did_action( ‘init’ ) usage.
#35
@
7 weeks ago
@jason_the_adams My hesitation has nothing to do with the value that Abilities API would bring and everything to do with the fact that so little has been built with it. For example, you mention four contexts, only one of
If this is committed for beta 1, that means there are 21 days until RC1 and 42 days until release. That's not a lot of time to get feedback, iterate, get more feedback, iterate again, ensure that documentation is ready, and overall ensure that come 7.0 we aren't feeling backed into the question of if only the code was structured differently or worse, questioning if this needs large changes in 6.9.1.
7 weeks ago
#36
I renamed REST API controllers and routes based on the feedback in https://github.com/WordPress/wordpress-develop/pull/9410/commits/655d987d309d48c958ff2974de4b93ec9f0831e1:
WP_REST_Abilities_V1_List_Controller/wp-abilities/v1/abilities/(?P<name>[a-zA-Z0-9\-\/]+)/wp-abilities/v1/abilities
WP_REST_Abilities_V1_Run_Controller/wp-abilities/v1/abilities/(?P<name>[a-zA-Z0-9\-\/]+?)/run
7 weeks ago
#37
Initial set of changes enforcing init hook before creating WP_Abilities_Registry instance and WP_Ability_Categories_Registry instance is in place with https://github.com/WordPress/wordpress-develop/pull/9410/commits/4a439fdaa3b460c30c76c0d3183852fd53c59187. I will improve test coverage for ability categories later.
7 weeks ago
#38
The last part of the feedback from https://github.com/WordPress/wordpress-develop/pull/9410#discussion_r2445966990 related to promoting WP_Ability::validate_input() to a public method and moving outside of WP_Ability::check_permissions() was addressed.
CI is extremely slow at the moment, but that's the last missing confirmation needed to ensure all changes work as expected.
#39
@
7 weeks ago
- Owner set to gziolo
- Status changed from new to assigned
@gziolo assigning you so that this ticket has an owner and since you've been driving things
#40
@
7 weeks ago
Can you go a bit deeper on what you mean by "self-authenticating"? I'm not finding anything in the github repo or in slack that describes the API in such a way.
I think he means self-authorizing. That is, the Ability can do a permissions check prior to executing.
Correct. Those two words always confuse me. Thank you @jason_the_adams, for providing further explanation. That's a really powerful contract in PHP: whatever input and permissions are requested, the consumer has to fulfill them.
If this is committed for beta 1, that means there are 21 days until RC1 and 42 days until release. That's not a lot of time to get feedback, iterate, get more feedback, iterate again, ensure that documentation is ready, and overall ensure that come 7.0 we aren't feeling backed into the question of if only the code was structured differently or worse, questioning if this needs large changes in 6.9.1.
I'm finished with addressing all the feedback raised in the review. Now, I'm mostly waiting for CI to finish and report that everything is green to proceed with the merge. Realistically, we have 3 weeks to gather all the feedback from extenders who haven't reported back so far on how the API integrates with their systems. As for all other feedback that was raised during the testing period through the Composer package released during WC US, everything was addressed.
@karmatosed, what would be helpful at this point is opening an issue on GitHub or on WordPress Trac that serves as a single place for project maintainers to report their integration efforts, so we have a better overview of how the process is going.
I know that [Woo has updated https://github.com/woocommerce/woocommerce/pull/60799] the Composer package to v0.3.0 yesterday. The plan is to update the Composer package again as soon as possible with the same code as we are adding to WordPress trunk. So, we will have at least one big plugin that tests at scale in active development, the latest version of the API.
This ticket was mentioned in PR #10380 on WordPress/wordpress-develop by @gziolo.
7 weeks ago
#42
Trac ticket: https://core.trac.wordpress.org/ticket/64098
This ticket was mentioned in PR #10402 on WordPress/wordpress-develop by @jorbin.
7 weeks ago
#48
@gziolo commented on PR #10402:
7 weeks ago
#49
Is this stricly necessary? I followed the feedback from @TimothyBJacobs (https://github.com/WordPress/wordpress-develop/pull/9410#issuecomment-3422905682) when renaming the route and controller.
@jorbin commented on PR #10402:
7 weeks ago
#50
I think so since the name of the resource is ability categories, not categories.
@TimothyBlynJacobs commented on PR #10402:
7 weeks ago
#51
IMO it being within the wp-abilities/v1 namespace means we don't need to, and shouldn't, duplicate the naming here.
This ticket was mentioned in PR #10424 on WordPress/wordpress-develop by @gziolo.
6 weeks ago
#54
Trac ticket: https://core.trac.wordpress.org/ticket/64098
Addresses feedback raised by @jorgefilipecosta during syncing changes to Abilities API repository:
This aligns with how translations are handled across all places in the Abilities API codebase.
@gziolo commented on PR #10424:
6 weeks ago
#56
Committed with https://core.trac.wordpress.org/changeset/61071.
@jorbin commented on PR #10402:
5 weeks ago
#58
My thinking with being specific is that it prevents any confusion between categories and abilities categories. This was what I view as the consensus reached in #9410. While this endpoint is inside the wp-abilities namespace, it's not duplicative since the name is abilities categories not categories. By being consistent and always using the full and accurate name, there is less of a chance to generate confusion.
I think this is important to get right since this isn't something that will be easy to change after 6.9 is released.
This ticket was mentioned in PR #10452 on WordPress/wordpress-develop by @gziolo.
5 weeks ago
#59
Trac ticket: https://core.trac.wordpress.org/ticket/64098
Follow-up for https://github.com/WordPress/wordpress-develop/pull/9410.
Raised by @JasonTheAdams and @felixarntz in https://github.com/WordPress/abilities-api/pull/126#discussion_r2453289205:
I'm curious why we're using
did_action()and notdoing_action?
I did provide similar feedback somewhere else (I believe on the Core PR) - I think allowing registration at any arbitrary point means we're being "forgiving" to developers doing it wrong, which can then lead to far more obscure problems down the line.
I think clearly defined APIs and, given WordPress's procedural nature, clearly defined registration timing are crucial to avoid more complex problems. Better tell the developer they should fix something rather than them running into a problem later that they have no idea on why it's occurring.
Although the code modifications were simple, getting the unit tests to pass was quite an adventure. I'm still not entirely convinced I took the most elegant approach for simulating the proper conditions, but my focus was to make the tests pass with the minimal set of changes necessary.
@jorgefilipecosta commented on PR #10452:
5 weeks ago
#61
@jorbin commented on PR #10402:
5 weeks ago
#62
In order for thsi to make RC1, I'm planning to commit this on Monday, please get any reviews folks have in done before them.
@TimothyBlynJacobs commented on PR #10402:
4 weeks ago
#63
I think this is important to get right since this isn't something that will be easy to change after 6.9 is released.
Agreed.
My thinking with being specific is that it prevents any confusion between categories and abilities categories.
Adopting a specific namespace for the API allows us to organize like endpoints and reduce duplicative naming. Ultimately, Code is Poetry, and I think APIs like:
/wp-abilities/v1/categories /wp-abilities/v1/abilities?category=blah
Are more elegant than:
/wp-abilities/v1/ability-cateogires /wp-abilities/v1/abilities?ability_category=blah
it prevents any confusion between categories and abilities categories
I don't think this is likely to happen. I think the segmentation provided by the namespace and the API structure is pretty different.
@jorbin commented on PR #10402:
4 weeks ago
#64
Adopting a specific namespace for the API allows us to organize like endpoints and reduce duplicative naming. Ultimately, Code is Poetry, and I think APIs like:
/wp-abilities/v1/categories /wp-abilities/v1/abilities?category=blahAre more elegant than:
/wp-abilities/v1/ability-cateogires /wp-abilities/v1/abilities?ability_category=blah
The problem is that it's not accurate. These are not categories, they are ability categories. Using a shortened form that is the name of something else doesn't reduce duplicative naming, it makes it inaccurate.
@TimothyBlynJacobs commented on PR #10402:
4 weeks ago
#65
The argument I understand you to be making, is that the API namespace doesn't matter for naming, and doesn't provide any scoping. I just can't get behind that.
These are not categories, they are ability categories.
I'm struggling to understand what you mean by this. Yes, they are used to categorize abilities. And that should be evident by their URL including "abilities".
Most resources in this API are going to also be about abilities, and I don't want us to need to prefix every one of them with the word ability since it is already described by the namespace.
The mapping of PHP functions doesn't need to be an exact one-to-one with how they are represented in the REST API. We see this in other Core APIs like /wp/v2/types and /wp/v2/statuses. The PHP functions are referring only to "post types" and "post statuses", but they aren't included in the URL.
But even if we do look at the PHP API, we can see that the abilities portion of the symbol is to provide scoping. For example, wp_register_ability() takes a category argument, not an ability_category. The hook to register categories is wp_abilities_api_categories_init not wp_abilities_api_ability_categories_init.
@jorbin commented on PR #10402:
4 weeks ago
#66
I'm struggling to understand what you mean by this. Yes, they are used to categorize abilities. And that should be evident by their URL including "abilities".
The consensus decided in #9410 was to name them Abilities Categories with the specific idea being "We always refer to them as Ability Categories and not merely "category"". What I'm hoping to do here is to live up to that consensus.
But even if we do look at the PHP API, we can see that the abilities portion of the symbol is to provide scoping. For example, wp_register_ability() takes a category argument, not an ability_category. The hook to register categories is wp_abilities_api_categories_init not wp_abilities_api_ability_categories_init.
Thanks, I'll open a new PR to fix that.
#67
@
4 weeks ago
- Keywords add-to-field-guide added; needs-dev-note removed
There is now a devnote that should be included in the field guide: https://make.wordpress.org/core/2025/11/10/abilities-api-in-wordpress-6-9/
Trac ticket: https://core.trac.wordpress.org/ticket/64098
Testing how the proposed implementation for the Abilities API integrates with WordPress Core: