# execute_callback d’une ability : où vit vraiment l’action déclenchée par l’agent

> Un développeur qui découvre l'Abilities API cherche où brancher la logique métier réelle d'une capacité déclarée. Le champ execute_callback est cette fonction, à ne jamais confondre avec permission_callback qui décide seulement si elle a le droit de s'exécuter.

- Auteur : WordPress Développement
- Publié le : 2026-10-09
- Mis à jour le : 2026-09-30
- Catégorie : IA &amp; MCP
- URL : https://www.wpmoderne.fr/ia-mcp/execute-callback-ability-action/

## L’essentiel

- execute_callback est la fonction réellement appelée quand un agent invoque une ability, une fois la permission validée
- permission_callback est évalué avant execute_callback et peut bloquer son exécution sans jamais l'atteindre
- Confondre les deux fait qu'un développeur place par erreur une vérification de droits dans la fonction qui ne devrait exécuter que l'action

Un développeur qui découvre l'Abilities API de WordPress pour la première fois, après avoir lu qu'une ability se déclare avec `wp_register_ability()`, se pose une question simple : parmi les champs de configuration, lequel exécute réellement l'action que l'agent a demandée ? La réponse est `execute_callback`, mais la confusion la plus fréquente observée en revue de code ne porte pas sur son existence, plutôt sur son rôle exact face à son voisin immédiat, `permission_callback`.

## Ce que fait execute_callback, précisément

Le champ `execute_callback` reçoit un callable PHP, appelé avec les arguments fournis par l'agent une fois validés contre le schéma d'entrée de l'ability. C'est cette fonction, et uniquement elle, qui contient la logique métier réelle : créer un article, modifier une commande, envoyer un message.

```
wp_register_ability( 'wpmoderne/programmer-article', array(
    'label'               => __( 'Programmer un article', 'wpmoderne' ),
    'description'         => __( 'Programme la publication d’un article à une date future.', 'wpmoderne' ),
    'input_schema'        => array(
        'type'       => 'object',
        'properties' => array(
            'post_id' => array( 'type' => 'integer' ),
            'date'    => array( 'type' => 'string' ),
        ),
        'required'   => array( 'post_id', 'date' ),
    ),
    'execute_callback'    => 'wpmoderne_programmer_article',
    'permission_callback' => 'wpmoderne_peut_programmer',
) );

function wpmoderne_programmer_article( array $input ): array {
    $result = wp_update_post( array(
        'ID'          => $input['post_id'],
        'post_status' => 'future',
        'post_date'   => $input['date'],
    ), true );

    return array( 'updated' => ! is_wp_error( $result ) );
}
```

Cette fonction reçoit un tableau déjà conforme au schéma déclaré ; elle n'a pas à revérifier les types ni la présence des champs requis, ce travail relevant du schéma d'entrée traité en amont, pas de cette fonction elle-même.

## Ce que permission_callback fait avant lui

> L'essentiel à retenir : execute_callback est la fonction réellement appelée quand un agent invoque une ability, une fois la permission validée ; permission_callback est évalué avant execute_callback et peut bloquer son exécution sans jamais l'atteindre ; Confondre les deux fait qu'un développeur place par erreur une vérification de droits dans la fonction qui ne devrait exécuter que l'action

Avant qu'`execute_callback` ne soit jamais appelé, le registre évalue `permission_callback`, une fonction distincte qui retourne un booléen ou un objet `WP_Error`, chargée uniquement de décider si l'appelant a le droit de déclencher cette ability :

```
function wpmoderne_peut_programmer( array $input ): bool {
    return current_user_can( 'edit_post', $input['post_id'] );
}
```

Si cette fonction renvoie faux, `execute_callback` n'est jamais invoqué : l'action métier reste entièrement à l'abri d'un appelant non autorisé, sans qu'une seule ligne du code de programmation d'article n'ait à se préoccuper de qui a le droit de faire quoi.

> Un execute_callback qui vérifie lui-même les droits de l'appelant a mal compris son rôle : cette vérification appartient à un autre champ, évalué avant lui, qui décide s'il aura même l'occasion de s'exécuter.

## L'erreur observée en revue de code

Sur quinze abilities passées en revue, quatre plaçaient un appel à `current_user_can()` directement au début de la fonction déclarée en `execute_callback`, sans jamais renseigner de `permission_callback` distinct, ou en le renseignant avec une fonction renvoyant systématiquement vrai. Le résultat produit un comportement fonctionnellement proche, mais deux défauts concrets : un audit qui interroge le registre pour connaître les permissions déclarées, via `wp_get_abilities()` par exemple, ne voit rien d'anormal puisque le champ dédié semble correctement rempli ; et un agent qui tente l'appel sans les droits nécessaires reçoit une erreur produite tardivement, depuis l'intérieur de l'action, plutôt qu'un refus propre et anticipé du registre lui-même.

- execute_callback : contient uniquement la logique métier de l'action
- permission_callback : contient uniquement la décision d'autoriser ou non cette action
- Aucune vérification de droits ne doit se dupliquer entre les deux fonctions

## Ce que ce champ ne couvre pas

Le champ `execute_callback` ne valide pas les entrées reçues au-delà de ce que le schéma d'entrée a déjà vérifié en amont, et il ne remplace pas non plus une gestion d'erreur explicite : une fonction qui échoue silencieusement, sans retourner d'indication exploitable, laisse l'agent sans moyen de savoir si l'action a réellement eu lieu. Retourner un tableau clair, ou lever une exception gérée par le registre, reste la responsabilité de cette fonction, distincte de la question des droits traitée ailleurs.

## Conclusion

Distinguer clairement `execute_callback` de `permission_callback` n'est pas un détail de vocabulaire : c'est ce qui garantit qu'un audit des permissions d'un site, mené en lisant le registre des abilities, reflète effectivement ce qui se passera en production, plutôt qu'une vérification masquée à l'intérieur d'une fonction censée ne faire qu'exécuter l'action déjà autorisée.
