-
Notifications
You must be signed in to change notification settings - Fork 72
Feature Request: Unified AI Management Layer for WordPress Core #348
Description
What problem does this address?
WordPress 7.0 ships a powerful AI foundation the AI Client, Abilities API, Connectors UI, and MCP Adapter but lacks a centralized management layer that ties together permission control, usage metering, intelligent provider routing, and machine-readable capability discovery into a single, cohesive system.
Today, these concerns are being addressed independently by different contributors, plugins, and proposals each solving a slice of the problem without coordination:
| Concern | Current State | Gap |
|---|---|---|
| Permission control | wp_ai_client_prevent_prompt filter (binary allow/deny) |
No per-plugin, per-feature, or per-capability granularity |
| Usage metering | None in Core | No token tracking, cost estimation, or usage dashboards |
| Provider routing | First-compatible-model fallback via using_model_preference() |
No capability-aware routing, no admin-configurable routing rules |
| Capability discovery | getSupportedCapabilities() on ModelMetadata |
Not surfaced to admins, not composable into routing decisions |
| AI availability control | WP_AI_SUPPORTED constant, wp_ai_client_prevent_prompt filter |
Best-effort caller attribution, no structured plugin identity |
The community has already identified these gaps:
- #342 - @nikolas4175-godaddy proposed a four-layer permission model (master switch → plugin-level → functionality-level → provider routing)
- #345 - @jeffpaul captured @ifahimreza's request for monthly token/request limits and a WP-Admin usage dashboard with per-plugin cost tracking
- ai-router by Per Søderlind - Routes AI requests to different provider configurations based on capability
- ai-valve by Per Søderlind - Controls, meters, and permission-gates AI usage from plugins
- AI Not by @haktansuren - Per-plugin allow/deny governance using
wp_ai_client_prevent_promptwith best-effort call-stack attribution and optional local logging - disable-ai-toolkit by AcrossWP - Overrides
wp_supports_ai()for testing, with WP-CLI support - Enable Abilities for MCP - Admin toggles for which Abilities are exposed via MCP (24 abilities, 5 categories)
- WordPress LLM Architecture by @GLWalker - A deterministic, layer-separated corpus making WordPress machine-readable for AI agents (symbols, events, registrations, patterns)
Each of these is valuable, but they don't compose. A site administrator today would need to install and configure 3–5 separate plugins just to get basic permission + routing + metering - with no guarantee they work together.
This proposal unifies all of these concerns into a single Core management layer.
What is your proposed solution?
Overview
A Unified AI Management Layer (working name: wp-ai-management) that sits between the AI Client prompt pipeline and the provider execution layer, providing:
- Structured Permissions - Granular allow/deny at plugin, feature, and capability levels
- Usage Metering & Budgets - Token tracking, cost estimation, configurable limits, and alerting
- Intelligent Provider Routing - Capability-aware, rule-based routing with admin-configurable overrides
- Machine-Readable Capability Registry - Structured capability metadata that enables both admin UIs and LLM reasoning
All four subsystems share a common data model and hook into the existing wp_ai_client_prevent_prompt filter and prompt builder pipeline, requiring zero breaking changes to the current AI Client API.
Architecture
System Context
┌─────────────────────────────────────────────────────────────────────┐
│ WordPress 7.0 Core │
│ │
│ ┌──────────┐ ┌──────────────────────────────────────────────┐ │
│ │ Plugin A │───▶│ AI CLIENT PROMPT PIPELINE │ │
│ └──────────┘ │ │ │
│ ┌──────────┐ │ wp_ai_client_prompt() │ │
│ │ Plugin B │───▶│ │ │ │
│ └──────────┘ │ ▼ │ │
│ ┌──────────┐ │ ┌─────────────────────────────────────┐ │ │
│ │ Plugin C │───▶│ │ UNIFIED AI MANAGEMENT LAYER │ │ │
│ └──────────┘ │ │ (this proposal) │ │ │
│ │ │ │ │ │
│ │ │ ┌────────────┐ ┌───────────────┐ │ │ │
│ │ │ │ Permission │ │ Usage │ │ │ │
│ │ │ │ Gate │ │ Meter │ │ │ │
│ │ │ └─────┬──────┘ └───────┬───────┘ │ │ │
│ │ │ │ │ │ │ │
│ │ │ ▼ ▼ │ │ │
│ │ │ ┌────────────┐ ┌───────────────┐ │ │ │
│ │ │ │ Provider │ │ Capability │ │ │ │
│ │ │ │ Router │ │ Registry │ │ │ │
│ │ │ └─────┬──────┘ └───────────────┘ │ │ │
│ │ └────────┼──────────────────────────┘ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ PROVIDER EXECUTION LAYER │ │ │
│ │ │ (Anthropic / Google / OpenAI) │ │ │
│ │ └──────────────────────────────────┘ │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Data Flow: Prompt Lifecycle
Plugin calls wp_ai_client_prompt('...')
│
▼
┌──────────────────────────┐
│ 1. CALLER IDENTIFICATION │
│ │
│ Resolve plugin identity │
│ via registered plugin │
│ slug (not call-stack │
│ inspection) │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐ ┌─────────────────────┐
│ 2. PERMISSION GATE │────▶│ Return WP_Error │
│ │ NO │ 'ai_permission_ │
│ Check: Master switch │ │ denied' │
│ Check: Plugin allowed? │ └─────────────────────┘
│ Check: Feature allowed? │
│ Check: Capability type │
│ allowed? │
└────────────┬─────────────┘
│ YES
▼
┌──────────────────────────┐ ┌─────────────────────┐
│ 3. BUDGET CHECK │────▶│ Return WP_Error │
│ │ NO │ 'ai_budget_ │
│ Check: Global budget │ │ exceeded' │
│ Check: Plugin budget │ └─────────────────────┘
│ Check: User/role budget │
└────────────┬─────────────┘
│ OK
▼
┌──────────────────────────┐
│ 4. PROVIDER ROUTING │
│ │
│ Match: Required caps │
│ Apply: Admin routing │
│ rules │
│ Apply: Plugin preference │
│ (model_preference)│
│ Fallback: Best available │
│ model │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ 5. EXECUTE PROMPT │
│ │
│ Send to resolved provider│
│ Receive result │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ 6. RECORD USAGE │
│ │
│ Log: plugin, feature, │
│ provider, model, │
│ tokens (in/out), │
│ estimated cost, │
│ timestamp, user │
│ │
│ Update: Running totals │
│ Check: Alert thresholds │
└──────────────────────────┘
Data Flow: Admin Configuration
┌────────────────────────────────────────────────────────┐
│ WP-ADMIN: Settings > AI Management │
│ │
│ ┌─────────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ Permissions │ │ Budgets │ │ Routing Rules │ │
│ │ Tab │ │ Tab │ │ Tab │ │
│ └──────┬──────┘ └────┬─────┘ └───────┬─────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ REST API Endpoints │ │
│ │ /wp-json/wp/v2/ai-management/permissions │ │
│ │ /wp-json/wp/v2/ai-management/budgets │ │
│ │ /wp-json/wp/v2/ai-management/routing │ │
│ │ /wp-json/wp/v2/ai-management/usage │ │
│ │ /wp-json/wp/v2/ai-management/capabilities │ │
│ └──────────────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ wp_options Storage │ │
│ │ │ │
│ │ ai_management_permissions (JSON) │ │
│ │ ai_management_budgets (JSON) │ │
│ │ ai_management_routing (JSON) │ │
│ │ ai_management_usage_log (Custom Table) │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ │
│ │ Usage │ Real-time dashboard: │
│ │ Dashboard │ - Calls by plugin (bar chart) │
│ │ Tab │ - Token usage over time (line) │
│ │ │ - Estimated cost by provider │
│ │ │ - Budget utilization (gauge) │
│ └──────────────┘ │
└────────────────────────────────────────────────────────┘
Data Flow: Machine-Readable Capability Discovery
┌──────────────────────────────────────────────────────────────┐
│ CAPABILITY REGISTRY │
│ │
│ Aggregates from: │
│ ┌──────────────────┐ ┌────────────────────┐ │
│ │ AI Client │ │ Abilities API │ │
│ │ getSupportedCaps │ │ Registered │ │
│ │ per provider │ │ Abilities │ │
│ └────────┬─────────┘ └──────────┬─────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Unified Capability Map │ │
│ │ │ │
│ │ { │ │
│ │ "text_generation": { │ │
│ │ "providers": ["anthropic", "openai", "google"], │ │
│ │ "models": [...], │ │
│ │ "supports_json_schema": true, │ │
│ │ "supports_system_instructions": true, │ │
│ │ "max_context_window": 200000 │ │
│ │ }, │ │
│ │ "image_generation": { │ │
│ │ "providers": ["openai"], │ │
│ │ "models": [...], │ │
│ │ "supports_orientation": true │ │
│ │ } │ │
│ │ } │ │
│ └───────────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ REST API │ │ Router │ │ MCP / LLM │ │
│ │ /caps │ │ (internal) │ │ Discovery │ │
│ │ endpoint │ │ │ │ (machine- │ │
│ └──────────────┘ └────────────┘ │ readable) │ │
│ └──────────────────┘ │
│ │
│ Exposed as: │
│ - REST endpoint for admin UI and external tooling │
│ - Internal API for the routing engine │
│ - Structured schema consumable by LLM agents │
│ (aligned with GLWalker's WordPress LLM Architecture │
│ contract model: symbols + events + registrations) │
└──────────────────────────────────────────────────────────────┘
Detailed Design
1. Structured Permissions
Builds on the four-layer model from #342 with concrete implementation:
1.1 Plugin Identity Registration
Instead of best-effort call-stack inspection (as noted by @haktansuren in AI Not), plugins declare their AI usage at registration time:
<?php
/**
* Plugin registers its AI features during init.
* This replaces call-stack inspection with explicit declaration.
*/
add_action( 'init', function () {
wp_register_ai_consumer(
'my-seo-plugin/my-seo-plugin.php', // Plugin basename (unique identifier).
array(
'features' => array(
'meta-generation' => array(
'label' => __( 'Meta Description Generation', 'my-seo-plugin' ),
'capabilities' => array( 'text_generation' ),
'description' => __( 'Generates SEO meta descriptions from post content.', 'my-seo-plugin' ),
),
'image-alt-text' => array(
'label' => __( 'Image Alt Text', 'my-seo-plugin' ),
'capabilities' => array( 'text_generation' ),
'description' => __( 'Generates descriptive alt text for images.', 'my-seo-plugin' ),
),
),
)
);
});1.2 Permission Resolution
<?php
/**
* Permissions are stored as a structured option and resolved
* through a filter chain that respects the four-layer hierarchy.
*
* Layer 1: Master switch - WP_AI_SUPPORTED / wp_supports_ai()
* Layer 2: Plugin-level - Allow/deny per plugin basename
* Layer 3: Feature-level - Allow/deny per registered feature
* Layer 4: Capability-level - Allow/deny per AI capability type
* (text_generation, image_generation, etc.)
*/
// Example stored permission structure (ai_management_permissions option).
$permissions = array(
'default_policy' => 'deny', // 'allow' or 'deny'. Deny = opt-in model (recommended).
'plugins' => array(
'my-seo-plugin/my-seo-plugin.php' => array(
'allowed' => true,
'features' => array(
'meta-generation' => array( 'allowed' => true ),
'image-alt-text' => array( 'allowed' => true ),
),
),
'some-other-plugin/main.php' => array(
'allowed' => false, // Entire plugin denied.
),
),
'capabilities' => array(
'text_generation' => array( 'allowed' => true ),
'image_generation' => array( 'allowed' => false ), // Globally deny image gen.
),
);1.3 Integration with existing filter
<?php
/**
* Hooks into the existing wp_ai_client_prevent_prompt filter.
* No new filter required - works with the current AI Client API.
*/
add_filter(
'wp_ai_client_prevent_prompt',
'wp_ai_management_check_permissions',
10,
2
);
/**
* Check permissions against the management layer.
*
* @param bool $prevent Whether to prevent the prompt.
* @param WP_AI_Client_Prompt_Builder $builder The prompt builder instance.
* @return bool
*/
function wp_ai_management_check_permissions( bool $prevent, WP_AI_Client_Prompt_Builder $builder ): bool {
if ( $prevent ) {
return true; // Already prevented by another filter.
}
$caller = wp_ai_management_resolve_caller( $builder );
$context = wp_ai_management_build_context( $caller, $builder );
// Layer 1: Master switch (already handled by wp_supports_ai()).
// Layer 2: Plugin-level permission.
if ( ! wp_ai_management_plugin_allowed( $context['plugin'] ) ) {
return true;
}
// Layer 3: Feature-level permission.
if ( $context['feature'] && ! wp_ai_management_feature_allowed( $context['plugin'], $context['feature'] ) ) {
return true;
}
// Layer 4: Capability-level permission.
if ( ! wp_ai_management_capability_allowed( $context['capability'] ) ) {
return true;
}
return false;
}2. Usage Metering & Budgets
Addresses #345 with a concrete implementation:
2.1 Usage Logging
<?php
/**
* Hooks into the prompt result to record usage after execution.
* Uses a lightweight custom table for efficient querying.
*/
// Table schema (created on activation).
global $wpdb;
$table = $wpdb->prefix . 'ai_usage_log';
/*
CREATE TABLE {$table} (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
plugin_slug VARCHAR(191) NOT NULL DEFAULT '',
feature_slug VARCHAR(191) NOT NULL DEFAULT '',
provider VARCHAR(100) NOT NULL DEFAULT '',
model VARCHAR(100) NOT NULL DEFAULT '',
capability_type VARCHAR(50) NOT NULL DEFAULT 'text_generation',
tokens_input INT UNSIGNED NOT NULL DEFAULT 0,
tokens_output INT UNSIGNED NOT NULL DEFAULT 0,
estimated_cost DECIMAL(10,6) NOT NULL DEFAULT 0.000000,
user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_plugin_date (plugin_slug, created_at),
INDEX idx_provider_date (provider, created_at),
INDEX idx_created (created_at)
) {$charset_collate};
*/2.2 Budget Configuration
<?php
/**
* Budget structure stored in ai_management_budgets option.
* Supports global, per-plugin, and per-role limits.
*/
$budgets = array(
'global' => array(
'monthly_token_limit' => 1000000, // 0 = unlimited.
'monthly_cost_limit' => 50.00, // USD. 0 = unlimited.
'alert_threshold_pct' => 80, // Alert at 80% usage.
'alert_email' => get_option( 'admin_email' ),
),
'per_plugin' => array(
'my-seo-plugin/my-seo-plugin.php' => array(
'monthly_token_limit' => 200000,
'monthly_cost_limit' => 10.00,
),
),
'per_role' => array(
'editor' => array(
'daily_request_limit' => 50,
),
),
);2.3 Budget Enforcement (in the prompt pipeline)
<?php
/**
* Budget check runs after permission gate, before provider routing.
* Returns WP_Error with specific code if budget exceeded.
*/
function wp_ai_management_check_budget( array $context ): ?WP_Error {
$period_start = gmdate( 'Y-m-01 00:00:00' ); // First of current month.
// Global budget check.
$global_usage = wp_ai_management_get_usage_totals( $period_start );
$global_budget = wp_ai_management_get_budget( 'global' );
if ( $global_budget['monthly_token_limit'] > 0
&& $global_usage['total_tokens'] >= $global_budget['monthly_token_limit'] ) {
return new WP_Error(
'ai_budget_exceeded',
__( 'Monthly AI token budget has been reached.', 'default' ),
array( 'status' => 429 )
);
}
if ( $global_budget['monthly_cost_limit'] > 0
&& $global_usage['total_cost'] >= $global_budget['monthly_cost_limit'] ) {
return new WP_Error(
'ai_budget_exceeded',
__( 'Monthly AI cost budget has been reached.', 'default' ),
array( 'status' => 429 )
);
}
// Per-plugin budget check.
$plugin_budget = wp_ai_management_get_budget( 'per_plugin', $context['plugin'] );
if ( $plugin_budget ) {
$plugin_usage = wp_ai_management_get_usage_totals( $period_start, $context['plugin'] );
// ... same pattern as global check.
}
return null; // Budget OK.
}3. Intelligent Provider Routing
Extends the capability-based routing concept from Per Søderlind's ai-router, integrated into Core's prompt pipeline:
3.1 Routing Rules
<?php
/**
* Admin-configurable routing rules stored in ai_management_routing option.
* Rules are evaluated in priority order. First match wins.
*/
$routing_rules = array(
array(
'name' => 'Image gen via OpenAI',
'priority' => 10,
'conditions' => array(
'capability' => 'image_generation',
),
'route_to' => array(
'provider' => 'openai',
'model' => 'gpt-image-1',
),
),
array(
'name' => 'Long-context text via Anthropic',
'priority' => 20,
'conditions' => array(
'capability' => 'text_generation',
'min_context_tokens' => 50000,
),
'route_to' => array(
'provider' => 'anthropic',
'model' => 'claude-sonnet-4-6',
),
),
array(
'name' => 'SEO plugin uses budget model',
'priority' => 30,
'conditions' => array(
'plugin' => 'my-seo-plugin/my-seo-plugin.php',
),
'route_to' => array(
'provider' => 'google',
'model' => 'gemini-2.5-flash',
),
),
);3.2 Router Resolution
<?php
/**
* Resolves the best provider/model for a given prompt context.
*
* Priority order:
* 1. Admin routing rules (highest priority match)
* 2. Plugin's using_model_preference() (developer hint)
* 3. Capability-aware best-match from available providers
*
* @param array $context Caller context (plugin, feature, capability).
* @param WP_AI_Client_Prompt_Builder $builder The prompt builder.
* @return array { provider: string, model: string } | WP_Error
*/
function wp_ai_management_resolve_route( array $context, WP_AI_Client_Prompt_Builder $builder ) {
$rules = get_option( 'ai_management_routing', array() );
// Sort by priority.
usort( $rules, function ( $a, $b ) {
return ( $a['priority'] ?? 100 ) - ( $b['priority'] ?? 100 );
});
foreach ( $rules as $rule ) {
if ( wp_ai_management_rule_matches( $rule['conditions'], $context, $builder ) ) {
// Verify the target provider/model is actually available.
if ( wp_ai_management_provider_available( $rule['route_to'] ) ) {
return $rule['route_to'];
}
}
}
// No routing rule matched - fall through to default AI Client behavior.
// The existing using_model_preference() and provider fallback logic handles this.
return null;
}3.3 Integration Point
The router integrates by wrapping the prompt builder before execution. The AI Client's existing using_model_preference() mechanism is used - the management layer doesn't bypass the client, it configures it:
<?php
/**
* Applies routing decision to the prompt builder.
* Uses the existing model preference API - no internal modification needed.
*/
function wp_ai_management_apply_route( WP_AI_Client_Prompt_Builder $builder, ?array $route ): void {
if ( null === $route ) {
return; // Use default behavior.
}
// Prepend the routed model as highest-priority preference.
// The AI Client's existing fallback logic handles unavailability.
$builder->using_model_preference( $route['model'] );
}4. Machine-Readable Capability Registry
Inspired by @GLWalker's WordPress LLM Architecture project, the capability registry provides structured, machine-readable metadata about what AI capabilities exist on a WordPress site - consumable by both admin UIs and external AI agents.
4.1 Unified Capability Map
<?php
/**
* Builds a unified capability map from all configured providers.
* Consumed by the admin UI, REST API, routing engine, and MCP adapter.
*
* @return array Structured capability data.
*/
function wp_ai_management_get_capability_map(): array {
$providers = wp_ai_client_get_providers(); // From the AI Client registry.
$map = array();
foreach ( $providers as $provider_slug => $provider ) {
foreach ( $provider->get_models() as $model ) {
$metadata = $model->getMetadata();
$capabilities = $metadata->getSupportedCapabilities();
foreach ( $capabilities as $cap ) {
if ( ! isset( $map[ $cap ] ) ) {
$map[ $cap ] = array(
'providers' => array(),
'models' => array(),
'metadata' => array(),
);
}
$map[ $cap ]['providers'][] = $provider_slug;
$map[ $cap ]['models'][] = array(
'provider' => $provider_slug,
'model_id' => $model->getId(),
'context_window' => $metadata->getContextWindow(),
'supports' => array(
'json_schema' => $metadata->supportsJsonSchema(),
'system_instructions' => $metadata->supportsSystemInstructions(),
'function_calling' => $metadata->supportsFunctionCalling(),
),
);
}
}
}
// Deduplicate providers.
foreach ( $map as &$cap_data ) {
$cap_data['providers'] = array_values( array_unique( $cap_data['providers'] ) );
}
return $map;
}4.2 REST Endpoint for Capability Discovery
<?php
/**
* Registers capability discovery endpoint.
* Consumable by admin UIs, external tooling, and LLM agents.
*/
add_action( 'rest_api_init', function () {
register_rest_route(
'wp/v2',
'/ai-management/capabilities',
array(
'methods' => 'GET',
'callback' => 'wp_ai_management_rest_get_capabilities',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
)
);
});
/**
* Returns the unified capability map with permission and budget overlays.
* Response follows a structured schema suitable for machine consumption,
* aligned with the contract model from WordPress LLM Architecture:
*
* - symbols: What capabilities exist
* - registrations: Which providers/models are wired in
* - events: What hooks/filters control behavior
*
* @param WP_REST_Request $request The REST request.
* @return WP_REST_Response
*/
function wp_ai_management_rest_get_capabilities( WP_REST_Request $request ): WP_REST_Response {
$map = wp_ai_management_get_capability_map();
$permissions = get_option( 'ai_management_permissions', array() );
$response = array(
'schema_version' => '1.0.0',
'site_url' => home_url(),
'capabilities' => array(),
);
foreach ( $map as $cap_name => $cap_data ) {
$allowed = wp_ai_management_capability_allowed( $cap_name );
$response['capabilities'][ $cap_name ] = array(
'available' => ! empty( $cap_data['providers'] ),
'allowed' => $allowed,
'providers' => $cap_data['providers'],
'models' => $cap_data['models'],
);
}
return rest_ensure_response( $response );
}Full Stack Code Structure
wp-includes/
└── ai-management/
├── class-wp-ai-management.php # Main orchestrator, filter registration
├── class-wp-ai-management-permissions.php # Permission gate logic
├── class-wp-ai-management-budget.php # Budget enforcement and tracking
├── class-wp-ai-management-router.php # Provider routing engine
├── class-wp-ai-management-capability-map.php# Capability registry / aggregation
├── class-wp-ai-management-usage-logger.php # Usage logging to custom table
├── class-wp-ai-management-alerting.php # Threshold alerts (email, admin notice)
└── rest-api/
├── class-wp-rest-ai-permissions-controller.php
├── class-wp-rest-ai-budgets-controller.php
├── class-wp-rest-ai-routing-controller.php
├── class-wp-rest-ai-usage-controller.php
└── class-wp-rest-ai-capabilities-controller.php
wp-admin/
└── includes/
└── ai-management/
├── ai-management-page.php # Settings > AI Management page registration
└── ai-management-dashboard-widget.php # Optional: dashboard widget for usage
packages/
└── ai-management/
└── src/
├── index.js # Package entry point
├── store/
│ ├── index.js # @wordpress/data store registration
│ ├── actions.js # REST API mutations
│ ├── selectors.js # Data selectors
│ └── resolvers.js # REST API fetchers
├── components/
│ ├── permissions-panel/
│ │ ├── index.js # Plugin permission toggles
│ │ ├── plugin-row.js # Per-plugin allow/deny + feature toggles
│ │ └── capability-toggles.js # Global capability type toggles
│ ├── budgets-panel/
│ │ ├── index.js # Budget configuration
│ │ ├── global-budget-form.js # Global token/cost limits
│ │ ├── plugin-budget-form.js # Per-plugin limits
│ │ └── role-budget-form.js # Per-role limits
│ ├── routing-panel/
│ │ ├── index.js # Routing rules list
│ │ ├── rule-editor.js # Rule condition + target editor
│ │ └── capability-matrix.js # Visual cap × provider matrix
│ ├── usage-dashboard/
│ │ ├── index.js # Usage overview
│ │ ├── usage-by-plugin-chart.js # Bar chart: calls by plugin
│ │ ├── usage-over-time-chart.js # Line chart: tokens over time
│ │ ├── cost-by-provider-chart.js # Pie chart: cost distribution
│ │ └── budget-gauge.js # Budget utilization indicator
│ └── capability-explorer/
│ ├── index.js # Browse all capabilities
│ └── provider-model-matrix.js # Cap × provider availability grid
└── hooks/
├── use-permissions.js
├── use-budgets.js
├── use-routing.js
└── use-usage.js
WP-CLI commands:
├── wp ai-management permission list # List all plugin permissions
├── wp ai-management permission allow <plugin> # Allow a plugin
├── wp ai-management permission deny <plugin> # Deny a plugin
├── wp ai-management budget show # Show current budget status
├── wp ai-management budget set --global-tokens=N # Set global token limit
├── wp ai-management routing list # List routing rules
├── wp ai-management routing add <json> # Add a routing rule
├── wp ai-management usage summary # Current period usage summary
├── wp ai-management usage export --format=csv # Export usage log
└── wp ai-management capabilities list # List all available capabilities
REST API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/wp/v2/ai-management/permissions |
List all plugin permissions and capability rules |
POST |
/wp/v2/ai-management/permissions |
Update permission rules |
GET |
/wp/v2/ai-management/budgets |
Get current budget configuration and utilization |
POST |
/wp/v2/ai-management/budgets |
Update budget configuration |
GET |
/wp/v2/ai-management/routing |
List routing rules |
POST |
/wp/v2/ai-management/routing |
Create/update routing rules |
DELETE |
/wp/v2/ai-management/routing/{id} |
Delete a routing rule |
GET |
/wp/v2/ai-management/usage |
Query usage log with filters (plugin, provider, date range) |
GET |
/wp/v2/ai-management/usage/summary |
Aggregated usage summary for current period |
GET |
/wp/v2/ai-management/capabilities |
Unified capability map with permission overlays |
All endpoints require manage_options capability. Endpoints return standard WP_REST_Response objects compatible with @wordpress/api-fetch.
WP-CLI Commands
COMMANDS
wp ai-management permission list
List all registered AI consumers and their permission status.
--format=<table|json|csv>
wp ai-management permission allow <plugin-basename>
Grant AI access to a specific plugin.
--feature=<feature-slug> Optional: allow only a specific feature.
wp ai-management permission deny <plugin-basename>
Revoke AI access from a specific plugin.
--feature=<feature-slug> Optional: deny only a specific feature.
wp ai-management budget show
Display current budget configuration and utilization.
--format=<table|json>
wp ai-management budget set
Update budget limits.
--global-tokens=<number> Monthly global token limit.
--global-cost=<number> Monthly global cost limit (USD).
--plugin=<basename> Target a specific plugin.
--plugin-tokens=<number> Monthly plugin token limit.
--alert-threshold=<pct> Alert threshold percentage.
wp ai-management routing list
List all routing rules in priority order.
--format=<table|json>
wp ai-management routing add <json-rule>
Add a new routing rule (accepts JSON string).
wp ai-management routing remove <rule-id>
Remove a routing rule.
wp ai-management usage summary
Show aggregated usage for the current billing period.
--plugin=<basename> Filter by plugin.
--provider=<slug> Filter by provider.
--period=<YYYY-MM> Specific month (default: current).
--format=<table|json>
wp ai-management usage export
Export raw usage log.
--format=<csv|json>
--period=<YYYY-MM>
--output=<filepath>
wp ai-management capabilities list
List all available AI capabilities with provider/model support.
--format=<table|json>
Phased Implementation Plan
Phase 1: Foundation (Target: WordPress 7.1)
wp_register_ai_consumer()API for plugin identity registration- Permission gate (4 layers) integrated via
wp_ai_client_prevent_prompt - Usage logging custom table and recording hook
- REST API endpoints for permissions and usage
- WP-CLI
permissionandusagesubcommands - Basic admin screen under Settings > AI Management (permissions tab)
Phase 2: Budgets & Routing (Target: WordPress 7.1 or 7.2)
- Budget configuration storage and enforcement
- Alert system (email + admin notices)
- Provider routing engine with admin-configurable rules
- REST API endpoints for budgets and routing
- WP-CLI
budgetandroutingsubcommands - Admin UI: budget tab, routing tab, usage dashboard
Phase 3: Capability Intelligence (Target: WordPress 7.2)
- Unified capability map aggregation
- Machine-readable capability endpoint
- Capability explorer in admin UI
- Integration with MCP Adapter for capability exposure
- Structured schema aligned with WordPress LLM Architecture contracts
Prior Art & Credits
This proposal builds on and unifies work from the following contributors and projects:
| Contributor | Contribution | Reference |
|---|---|---|
| @nikolas4175-godaddy | Four-layer permission model proposal | #342 |
| @jeffpaul | Usage safeguards issue creation | #345 |
| @ifahimreza | Original request for usage limits and cost dashboard | Comment on AI Client dev note |
| Per Søderlind | ai-router (capability-based provider routing) | ai-router plugin |
| Per Søderlind | ai-valve (usage metering and permission gating) | ai-valve plugin |
| @haktansuren / HANDL Digital | AI Not (per-plugin allow/deny governance via wp_ai_client_prevent_prompt) |
ai-not on GitHub |
| AcrossWP | disable-ai-toolkit (wp_supports_ai() overrides + WP-CLI) |
disable-ai-toolkit on GitHub |
| @GLWalker | WordPress LLM Architecture (machine-readable WP corpus) | WordPress-LLM-Architecture on GitHub |
| Enable Abilities for MCP (author) | Admin toggles for ability exposure to MCP | Enable Abilities for MCP plugin |
| @flixos90 (Felix Arntz) | AI Client architecture and dev note | AI Client dev note |
| @flixos90 | PHP AI Client SDK | make.wordpress.org/ai/2025/07/17/php-ai-api/ |
| @isotropic (James LePage) | Abilities API design | make.wordpress.org/ai/2025/07/17/abilities-api/ |
| WordPress Core AI team | MCP Adapter | MCP Adapter on GitHub |
Related Issues
- #342 - Add permission controls for plugins to use a connected provider
- #345 - Add usage safeguards to AI Client (limits, visibility, and cost awareness)
- #149 - Observability layer
- #64872 - JS API in Core discussion (Trac)
- #64873 - REST endpoints in Core discussion (Trac)
Open Questions
-
Should the permission default be allow or deny? This proposal recommends deny (opt-in) for cost safety, but allow (opt-out) is more backward-compatible with existing plugins that already use the AI Client.
-
Where should the admin UI live? This proposal suggests Settings > AI Management as a top-level submenu. An alternative is to extend the existing Settings > Connectors page with additional tabs.
-
Cost estimation accuracy - Token costs vary by provider and change frequently. Should Core maintain a cost table, or should provider plugins supply per-model pricing metadata?
-
Relationship to
using_model_preference()- The routing engine currently works with the existing model preference API. Should it also be able to override a plugin's preference when an admin routing rule is configured? -
Custom table vs. options API for usage logging - High-volume sites could generate significant usage data. A custom table with retention policies (auto-purge after N months) is proposed. Is this acceptable for Core, or should this be deferred to a plugin?