[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