Skip to content

Abilities API: Add an eligibility callback for situational relevance - #13356

Draft
gziolo wants to merge 2 commits into
WordPress:trunkfrom
gziolo:add/abilities-eligibility-callback
Draft

Abilities API: Add an eligibility callback for situational relevance#13356
gziolo wants to merge 2 commits into
WordPress:trunkfrom
gziolo:add/abilities-eligibility-callback

Conversation

@gziolo

@gziolo gziolo commented Sep 1, 2026

Copy link
Copy Markdown
Member

What

This is a draft to explore the design in the open.

An ability can declare an eligibility_callback when it is registered. The callback receives an array that describes where the caller is. It returns true or false to say if the ability is useful there. wp_get_abilities() accepts a new eligibility_context argument. Abilities whose callback returns false are left out. The REST collection accepts the same data through an eligibility_context query parameter.

The first user of this feature is a WebMCP adapter (WordPress/ai#448). It registers tools for each admin screen and each frontend page. A site with hundreds of abilities can then expose only the few that matter on the current page.

Contract

Three things stay separate:

  • Permission: can the current user run this? Checked by permission_callback when the ability runs.
  • Exposure: does the site owner allow this ability on this surface? See Unifiied Abilities exposure controls ai#354.
  • Eligibility: does the ability author think it is useful in this context? This PR.

Eligibility is not a security check. The callback runs only when listing abilities. It never runs when an ability executes. It never runs on the single ability REST route. The context comes from the caller and is not verified. Nothing security related may depend on it.

The result without a context is the upper bound. With no context, callbacks are not called and every ability is included. Context keys can only remove abilities from a result. They can never add more. This keeps the MCP adapter's tools/list complete, because it passes no context.

An ability without a callback is always included. A callback that returns something that is not a boolean is treated as true.

Core does not define the context keys. Callers and ability authors agree on them. Plugins should prefix their own keys, like plugin-slug/key. The REST parameter declares no properties, so values arrive as strings. A plugin can declare typed keys with the existing rest_abilities_collection_params filter.

New API

  • eligibility_callback registration argument. Must be callable.
  • WP_Ability::is_eligible( array $eligibility_context = array() ): bool, with a wp_ability_eligibility_result filter. It follows the same pattern as the other lifecycle filters.
  • eligibility_context argument for wp_get_abilities(). It runs in the same loop, after the category, namespace, and meta filters and before item_include_callback. The wp_get_abilities_item_include filter can see it through $args.
  • eligibility_context object parameter on the wp-abilities/v1/abilities route. Bracket syntax works: eligibility_context[post_type]=product.

Open questions

  • Should an empty context still call the callbacks? Right now it does not. Evaluation starts only when the caller passes at least one key.
  • The Trac ticket does not exist yet. The new tests will get @ticket annotations once it does.
  • The JavaScript side (@wordpress/abilities and @wordpress/core-abilities) lives in the Gutenberg repository and will follow separately.

🤖 Generated with Claude Code

An ability can declare an eligibility_callback at registration. The
callback receives an associative array describing the caller's usage
context and returns whether the ability applies there.
wp_get_abilities() accepts an eligibility_context argument and drops
abilities whose callback returns false. The abilities REST collection
accepts the same context through an eligibility_context query parameter.
Eligibility is consulted only when listing abilities, never on execute,
and it is not a security boundary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant