Les points d’accroche de Plugin sont des points d’extension intégrés au processus pour les Plugins OpenClaw. Utilisez-les lorsqu’un Plugin doit inspecter ou modifier les exécutions d’agent, les appels d’outil, le flux de messages, le cycle de vie des sessions, le routage des sous-agents, les installations ou le démarrage du Gateway. Utilisez plutôt les points d’accroche internes lorsque vous voulez un petit scriptDocumentation Index
Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
HOOK.md installé par l’opérateur pour les événements de commande et de Gateway tels que
/new, /reset, /stop, agent:bootstrap ou gateway:startup.
Démarrage rapide
Enregistrez des points d’accroche de Plugin typés avecapi.on(...) depuis le point d’entrée de votre Plugin :
priority décroissante. Les points d’accroche
de même priorité conservent l’ordre d’enregistrement.
api.on(name, handler, opts?) accepte :
priority- ordre des gestionnaires (les valeurs plus élevées s’exécutent en premier).timeoutMs- budget facultatif par point d’accroche. Lorsqu’il est défini, l’exécuteur de points d’accroche abandonne ce gestionnaire après l’expiration du budget et continue avec le suivant, au lieu de laisser une configuration ou un rappel lent consommer le délai d’expiration de modèle configuré par l’appelant. Omettez-le pour utiliser le délai d’expiration d’observation/décision par défaut que l’exécuteur de points d’accroche applique de façon générique.
hooks.timeouts.<hookName> remplace hooks.timeoutMs, qui remplace la valeur
api.on(..., { timeoutMs }) définie par le Plugin. Chaque valeur configurée doit
être un entier positif inférieur ou égal à 600000 millisecondes. Privilégiez les remplacements par point d’accroche
pour les points d’accroche connus comme lents afin qu’un Plugin ne reçoive pas un budget plus long
partout.
Chaque point d’accroche reçoit event.context.pluginConfig, la configuration résolue du
Plugin qui a enregistré ce gestionnaire. Utilisez-la pour les décisions de point d’accroche qui nécessitent
les options actuelles du Plugin ; OpenClaw l’injecte par gestionnaire sans modifier
l’objet d’événement partagé vu par les autres Plugins.
Catalogue des points d’accroche
Les points d’accroche sont groupés selon la surface qu’ils étendent. Les noms en gras acceptent un résultat de décision (blocage, annulation, remplacement ou exigence d’approbation) ; tous les autres sont uniquement d’observation. Tour d’agentbefore_model_resolve- remplacer le fournisseur ou le modèle avant le chargement des messages de sessionagent_turn_prepare- consommer les injections de tour de Plugin mises en file d’attente et ajouter du contexte du même tour avant les points d’accroche d’invitebefore_prompt_build- ajouter du contexte dynamique ou du texte d’invite système avant l’appel au modèlebefore_agent_start- phase combinée conservée uniquement pour compatibilité ; privilégiez les deux points d’accroche ci-dessusbefore_agent_run- inspecter l’invite finale et les messages de session avant la soumission au modèle, et bloquer éventuellement l’exécutionbefore_agent_reply- court-circuiter le tour de modèle avec une réponse synthétique ou le silencebefore_agent_finalize- inspecter la réponse finale naturelle et demander un passage de modèle supplémentaireagent_end- observer les messages finaux, l’état de réussite et la durée d’exécutionheartbeat_prompt_contribution- ajouter du contexte propre à Heartbeat pour les Plugins de surveillance en arrière-plan et de cycle de vie
model_call_started/model_call_ended- observer les métadonnées assainies d’appel fournisseur/modèle, le minutage, le résultat et les hachages bornés d’identifiants de requête, sans contenu d’invite ni de réponsellm_input- observer l’entrée du fournisseur (invite système, invite, historique)llm_output- observer la sortie du fournisseur
before_tool_call- réécrire les paramètres d’outil, bloquer l’exécution ou exiger une approbationafter_tool_call- observer les résultats d’outil, les erreurs et la duréetool_result_persist- réécrire le message de l’assistant produit à partir d’un résultat d’outilbefore_message_write- inspecter ou bloquer une écriture de message en cours (rare)
inbound_claim- prendre en charge un message entrant avant le routage vers l’agent (réponses synthétiques)message_received- observer le contenu entrant, l’expéditeur, le fil et les métadonnéesmessage_sending- réécrire le contenu sortant ou annuler la remisemessage_sent- observer la réussite ou l’échec de la remise sortantebefore_dispatch- inspecter ou réécrire une expédition sortante avant le transfert au canalreply_dispatch- participer au pipeline final d’expédition de réponse
session_start/session_end- suivre les limites du cycle de vie des sessions. Lereasonde l’événement est l’une des valeursnew,reset,idle,daily,compaction,deleted,shutdown,restartouunknown. Les valeursshutdownetrestartsont déclenchées par le finaliseur d’arrêt du Gateway lorsque le processus est arrêté ou redémarré alors que des sessions sont encore actives, afin que les Plugins en aval (comme les magasins de mémoire ou de transcriptions) puissent finaliser les lignes fantômes qui resteraient autrement dans un état ouvert entre les redémarrages. Le finaliseur est borné afin qu’un Plugin lent ne puisse pas bloquer SIGTERM/SIGINT.before_compaction/after_compaction- observer ou annoter les cycles de Compactionbefore_reset- observer les événements de réinitialisation de session (/reset, réinitialisations programmatiques)
subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended- coordonner le routage des sous-agents et la remise de fin d’exécution
gateway_start/gateway_stop- démarrer ou arrêter les services gérés par le Plugin avec le Gatewaycron_changed- observer les changements du cycle de vie Cron gérés par le Gateway (ajouté, mis à jour, supprimé, démarré, terminé, planifié)before_install- inspecter les analyses d’installation de Skills ou de Plugins et les bloquer éventuellement
Politique d’appel d’outil
before_tool_call reçoit :
event.toolNameevent.paramsevent.derivedPathsfacultatif, contenant des indices de chemins cibles déduits par l’hôte au mieux pour des enveloppes d’outil bien connues telles queapply_patch; lorsqu’ils sont présents, ces chemins peuvent être incomplets ou surestimer ce que l’outil touchera réellement (par exemple avec des entrées mal formées ou partielles)event.runIdfacultatifevent.toolCallIdfacultatif- des champs de contexte comme
ctx.agentId,ctx.sessionKey,ctx.sessionId,ctx.runId,ctx.jobId(défini sur les exécutions pilotées par Cron) et le diagnosticctx.trace
block: trueest terminal et ignore les gestionnaires de priorité inférieure.block: falseest traité comme une absence de décision.paramsréécrit les paramètres d’outil pour l’exécution.requireApprovalmet en pause l’exécution de l’agent et interroge l’utilisateur via les approbations de Plugin. La commande/approvepeut approuver à la fois les approbations d’exécution et de Plugin.- Un
block: truede priorité inférieure peut toujours bloquer après qu’un point d’accroche de priorité supérieure a demandé une approbation. onResolutionreçoit la décision d’approbation résolue -allow-once,allow-always,deny,timeoutoucancelled.
api.registerTrustedToolPolicy(...). Elles s’exécutent avant les points d’accroche
before_tool_call ordinaires et avant les décisions de Plugins externes. Utilisez-les uniquement
pour des garde-fous approuvés par l’hôte tels que la politique d’espace de travail, l’application des budgets ou
la sécurité de workflows réservés. Les Plugins externes doivent utiliser les points d’accroche before_tool_call
normaux.
Persistance des résultats d’outil
Les résultats d’outil peuvent inclure desdetails structurés pour le rendu d’interface utilisateur, les diagnostics,
le routage des médias ou les métadonnées gérées par le Plugin. Traitez details comme des métadonnées d’exécution,
et non comme du contenu d’invite :
- OpenClaw retire
toolResult.detailsavant le rejeu côté fournisseur et l’entrée de Compaction afin que les métadonnées ne deviennent pas du contexte de modèle. - Les entrées de session persistées conservent uniquement des
detailsbornés. Les détails surdimensionnés sont remplacés par un résumé compact etpersistedDetailsTruncated: true. tool_result_persistetbefore_message_writes’exécutent avant la limite finale de persistance. Les points d’accroche doivent néanmoins garder lesdetailsrenvoyés petits et éviter de placer du texte pertinent pour l’invite uniquement dansdetails; placez la sortie d’outil visible par le modèle danscontent.
Points d’accroche d’invite et de modèle
Utilisez les points d’accroche propres à chaque phase pour les nouveaux Plugins :before_model_resolve: reçoit uniquement l’invite actuelle et les métadonnées des pièces jointes. RenvoyezproviderOverrideoumodelOverride.agent_turn_prepare: reçoit l’invite actuelle, les messages de session préparés, et toutes les injections en file d’attente à usage unique drainées pour cette session. RenvoyezprependContextouappendContext.before_prompt_build: reçoit l’invite actuelle et les messages de session. RenvoyezprependContext,appendContext,systemPrompt,prependSystemContextouappendSystemContext.heartbeat_prompt_contribution: s’exécute uniquement pour les tours Heartbeat et renvoieprependContextouappendContext. Il est destiné aux moniteurs en arrière-plan qui doivent résumer l’état actuel sans modifier les tours initiés par l’utilisateur.
before_agent_start reste disponible pour compatibilité. Privilégiez les points d’accroche explicites ci-dessus
afin que votre Plugin ne dépende pas d’une phase combinée héritée.
before_agent_run s’exécute après la construction de l’invite et avant toute entrée de modèle,
y compris le chargement des images propres à l’invite et l’observation llm_input. Il reçoit
l’entrée utilisateur actuelle sous forme de prompt, ainsi que l’historique de session chargé dans messages
et l’invite système active. Renvoyez { outcome: "block", reason, message? }
pour arrêter l’exécution avant que le modèle puisse lire l’invite. reason est interne ;
message est le remplacement visible par l’utilisateur. Les seuls résultats pris en charge sont
pass et block ; les formes de décision non prises en charge échouent en mode fermé.
Lorsqu’une exécution est bloquée, OpenClaw stocke uniquement le texte de remplacement dans
message.content, plus des métadonnées de blocage non sensibles comme l’identifiant du Plugin
bloqueur et l’horodatage. Le texte utilisateur d’origine n’est conservé ni dans la transcription ni dans le contexte futur. Les raisons de blocage internes sont traitées comme sensibles et exclues des
charges utiles de transcription, d’historique, de diffusion, de journalisation et de diagnostic. L’observabilité
doit utiliser des champs assainis comme l’identifiant du bloqueur, le résultat, l’horodatage ou une catégorie sûre.
before_agent_start et agent_end incluent event.runId lorsque OpenClaw peut
identifier l’exécution active. La même valeur est également disponible sur ctx.runId.
Les exécutions pilotées par Cron exposent aussi ctx.jobId (l’identifiant de la tâche Cron d’origine) afin que
les points d’accroche de Plugin puissent limiter la portée des métriques, des effets de bord ou de l’état à une tâche planifiée spécifique.
Pour les exécutions provenant d’un canal, ctx.messageProvider est la surface fournisseur telle que
discord ou telegram, tandis que ctx.channelId est l’identifiant de cible de conversation
lorsqu’OpenClaw peut en déduire un à partir de la clé de session ou des métadonnées
de remise.
agent_end est un point d’accroche d’observation et s’exécute sans attente de résultat après le tour. L’exécuteur de points d’accroche applique un délai d’expiration de 30 secondes afin qu’un Plugin bloqué ou un point de terminaison de vectorisation
ne puisse pas laisser la promesse du point d’accroche en attente indéfiniment. Un délai d’expiration est journalisé et
OpenClaw continue ; cela n’annule pas le travail réseau géré par le Plugin sauf si le
Plugin utilise également son propre signal d’abandon.
Utilisez model_call_started et model_call_ended pour la télémétrie des appels fournisseur
qui ne doit pas recevoir les prompts bruts, l’historique, les réponses, les en-têtes, les corps de
requête ni les ID de requête fournisseur. Ces hooks incluent des métadonnées stables comme
runId, callId, provider, model, les champs optionnels api/transport, les champs terminaux
durationMs/outcome, et upstreamRequestIdHash quand OpenClaw peut dériver un
hachage borné de l’ID de requête fournisseur.
before_agent_finalize s’exécute uniquement lorsqu’un harness est sur le point d’accepter une
réponse finale naturelle de l’assistant. Ce n’est pas le chemin d’annulation /stop et il ne
s’exécute pas lorsque l’utilisateur interrompt un tour. Retournez { action: "revise", reason } pour demander
au harness un passage modèle supplémentaire avant la finalisation, { action: "finalize", reason? } pour forcer la finalisation, ou omettez un résultat pour continuer.
Les hooks natifs Stop de Codex sont relayés dans ce hook comme des décisions OpenClaw
before_agent_finalize.
Lors du retour de action: "revise", les plugins peuvent inclure des métadonnées retry pour rendre
le passage modèle supplémentaire borné et sûr à rejouer :
instruction est ajouté à la raison de révision envoyée au harness.
idempotencyKey permet à l’hôte de compter les nouvelles tentatives pour la même requête de plugin à travers
des décisions de finalisation équivalentes, et maxAttempts plafonne le nombre de passages supplémentaires que
l’hôte autorisera avant de continuer avec la réponse finale naturelle.
Les plugins non groupés qui ont besoin de hooks de conversation bruts (before_model_resolve,
before_agent_reply, llm_input, llm_output, before_agent_finalize,
agent_end, ou before_agent_run) doivent définir :
plugins.entries.<id>.hooks.allowPromptInjection=false.
Extensions de session et injections au tour suivant
Les plugins de workflow peuvent conserver un petit état de session compatible JSON avecapi.registerSessionExtension(...) et le mettre à jour via la méthode Gateway
sessions.pluginPatch. Les lignes de session projettent l’état d’extension enregistré
via pluginExtensions, ce qui permet à Control UI et aux autres clients d’afficher
un statut appartenant au plugin sans connaître ses détails internes.
Utilisez api.enqueueNextTurnInjection(...) lorsqu’un plugin a besoin qu’un contexte durable
atteigne le prochain tour de modèle exactement une fois. OpenClaw vide les injections en file avant
les hooks de prompt, abandonne les injections expirées et déduplique par idempotencyKey
par plugin. C’est le bon point d’intégration pour les reprises d’approbation, les résumés de politique,
les deltas de moniteur en arrière-plan et les continuations de commande qui doivent être visibles par
le modèle au tour suivant, mais ne doivent pas devenir du texte permanent de prompt système.
Les sémantiques de nettoyage font partie du contrat. Le nettoyage des extensions de session et
les callbacks de nettoyage du cycle de vie runtime reçoivent reset, delete, disable, ou
restart. L’hôte supprime l’état d’extension de session persistant du plugin propriétaire
et les injections au tour suivant en attente pour reset/delete/disable ; restart conserve
l’état de session durable tandis que les callbacks de nettoyage permettent aux plugins de libérer les tâches
du planificateur, le contexte d’exécution et d’autres ressources hors bande de l’ancienne génération
runtime.
Hooks de message
Utilisez les hooks de message pour la politique de routage et de livraison au niveau du canal :message_received: observer le contenu entrant, l’expéditeur,threadId,messageId,senderId, la corrélation optionnelle d’exécution/session et les métadonnées.message_sending: réécrirecontentou retourner{ cancel: true }.message_sent: observer le succès ou l’échec final.
content peut contenir la transcription parlée masquée
même lorsque la charge utile du canal n’a aucun texte/légende visible. La réécriture de ce
content met à jour uniquement la transcription visible par le hook ; elle n’est pas rendue comme une
légende de média.
Les contextes de hook de message exposent des champs de corrélation stables lorsqu’ils sont disponibles :
ctx.sessionKey, ctx.runId, ctx.messageId, ctx.senderId, ctx.trace,
ctx.traceId, ctx.spanId, ctx.parentSpanId, et ctx.callDepth. Préférez
ces champs de première classe avant de lire les métadonnées héritées.
Préférez les champs typés threadId et replyToId avant d’utiliser des métadonnées propres au canal.
Règles de décision :
message_sendingaveccancel: trueest terminal.message_sendingaveccancel: falseest traité comme une absence de décision.- Le
contentréécrit continue vers les hooks de priorité inférieure sauf si un hook ultérieur annule la livraison. message_sendingpeut retournercancelReasonet desmetadatabornées avec une annulation. Les nouvelles API de cycle de vie des messages exposent cela comme un résultat de livraison supprimée avec la raisoncancelled_by_message_sending_hook; la livraison directe héritée continue de retourner un tableau de résultats vide par compatibilité.message_sentsert uniquement à l’observation. Les échecs de gestionnaire sont journalisés et ne modifient pas le résultat de livraison.
Hooks d’installation
before_install s’exécute après l’analyse intégrée des installations de Skills et de plugins.
Retournez des résultats supplémentaires ou { block: true, blockReason } pour arrêter
l’installation.
block: true est terminal. block: false est traité comme une absence de décision.
Cycle de vie du Gateway
Utilisezgateway_start pour les services de plugin qui ont besoin d’un état appartenant au Gateway. Le
contexte expose ctx.config, ctx.workspaceDir, et ctx.getCron?.() pour
l’inspection et les mises à jour de cron. Utilisez gateway_stop pour nettoyer les ressources
de longue durée.
Ne vous appuyez pas sur le hook interne gateway:startup pour les services runtime
appartenant au plugin.
cron_changed se déclenche pour les événements de cycle de vie cron appartenant au gateway avec une charge utile
d’événement typée couvrant les raisons added, updated, removed, started, finished,
et scheduled. L’événement transporte un instantané PluginHookGatewayCronJob
(incluant state.nextRunAtMs, state.lastRunStatus, et
state.lastError lorsqu’il est présent) ainsi qu’un PluginHookGatewayCronDeliveryStatus
de not-requested | delivered | not-delivered | unknown. Les événements de suppression
transportent toujours l’instantané de la tâche supprimée afin que les planificateurs externes puissent
réconcilier l’état. Utilisez ctx.getCron?.() et ctx.config depuis le contexte
runtime lors de la synchronisation de planificateurs de réveil externes, et gardez OpenClaw comme
source de vérité pour les vérifications d’échéance et l’exécution.
Dépréciations à venir
Quelques surfaces adjacentes aux hooks sont dépréciées mais toujours prises en charge. Migrez avant la prochaine version majeure :- Enveloppes de canal en texte brut dans les gestionnaires
inbound_claimetmessage_received. LisezBodyForAgentet les blocs structurés de contexte utilisateur au lieu d’analyser le texte d’enveloppe plat. Voir Enveloppes de canal en texte brut → BodyForAgent. before_agent_startreste présent pour la compatibilité. Les nouveaux plugins doivent utiliserbefore_model_resolveetbefore_prompt_buildau lieu de la phase combinée.onResolutiondansbefore_tool_callutilise désormais l’union typéePluginApprovalResolution(allow-once/allow-always/deny/timeout/cancelled) au lieu d’unstringlibre.
command-auth → command-status - voir
Migration du Plugin SDK → Dépréciations actives.
Liens connexes
- Migration du Plugin SDK - dépréciations actives et calendrier de suppression
- Créer des plugins
- Vue d’ensemble du Plugin SDK
- Points d’entrée de Plugin
- Hooks internes
- Internes de l’architecture de Plugin