I was on a call with a client last week. They run a complex membership site: WooCommerce, custom post types, and a half-dozen other plugins. They wanted to plug in a new external AI service that would generate summaries for their premium content automatically. The catch was that the AI tool needed a clean, reliable way to ask the site, “What can you do, and how do I ask for it?” Right now the answer was a mess: a few custom AJAX endpoints here, some poorly documented plugin functions there. A classic integration headache.
This is exactly the kind of headache the new Abilities API in WordPress 6.9 is meant to solve, and not only for AI. It is a foundational shift in how we should be building discoverable, interoperable functions in WordPress. Before it, we were mostly winging it.
My first thought was to build another custom REST endpoint for this one AI tool and be done with it. That would have worked for now. But next month they will want to connect a different service, maybe for analytics or user management, and then I am building another one-off endpoint, and another. That is how you end up with a brittle system that nobody can maintain, a short-term fix that piles up technical debt quickly.
How the Abilities API actually fixes this mess
Instead of isolated endpoints, the Abilities API gives you one standardized registry. You register a function, an “ability,” and define what it does, what inputs it takes, what it returns, and who is allowed to run it. That definition is self-documenting and machine-readable, so any service, internal or external, can ask WordPress for its list of registered abilities and know how to work with them. No more digging through source code.
Think of it as a universal command palette for your site’s functions. It is a real step up. The core team has done serious groundwork here, which you can read about in the official dev notes on the WordPress Core blog.
In practice, that means for my client I register an ability that fetches the latest premium post instead of building a custom endpoint. It looks something like this.
<?php
// 1. Register a category for our custom abilities
add_action( 'wp_abilities_api_categories_init', 'bbioon_register_ability_categories' );
function bbioon_register_ability_categories() {
wp_register_ability_category(
'content-tools',
[
'label' => __( 'Content Tools', 'bbioon' ),
'description' => __( 'Custom abilities for managing site content.', 'bbioon' ),
]
);
}
// 2. Register the actual ability
add_action( 'wp_abilities_api_init', 'bbioon_register_abilities' );
function bbioon_register_abilities() {
// First, check if the function exists for backward compatibility
if ( ! function_exists( 'wp_register_ability' ) ) {
return;
}
wp_register_ability(
'bbioon/get-premium-post-summary',
[
'label' => __( 'Get Premium Post Summary', 'bbioon' ),
'description' => __( 'Retrieves the title and excerpt of the latest premium post.', 'bbioon' ),
'category' => 'content-tools',
'output_schema' => [
'type' => 'object',
'properties' => [
'title' => [ 'type' => 'string' ],
'excerpt' => [ 'type' => 'string' ],
'url' => [ 'type' => 'string' ],
],
],
'execute_callback' => 'bbioon_get_latest_premium_post_data',
'permission_callback' => function() {
// Only allow users who can edit posts to run this.
return current_user_can( 'edit_posts' );
},
'meta' => [
'show_in_rest' => true, // This makes it available via the REST API
]
]
);
}
// 3. The function that does the work
function bbioon_get_latest_premium_post_data() {
$args = [
'post_type' => 'post',
'posts_per_page' => 1,
'meta_key' => '_is_premium', // Assuming a meta key for premium content
'meta_value' => '1',
];
$latest_posts = get_posts( $args );
if ( empty( $latest_posts ) ) {
return new WP_Error( 'not_found', 'No premium posts found.' );
}
$post = $latest_posts[0];
return [
'title' => get_the_title( $post ),
'excerpt' => has_excerpt( $post ) ? get_the_excerpt( $post ) : wp_trim_words( $post->post_content, 40 ),
'url' => get_permalink( $post ),
];
}
So what does this get you?
This is not just a shiny new toy for developers. The Abilities API is a real improvement to WordPress architecture. A few things stand out:
- It forces cleaner code: defining schemas and permissions upfront pushes you toward a more structured approach, instead of random functions scattered everywhere.
- It is future-proof: it lays groundwork for more advanced integrations, especially with AI and automation tools, so building this way now leaves you ready for what comes next.
- It simplifies integrations: next time a client wants to connect a new service, you do not build a whole new API, you just register a new ability.
This gets complicated quickly. If you are tired of untangling someone else’s mess and just want your site to work, get in touch with my team. We have probably seen it before.
Adopting the Abilities API now moves you away from quick hacks and toward WordPress applications that are easier to maintain and extend. It is a better way to build, and honestly it is overdue.