#64791 closed enhancement (fixed)
Connectors: Extensibility API allowing plugins to register custom connector cards
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 7.0 | Priority: | normal |
| Severity: | normal | Version: | trunk |
| Component: | Administration | Keywords: | has-patch has-unit-tests has-dev-note |
| Focuses: | Cc: |
Description (last modified by )
The Connectors screen needs a formal extensibility API so that third-party plugins can register their own connector cards — including custom UI for OAuth flows, multi-step configuration, or non-API-key authentication methods — without being limited to the default API key input card.
The Connectors screen was introduced in https://core.trac.wordpress.org/ticket/64730 (https://github.com/WordPress/gutenberg/pull/75833). https://github.com/WordPress/gutenberg/pull/76014 added dynamic registration from the WP AI Client PHP registry, so provider plugins using AiClient::defaultRegistry()->registerProvider() with api_key authentication now appear automatically. This was a significant step, but the extensibility story remains incomplete.
Current behavior
- Only providers with
api_keyauthentication are surfaced on the Connectors screen. All other authentication methods are filtered out. - Every connector card renders the same default UI: a text input for the API key, with save/remove actions.
- Third-party plugins can register a provider in PHP and have it appear on the screen, but they cannot customize how their card looks or behaves.
- There is no mechanism for plugins to add connector types that go beyond AI providers (e.g., OAuth-based services, webhook configurations, or other integration patterns the Connectors screen could support in the future).
Expected behavior
Plugins should be able to:
- Register a connector card with custom UI — for example, an OAuth flow with an "Authorize" button and token status, or a multi-field configuration form.
- Register connectors using authentication methods other than API keys — OAuth, app passwords, bearer tokens, etc.
- Provide card metadata from PHP without needing to enqueue their own JavaScript for simple cases. The current
script_module_databridge from PHP to JS is a reasonable pattern, but the API should be explicit about what metadata plugins can provide (name, description, icon, credentials URL, authentication type, status). - Inject custom rendering on the JS side when the default card layout is insufficient — via a formal JS API that was marked as experimental initially.
Proposed scope
- Define a PHP API for registering connector cards with metadata (name, description, icon, credentials URL, authentication type, custom fields).
- Provide a JS-side API for plugins that need custom card rendering.
- Ensure the default API key card remains the automatic fallback.
- Document the extensibility API with examples for both PHP-only and PHP+JS integration patterns.
Change History (30)
This ticket was mentioned in PR #11175 on WordPress/wordpress-develop by @gziolo.
3 weeks ago
#3
- Keywords has-patch has-unit-tests added
@gziolo commented on PR #11175:
3 weeks ago
#4
It's something I still feel comfortable shipping in WordPress 7.0 if we can agree that it would be a valuable addition. Nearly the same structure gets passed to the client as the filter wp_connectors_settings receives, so it's fine to seal it as a contract.
#7
@
3 weeks ago
We'd be interested in using this for adding Akismet to the list of connectors; it would probably fall under use case 4. I'm happy to test and offer feedback as the API evolves.
@gziolo commented on PR #11175:
3 weeks ago
#8
@felixarntz Thanks for the thoughtful review! I agree that a registry class with an action hook would be the better pattern here — it's consistent with how Core handles registration elsewhere (register_block_type, register_post_type, wp_register_ability, etc.) and avoids the pitfalls of filters with nested structured data.
I also realized that we already have a way to filter what reaches the frontend via the script_module_data_options-connectors-wp-admin filter, which reduces the need for a filter on the registration side as currently proposed in this PR.
I'm going to explore your proposed approach with WP_Connector_Registry + a wp_connectors_init action. Will update the PR once I have something to show.
@gziolo commented on PR #11175:
3 weeks ago
#9
@felixarntz, I quickly prototyped the idea you outlined. Does it align with what you had in mind?
@gziolo commented on PR #11175:
3 weeks ago
#10
I addressed all the remaining feedback and updated the PR's description to reflect the current version. I also applied additional enhancements to the PHPStan Connector type. If there is no further feedback, I plan to commit the changes tomorrow.
@gziolo commented on PR #11175:
2 weeks ago
#11
I drafted PR for Gutenberg to sync all the changes: https://github.com/WordPress/gutenberg/pull/76364. It's a first pass, and I need to have a closer look at both implementations.
#13
@
2 weeks ago
The scope for WP 7.0 has been covered, so I closed this ticket. There is additional follow-up work needed, but another ticket will be required, which I will handle soon.
@gziolo commented on PR #11175:
2 weeks ago
#14
As I go through the codebase again, I noticed that we don't need one method anymore after all the refactorings applied:
We can simply apply the sorting before we send the data to JS. I will patch it shortly.
This ticket was mentioned in PR #11227 on WordPress/wordpress-develop by @gziolo.
2 weeks ago
#15
## Summary
- Removes the private
_wp_connectors_get_connector_settings()wrapper, which only calledwp_get_connectors()and appliedksort(). - Callers now use
wp_get_connectors()directly. - The alphabetical sort is applied in
_wp_connectors_get_connector_script_module_data()just before data is passed to JavaScript — the only place where ordering matters. - Expands the
@returnPHPDoc onwp_get_connectors()with the full array shape previously documented on the removed helper. - Renames the test class from
wpConnectorsGetConnectorSettingstowpGetConnectors, targetingwp_get_connectors()directly.
## Test plan
- [ ] Run
npm run test:php -- --filter=connectorsand confirm all 54 tests pass. - [ ] Run
npm run env:composer -- lint -- src/wp-includes/connectors.phpand confirm no PHPCS violations.
🤖 Generated with Claude Code
@gziolo commented on PR #11227:
2 weeks ago
#16
@westonruter, I would appreciate your guidance on how to handle PHPDoc and PHPStan for wp_get_connectors() that wraps the same method from get_all_registered from WP_Connector_Registry.
@gziolo commented on PR #11175:
2 weeks ago
#18
https://github.com/WordPress/wordpress-develop/pull/11227 is ready for review.
@gziolo commented on PR #11227:
2 weeks ago
#19
@westonruter, thank you for all the insights. I still need to do a round of cleanup to align PHPDoc shapes for the connector array.
@gziolo commented on PR #11227:
2 weeks ago
#20
It's really hard to draw the line of when to include the entire shape of the return value. Maybe it's enough to combine the PHPStan type and a very generic array as @return. The only place where we must document the entire shape is WP_Connectors_Registry::register. That's something we can decide on later, though.
#24
@
2 weeks ago
Is there documentation outside of the code for how to use this new feature? I've tried implementing it for Akismet's API key (which is maybe premature, since only ai_provider types are supported), and it doesn't seem functional apart from showing the form for entering the API key.
This ticket was mentioned in PR #11244 on WordPress/wordpress-develop by @gziolo.
2 weeks ago
#25
Trac ticket: https://core.trac.wordpress.org/ticket/64791
Follow-up for https://github.com/WordPress/wordpress-develop/pull/11175
## Summary
- Add file-level overview explaining the Connectors API and how AI providers integrate automatically.
- Add usage examples and cross-references to public API functions.
- Document admin UI scope: only
ai_provider+api_keyconnectors get full UI today. - Fix code examples to use the correct unregister/register override pattern.
## Test plan
- [x] Documentation-only change — no functional impact.
🤖 Generated with Claude Code
@gziolo commented on PR #11175:
2 weeks ago
#26
I'm working on enhancements to the code documentation:
@gziolo commented on PR #11244:
2 weeks ago
#27
# Dev Note
# Introducing the Connectors API in WordPress 7.0
WordPress 7.0 introduces the Connectors API — a new framework for registering and managing connections to external services. The initial focus is on AI providers, giving WordPress a standardized way to handle API key management, provider discovery, and admin UI for configuring AI services.
This post walks through what the Connectors API does, how it works under the hood, and what plugin developers need to know.
## Table of Contents
- What is a connector?
- How AI providers are auto-discovered
- The Settings > Connectors admin screen
- Authentication and API key management
- Public API functions
- Overriding connector metadata
- The initialization lifecycle
- Looking ahead
## What is a connector?
A connector represents a connection to an external service. Each connector carries standardized metadata — a display name, description, logo, authentication configuration, and an optional association with a WordPress.org plugin. The system currently focuses on AI providers, but the architecture is designed to support additional connector types in future releases.
WordPress 7.0 ships with three built-in connectors: Anthropic, Google, and OpenAI. These are registered automatically during initialization and appear on the new Settings > Connectors admin screen.
Each connector is stored as an associative array with the following shape:
array(
'name' => 'Anthropic',
'description' => 'Text generation with Claude.',
'logo_url' => 'https://example.com/anthropic-logo.svg',
'type' => 'ai_provider',
'authentication' => array(
'method' => 'api_key',
'credentials_url' => 'https://platform.claude.com/settings/keys',
'setting_name' => 'connectors_ai_anthropic_api_key',
),
'plugin' => array(
'slug' => 'ai-provider-for-anthropic',
),
)
## How AI providers are auto-discovered
If you're building an AI provider plugin that integrates with the WP AI Client, you don't need to register a connector manually. The Connectors API automatically discovers providers from the WP AI Client's ProviderRegistry and creates connectors with the correct metadata.
Here's what happens during initialization:
- Built-in connectors (Anthropic, Google, OpenAI) are registered with hardcoded defaults.
- The system queries the WP AI Client registry for all registered providers.
- For each provider, metadata (name, description, logo, authentication method) is merged on top of the defaults, with provider registry values taking precedence.
- The
wp_connectors_initaction fires so plugins can override metadata or register additional connectors.
The authentication method (api_key or none) is determined by the provider's metadata in the WP AI Client. For api_key providers, a setting_name is automatically generated following the pattern connectors_ai_{$id}_api_key — the same naming convention used for environment variables and PHP constants (e.g., provider anthropic maps to ANTHROPIC_API_KEY for env/constant lookup).
In short: if your AI provider plugin registers with the WP AI Client, the connector is created for you. No additional code is needed.
## The Settings > Connectors admin screen
Registered ai_provider connectors appear on a new Settings > Connectors admin screen. The screen renders each connector as a card, and the registry data drives what's displayed:
-
name,description, andlogo_urlare shown on the card. -
plugin.slugenables install/activate controls — the screen checks whether the associated plugin is installed and active, and shows the appropriate action button. -
authentication.credentials_urlis rendered as a link directing users to the provider's site to obtain API credentials. - For
api_keyconnectors, the screen shows the current key source (environment variable, PHP constant, or database) and connection status.
Connectors with other authentication methods or types are stored in the PHP registry and exposed via the script module data, but currently require a client-side JavaScript registration for custom frontend UI.
## Authentication and API key management
Connectors support two authentication methods:
-
api_key— Requires an API key, which can be provided via environment variable, PHP constant, or the database (checked in that order). -
none— No authentication required.
### API key source priority
For api_key connectors, the system looks for a key in this order:
- Environment variable — e.g.,
ANTHROPIC_API_KEY - PHP constant — e.g.,
define( 'ANTHROPIC_API_KEY', 'sk-...' ); - Database — stored through the admin screen
The naming convention follows the pattern {PROVIDER_ID}_API_KEY in CONSTANT_CASE. For example, provider anthropic maps to ANTHROPIC_API_KEY.
## Public API functions
The Connectors API provides three public functions for querying the registry. These are available after init.
### wp_is_connector_registered()
Checks if a connector is registered:
if ( wp_is_connector_registered( 'anthropic' ) ) {
// The Anthropic connector is available.
}
### wp_get_connector()
Retrieves a single connector's data:
$connector = wp_get_connector( 'anthropic' );
if ( $connector ) {
echo $connector['name']; // 'Anthropic'
}
Returns an associative array with keys: name, description, type, authentication, and optionally logo_url and plugin. Returns null if the connector is not registered.
### wp_get_connectors()
Retrieves all registered connectors, keyed by connector ID:
$connectors = wp_get_connectors();
foreach ( $connectors as $id => $connector ) {
printf( '%s: %s', $connector['name'], $connector['description'] );
}
## Overriding connector metadata
The wp_connectors_init action fires after all built-in and auto-discovered connectors have been registered. Plugins can use this hook to override metadata on existing connectors.
Since the registry rejects duplicate IDs, overriding requires an unregister, modify, register sequence:
add_action( 'wp_connectors_init', function ( WP_Connector_Registry $registry ) {
if ( $registry->is_registered( 'anthropic' ) ) {
$connector = $registry->unregister( 'anthropic' );
$connector['description'] = __( 'Custom description for Anthropic.', 'my-plugin' );
$registry->register( 'anthropic', $connector );
}
} );
Key points about the override pattern:
- Always check
is_registered()before callingunregister()— callingunregister()on a non-existent connector triggers a_doing_it_wrong()notice. -
unregister()returns the connector data, which you can modify and pass back toregister(). - Connector IDs must match the pattern
/^[a-z0-9_]+$/(lowercase alphanumeric and underscores only).
### Registry methods
Within the wp_connectors_init callback, the WP_Connector_Registry instance provides these methods:
| Method | Description |
|---|---|
register( $id, $args ) | Register a new connector. Returns the connector data or null on failure.
|
unregister( $id ) | Remove a connector and return its data. Returns null if not found.
|
is_registered( $id ) | Check if a connector exists. |
get_registered( $id ) | Retrieve a single connector's data. |
get_all_registered() | Retrieve all registered connectors. |
Outside of the wp_connectors_init callback, use the public API functions (wp_get_connector(), wp_get_connectors(), wp_is_connector_registered()) instead of accessing the registry directly.
## The initialization lifecycle
Understanding the initialization sequence helps when deciding where to hook in:
During the init action, _wp_connectors_init() runs and:
- Creates the
WP_Connector_Registrysingleton. - Registers built-in connectors (Anthropic, Google, OpenAI) with hardcoded defaults.
- Auto-discovers providers from the WP AI Client registry and merges their metadata on top of defaults.
- Fires the
wp_connectors_initaction — this is where plugins override metadata or register additional connectors.
The wp_connectors_init action is the only supported entry point for modifying the registry. Attempting to set the registry instance outside of init triggers a _doing_it_wrong() notice.
## Looking ahead
The Connectors API in WordPress 7.0 is scoped to AI providers, but the underlying architecture is designed to grow. Currently, only ai_provider connectors with api_key authentication receive the full admin UI treatment. The PHP registry already accepts any connector type — what's missing is the frontend integration for non-AI connector types.
Future releases are expected to:
- Expand support for additional authentication methods beyond
api_keyandnone. - Lift the
ai_providertype restriction for the admin screen. - Provide a client-side JavaScript registration API for custom connector UI.
When those capabilities land, the wp_connectors_init action will be the primary hook for registering new connector types.
---
_Props to @jorgefilipecosta, @shaunandrews @felixarntz, @jameswlepage, @gziolo and others for contributing to the Connectors API._
_#7-0, #dev-notes_
Trac ticket: https://core.trac.wordpress.org/ticket/64791
## Summary
wp_connectors_settingsfilter in_wp_connectors_get_connector_settings()so plugins can add, modify, or remove connectors displayed on the Connectors screen.setting_nameis auto-generated — so connectors added via the filter withtype => 'ai_provider'andmethod => 'api_key'automatically get theirsetting_namepopulated.setting_namegeneration to requiretype === 'ai_provider', preventing non-AI connectors from receiving an incorrectconnectors_ai_*setting name.### Use cases
api_keytonone)ksort)Follows from the discussion in https://github.com/WordPress/gutenberg/pull/76014#discussion_r2868695097.
## Test plan
npm run test:php -- --group connectorspasses (20 tests, 98 assertions)api_keyauth getssetting_nameauto-generatedapi_keyauth does not getsetting_name🤖 Generated with Claude Code