Hooks
November 14, 2025 ยท View on GitHub
The Abilities API provides WordPress Action and Filter Hooks that allow developers to monitor and respond to ability execution events.
Quick Links
Actions
wp_abilities_api_categories_init
Fires when the category registry is first initialized. This is the proper hook to use when registering categories.
do_action( 'wp_abilities_api_categories_init', $registry );
Parameters
$registry(\WP_Ability_Categories_Registry): The category registry instance.
Usage Example
add_action( 'wp_abilities_api_categories_init', 'my_plugin_register_categories' );
/**
* Register custom ability categories.
*
* @param \WP_Ability_Categories_Registry $registry The category registry instance.
*/
function my_plugin_register_categories( $registry ) {
wp_register_ability_category( 'ecommerce', array(
'label' => __( 'E-commerce', 'my-plugin' ),
'description' => __( 'Abilities related to e-commerce functionality.', 'my-plugin' ),
));
wp_register_ability_category( 'analytics', array(
'label' => __( 'Analytics', 'my-plugin' ),
'description' => __( 'Abilities that provide analytical data and insights.', 'my-plugin' ),
));
}
wp_abilities_api_init
Fires when the abilities registry has been initialized. This is the proper hook to use when registering abilities.
do_action( 'wp_abilities_api_init', $registry );
Parameters
$registry(\WP_Abilities_Registry): The abilities registry instance.
Usage Example
add_action('wp_abilities_api_init', 'my_plugin_register_abilities');
/**
* Register custom abilities.
*/
function my_plugin_register_abilities() {
wp_register_ability( 'my-plugin/ability', array(
'label' => __( 'Title', 'my-plugin' ),
'description' => __( 'Description.', 'my-plugin' ),
'category' => 'analytics',
'input_schema' => array(
'type' => 'object',
'properties' => array(),
'additionalProperties' => false,
),
'output_schema' => array(
'type' => 'string',
'description' => 'The site title.',
),
'execute_callback' => 'my_plugin_get_site_title',
'permission_callback' => '__return_true', // Everyone can access this
'meta' => array(
'show_in_rest' => true, // Optional: expose via REST API
),
) );
}
wp_before_execute_ability
Fires immediately before an ability gets executed, after permission checks have passed but before the execution callback is called.
do_action( 'wp_before_execute_ability', $ability_name, $input );
Parameters
$ability_name(string): The namespaced name of the ability being executed (e.g.,my-plugin/get-posts).$input(mixed): The input data passed to the ability.
Usage Example
add_action( 'wp_before_execute_ability', 'log_ability_execution', 10, 2 );
/**
* Log each ability execution attempt.
* @param string $ability_name The name of the ability being executed.
* @param mixed $input The input data passed to the ability.
*/
function log_ability_execution( string $ability_name, $input ) {
error_log( 'About to execute ability: ' . $ability_name );
if ( $input !== null ) {
error_log( 'Input: ' . wp_json_encode( $input ) );
}
}
wp_after_execute_ability
Fires immediately after an ability has finished executing successfully, after output validation has passed.
do_action( 'wp_after_execute_ability', string $ability_name, $input, $result );
Parameters
$ability_name(string): The namespaced name of the ability that was executed.$input(mixed): The input data that was passed to the ability.$result(mixed): The validated result returned by the ability's execution callback.
Usage Example
add_action( 'wp_after_execute_ability', 'log_ability_result', 10, 3 );
/**
* Log the result of each ability execution.
*
* @param string $ability_name The name of the executed ability.
* @param mixed $input The input data passed to the ability.
* @param mixed $result The result returned by the ability.
*/
function log_ability_result( string $ability_name, $input, $result ) {
error_log( 'Completed ability: ' . $ability_name );
error_log( 'Result: ' . wp_json_encode( $result ) );
}
Filters
wp_register_ability_args
Allows modification of an Ability's args before they are validated and used to instantiate the Ability.
$args = apply_filters( 'wp_register_ability_args', array $args, string $ability_name );
Parameters
$args(array<string,mixed>): The arguments used to instantiate the ability. See wp_register_ability() for the full list of args.$ability_name(string): The namespaced name of the ability being registered (e.g.,my-plugin/get-posts).
Usage Example
add_filter( 'wp_register_ability_args', 'my_modify_ability_args', 10, 2 );
/**
* Modify ability args before validation.
*
* @param array<string,mixed> $args The arguments used to instantiate the ability.
* @param string $ability_name The name of the ability, with its namespace.
*
* @return array<string,mixed> The modified ability arguments.
*/
function my_modify_ability_args( array $args, string $ability_name ): array {
// Check if the ability name matches what you're looking for.
if ( 'my-namespace/my-ability' !== $ability_name ) {
return $args;
}
// Modify the args as needed.
$args['label'] = __('My Custom Ability Label');
// You can use the old args to build new ones.
$args['description'] = sprintf(
/* translators: 1: Ability name 2: Previous description */
__('This is a custom description for the ability %s. Previously the description was %s', 'text-domain'),
$ability_name,
$args['description'] ?? 'N/A'
);
// Even if they're callbacks.
$args['permission_callback' ] = static function ( $input = null ) use ( $args, $ability_name ) {
$previous_check = is_callable( $args['permission_callback'] ) ? $args['permission_callback']( $input ) : true;
// If we already failed, no need for stricter checks.
if ( ! $previous_check || is_wp_error( $previous_check ) ) {
return $previous_check;
}
return current_user_can( 'my_custom_ability_cap', $ability_name );
}
return $args;
}
wp_register_ability_category_args
Allows modification of a category's arguments before validation.
$args = apply_filters( 'wp_register_ability_category_args', array $args, string $slug );
Parameters
$args(array<string,mixed>): The arguments used to instantiate the category (label, description).$slug(string): The slug of the category being registered.
Usage Example
add_filter( 'wp_register_ability_category_args', 'my_modify_category_args', 10, 2 );
/**
* Modify category args before validation.
*
* @param array<string,mixed> $args The arguments used to instantiate the category.
* @param string $slug The slug of the category being registered.
*
* @return array<string,mixed> The modified category arguments.
*/
function my_modify_category_args( array $args, string $slug ): array {
if ( 'my-category' === $slug ) {
$args['label'] = __( 'My Custom Label', 'my-plugin' );
$args['description'] = __( 'My custom description for this category.', 'my-plugin' );
}
return $args;
}