[wp-trac] [WordPress Trac] #65097: Add action to `WP_AI_Client_Prompt_Builder` for builder-level configuration injection
WordPress Trac
noreply at wordpress.org
Sat Apr 18 08:45:07 UTC 2026
#65097: Add action to `WP_AI_Client_Prompt_Builder` for builder-level configuration
injection
-----------------------------+-----------------------------------
Reporter: takshil | Owner: (none)
Type: feature request | Status: new
Priority: normal | Milestone: Awaiting Review
Component: AI | Version:
Severity: normal | Keywords: 2nd-opinion has-patch
Focuses: |
-----------------------------+-----------------------------------
== Problem ==
Currently, model selection happens in one of two places:
1. '''Inside the SDK / connector''' - provider-default model ordering. Its
useful but provider-scoped, cannot express ''cross-provider'' preferences
like "use OpenAI for text, Mistral for images."
2. '''Inside each consumer plugin''' - hardcoded `using_model_preference(
'gpt-5.4', 'claude-sonnet-4-6' )`. Fragmented, opaque to site owners, no
shared coordination.
There is no third place - no site-owner-controlled layer that applies
across all consumer plugins. A standalone "preferences" plugin can store
the user's choices but has no way to inject them into builders constructed
elsewhere, because no construction time hook exists.
== Proposed solution ==
Add one action at the end of `WP_AI_Client_Prompt_Builder::__construct()`,
immediately after the existing default-timeout block:
{{{#!php
<?php
// In wp-includes/ai-client/class-wp-ai-client-prompt-builder.php
/**
* Fires after a prompt builder is constructed, before any caller
chaining.
*
* Allows plugins to apply default configuration that callers can still
override via subsequent
* fluent method calls. Because this fires at construction, any chain
applied
* by the caller takes precedence per the SDK's first-match resolution.
*
* @since 7.x.0
*
* @param WP_AI_Client_Prompt_Builder $builder The newly constructed
builder.
* @param mixed $prompt The initial prompt content.
*/
do_action_ref_array( 'wp_ai_client_prompt_builder_init', array( $this,
$prompt ) );
}}}
=== Caller precedence is automatic ===
{{{
1. Core constructs builder
2. wp_ai_client_default_request_timeout fires → sets timeout
3. wp_ai_client_prompt_builder_init fires → preferences plugin chains
->using_model_preference('gpt-5.4', 'mistral-image-v1', ...)
4. Builder returns to the caller
5. Caller chains its own potentially by a plugin allowing user's
preferences
to be set with a UI->using_model_preference('claude-sonnet-4-6').
Could be a separate plugin for now, I have some ideas.
6. SDK's first-match resolution at generate_*() time picks the first model
that (a) supports the requested capability and (b) has credentials.
The caller's explicit preference wins because it's evaluated first.
}}}
== Why an Action? ==
It comes down to what listeners will dominantly do:
- Mutate via `->using_model_preference()` chains → action is the cleaner
fit (no return tax, natural accumulation)
- Replace/decorate the builder → filter is required
Going towards `pre_get_posts` precedent. Core's go-to hook for "mutate a
fluent/builder-like object" is an action, not a filter, precisely because
filtering a stateful mutable object invites bugs. This is the closest
analog I thought of in core. Though open to discussion for filter if the
AI team prefers consistency with the existing two filters in this file
== Discussion ==
* Slack: WordPress.org `#core-ai`, thread starting 2026-04-17
(https://wordpress.slack.com/archives/C08TJ8BPULS/p1776411977337179).
--
Ticket URL: <https://core.trac.wordpress.org/ticket/65097>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list