На протяжении десятилетий плагины и темы WordPress создавались в расчете исключительно на прямое взаимодействие с человеком через административный веб-интерфейс или на жестко закодированные интеграции через хуки и REST API. С распространением автономных AI-агентов (Cursor, Claude Code, автономные агенты поддержки, AI-пайплайны публикаций) возникла потребность в стандартизированном интерфейсе функционального вызова (Function Calling / Tool Use).
В версиях WordPress 6.9 и 7.0 ядро внедрило стандарт Abilities API (включая Client-Side Abilities API). Этот механизм превращает компоненты WordPress в Agent-Callable сущности — самодокументируемые функциональные инструменты, которые внешние и внутренние AI-агенты могут:
/wp-json/wp/v2/abilities с получением документации и схем аргументов.permission_callback проверяет матрицу прав текущей сессии (Capabilities) и блокирует несанкционированные действия.Idempotency-Key исключает риск повторных списаний средств, дублирования купонов или повторного создания записей при сетевых сбоях и повторах запросов модели (Agent Retry Loops).Внутренний конвейер вызова способности агентом через Abilities API ядра:
[ Автономный AI-Агент (Cursor / Claude Code / Поддержка) ]
|
v (1. Интроспекция: какие инструменты доступны?)
[ GET /wp-json/wp/v2/abilities ]
|
v (Возврат схем: refund_order, create_coupon, set_meta)
[ Агент генерирует Tool Call с аргументами и Idempotency Key ]
|
v (2. Вызов через шлюз Abilities API)
[ wp_execute_ability('agentic-lab/create-coupon', $payload) ]
|
+-----------------+-----------------+
| Проверка прав: current_user_can() | -> При отказе: 403 Forbidden
| Валидация схемы: JSON Schema D7 | -> При ошибке типов: 400 Bad Request
| Проверка кэша Idempotency-Key | -> При дубле: возврат кэшированного ответа
+-----------------+-----------------+
|
v (3. Вызов обработчика плагина: execute_callback)
[ WooCommerce CRUD: WC_Coupon::save() ]
|
v (4. Формирование типизированного ответа)
[ Запись в Audit Log: do_action('wp_ability_executed') ]
|
v
[ Агент получает структурированный DTO результат ]Декларация способности с описанием, категорией и строгой JSON Schema.
Внешний агент считывает список доступных инструментов сайта и их параметров.
Модель формулирует аргументы вызова и передает уникальный Idempotency Key.
Ядро проверяет матрицу прав пользователя и типы переданных параметров.
Выполнение бизнес-логики, сохранение в базу и триггер события аудита.
agentic-lab/generate-promo-code.core/publish-release-notes.media/compress-attachment.woocommerce/flag-fraud-order.Ниже приведен эталонный производственный артефакт регистрации способности генерации промокодов WooCommerce с гарантией идемпотентности и проверкой прав.
<?php
declare(strict_types=1);
/**
* Author: Artur Yusupov (Fullstack Agentic Lab)
* Package: @agentic-lab/abilities
* Module: CommercePromoCodeAbility
* Standard: WordPress 7.0+ Abilities API / WooCommerce HPOS / PHP 8.4
*/
namespace AgenticLab\Abilities;
use WC_Coupon;
use WP_Error;
use Throwable;
final class CommercePromoCodeAbility
{
public static function register(): void
{
if (!function_exists('wp_register_ability')) {
return;
}
wp_register_ability('agentic-lab/generate-promo-code', [
'label' => __('Создать скидочный промокод для клиента', 'agentic-lab'),
'description' => __('Генерирует персональный скидочный купон WooCommerce с заданным процентом скидки и ограничением по времени.', 'agentic-lab'),
'category' => 'ecommerce',
'idempotent' => true,
// JSON Schema Draft 7 входных параметров для ИИ-агента
'parameters_schema' => [
'type' => 'object',
'properties' => [
'discount_percent' => [
'type' => 'integer',
'minimum' => 1,
'maximum' => 50,
'description' => 'Процент скидки на заказ (от 1 до 50%).',
],
'customer_email' => [
'type' => 'string',
'format' => 'email',
'description' => 'Email покупателя, для которого генерируется персональный купон.',
],
'expiry_days' => [
'type' => 'integer',
'minimum' => 1,
'maximum' => 30,
'default' => 7,
'description' => 'Количество дней до истечения срока действия купона.',
],
'idempotency_key' => [
'type' => 'string',
'description' => 'Уникальный UUIDv4 запроса для предотвращения повторной генерации купона.',
],
],
'required' => ['discount_percent', 'customer_email', 'idempotency_key'],
'additionalProperties' => false,
],
// Проверка прав доступа: только персонал магазина может создавать купоны
'permission_callback' => static function (): bool {
return current_user_can('manage_woocommerce');
},
// Исполняемый колбэк при вызове агентом
'execute_callback' => [self::class, 'execute'],
]);
}
/**
* @param array<string, mixed> $args Входные аргументы после валидации схемы
* @return array<string, mixed>|WP_Error
*/
public static function execute(array $args): array|WP_Error
{
$idempotencyKey = (string) $args['idempotency_key'];
$cacheKey = 'agentic_ability_promo_' . md5($idempotencyKey);
// 1. Проверка идемпотентности: исключаем повторное создание при ретрае агента
$cachedResult = get_transient($cacheKey);
if ($cachedResult !== false && is_array($cachedResult)) {
return $cachedResult;
}
$discount = (int) $args['discount_percent'];
$email = sanitize_email((string) $args['customer_email']);
$days = (int) ($args['expiry_days'] ?? 7);
// Генерация уникального человекочитаемого кода купона
$couponCode = strtoupper(sprintf('GIFT-%d-%s', $discount, wp_generate_password(6, false)));
try {
$coupon = new WC_Coupon();
$coupon->set_code($couponCode);
$coupon->set_discount_type('percent');
$coupon->set_amount($discount);
$coupon->set_individual_use(true);
$coupon->set_usage_limit(1); // Одноразовый купон
$coupon->set_customer_email([$email]);
$coupon->set_date_expires(time() + ($days * DAY_IN_SECONDS));
$coupon->set_description(sprintf('Сгенерировано AI-агентом для %s', $email));
$couponId = $coupon->save();
if ($couponId === 0) {
return new WP_Error('coupon_creation_failed', __('Ошибка сохранения купона в WooCommerce.', 'agentic-lab'));
}
$response = [
'success' => true,
'coupon_id' => $couponId,
'coupon_code' => $couponCode,
'discount_percent' => $discount,
'customer_email' => $email,
'expires_at' => gmdate('Y-m-d H:i:s', time() + ($days * DAY_IN_SECONDS)),
];
// Сохраняем результат в транзиентах на 24 часа для гарантии идемпотентности
set_transient($cacheKey, $response, DAY_IN_SECONDS);
// Системный аудит вызова способности
do_action('wp_ability_executed', 'agentic-lab/generate-promo-code', $response, get_current_user_id());
return $response;
} catch (Throwable $e) {
return new WP_Error(
'ability_execution_error',
sprintf(__('Сбой выполнения способности: %s', 'agentic-lab'), $e->getMessage())
);
}
}
}
// Регистрация в хуке ядра WordPress 7.0
add_action('wp_register_abilities', [CommercePromoCodeAbility::class, 'register']);Симптом: При задержке ответа сети ИИ-агент повторяет запрос Tool Call и создает 3 одинаковых купона на скидку или списывает деньги несколько раз.
Причина: Обработчик способности не проверяет idempotency_key и выполняет мутацию базы данных при каждом вызове.
Решение: Обязательное использование уникального idempotency_key и кэширование успешного ответа в транзиентах или Redis.
Симптом: Любой неавторизованный пользователь или бот может удалить контент или нагенерировать промокоды через публичный эндпоинт способностей.
Причина: Разработчик оставил заглушку 'permission_callback' => '__return_true' для мутирующей способности.
Решение: Строгая проверка прав текущего пользователя через current_user_can().
Симптом: Агент передает отрицательные проценты скидок (-100%) или небезопасные строки, ломая расчеты чекаута.
Причина: Отсутствие ограничений minimum, maximum и регулярных выражений валидации в parameters_schema.
Решение: Описывать схемы со строгими диапазонами чисел, валидацией форматов email и additionalProperties: false.
Симптом: Агент не может программно распарсить результат (например, получить код созданного купона) и начинает галлюцинировать.
Причина: Функция execute_callback возвращает строку вида "Купон успешно создан!".
Решение: Всегда возвращать ассоциативный массив с типизированными ключами (coupon_code, coupon_id, expires_at).
Плагин декларирует способность, ее права и JSON Schema в хуке wp_register_abilities.
ИИ-агент запрашивает инструменты и выбирает способность на основе описания.
Ядро проверяет RBAC-права, валидирует схему и проверяет Idempotency-Key.
Вызов execute_callback с сохранением сущности в базе данных WooCommerce.
Триггер события аудита wp_ability_executed и возврат структурированного ответа.