[wp-trac] [WordPress Trac] #65358: AI Provider Priority and Fallback

WordPress Trac noreply at wordpress.org
Wed May 27 14:56:14 UTC 2026


#65358: AI Provider Priority and Fallback
-----------------------------+-----------------------------
 Reporter:  georgestephanis  |      Owner:  (none)
     Type:  enhancement      |     Status:  new
 Priority:  normal           |  Milestone:  Awaiting Review
Component:  AI               |    Version:  7.0
 Severity:  normal           |   Keywords:
  Focuses:                   |
-----------------------------+-----------------------------
 **AI Disclosure:** While I found and have been exploring this issue, I've
 leveraged LLMs such as Claude and Copilot to aid in detailing the
 intricacies of a new API and libraries and to aid in trying to make my
 ramblings more intelligible.


 ----


 WordPress 7.0 introduced a Connectors API and a Settings > Connectors
 screen that lets site owners connect multiple AI providers (OpenAI,
 Anthropic, Google, and third-party plugins).  However, the underlying AI
 client (`php-ai-client`) has no way to honour a site owner's preference
 about **which provider to use first**, and no way to **automatically try
 the next provider** when the chosen one fails.  The result is that
 provider selection is effectively random from the site owner's
 perspective, and a single provider outage or rate-limit error produces a
 hard failure even when other connected providers could fulfil the request.

 This ticket proposes two related changes to WordPress core:

 1. A filter that lets plugins express a preferred provider order.
 2. Automatic fallback to the next provider in that order when generation
 fails.

 ## Background: how the AI client selects a provider today

 When WordPress (or a plugin) calls `wp_ai_client_prompt()`, it returns a
 `WP_AI_Client_Prompt_Builder`.  Calling `->generate_text()` (or any other
 generation method) on that builder triggers the following sequence inside
 `PromptBuilder::generateResult()`:

 1. `getConfiguredModel()` calls
 `ProviderRegistry::findModelsMetadataForSupport()` to discover every
 registered provider/model pair that meets the capability requirements.
 2. `findModelsMetadataForSupport()` iterates
 `$this->registeredIdsToClassNames` — a plain PHP array whose insertion
 order equals the order in which AI provider plugins registered themselves,
 which in practice equals plugin-activation order.
 3. The first matching provider/model in that list is selected.  No filter
 is applied; there is no concept of "preferred" provider at this layer.
 4. `executeModelGeneration()` calls the chosen model directly.  There is
 no try/catch around the actual API call: if the provider returns a rate-
 limit error, an authentication failure, or a service outage, the exception
 propagates immediately to the caller.  No other provider is tried.

 The `ai` core plugin adds a partial workaround for features that extend
 `Abstract_Ability`: three filters (`wpai_preferred_text_models`,
 `wpai_preferred_image_models`, `wpai_preferred_vision_models`) let plugins
 reorder the `[provider, model]` preference list that is passed to
 `->usingModelPreference()`.  This covers those features only.  Any code
 that calls `wp_ai_client_prompt()` directly — including core itself and
 third-party plugins that do not depend on the `ai` plugin — bypasses these
 filters entirely.

 ## Problem 1 — No user-configurable provider priority

 ### Current behaviour

 A site with OpenAI, Anthropic, and Google all connected has no way to tell
 WordPress "prefer Anthropic for all AI features."  The provider that was
 activated first wins every time.  Plugin deactivation/reactivation order,
 bulk-activation order, or a hosting environment that activates plugins in
 filesystem order can all silently change which provider is used.

 ### User impact

 - **Cost control**: a site owner may have a cheaper or free-tier provider
 they want tried first, falling back to a more expensive one only if
 needed.
 - **Quality control**: different providers have different strengths; a
 site owner may strongly prefer one model for writing tasks and another for
 image generation.
 - **Compliance / data residency**: some organisations must route data
 through a specific provider for legal reasons.  Activation order gives
 them no guarantee.
 - **Predictability**: when AI-generated output changes unexpectedly, the
 root cause is often a silent provider switch.  There is currently no way
 to lock a preference without writing custom code.

 ## Problem 2 — No automatic fallback when a provider fails

 ### Current behaviour

 Once `PromptBuilder` has selected a provider, it calls the provider's
 generation method directly inside `executeModelGeneration()`.  The call is
 not wrapped in any error handling.  A runtime exception — caused by a
 rate-limit response, an expired API key, a provider outage, a network
 timeout, or a quota exhaustion — propagates immediately to the caller as
 an unhandled exception.

 No other provider is tried, even if multiple connected providers could
 fulfil exactly the same request.

 ### User impact

 - **Silent feature failures**: an excerpt-generation button returns an
 error to the editor even though two other connected and working providers
 exist on the site.
 - **Rate limits become site-wide outages**: hitting an API rate limit on
 the primary provider disables all AI features for every user on the site
 until the limit resets, even if a secondary provider is available.
 - **Reliability expectation gap**: site owners who connect multiple
 providers reasonably expect that doing so provides redundancy.  It does
 not today.
 - **No cost-aware routing**: there is no way to attempt a cheaper
 provider, accept failure only from that one, and escalate to a more
 expensive provider — a common pattern in production AI applications.

 #### Important design considerations

 - **Only runtime failures trigger fallback.**  Configuration errors
 (`InvalidArgumentException`) — e.g. an unsupported capability — should
 still propagate immediately.  Falling back to a different provider will
 not fix a misconfigured prompt.
 - **Fallback should be opt-in or clearly documented.**  Some callers may
 not want silent fallback (e.g. a feature that explicitly requires a
 specific provider's output format).  A filter such as
 `wp_ai_provider_fallback_enabled` (defaulting `true`) would let callers
 disable it when needed.
 - **An action hook on provider failure** (`wp_ai_provider_failed`) would
 allow monitoring plugins to surface repeated failures to the site admin,
 which is valuable operational feedback independently of the priority
 feature.


 ## How these two changes interact

 Priority and fallback are independent features that compose naturally (oh
 gosh will this table markdown syntax work in trac...)

 | Scenario | With priority only | With priority + fallback |
 |---|---|---|
 | Multiple providers connected, all working | Preferred provider used |
 Preferred provider used |
 | Preferred provider hits rate limit | Hard error | Next provider tried
 automatically |
 | Preferred provider has an outage | Hard error | Next provider tried
 automatically |
 | No providers connected | Error (unchanged) | Error (unchanged) |

 The priority filter determines the order; the fallback loop determines
 what happens when an item in that order fails.  Neither requires the
 other, but together they deliver the reliability that the existence of a
 multi-provider UI implies.

 ## Current workarounds and their limitations

 | Approach | What it covers | What it misses |
 |---|---|---|
 | `wpai_preferred_text/image/vision_models` filters (bundled `ai` plugin)
 | `Abstract_Ability` subclasses | Direct `wp_ai_client_prompt()` callers;
 requires `ai` plugin |
 | `wp_get_preferred_ai_connector()` (connector-priority plugin) | Anything
 that calls it explicitly | Must be called by every third-party developer;
 no fallback |
 | `script_module_data_*` filter reordering | Connectors screen UI order |
 Runtime provider selection |
 | No fallback mechanism exists at any layer | — | All callers |

 A proof-of-concept plugin ([connector-
 priority](https://github.com/georgestephanis/connector-priority))
 demonstrates the full UI and storage side: drag-and-drop ordering, REST-
 exposed
 option, PHP API, and the `script_module_data_*` reordering.  The remaining
 gap is
 entirely within `php-ai-client` and requires the core changes described
 above.

 ## Prior art

 - The bundled `ai` plugin already implements this pattern one level below
 `PromptBuilder`, via `wpai_preferred_text_models` etc.  The proposed
 `wp_ai_provider_priority` filter is the same idea lifted to the layer that
 all callers share.
 - Production AI infrastructure (AWS Bedrock fallback models, Azure OpenAI
 fallback deployments, LangChain's fallback chains) universally treats "try
 next provider on failure" as a first-class concern, not an application-
 level responsibility.
 - The connector-priority plugin's `_connector_priority_sort_models()`
 function (which re-sorts `[provider, model]` pairs) is essentially the
 same algorithm as the proposed `ProviderRegistry` change, just applied at
 a different layer.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/65358>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list