La API de Abilities, introducida en WordPress 6.9, establece un lenguaje común que permite a todos los componentes de WordPress —tanto del núcleo como de los plugins— mostrar su funcionalidad de una forma unificada y comprensible tanto para las personas como para las máquinas. Esto hace que tu sitio de WordPress esté preparado para integrarse con herramientas de automatización externas de forma estandarizada y segura.
Si te estás preguntando cuáles podrían ser algunos casos de uso de la API Abilities, piensa en un modelo de IA que guíe al usuario a lo largo del proceso de compra e incluso le permita completar la compra sin tener que visitar tu sitio web de comercio electrónico. O piensa en un pipeline de CI/CD en GitHub Actions que procese texto extraído de un archivo de audio o vídeo y lo envíe a WordPress para su publicación. Los casos de uso son infinitos.
La API Abilities cambia por completo el papel de WordPress dentro del ecosistema. Ya no es solo un blog, ni siquiera un CMS; ahora, WordPress funciona como un motor de ejecución distribuido que se puede coordinar desde fuera, como una especie de sistema operativo, totalmente preparado para agentes autónomos.
¿Tienes curiosidad por saber más? Vamos a profundizar en el tema.
Para qué sirve una ability
Una ability (o capacidad) es una funcionalidad detectable y ejecutable en un sitio de WordPress que permite realizar operaciones específicas para entidades externas (como modelos de IA) o componentes internos.
La API se puede usar para cosas como:
- Buscar contenido o realizar operaciones específicas en la base de datos
- Leer los ajustes de configuración del sitio
- Crear una entrada
- Convertir una estructura JSON en bloques de Gutenberg
Exponer una ability significa hacer que una funcionalidad concreta sea interoperable. Para que una ability pueda detectarse y utilizarse, primero tiene que registrarse en un catálogo centralizado. Solo así WordPress y los modelos de IA podrán detectarla, entender su finalidad e invocarla cuando sea necesario.
Por defecto, las funcionalidades de tus plugins están totalmente aisladas. Al registrar una ability, declaras que la lógica subyacente está disponible como servicio para todo el ecosistema.
Veamos un ejemplo. Si tu plugin tiene una función que convierte un objeto JSON inicial en contenido estructurado listo para los bloques de Gutenberg, puedes registrarla como una ability. Esto permite que otras herramientas con los permisos necesarios activen exactamente la misma función.
En nuestro tutorial anterior sobre Clientes de IA de WordPress, el plugin se encargaba de la lógica principal de enviar un archivo de audio al modelo de IA, que a su vez devolvía una respuesta estructurada en JSON para generar bloques de Gutenberg. Sin embargo, esa funcionalidad se limitaba a nuestro plugin. Al registrar este proceso como una ability, se separa la ejecución, y cualquier entidad externa puede activar toda la lógica del plugin simplemente pasando un objeto JSON que contenga el ID de un archivo de audio.
Una ability actúa como un contrato formal entre la lógica PHP subyacente y cualquier entidad que solicite su ejecución. El contrato especifica los datos que la ability espera como entrada, su propósito y el esquema de datos que devuelve como salida.
Cuando registras una ability, se añade al registro de abilities de tu sitio. A partir de ese momento, WordPress actúa como una pasarela segura: verifica la autenticación y valida los datos entrantes según el esquema establecido por el contrato. WordPress redirige la solicitud a la función PHP subyacente solo si el payload cumple estrictamente con el contrato.
Una ability es agnóstica. WordPress no necesita saber qué entidad concreta solicita el acceso; solo comprueba que la solicitud esté autorizada y cumpla con las restricciones del contrato.
Al registrar una ability, tu plugin ya no es solo una extensión con su propia lógica interna, sino que se convierte en un proveedor de servicios para todo el ecosistema. Ya se trate de una app móvil, un script de automatización como Make.com o Zapier, un agente de IA o un servidor que se comunica a través del protocolo MCP, estas entidades sabrán exactamente cómo activar operaciones estructuradas en tu sitio.
Cómo trabajar con la API Abilities
La API Abilities ofrece un conjunto completo de funciones que te permiten detectar las abilities registradas en tu sitio, activarlas, además de registrarlas y darlas de baja.
Trabaja con las abilities de tu sitio
Puedes obtener una lista de todas las abilities registradas o recuperar un objeto de una ability concreta. También puedes comprobar ciertas condiciones, como si una ability específica está registrada o si el agente tiene permisos para activarla.
Obtener una lista de las capacidades registradas en tu sitio
La función wp_get_abilities() devuelve una array con todas las abilities registradas. Puedes probarla usando WP-CLI. Una vez que te conectes a tu sitio vía SSH, ve al directorio raíz del sitio, donde está tu archivowp-config.php, usando los siguientes comandos:
cd /path/to/your/site
ls wp-config.php
A continuación, asegúrate de que WP-CLI reconoce la instalación de tu sitio:
wp core is-installed
wp option get siteurl
Si aparece la URL de tu sitio, ya estás listo para ejecutar el siguiente comando:
wp eval '$abilities = wp_get_abilities(); foreach ( $abilities as $a ) { echo $a->get_name() . PHP_EOL; }'
Este comando ejecuta código PHP en tu terminal. El código PHP solicita los nombres de todas las abilities registradas en tu sitio y, por defecto, debería dar la siguiente respuesta:
core/get-site-info
core/get-user-info
core/get-environment-info
Puedes solicitar un conjunto de datos más completo con el siguiente comando:
wp eval '
$all_abilities = wp_get_abilities();
foreach ( $all_abilities as $ability ) {
echo "Ability Name: " . esc_html( $ability->get_name() ) . "\n";
echo "Label: " . esc_html( $ability->get_label() ) . "\n";
echo "Category: " . esc_html( $ability->get_category() ) . "\n";
echo "Description: " . esc_html( $ability->get_description() ) . "\n";
echo "---\n";
}
'
Cuando ejecutes este comando en un sitio nuevo de WordPress 7.0, la terminal mostrará la siguiente respuesta:
Ability Name: core/get-site-info
Label: Get Site Information
Category: site
Description: Returns site information configured in WordPress. By default returns all fields, or optionally a filtered subset.
---
Ability Name: core/get-user-info
Label: Get User Information
Category: user
Description: Returns profile details for the current authenticated user to support personalization, auditing, and access-aware behavior. By default returns all fields, or optionally a filtered subset.
---
Ability Name: core/get-environment-info
Label: Get Environment Info
Category: site
Description: Returns core details about the site's runtime context for diagnostics and compatibility (environment, PHP runtime, database server info, WordPress version). By default returns all fields, or optionally a filtered subset.
---
Obtener un objeto ability
La función wp_get_ability() devuelve un único objeto ability por su nombre. Puedes probarla en WP-CLI con este comando:
wp eval '
$ability = wp_get_ability( "core/get-site-info" );
if ( ! $ability ) {
echo "Ability not found\n";
exit( 1 );
}
echo "Name: " . $ability->get_name() . "\n";
echo "Label: " . $ability->get_label() . "\n";
echo "Category: " . $ability->get_category() . "\n";
echo "Description: " . $ability->get_description() . "\n";
echo "nInput Schema:\n";
var_dump( $ability->get_input_schema() );
echo "nOutput Schema:\n";
var_dump( $ability->get_output_schema() );
echo "nMeta:\n";
var_dump( $ability->get_meta() );
'
Si la ability está correctamente registrada en tu sitio, recibirás la siguiente respuesta en tu terminal:
Name: core/get-site-info
Label: Get Site Information
Category: site
Description: Returns site information configured in WordPress. By default returns all fields, or optionally a filtered subset.
Input Schema:
array(4) {
["type"]=>
string(6) "object"
["properties"]=>
array(1) {
["fields"]=>
array(3) {
["type"]=>
string(5) "array"
["items"]=>
array(2) {
["type"]=>
string(6) "string"
["enum"]=>
array(8) {
[0]=>
string(4) "name"
[1]=>
string(11) "description"
[2]=>
string(3) "url"
[3]=>
string(5) "wpurl"
[4]=>
string(11) "admin_email"
[5]=>
string(7) "charset"
[6]=>
string(8) "language"
[7]=>
string(7) "version"
}
}
["description"]=>
string(81) "Optional: Limit response to specific fields. If omitted, all fields are returned."
}
}
["additionalProperties"]=>
bool(false)
["default"]=>
array(0) {
}
}
Output Schema:
array(3) {
["type"]=>
string(6) "object"
["properties"]=>
array(8) {
["name"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(10) "Site Title"
["description"]=>
string(15) "The site title."
}
["description"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(7) "Tagline"
["description"]=>
string(17) "The site tagline."
}
["url"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(18) "Site Address (URL)"
["description"]=>
string(94) "The public URL where visitors access the site. May differ from the WordPress installation URL."
}
["wpurl"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(23) "WordPress Address (URL)"
["description"]=>
string(83) "The URL where WordPress core files are served. May differ from the public site URL."
}
["admin_email"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(28) "Administration Email Address"
["description"]=>
string(37) "The site administrator email address."
}
["charset"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(12) "Site Charset"
["description"]=>
string(28) "The site character encoding."
}
["language"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(13) "Site Language"
["description"]=>
string(42) "The site locale in dash form (e.g. en-US)."
}
["version"]=>
array(3) {
["type"]=>
string(6) "string"
["title"]=>
string(17) "WordPress Version"
["description"]=>
string(48) "The WordPress core version running on this site."
}
}
["additionalProperties"]=>
bool(false)
}
Meta:
array(2) {
["annotations"]=>
array(3) {
["readonly"]=>
bool(true)
["destructive"]=>
bool(false)
["idempotent"]=>
bool(true)
}
["show_in_rest"]=>
bool(true)
}
Comprobar si una ability está registrada
La función wp_has_ability() te permite comprobar si una ability está registrada. En WP-CLI, puedes usarla así:
wp eval '
if ( wp_has_ability( "core/get-site-info" ) ) {
echo "✓ core/get-site-info is registered\n";
} else {
echo "✗ core/get-site-info not found\n";
}
'
Si la ability está registrada, aparecerá el siguiente mensaje en la terminal:
✓ core/get-site-info is registered
Comprobar los permisos del agente
Puedes comprobar si el usuario actual tiene permisos para ejecutar una ability utilizando el método check_permissions() del objeto $ability. Este método devuelve true, false o un objeto WP_Error. Intentemos llamar a este método desde la terminal con el siguiente comando de WP-CLI:
wp --user=1 eval '
$ability = wp_get_ability( "core/get-site-info" );
if ( $ability ) {
$has_permissions = $ability->check_permissions();
if ( true === $has_permissions ) {
echo "You have permissions to execute this ability.";
} else {
if ( is_wp_error( $has_permissions ) ) {
error_log( "Permissions check failed: " . $has_permissions->get_error_message() );
}
echo "You do not have permissions to execute this ability.";
}
} else {
echo "Ability not found.";
}
'
Aquí hemos establecido --user=1, por lo que recibirás la siguiente respuesta:
You have permissions to execute this ability.
Registrar una ability
Ahora es el momento de registrar una ability. Para mostrar un caso de uso real, vamos a ampliar el plugin que describimos en nuestro artículo sobre Clientes de IA de WordPress. El plugin envía un archivo de audio al modelo de IA para extraer el texto y activar la generación de bloques de Gutenberg. En esta sección, veremos cómo registrar este proceso como una ability para que cualquier entidad con los permisos necesarios pueda descubrirla y utilizarla.
Antes de registrar una nueva ability, tienes que registrar una nueva categoría de ability.
Para ello, tendrás que conectar la función wp_register_ability_category() al hook wp_abilities_api_categories_init.
La función acepta un slug de categoría único y un array asociativo de argumentos.
A continuación te explicamos cómo registrar tu categoría de ability:
function aicb_register_ability_category(): void {
if ( ! function_exists( 'wp_register_ability_category' ) ) {
return;
}
wp_register_ability_category(
'content-generation',
array(
'label' => 'Content Generation',
'description' => 'AI-powered content transformation and structuring abilities',
)
);
}
add_action( 'wp_abilities_api_categories_init', 'aicb_register_ability_category' );
El siguiente paso es registrar la ability. Para ello, tendrás que conectar la función wp_register_ability() a la acción wp_abilities_api_init.
La función acepta dos argumentos: el nombre de la ability, incluyendo su espacio de nombres, y un array de argumentos para la configuración de la ability.
Aquí tienes el registro de la ability para el plugin AI Content Builder:
function aicb_register_audio_to_gutenberg_blocks_ability(): void {
if ( ! function_exists( 'wp_register_ability' ) ) {
return;
}
$input_schema = array( ... );
$output_schema = array( ... );
wp_register_ability(
'ai-content-builder/audio-to-gutenberg-blocks',
array(
'category' => 'content-generation',
'label' => 'Audio to Gutenberg Blocks',
'description' => 'Transcribes audio and converts the content into WordPress Gutenberg-compatible block objects.',
'input_schema' => $input_schema,
'output_schema' => $output_schema,
'execute_callback' => 'aicb_audio_to_gutenberg_blocks_callback',
'permission_callback' => static function (): bool {
return current_user_can( 'edit_posts' );
},
'meta' => array(
'show_in_rest' => true,
'annotations' => array(
'readonly' => false,
'destructive' => false,
'idempotent' => false,
'instructions' => 'Processes an audio attachment: transcribes it, generates structured blog content via AI, and returns Gutenberg-ready block objects.',
),
),
)
);
}
add_action( 'wp_abilities_api_init', 'aicb_register_audio_to_gutenberg_blocks_ability' );
En la llamada a la función wp_register_ability, hemos configurado los siguientes argumentos:
category: La categoría a la que pertenece la ability.label: El nombre que se muestra de la ability.description: Una breve descripción de lo que hace la ability y para qué sirve.input_schema: El esquema de datos para los argumentos de entrada.output_schema: El esquema de datos que proporciona y devuelve la ability.execute_callback: La función callback que se ejecutará cuando se active la ability.permission_callback: Una función callback que se ejecuta para comprobar que el agente tiene los permisos necesarios para ejecutar la ability.meta: Un array de campos de metadatos adicionales para la capacidad.show_in_rest: Determina si se muestra o no la función dentro de la API REST de WordPress.annotations: Un array de elementos descriptivos que definen el comportamiento de la ability.
input_schema es un array que define el contrato de entrada de la ability. Representa la definición del esquema JSON para validar la entrada de la ability. En nuestro caso concreto, se define así:
$input_schema = array(
'type' => 'object',
'properties' => array(
'audio_id' => array(
'type' => 'integer',
'description' => 'The ID of the audio attachment to process and convert into Gutenberg blocks.',
),
),
'required' => array( 'audio_id' ),
);
Este esquema JSON representa el formato que deben seguir los datos de entrada para utilizar esta función.
output_schema es el contrato de salida que devuelve la función. En nuestro ejemplo, cada elemento es un objeto que representa un bloque JSON:
$output_schema = array(
'type' => 'object',
'properties' => array(
'title' => array( 'type' => 'string' ),
'sections' => array(
'type' => 'array',
'items' => array( 'type' => 'object' ),
),
'blocks' => array(
'type' => 'array',
'items' => array( 'type' => 'object' ),
),
'transcript' => array( 'type' => 'string' ),
),
'required' => array( 'blocks' ),
);
El siguiente paso es definir la función de callback que se ejecuta cuando se activa la capacidad (mira el código completo en GitHub):
function aicb_audio_to_gutenberg_blocks_callback( array $args ) {
// missing code
// see GitHub
...
$structured_json = wp_ai_client_prompt( $prompt )
->using_system_instruction( $instructions )
->using_temperature( 0.4 )
->as_json_response( $schema )
->generate_text();
if ( is_wp_error( $structured_json ) ) {
return $structured_json;
}
$structured = json_decode( (string) $structured_json, true );
if ( ! is_array( $structured ) ) {
return new WP_Error(
'invalid_ai_json',
'Could not parse structured AI response.',
array( 'status' => 500 )
);
}
// Normalize the output.
$normalized = aicb_normalize_structured_post( $structured );
if ( '' === $normalized['title'] && empty( $normalized['sections'] ) ) {
return new WP_Error(
'empty_structured_content',
'The AI provider returned empty structured content.',
array( 'status' => 500 )
);
}
// Convert to Gutenberg blocks.
$blocks = aicb_sections_to_blocks( $normalized['title'], $normalized['sections'] );
return $blocks;
}
Esta función invoca dos funciones personalizadas. La primera (aicb_normalize_structured_post) normaliza la salida de la IA a un formato predefinido y limpia los datos:
function aicb_normalize_structured_post( array $structured ): array {
$title = isset( $structured['title'] )
? sanitize_text_field( (string) $structured['title'] )
: '';
$sections = array();
if ( isset( $structured['sections'] ) && is_array( $structured['sections'] ) ) {
foreach ( $structured['sections'] as $section ) {
if ( ! is_array( $section ) ) {
continue;
}
$heading = isset( $section['heading'] )
? sanitize_text_field( (string) $section['heading'] )
: '';
$level = 2;
$paragraphs = array();
if ( isset( $section['paragraphs'] ) && is_array( $section['paragraphs'] ) ) {
foreach ( $section['paragraphs'] as $paragraph ) {
$clean_paragraph = trim( sanitize_textarea_field( (string) $paragraph ) );
if ( '' !== $clean_paragraph ) {
$paragraphs[] = $clean_paragraph;
}
}
}
$bullet_points = array();
if ( isset( $section['bullet_points'] ) && is_array( $section['bullet_points'] ) ) {
foreach ( $section['bullet_points'] as $bullet_point ) {
$clean_bullet_point = trim( sanitize_text_field( (string) $bullet_point ) );
if ( '' !== $clean_bullet_point ) {
$bullet_points[] = $clean_bullet_point;
}
}
}
if ( '' === $heading || empty( $paragraphs ) ) {
continue;
}
$sections[] = array(
'heading' => $heading,
'level' => $level,
'paragraphs' => $paragraphs,
'bullet_points' => $bullet_points,
);
}
}
return array(
'title' => $title,
'sections' => $sections,
);
}
La función acepta un array estructurado de objetos JSON, normaliza y depura los datos, y devuelve una array que contiene el título y las secciones.
La segunda función (aicb_sections_to_blocks) convierte los datos normalizados en objetos descriptores de bloques y se define así:
function aicb_sections_to_blocks( string $title, array $sections ): array {
$blocks = array();
foreach ( $sections as $section ) {
if ( ! is_array( $section ) ) {
continue;
}
$heading = isset( $section['heading'] ) ? trim( (string) $section['heading'] ) : '';
if ( '' === $heading ) {
continue;
}
$paragraphs = array();
if ( isset( $section['paragraphs'] ) && is_array( $section['paragraphs'] ) ) {
foreach ( $section['paragraphs'] as $paragraph ) {
$clean = trim( (string) $paragraph );
if ( '' !== $clean ) {
$paragraphs[] = $clean;
}
}
}
if ( empty( $paragraphs ) ) {
continue;
}
$blocks[] = array(
'name' => 'core/heading',
'attributes' => array(
'content' => $heading,
'level' => 2,
),
);
foreach ( $paragraphs as $paragraph ) {
$blocks[] = array(
'name' => 'core/paragraph',
'attributes' => array(
'content' => $paragraph,
),
);
}
if ( isset( $section['bullet_points'] ) && is_array( $section['bullet_points'] ) ) {
$bullet_items_html = '';
foreach ( $section['bullet_points'] as $bullet_point ) {
$clean_bullet = trim( sanitize_text_field( (string) $bullet_point ) );
if ( '' === $clean_bullet ) {
continue;
}
// core/list expects HTML in the `values` attribute.
$bullet_items_html .= '<li>' . esc_html( $clean_bullet ) . '</li>';
}
if ( '' !== $bullet_items_html ) {
$blocks[] = array(
'name' => 'core/list',
'attributes' => array(
'values' => '<ul>' . $bullet_items_html . '</ul>',
),
);
}
}
}
return $blocks;
}
Estos son los puntos clave de esta función:
- La función acepta dos argumentos: una cadena que representa el título de la publicación y un array con las secciones generadas por el modelo de IA.
- Para cada sección, la función genera un encabezado y al menos un párrafo.
- Si hay viñetas, genera el número correspondiente de elementos de la lista.
- La función devuelve un array
$blocksde objetos descriptores de bloques, que es el contrato de salida que devuelve la ability ($output_schema).
Ten en cuenta que el resultado de la función no es el código de marcado del bloque sin procesar. Este se generará en el lado del cliente mediante la función createBlock de JavaScript.
Por ejemplo, el elemento de título de una sección se representa mediante el siguiente objeto:
if ( '' !== $heading ) {
$blocks[] = array(
'name' => 'core/heading',
'attributes' => array(
'content' => $heading,
'level' => ( 3 === $level ) ? 3 : 2,
),
);
}
Una vez que hayas registrado tu ability, puedes ejecutar en tu terminal los mismos comandos de WP-CLI que has visto antes para obtener los detalles. El siguiente código generará el esquema de entrada para tu capacidad:
wp --user=1 eval '
$ability = wp_get_ability( "ai-content-builder/audio-to-gutenberg-blocks" );
if ( ! $ability ) {
echo "Ability not found\n";
exit( 1 );
}
echo "Input Schema:\n";
var_dump( $ability->get_input_schema() );
'
Este es el resultado en la terminal:
Input Schema:
array(3) {
["type"]=>
string(6) "object"
["properties"]=>
array(1) {
["audio_id"]=>
array(2) {
["type"]=>
string(7) "integer"
["description"]=>
string(76) "The ID of the audio attachment to process and convert into Gutenberg blocks."
}
}
["required"]=>
array(1) {
[0]=>
string(8) "audio_id"
}
}
Del mismo modo, puedes recuperar el esquema de salida de la ability:
wp --user=1 eval '
$ability = wp_get_ability( "ai-content-builder/audio-to-gutenberg-blocks" );
if ( ! $ability ) {
echo "Ability not found\n";
exit( 1 );
}
echo "Output Schema:\n";
var_dump( $ability->get_output_schema() );
'
También puedes mostrar el objeto completo de tu ability con el siguiente comando:
wp eval '
$ability = wp_get_ability( "ai-content-builder/audio-to-gutenberg-blocks" );
if ( ! $ability ) {
echo "Ability not found\n";
exit( 1 );
}
echo "Name: " . $ability->get_name() . "\n";
echo "Label: " . $ability->get_label() . "\n";
echo "Category: " . $ability->get_category() . "\n";
echo "Description: " . $ability->get_description() . "\n";
echo "nInput Schema:\n";
var_dump( $ability->get_input_schema() );
echo "nOutput Schema:\n";
var_dump( $ability->get_output_schema() );
'
Ejecutar una ability
Para ejecutar una ability, usarás el método execute() del objeto $ability. Puedes probar a ejecutar el siguiente código PHP a través de WP-CLI para activar la capacidad core/get-site-info:
wp --user=1 eval '
$ability = wp_get_ability( "core/get-site-info" );
if ( ! $ability ) {
echo "Ability not found\n";
exit(1);
}
$result = $ability->execute();
if ( is_wp_error( $result ) ) {
echo "ERROR: " . $result->get_error_message() . "\n";
exit(1);
}
echo json_encode( $result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . "\\n";
'
Cuando ejecutes este comando, la ability te proporcionará un objeto JSON similar al siguiente:
{
"name": "WordPress 7.0",
"description": "",
"url": "http://yoursite.kinsta.cloud",
"wpurl": "http://yoursite.kinsta.cloud",
"admin_email": "[email protected]",
"charset": "UTF-8",
"language": "en-US",
"version": "7.1-alpha-62550"
}
Lo anterior es solo un ejemplo sencillo de una ability que te proporciona datos para tu sitio.
Como ya hemos dicho, una ability puede necesitar datos de entrada, realizar operaciones con esos datos y devolver un resultado estructurado. Podemos ver un ejemplo de esto con la ability que registramos en la sección anterior.
Sin salir de tu terminal, ve al directorio raíz de tu sitio y ejecuta el siguiente código PHP:
wp --user=1 eval '
$ability = wp_get_ability( "ai-content-builder/audio-to-gutenberg-blocks" );
if ( ! $ability ) {
echo "Ability not found\n";
exit( 1 );
}
$input = array( "audio_id" => 1755 );
$result = $ability->execute( $input );
if ( is_wp_error( $result ) ) {
echo "ERROR: " . $result->get_error_message() . "\n";
exit( 1 );
}
echo json_encode( $result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . "\n";
'
El método execute pasa los datos de entrada estructurados a la ability, que devuelve un array de objetos listos para convertirse en bloques de Gutenberg:
[
{
"name": "core/heading",
"attributes": {
"content": "A Well-Deserved Rest Day in Marrakech",
"level": 2
}
},
{
"name": "core/paragraph",
"attributes": {
"content": "On April 24th, our group of seven motorcyclists took a break from the open road..."
}
},
{
"name": "core/heading",
"attributes": {
"content": "Exploring Jemaa el-Fnaa and the Medina",
"level": 2
}
},
{
"name": "core/paragraph",
"attributes": {
"content": "Our journey led us straight to Jemaa el-Fnaa, the legendary main square of Marrakech..."
}
},
{
"name": "core/list",
"attributes": {
"values": "<ul><li>Navigating the bustling souks and narrow alleys of the ancient Medina.</li><li>Savoring traditional Moroccan and Berber dishes.</li><li>Experiencing the vibrant street performances and food stalls of Jemaa el-Fnaa at night.</li></ul>"
}
},
...
]
Integración con la API REST
La API Abilities de WordPress ofrece una estructura de enrutamiento unificada que permite a agentes externos consultar mediante programación las categorías de abilities disponibles (/categories), inspeccionar contratos de capacidades específicos (/abilities/{name}) y ejecutar una ability concreta utilizando el endpoint estándar run (/abilities/{name}/run).
Aquí tienes, por ejemplo, una solicitud GET que devuelve la lista de categorías de nuestro sitio de prueba:
https://yoursite.kinsta.cloud/wp-json/wp-abilities/v1/categories

Cuando registramos la ability en el ejemplo anterior, establecimos el parámetro show_in_rest en true. Al hacerlo, conseguimos que nuestra ability fuera accesible automáticamente a través de estos endpoints nativos de la API REST de WordPress, dentro del espacio de nombres centralizado del núcleo (wp-abilities/v1).
Esto significa que no hace falta que configures manualmente rutas personalizadas desde cero para invocar una ability desde un entorno externo. Los agentes externos pueden detectar y ejecutar tu función mediante solicitudes HTTP estándar.
Puedes consultar el contrato específico de nuestra ability con la siguiente solicitud GET:
https://yoursite.kinsta.cloud/wp-json/wp-abilities/v1/abilities/ai-content-builder/audio-to-gutenberg-blocks
Por último, puedes activar la ability con una solicitud POST autenticada:
https://yoursite.kinsta.cloud/wp-json/wp-abilities/v1/abilities/ai-content-builder/audio-to-gutenberg-blocks/run
Al enviar este tipo de solicitud, asegúrate de haber especificado los datos de entrada. Para nuestro ejemplo, hemos establecido el siguiente JSON en el cuerpo de la solicitud:
{
"input": {
"audio_id": YOUR_AUDIO_ID
}
}

Nuestra ability procesó el audio y lo envió al modelo de IA configurado en el sitio. El modelo devolvió una salida estructurada que posteriormente se normalizó y depuró, devolviendo finalmente el siguiente array de objetos que contiene los atributos del bloque:
{
"blocks": [
{
"name": "core/heading",
"attributes": { "content": "A Welcome Rest Day in Marrakech", "level": 2 }
},
{
"name": "core/paragraph",
"attributes": { "content": "On April 24, our group of seven motorcyclists paused our journey..." }
}
]
}
Y este es precisamente el resultado que buscábamos.
El futuro de WordPress es agéntico
Mientras que el Cliente de IA (AI Client) y la nueva arquitectura de conectores incorporan capacidades de procesamiento de IA a WordPress, la API Abilities redefine la forma en que WordPress interactúa con el mundo exterior. Estamos viviendo un cambio de paradigma radical, pasando de una arquitectura web tradicional— basada en la interacción manual del usuario, en la que cada integración requería endpoints personalizados y una asignación manual— a una arquitectura basada en la intención, diseñada desde cero para la automatización.
Para los desarrolladores de WordPress, la nueva API Abilities supone un punto de inflexión arquitectónico, que se caracteriza por desacoplar la funcionalidad de los plugins que contienen su lógica, reforzar la seguridad a través del contrato de entrada/salida y permitir la interoperabilidad nativa en todo el ecosistema.
En conjunto, estas funcionalidades garantizan que la API Abilities no sea simplemente otra API más, sino un auténtico motor de ejecución distribuida que te permite vislumbrar un futuro cada vez más autónomo para WordPress.