WP Manifestindependent plugin directory
manifest / ai / wp-ai-gateway

WP AI Gateway

OpenAI-compatible AI gateway for WordPress, backed by the WordPress AI Client

by Chris Huber · github.com/automattic/wp-ai-gateway · website

2stars
1forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/automattic/wp-ai-gateway/archive/refs/heads/main.zip

OpenAI-compatible AI gateway for WordPress, backed by the WordPress AI Client.

WP AI Gateway lets external clients use a WordPress site as an AI provider endpoint. The site owns authentication, model routing, and provider credentials; clients only receive a scoped gateway token.

Any OpenAI-compatible client
        |
        v
WP AI Gateway
        |
        v
WordPress AI Client
        |
        v
Configured provider and model

Requirements

  • WordPress 7.0 or newer, including the bundled WordPress AI Client
  • PHP 7.4 or newer
  • At least one WordPress AI Client provider plugin configured on the site

What It Does

  • Exposes OpenAI-compatible /models, /responses, and /embeddings REST endpoints.
  • Authenticates external clients with independently revocable site-issued bearer tokens.
  • Supports short-lived, WordPress-user-bound runtime credentials limited to site-default.
  • Routes site-default to the provider/model configured on the WordPress site.
  • Resolves provider API keys from Connectors-style options, constants, environment variables, or the wp_ai_gateway_provider_api_key filter.
  • Preserves provider-supplied authentication when a provider owns its own request-auth flow.
  • Normalizes Responses input, tools, and tool history into WordPress AI Client DTOs so providers never need to implement the Responses wire protocol.
  • Supports Responses function tools, including parallel calls and tool-result conversation history.
  • Serves Responses API events as text/event-stream when stream: true.

Architecture

The plugin is intentionally generic. It does not know which OpenAI-compatible client is calling it, and it does not special-case any provider plugin.

plugin.php
  |
  v
Plugin bootstrap
  |-- RestController       OpenAI-compatible REST routes
  |-- TokenAuthenticator   Scoped client minting, policy, and validation
  |-- ProviderRouter       site-default and provider:model-id routing
  |-- AiClientBridge       WordPress AI Client registry/model dispatch
  |-- OpenAiResponse       OpenAI-compatible payload/error helpers
  |-- SettingsPage         wp-admin provider/model settings
  `-- CliCommand           wp ai-gateway configure/token/status

Core files:

  • plugin.php loads the plugin and registers hooks.
  • inc/constants.php defines option names, REST namespace, and site-default.
  • inc/class-rest-controller.php owns /models, /responses, and /embeddings.
  • inc/class-token-authenticator.php owns external client bearer-token behavior.
  • inc/class-provider-router.php resolves site-default and provider:model-id model names.
  • inc/class-ai-client-bridge.php adapts normalized requests to WordPress AI Client.
  • inc/class-openai-response.php keeps response and error shapes OpenAI-compatible.
  • inc/class-settings-page.php owns the minimal wp-admin settings page.
  • inc/class-cli-command.php owns automation-friendly WP-CLI setup/status commands.

Endpoints

GET  /wp-json/wp-ai-gateway/v1/models
POST /wp-json/wp-ai-gateway/v1/responses
POST /wp-json/wp-ai-gateway/v1/embeddings

The /models response always includes site-default, plus provider-qualified aliases discovered from the site's registered WordPress AI Client providers when model discovery succeeds. Discovered provider models include provider-neutral capabilities and gateway_metadata fields so retrieval workflows can identify embedding_generation support without knowing provider-specific model shapes.

Embedding requests use the same site-default and provider:model-id routing as Responses generation. Execution requires WordPress AI Client embedding generation result support.

External model aliases use this shape:

provider:model-id

For example:

example-provider:example-model

Setup

Install and activate the plugin on a WordPress 7.0+ site.

Configure the site-default route:

wp ai-gateway configure example-provider example-model

Generate or rotate the trusted legacy site-wide bearer token:

wp ai-gateway token

Store the printed token in the trusted external client. It is stored on the site as a SHA-256 hash and is not shown again. Running this command again invalidates the previous legacy token.

For automation that needs the token value without WP-CLI's success message, use:

wp ai-gateway token --porcelain

For a hosted or ephemeral runtime, issue a constrained credential instead:

wp ai-gateway runtime-token --user=123 --expires-in=3600 --label=runtime-123 --porcelain

Runtime credentials are independently revocable, bound to an existing WordPress user, limited to site-default, and expire after one hour by default. The plaintext token is returned once; only its SHA-256 hash is stored.

List non-secret client metadata, rotate one client, or revoke one client without affecting others:

wp ai-gateway clients --format=json
wp ai-gateway rotate <client-id> --expires-in=3600 --porcelain
wp ai-gateway revoke <client-id>

When a scoped credential authenticates, the gateway establishes its bound WordPress user and fires wp_ai_gateway_client_authenticated with a non-secret principal. Provider integrations can use that hook to bind user-owned provider authentication for the request.

Site-owned control planes can dispatch /responses in-process with wp_ai_gateway_dispatch_openai_request(). The gateway authenticates and normalizes the request before WordPress AI Client selects and invokes the configured provider.

Check setup status without exposing secret values:

wp ai-gateway status --format=json

Example status shape:

{
  "configured": true,
  "provider": "example-provider",
  "model": "example-model",
  "token_hash_exists": true,
  "client_count": 1,
  "ai_client_available": true,
  "registered_providers": ["example-provider"],
  "provider_registered": true,
  "endpoints": {
    "models": "https://example.com/wp-json/wp-ai-gateway/v1/models",
    "responses": "https://example.com/wp-json/wp-ai-gateway/v1/responses"
  }
}

Provider Credentials

WP AI Gateway binds provider API keys before dispatching through WordPress AI Client only when an API key is available from the gateway's credential sources.

Credential resolution order:

  • wp_ai_gateway_provider_api_key filter
  • Environment variable, e.g. EXAMPLE_PROVIDER_API_KEY
  • Constant, e.g. EXAMPLE_PROVIDER_API_KEY
  • Connectors-style option, e.g. connectors_ai_example_provider_api_key

This means a site with a provider plugin and matching credential source configured can expose that provider through site-default without giving the upstream provider credential to the external client.

Providers that supply their own request authentication can be configured without a gateway-managed API key:

wp ai-gateway configure example-provider example-model

In that path the gateway validates only the external bearer token, then dispatches to the provider registry without injecting API-key authentication.

Smoke Tests

This repository includes a lightweight PHP smoke test that stubs the WordPress and AI Client surfaces used by the plugin:

php -l plugin.php
php -l tests/smoke.php
php tests/smoke.php

The smoke covers authentication and routing, Responses text generation, tool declarations, multi-candidate text plus tool calls, tool-result history, Responses SSE events, embeddings, and scoped credentials.

Responses Example

curl https://example.com/wp-json/wp-ai-gateway/v1/responses \
  -H "Authorization: Bearer $WP_AI_GATEWAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "site-default",
    "input": "Say hello from WordPress.",
    "stream": true
  }'

Scope

This is intentionally small for the first version.

In scope now:

  • Legacy site-wide bearer-token auth
  • Multiple scoped client credentials with expiry, revocation, rotation, user binding, and model allowlists
  • site-default model routing
  • OpenAI-compatible text chat responses
  • OpenAI-compatible function tools and structured tool history
  • Deterministic Server-Sent Event chat streams
  • OpenAI-compatible embedding request routing surface
  • Provider-neutral model capability and retrieval metadata
  • WordPress AI Client provider dispatch
  • Site-mediated raw SSE streaming

Future work:

  • Full embedding execution once WordPress AI Client exposes provider-neutral embedding results
  • Usage metering beyond provider-returned usage metadata
  • Budgets and quotas
  • Admin UI for token rotation
  • Rich multimodal message support

AI Assistance

This initial plugin scaffold was drafted with AI assistance using GPT-5.5, then reviewed and directed by Chris Huber.