Skip to content

Add extensibility hooks for system instructions, ability results, and post context#304

Open
Ryujiyasu wants to merge 4 commits intoWordPress:developfrom
Ryujiyasu:feat/hook-audit-extensibility-hooks
Open

Add extensibility hooks for system instructions, ability results, and post context#304
Ryujiyasu wants to merge 4 commits intoWordPress:developfrom
Ryujiyasu:feat/hook-audit-extensibility-hooks

Conversation

@Ryujiyasu
Copy link
Copy Markdown

@Ryujiyasu Ryujiyasu commented Mar 13, 2026

Summary

Implements the extensibility hooks agreed upon in the #34 hook audit discussion with @dkotter.

New Filters

1. System Instruction Filter (Abstract_Ability)

  • ai_experiments_system_instruction — Filters the system instruction text before it's passed to the AI model. Receives the instruction string, ability name, and data array.

2. Ability Result Filters (Abstract_Ability)

  • ai_experiments_ability_result — Generic filter applied to the result of any ability execution. Receives the result, ability name, and input.
  • ai_experiments_ability_result_{$name} — Dynamic filter for a specific ability (e.g., ai_experiments_ability_result_ai/title-generation). Receives the result and input.

3. Post Context Filters (in the Abilities, per discussion)

  • ai_experiments_get_post_details — Filters post details returned by the ai/get-post-details ability. Receives details array, post ID, and requested fields.
  • ai_experiments_get_post_terms — Filters terms returned by the ai/get-post-terms ability. Receives terms array, post ID, and allowed taxonomies.

Design Decisions

  • Result filtering is implemented via a filtered_execute_callback wrapper in Abstract_Ability that wraps the abstract execute_callback. This avoids requiring changes to every concrete ability class while ensuring all abilities get consistent filtering.
  • WP_Error results are not filtered — errors pass through unmodified.
  • Post context filters are in the Abilities only (not in get_post_context helper), as agreed with @dkotter.

Example Usage

// Modify system instructions for all abilities.
add_filter( 'ai_experiments_system_instruction', function( $instruction, $name, $data ) {
    return $instruction . "\n\nAlways respond in formal tone.";
}, 10, 3 );

// Filter title generation results.
add_filter( 'ai_experiments_ability_result_ai/title-generation', function( $result, $input ) {
    // Remove any titles that are too long.
    if ( is_array( $result ) ) {
        $result = array_filter( $result, fn( $title ) => strlen( $title ) <= 100 );
    }
    return $result;
}, 10, 2 );

// Redact sensitive fields from post details before AI processing.
add_filter( 'ai_experiments_get_post_details', function( $details, $post_id, $fields ) {
    unset( $details['author'] );
    return $details;
}, 10, 3 );

Closes #34

Test Plan

  • Verify existing ability tests still pass
  • Verify ai_experiments_system_instruction filter modifies system instructions
  • Verify ai_experiments_ability_result filter modifies ability results
  • Verify ai_experiments_get_post_details filter modifies post details
  • Verify ai_experiments_get_post_terms filter modifies post terms
  • Verify WP_Error results are not filtered
Open WordPress Playground Preview

… post context

Adds filters agreed upon in WordPress#34 hook audit discussion:

- `ai_experiments_system_instruction` in Abstract_Ability::get_system_instruction()
- `ai_experiments_ability_result` and `ai_experiments_ability_result_{$name}` for filtering ability execution results
- `ai_experiments_get_post_details` in get-post-details ability
- `ai_experiments_get_post_terms` in get-post-terms ability
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 13, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: Ryujiyasu <[email protected]>
Co-authored-by: dkotter <[email protected]>
Co-authored-by: gziolo <[email protected]>
Co-authored-by: jeffpaul <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Tests cover:
- ai_experiments_system_instruction filter modifies instructions
- ai_experiments_system_instruction filter receives correct ability name
- ai_experiments_ability_result filter modifies results
- ai_experiments_ability_result_{$name} dynamic filter works
- WP_Error results bypass filtering
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 57.89%. Comparing base (f2b29e6) to head (5483953).
⚠️ Report is 177 commits behind head on develop.

Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #304      +/-   ##
=============================================
- Coverage      58.03%   57.89%   -0.15%     
- Complexity       576      615      +39     
=============================================
  Files             37       46       +9     
  Lines           2955     3168     +213     
=============================================
+ Hits            1715     1834     +119     
- Misses          1240     1334      +94     
Flag Coverage Δ
unit 57.89% <100.00%> (-0.15%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jeffpaul jeffpaul requested a review from dkotter March 13, 2026 15:07
@jeffpaul jeffpaul added this to the 0.6.0 milestone Mar 13, 2026
@gziolo
Copy link
Copy Markdown
Member

gziolo commented Mar 16, 2026

The plugin is being renamed in #287 by @dkotter. There is a related feedback #287 (review) from @jeffpaul, which makes perfect sense here as well:

Imay want to consider updating other parts of the codebase to remove experiment-named items to make things simpler to maintain in the future even if that's a backcompat break (as generally something that would be easier to do before 7.0 than after).

This applies to the names of the proposed hooks. Let's finalize the naming conventions here. Also note that in WP core, all AI related hooks are prefixed with wp_.

@gziolo
Copy link
Copy Markdown
Member

gziolo commented Mar 16, 2026

Thanks for working on this, @Ryujiyasu! I'm very much in favor of adding extensibility filters — this is exactly the kind of developer control the plugin needs.

However, after reviewing this alongside prior work on the Abilities API, I think some of these filters would be better suited for WP core rather than the plugin. Here's my analysis:

Filters that should go to WP core

WP core already fires wp_after_execute_ability in WP_Ability::execute(), but as an action — not a filter — so developers can observe results but can't modify them. A core-level result filter would close that gap for all abilities.

ai_experiments_ability_result and ai_experiments_ability_result_{$name}

These are generic "filter the result of any ability execution" hooks — not AI-specific. The same concept was proposed in the Abilities API repo in the early phase of development:

Placing result filtering in core (inside WP_Ability::execute()) would be better because:

  1. It applies to all abilities, not just those extending Abstract_Ability from this plugin.
  2. It sits in the proper lifecycle — after do_execute(), integrated with output validation — rather than requiring the filtered_execute_callback workaround that adds a public method as an implementation detail.
  3. It avoids the current issue where filtered results that don't conform to the ability's output schema will cause validate_output() to fail silently.
  4. The relationship between result filters and the existing core action wp_after_execute_ability needs to be designed intentionally at the core level, so developers know whether they receive the original result or a filtered one.

Now that Abilities API development has moved to core, these filters should be proposed there. I'd be happy to help with that.

Filters that belong in this plugin

ai_experiments_system_instruction — This is plugin-specific (system instructions are an AI concept with no core equivalent). Looks good as-is.

ai_experiments_get_post_details / ai_experiments_get_post_terms — These filter data within plugin-specific utility abilities, or could they be also superseeded by filters added directly?

/**
* Filters the post details returned by the get-post-details ability.
*
* @since 0.5.0
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's replace all @since statements with x.x.x as we're not sure of the actual version until we prep a release (and we have a step in our release process to find and replace all of those)

@dkotter
Copy link
Copy Markdown
Collaborator

dkotter commented Mar 18, 2026

The plugin is being renamed in #287 by @dkotter. There is a related feedback #287 (review) from @jeffpaul, which makes perfect sense here as well:

Imay want to consider updating other parts of the codebase to remove experiment-named items to make things simpler to maintain in the future even if that's a backcompat break (as generally something that would be easier to do before 7.0 than after).

This applies to the names of the proposed hooks. Let's finalize the naming conventions here. Also note that in WP core, all AI related hooks are prefixed with wp_.

Note we've settled on wpai_ for our prefix (see #315) so we can update all hooks in this PR to use that now instead of ai_experiments_

@jeffpaul jeffpaul mentioned this pull request Mar 18, 2026
33 tasks
@dkotter dkotter modified the milestones: 0.6.0, 0.7.0 Mar 19, 2026
…_result filters

- Rename all hook prefixes from ai_experiments_ to wpai_ per WordPress#315 decision
- Replace @SInCE 0.5.0 with @SInCE x.x.x for release-time replacement
- Remove ability_result and ability_result_{$name} filters (to be proposed
  for WP core per @gziolo's feedback)
- Replace filtered_execute_callback with simple do_execute wrapper
- Remove related tests and Test_Error_Ability class
@gziolo
Copy link
Copy Markdown
Member

gziolo commented Mar 24, 2026

Remove ability_result and ability_result_{$name} filters (to be proposed for WP core per @gziolo's feedback)

I will have to open a WordPress Trac ticket so it's lined up for WP 7.1. I will see if we can find a way to include it in the AI plugin faster, conditionally. Maybe, through some feature detection or PHP version check.

@gziolo
Copy link
Copy Markdown
Member

gziolo commented Mar 30, 2026

I opened Abilities API: Add execution lifecycle filters to WP_Ability methods to track the functionality needed directly in WordPress core. I appreciate all the feedback as well!

I also included there a related note:

MCP Adapter (WordPress/mcp-adapter) implements mcp_adapter_-prefixed hooks for validation toggling, caching, and post-execution audit. The team has decided to maintain their own lower-level filters on top of whatever core provides (mcp-adapter#151), but richer core hooks would reduce the scope of what the adapter needs to re-implement.

It's worth looking at the same angle as the MCP adapter and figuring out whether additional filters in the execution flow are needed, or if it is fine to wait until WP 7.1 for what WP core will implement.

@Ryujiyasu
Copy link
Copy Markdown
Author

I think it's fine to wait for WP 7.1 for the execution lifecycle filters in core (Trac #64989). This PR is already scoped to plugin-specific hooks only, and adding interim ability result filters here would create backcompat overhead once core ships them. The MCP Adapter has different needs (caching, validation toggling) that justify their own hooks, but for this plugin, relying on core seems cleaner. Happy to help with the core implementation when the time comes.

@Ryujiyasu
Copy link
Copy Markdown
Author

Regarding wpai_get_post_details and wpai_get_post_terms — I kept them because they pass internal context like $post_id and $fields directly, which felt convenient for plugin-level use. That said, if you think core-level filters would cover this well enough, I'm happy to remove them.

The do_execute method was originally added to support ability_result
filters, which were removed in the previous commit. Revert to directly
registering execute_callback as it was before.
Copy link
Copy Markdown
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to add test coverage for wpai_get_post_terms and wpai_get_post_details, following wpai_system_instruction case. Otherwise, we are good to go.

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.

Audit Codebase for Strategic Hook Opportunities

4 participants