Plugins
Hooki Plugin
Hooki pluginów są punktami rozszerzeń działającymi w procesie dla pluginów OpenClaw. Używaj ich, gdy plugin musi sprawdzać lub zmieniać uruchomienia agentów, wywołania narzędzi, przepływ wiadomości, cykl życia sesji, routowanie subagentów, instalacje lub uruchamianie Gateway.
Zamiast tego użyj wewnętrznych hooków, gdy potrzebujesz małego
skryptu HOOK.md instalowanego przez operatora dla zdarzeń poleceń i Gateway, takich jak
/new, /reset, /stop, agent:bootstrap lub gateway:startup.
Szybki start
Zarejestruj typowane hooki pluginu za pomocą api.on(...) z punktu wejścia pluginu:
export default definePluginEntry({
id: "tool-preflight",
name: "Tool Preflight",
register(api) {
api.on(
"before_tool_call",
async (event) => {
if (event.toolName !== "web_search") {
return;
}
return {
requireApproval: {
title: "Run web search",
description: `Allow search query: ${String(event.params.query ?? "")}`,
severity: "info",
timeoutMs: 60_000,
timeoutBehavior: "deny",
},
};
},
{ priority: 50 },
);
},
});
Procedury obsługi hooków działają sekwencyjnie w malejącym porządku priority. Hooki o tym samym priorytecie
zachowują kolejność rejestracji.
api.on(name, handler, opts?) przyjmuje:
priority- kolejność procedur obsługi (wyższa wartość działa jako pierwsza).timeoutMs- opcjonalny budżet dla pojedynczego hooka. Gdy jest ustawiony, runner hooków przerywa tę procedurę obsługi po upływie budżetu i przechodzi do następnej, zamiast pozwolić, aby powolna konfiguracja lub odtwarzanie kontekstu zużyły skonfigurowany przez wywołującego limit czasu modelu. Pomiń go, aby użyć domyślnego limitu czasu obserwacji/decyzji, który runner hooków stosuje ogólnie.
Operatorzy mogą też ustawiać budżety hooków bez poprawiania kodu pluginu:
{
"plugins": {
"entries": {
"my-plugin": {
"hooks": {
"timeoutMs": 30000,
"timeouts": {
"before_prompt_build": 90000,
"agent_end": 60000
}
}
}
}
}
}
hooks.timeouts.<hookName> nadpisuje hooks.timeoutMs, które nadpisuje
wartość api.on(..., { timeoutMs }) zdefiniowaną przez autora pluginu. Każda skonfigurowana wartość musi
być dodatnią liczbą całkowitą nie większą niż 600000 milisekund. Preferuj nadpisania dla pojedynczych hooków
w przypadku znanych powolnych hooków, aby jeden plugin nie dostawał dłuższego budżetu
wszędzie.
Każdy hook otrzymuje event.context.pluginConfig, rozwiązaną konfigurację dla
pluginu, który zarejestrował tę procedurę obsługi. Używaj jej do decyzji hooków, które wymagają
aktualnych opcji pluginu; OpenClaw wstrzykuje ją dla każdej procedury obsługi bez mutowania
wspólnego obiektu zdarzenia widzianego przez inne pluginy.
Katalog hooków
Hooki są pogrupowane według powierzchni, którą rozszerzają. Nazwy zapisane pogrubieniem przyjmują wynik decyzji (blokada, anulowanie, nadpisanie lub wymaganie zatwierdzenia); wszystkie pozostałe są wyłącznie obserwacyjne.
Tura agenta
before_model_resolve- nadpisz dostawcę lub model przed załadowaniem wiadomości sesjiagent_turn_prepare- użyj zakolejkowanych wstrzyknięć tur pluginów i dodaj kontekst tej samej tury przed hookami promptubefore_prompt_build- dodaj dynamiczny kontekst lub tekst promptu systemowego przed wywołaniem modelubefore_agent_start- połączona faza tylko dla zgodności; preferuj dwa powyższe hookibefore_agent_run- sprawdź finalny prompt i wiadomości sesji przed przesłaniem do modelu oraz opcjonalnie zablokuj uruchomieniebefore_agent_reply- przerwij turę modelu syntetyczną odpowiedzią lub cisząbefore_agent_finalize- sprawdź naturalną odpowiedź finalną i zażądaj jeszcze jednego przebiegu modeluagent_end- obserwuj finalne wiadomości, stan powodzenia i czas trwania uruchomieniaheartbeat_prompt_contribution- dodaj kontekst wyłącznie dla Heartbeat dla pluginów monitorowania w tle i cyklu życia
Obserwacja konwersacji
model_call_started/model_call_ended- obserwuj oczyszczone metadane wywołań dostawcy/modelu, czas, wynik i ograniczone hashe identyfikatorów żądań bez treści promptu ani odpowiedzillm_input- obserwuj dane wejściowe dostawcy (prompt systemowy, prompt, historię)llm_output- obserwuj dane wyjściowe dostawcy
Narzędzia
before_tool_call- przepisz parametry narzędzia, zablokuj wykonanie lub wymagaj zatwierdzeniaafter_tool_call- obserwuj wyniki narzędzia, błędy i czas trwaniatool_result_persist- przepisz wiadomość asystenta utworzoną z wyniku narzędziabefore_message_write- sprawdź lub zablokuj trwający zapis wiadomości (rzadkie)
Wiadomości i dostarczanie
inbound_claim- przejmij wiadomość przychodzącą przed routowaniem agenta (odpowiedzi syntetyczne)message_received- obserwuj treść przychodzącą, nadawcę, wątek i metadanemessage_sending- przepisz treść wychodzącą lub anuluj dostarczeniemessage_sent- obserwuj powodzenie lub niepowodzenie dostarczenia wychodzącegobefore_dispatch- sprawdź lub przepisz dispatch wychodzący przed przekazaniem kanałowireply_dispatch- uczestnicz w finalnym potoku dispatchu odpowiedzi
Sesje i Compaction
session_start/session_end- śledź granice cyklu życia sesjibefore_compaction/after_compaction- obserwuj lub adnotuj cykle Compactionbefore_reset- obserwuj zdarzenia resetowania sesji (/reset, resety programowe)
Subagenci
subagent_spawning/subagent_delivery_target/subagent_spawned/subagent_ended- koordynuj routowanie subagentów i dostarczanie ukończenia
Cykl życia
gateway_start/gateway_stop- uruchom lub zatrzymaj usługi należące do pluginu wraz z Gatewaycron_changed- obserwuj zmiany cyklu życia Cron należącego do Gateway (dodano, zaktualizowano, usunięto, uruchomiono, zakończono, zaplanowano)before_install- sprawdź skany instalacji Skills lub pluginów i opcjonalnie zablokuj
Zasady wywołań narzędzi
before_tool_call otrzymuje:
event.toolNameevent.params- opcjonalne
event.runId - opcjonalne
event.toolCallId - pola kontekstu, takie jak
ctx.agentId,ctx.sessionKey,ctx.sessionId,ctx.runId,ctx.jobId(ustawiane przy uruchomieniach sterowanych przez Cron) oraz diagnostycznectx.trace
Może zwrócić:
type BeforeToolCallResult = {
params?: Record<string, unknown>;
block?: boolean;
blockReason?: string;
requireApproval?: {
title: string;
description: string;
severity?: "info" | "warning" | "critical";
timeoutMs?: number;
timeoutBehavior?: "allow" | "deny";
pluginId?: string;
onResolution?: (
decision: "allow-once" | "allow-always" | "deny" | "timeout" | "cancelled",
) => Promise<void> | void;
};
};
Reguły:
block: truejest końcowe i pomija procedury obsługi o niższym priorytecie.block: falsejest traktowane jak brak decyzji.paramsprzepisuje parametry narzędzia do wykonania.requireApprovalwstrzymuje uruchomienie agenta i prosi użytkownika przez zatwierdzenia pluginu. Polecenie/approvemoże zatwierdzać zarówno zatwierdzenia exec, jak i pluginu.block: trueo niższym priorytecie nadal może zablokować po tym, jak hook o wyższym priorytecie zażądał zatwierdzenia.onResolutionotrzymuje rozwiązaną decyzję zatwierdzenia -allow-once,allow-always,deny,timeoutlubcancelled.
Dołączone pluginy, które potrzebują zasad na poziomie hosta, mogą rejestrować zaufane zasady narzędzi
za pomocą api.registerTrustedToolPolicy(...). Działają one przed zwykłymi
hookami before_tool_call i przed decyzjami zewnętrznych pluginów. Używaj ich tylko
dla bramek zaufanych przez hosta, takich jak zasady obszaru roboczego, egzekwowanie budżetu lub
bezpieczeństwo zarezerwowanego workflow. Zewnętrzne pluginy powinny używać zwykłych hooków before_tool_call.
Utrwalanie wyników narzędzi
Wyniki narzędzi mogą zawierać strukturalne details do renderowania UI, diagnostyki,
routowania mediów lub metadanych należących do pluginu. Traktuj details jako metadane czasu działania,
nie jako treść promptu:
- OpenClaw usuwa
toolResult.detailsprzed odtworzeniem dla dostawcy i wejściem Compaction, aby metadane nie stały się kontekstem modelu. - Utrwalone wpisy sesji zachowują tylko ograniczone
details. Zbyt duże szczegóły są zastępowane zwartym podsumowaniem ipersistedDetailsTruncated: true. tool_result_persistibefore_message_writedziałają przed finalnym limitem utrwalania. Hooki mimo to powinny utrzymywać zwracanedetailsmałe i unikać umieszczania tekstu istotnego dla promptu wyłącznie wdetails; dane wyjściowe narzędzia widoczne dla modelu umieszczaj wcontent.
Hooki promptu i modelu
Dla nowych pluginów używaj hooków specyficznych dla faz:
before_model_resolve: otrzymuje tylko bieżący prompt i metadane załączników. ZwróćproviderOverridelubmodelOverride.agent_turn_prepare: otrzymuje bieżący prompt, przygotowane wiadomości sesji oraz wszystkie jednorazowe zakolejkowane wstrzyknięcia opróżnione dla tej sesji. ZwróćprependContextlubappendContext.before_prompt_build: otrzymuje bieżący prompt i wiadomości sesji. ZwróćprependContext,appendContext,systemPrompt,prependSystemContextlubappendSystemContext.heartbeat_prompt_contribution: działa tylko dla tur Heartbeat i zwracaprependContextlubappendContext. Jest przeznaczony dla monitorów w tle, które muszą podsumowywać bieżący stan bez zmieniania tur zainicjowanych przez użytkownika.
before_agent_start pozostaje dla zgodności. Preferuj jawne hooki powyżej,
aby twój plugin nie zależał od starszej połączonej fazy.
before_agent_run działa po skonstruowaniu promptu i przed dowolnymi danymi wejściowymi modelu,
w tym lokalnym ładowaniem obrazów promptu i obserwacją llm_input. Otrzymuje
bieżące dane wejściowe użytkownika jako prompt, a także załadowaną historię sesji w messages
i aktywny prompt systemowy. Zwróć { outcome: "block", reason, message? },
aby zatrzymać uruchomienie, zanim model będzie mógł odczytać prompt. reason jest wewnętrzne;
message jest zamiennikiem widocznym dla użytkownika. Jedynymi obsługiwanymi wynikami są
pass i block; nieobsługiwane kształty decyzji kończą się bezpiecznym zablokowaniem.
Gdy uruchomienie zostanie zablokowane, OpenClaw przechowuje tylko tekst zastępczy w
message.content oraz niewrażliwe metadane blokady, takie jak identyfikator blokującego pluginu
i znacznik czasu. Oryginalny tekst użytkownika nie jest zachowywany w transkrypcie ani przyszłym
kontekście. Wewnętrzne powody blokady są traktowane jako wrażliwe i wykluczane z
ładunków transkryptu, historii, broadcastu, logu i diagnostyki. Obserwowalność
powinna używać oczyszczonych pól, takich jak identyfikator blokującego, wynik, znacznik czasu lub bezpieczna
kategoria.
before_agent_start i agent_end zawierają event.runId, gdy OpenClaw może
zidentyfikować aktywne uruchomienie. Ta sama wartość jest też dostępna w ctx.runId.
Uruchomienia sterowane przez Cron udostępniają też ctx.jobId (identyfikator źródłowego zadania Cron), aby
hooki pluginów mogły ograniczać metryki, skutki uboczne lub stan do konkretnego zaplanowanego
zadania.
Dla uruchomień pochodzących z kanału ctx.messageProvider jest powierzchnią dostawcy, taką
jak discord lub telegram, natomiast ctx.channelId jest identyfikatorem docelowym konwersacji,
gdy OpenClaw może go wyprowadzić z klucza sesji lub metadanych dostarczenia.
agent_end jest hookiem obserwacyjnym i działa w trybie fire-and-forget po turze. Runner
hooków stosuje limit czasu 30 sekund, aby zablokowany plugin lub endpoint osadzania
nie mógł pozostawić obietnicy hooka w stanie oczekiwania na zawsze. Limit czasu jest logowany, a
OpenClaw kontynuuje; nie anuluje pracy sieciowej należącej do pluginu, chyba że
plugin używa również własnego sygnału przerwania.
Używaj model_call_started i model_call_ended do telemetrii wywołań dostawcy,
która nie powinna otrzymywać surowych promptów, historii, odpowiedzi, nagłówków, treści żądań
ani identyfikatorów żądań dostawcy. Te hooki zawierają stabilne metadane, takie jak
runId, callId, provider, model, opcjonalne api/transport, końcowe
durationMs/outcome oraz upstreamRequestIdHash, gdy OpenClaw może wyprowadzić
ograniczony hash identyfikatora żądania dostawcy.
before_agent_finalize działa tylko wtedy, gdy harness ma zaakceptować naturalną
finalną odpowiedź asystenta. Nie jest to ścieżka anulowania /stop i nie
działa, gdy użytkownik przerywa turę. Zwróć { action: "revise", reason }, aby poprosić
harness o jeszcze jeden przebieg modelu przed finalizacją, { action: "finalize", reason? }, aby wymusić finalizację, albo pomiń wynik, aby kontynuować.
Natywne hooki Stop Codex są przekazywane do tego hooka jako decyzje OpenClaw
before_agent_finalize.
Zwracając action: "revise", pluginy mogą dołączyć metadane retry, aby
dodatkowy przebieg modelu był ograniczony i bezpieczny do odtworzenia:
type BeforeAgentFinalizeRetry = {
instruction: string;
idempotencyKey?: string;
maxAttempts?: number;
};
instruction jest dołączane do powodu rewizji wysyłanego do mechanizmu testowego.
idempotencyKey pozwala hostowi liczyć ponowienia dla tego samego żądania pluginu w ramach
równoważnych decyzji finalizacji, a maxAttempts ogranicza liczbę dodatkowych przebiegów, na które
host pozwoli przed kontynuowaniem naturalnej końcowej odpowiedzi.
Pluginy spoza pakietu, które potrzebują surowych hooków konwersacji (before_model_resolve,
before_agent_reply, llm_input, llm_output, before_agent_finalize,
agent_end lub before_agent_run), muszą ustawić:
{
"plugins": {
"entries": {
"my-plugin": {
"hooks": {
"allowConversationAccess": true
}
}
}
}
}
Hooki modyfikujące prompt oraz trwałe wstrzyknięcia na następną turę można wyłączyć dla każdego pluginu
za pomocą plugins.entries.<id>.hooks.allowPromptInjection=false.
Rozszerzenia sesji i wstrzyknięcia na następną turę
Pluginy przepływu pracy mogą utrwalać niewielki stan sesji zgodny z JSON za pomocą
api.registerSessionExtension(...) i aktualizować go przez metodę Gateway
sessions.pluginPatch. Wiersze sesji udostępniają zarejestrowany stan rozszerzenia
przez pluginExtensions, pozwalając Control UI i innym klientom renderować
status należący do pluginu bez poznawania jego wewnętrznej implementacji.
Użyj api.enqueueNextTurnInjection(...), gdy plugin potrzebuje trwałego kontekstu,
który ma dotrzeć do następnej tury modelu dokładnie raz. OpenClaw opróżnia kolejkę wstrzyknięć przed
hookami promptu, odrzuca wygasłe wstrzyknięcia i deduplikuje je według idempotencyKey
dla każdego pluginu. To właściwy punkt rozszerzenia dla wznowień po zatwierdzeniu, podsumowań polityk,
delt monitorów działających w tle i kontynuacji poleceń, które powinny być widoczne dla
modelu w następnej turze, ale nie powinny stać się stałym tekstem promptu systemowego.
Semantyka czyszczenia jest częścią kontraktu. Czyszczenie rozszerzeń sesji i
wywołania zwrotne czyszczenia cyklu życia środowiska uruchomieniowego otrzymują reset, delete, disable lub
restart. Host usuwa trwały stan rozszerzenia sesji należący do danego pluginu
oraz oczekujące wstrzyknięcia na następną turę dla reset/delete/disable; restart zachowuje
trwały stan sesji, a wywołania zwrotne czyszczenia pozwalają pluginom zwolnić zadania
harmonogramu, kontekst uruchomieniowy i inne zasoby poza głównym kanałem dla starej generacji
środowiska uruchomieniowego.
Hooki wiadomości
Używaj hooków wiadomości do routingu na poziomie kanału i polityki dostarczania:
message_received: obserwuje treść przychodzącą, nadawcę,threadId,messageId,senderId, opcjonalną korelację uruchomienia/sesji oraz metadane.message_sending: przepisujecontentlub zwraca{ cancel: true }.message_sent: obserwuje ostateczny sukces albo niepowodzenie.
W przypadku odpowiedzi TTS zawierających tylko dźwięk content może zawierać ukryty zapis wypowiedzi
nawet wtedy, gdy ładunek kanału nie ma widocznego tekstu/podpisu. Przepisanie tego
content aktualizuje tylko zapis widoczny dla hooka; nie jest on renderowany jako
podpis multimediów.
Konteksty hooków wiadomości udostępniają stabilne pola korelacji, gdy są dostępne:
ctx.sessionKey, ctx.runId, ctx.messageId, ctx.senderId, ctx.trace,
ctx.traceId, ctx.spanId, ctx.parentSpanId i ctx.callDepth. Preferuj
te pola pierwszej klasy przed odczytywaniem starszych metadanych.
Preferuj typowane pola threadId i replyToId przed użyciem metadanych specyficznych dla kanału.
Reguły decyzji:
message_sendingzcancel: truejest terminalne.message_sendingzcancel: falsejest traktowane jako brak decyzji.- Przepisane
contentprzechodzi dalej do hooków o niższym priorytecie, chyba że późniejszy hook anuluje dostarczenie.
Hooki instalacji
before_install uruchamia się po wbudowanym skanowaniu instalacji Skills i pluginów.
Zwróć dodatkowe ustalenia albo { block: true, blockReason }, aby zatrzymać
instalację.
block: true jest terminalne. block: false jest traktowane jako brak decyzji.
Cykl życia Gateway
Używaj gateway_start dla usług pluginu, które potrzebują stanu należącego do Gateway. Kontekst
udostępnia ctx.config, ctx.workspaceDir i ctx.getCron?.() do inspekcji
i aktualizacji cron. Używaj gateway_stop do czyszczenia długo działających
zasobów.
Nie polegaj na wewnętrznym hooku gateway:startup dla usług środowiska uruchomieniowego
należących do pluginu.
cron_changed uruchamia się dla zdarzeń cyklu życia cron należących do gateway z typowanym
ładunkiem zdarzenia obejmującym powody added, updated, removed, started, finished
i scheduled. Zdarzenie przenosi migawkę PluginHookGatewayCronJob
(w tym state.nextRunAtMs, state.lastRunStatus i
state.lastError, gdy występują) oraz PluginHookGatewayCronDeliveryStatus
o wartości not-requested | delivered | not-delivered | unknown. Zdarzenia usunięcia
nadal przenoszą migawkę usuniętego zadania, aby zewnętrzne harmonogramy mogły
uzgodnić stan. Podczas synchronizowania zewnętrznych harmonogramów wybudzania używaj
ctx.getCron?.() i ctx.config z kontekstu środowiska uruchomieniowego, a OpenClaw zachowaj jako
źródło prawdy dla sprawdzania terminów i wykonywania.
Nadchodzące wycofania
Kilka powierzchni powiązanych z hookami jest przestarzałych, ale nadal obsługiwanych. Przeprowadź migrację przed następnym głównym wydaniem:
- Zwykłotekstowe koperty kanału w handlerach
inbound_claimimessage_received. OdczytujBodyForAgenti ustrukturyzowane bloki kontekstu użytkownika zamiast parsować płaski tekst koperty. Zobacz Zwykłotekstowe koperty kanału → BodyForAgent. before_agent_startpozostaje dla kompatybilności. Nowe pluginy powinny używaćbefore_model_resolveibefore_prompt_buildzamiast połączonej fazy.onResolutionwbefore_tool_callużywa teraz typowanej uniiPluginApprovalResolution(allow-once/allow-always/deny/timeout/cancelled) zamiast dowolnegostring.
Pełną listę - rejestrację możliwości pamięci, profil myślenia dostawcy,
zewnętrznych dostawców uwierzytelniania, typy wykrywania dostawców, akcesory środowiska uruchomieniowego zadań
oraz zmianę nazwy command-auth → command-status - znajdziesz w
Migracja Plugin SDK → Aktywne wycofania.
Powiązane
- Migracja Plugin SDK - aktywne wycofania i harmonogram usunięcia
- Tworzenie pluginów
- Omówienie Plugin SDK
- Punkty wejścia pluginu
- Hooki wewnętrzne
- Wewnętrzna architektura pluginów