---
read_when:
    - Ви створюєте Plugin, якому потрібні before_tool_call, before_agent_reply, хуки повідомлень або хуки життєвого циклу
    - Вам потрібно блокувати, переписувати або вимагати схвалення для викликів інструментів від Plugin
    - Ви обираєте між внутрішніми хуками та хуками Plugin
summary: 'Хуки Plugin: перехоплюють події життєвого циклу агента, інструмента, повідомлення, сеансу та Gateway'
title: Хуки Plugin
x-i18n:
    generated_at: "2026-04-28T17:17:10Z"
    model: gpt-5.5
    provider: openai
    source_hash: f600df47c67eb07d85b7b063f1189baf78a49efad727d8cadbd37f66745c4401
    source_path: plugins/hooks.md
    workflow: 16
---

Хуки Plugin — це внутрішньопроцесні точки розширення для плагінів OpenClaw. Використовуйте їх,
коли плагіну потрібно перевіряти або змінювати запуски агентів, виклики інструментів, потік повідомлень,
життєвий цикл сесії, маршрутизацію субагентів, установлення або запуск Gateway.

Натомість використовуйте [внутрішні хуки](/uk/automation/hooks), коли потрібен невеликий
встановлений оператором скрипт `HOOK.md` для командних подій і подій Gateway, як-от
`/new`, `/reset`, `/stop`, `agent:bootstrap` або `gateway:startup`.

## Швидкий старт

Реєструйте типізовані хуки Plugin за допомогою `api.on(...)` з точки входу вашого плагіна:

```typescript
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

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 },
    );
  },
});
```

Обробники хуків виконуються послідовно за спаданням `priority`. Хуки з однаковим пріоритетом
зберігають порядок реєстрації.

`api.on(name, handler, opts?)` приймає:

- `priority` — порядок обробників (вищий виконується першим).
- `timeoutMs` — необов’язковий бюджет для окремого хука. Якщо його задано, runner хука перериває цей
  обробник після вичерпання бюджету й переходить до наступного, замість того щоб
  повільне налаштування або відновлення спогадів витрачали налаштований для викликача час очікування моделі.
  Не вказуйте його, щоб використовувати стандартний тайм-аут спостереження/рішення, який
  runner хука застосовує загально.

Кожен хук отримує `event.context.pluginConfig`, розв’язану конфігурацію для
плагіна, який зареєстрував цей обробник. Використовуйте її для рішень хука, яким потрібні
поточні параметри плагіна; OpenClaw впроваджує її для кожного обробника, не змінюючи
спільний об’єкт події, який бачать інші плагіни.

## Каталог хуків

Хуки згруповано за поверхнею, яку вони розширюють. Назви, виділені **жирним**, приймають
результат рішення (заблокувати, скасувати, перевизначити або вимагати схвалення); усі інші призначені
лише для спостереження.

**Хід агента**

- `before_model_resolve` — перевизначити провайдера або модель до завантаження повідомлень сесії
- `agent_turn_prepare` — використати поставлені в чергу ін’єкції ходу плагіна й додати контекст того самого ходу перед хуками запиту
- `before_prompt_build` — додати динамічний контекст або текст системного запиту перед викликом моделі
- `before_agent_start` — комбінована фаза лише для сумісності; віддавайте перевагу двом хукам вище
- **`before_agent_reply`** — перервати хід моделі синтетичною відповіддю або мовчанням
- **`before_agent_finalize`** — перевірити природну фінальну відповідь і запросити ще один прохід моделі
- `agent_end` — спостерігати за фінальними повідомленнями, станом успіху й тривалістю запуску
- `heartbeat_prompt_contribution` — додати контекст лише для Heartbeat для фонових моніторів і плагінів життєвого циклу

**Спостереження за розмовою**

- `model_call_started` / `model_call_ended` — спостерігати за очищеними метаданими виклику провайдера/моделі, часом, результатом і обмеженими хешами ідентифікаторів запитів без вмісту запиту або відповіді
- `llm_input` — спостерігати за вхідними даними провайдера (системний запит, запит, історія)
- `llm_output` — спостерігати за вихідними даними провайдера

**Інструменти**

- **`before_tool_call`** — переписати параметри інструмента, заблокувати виконання або вимагати схвалення
- `after_tool_call` — спостерігати за результатами інструмента, помилками й тривалістю
- **`tool_result_persist`** — переписати повідомлення асистента, створене з результату інструмента
- **`before_message_write`** — перевірити або заблокувати запис повідомлення, що виконується (рідко)

**Повідомлення й доставка**

- **`inbound_claim`** — прийняти вхідне повідомлення до маршрутизації агента (синтетичні відповіді)
- `message_received` — спостерігати за вхідним вмістом, відправником, гілкою й метаданими
- **`message_sending`** — переписати вихідний вміст або скасувати доставку
- `message_sent` — спостерігати за успішною або невдалою вихідною доставкою
- **`before_dispatch`** — перевірити або переписати вихідне відправлення до передавання каналу
- **`reply_dispatch`** — брати участь у фінальному конвеєрі відправлення відповіді

**Сесії та Compaction**

- `session_start` / `session_end` — відстежувати межі життєвого циклу сесії
- `before_compaction` / `after_compaction` — спостерігати за циклами Compaction або анотувати їх
- `before_reset` — спостерігати за подіями скидання сесії (`/reset`, програмні скидання)

**Субагенти**

- `subagent_spawning` / `subagent_delivery_target` / `subagent_spawned` / `subagent_ended` — координувати маршрутизацію субагентів і доставку результату завершення

**Життєвий цикл**

- `gateway_start` / `gateway_stop` — запускати або зупиняти служби, якими володіє плагін, разом із Gateway
- `cron_changed` — спостерігати за змінами життєвого циклу Cron, яким володіє Gateway (додано, оновлено, видалено, запущено, завершено, заплановано)
- **`before_install`** — перевіряти сканування встановлення Skills або плагінів і за потреби блокувати

## Політика викликів інструментів

`before_tool_call` отримує:

- `event.toolName`
- `event.params`
- необов’язковий `event.runId`
- необов’язковий `event.toolCallId`
- поля контексту, як-от `ctx.agentId`, `ctx.sessionKey`, `ctx.sessionId`,
  `ctx.runId`, `ctx.jobId` (задано для запусків, керованих Cron), і діагностичний `ctx.trace`

Він може повернути:

```typescript
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;
  };
};
```

Правила:

- `block: true` є термінальним і пропускає обробники з нижчим пріоритетом.
- `block: false` вважається відсутністю рішення.
- `params` переписує параметри інструмента для виконання.
- `requireApproval` призупиняє запуск агента й запитує користувача через схвалення плагіна.
  Команда `/approve` може схвалювати як exec, так і схвалення плагіна.
- `block: true` з нижчим пріоритетом усе ще може заблокувати після того, як хук із вищим пріоритетом
  запросив схвалення.
- `onResolution` отримує розв’язане рішення схвалення — `allow-once`,
  `allow-always`, `deny`, `timeout` або `cancelled`.

Вбудовані плагіни, яким потрібна політика рівня хоста, можуть реєструвати довірені політики інструментів
за допомогою `api.registerTrustedToolPolicy(...)`. Вони виконуються перед звичайними
хуками `before_tool_call` і перед рішеннями зовнішніх плагінів. Використовуйте їх лише
для довірених хостом обмежень, як-от політика робочого простору, примусове дотримання бюджету або
безпека зарезервованих робочих процесів. Зовнішні плагіни мають використовувати звичайні
хуки `before_tool_call`.

### Збереження результатів інструментів

Результати інструментів можуть містити структуровані `details` для рендерингу UI, діагностики,
маршрутизації медіа або метаданих, якими володіє плагін. Ставтеся до `details` як до runtime-метаданих,
а не як до вмісту запиту:

- OpenClaw вилучає `toolResult.details` перед повторним відтворенням для провайдера й вхідними даними Compaction,
  щоб метадані не ставали контекстом моделі.
- Збережені записи сесії зберігають лише обмежені `details`. Завеликі details
  замінюються компактним підсумком і `persistedDetailsTruncated: true`.
- `tool_result_persist` і `before_message_write` виконуються перед фінальним
  обмеженням збереження. Хуки все одно мають тримати повернені `details` малими й уникати
  розміщення релевантного для запиту тексту лише в `details`; поміщайте видимий для моделі вихід інструмента
  у `content`.

## Хуки запиту й моделі

Використовуйте фазоспецифічні хуки для нових плагінів:

- `before_model_resolve`: отримує лише поточний запит і метадані вкладень.
  Поверніть `providerOverride` або `modelOverride`.
- `agent_turn_prepare`: отримує поточний запит, підготовлені повідомлення сесії
  та всі поставлені в чергу одноразові ін’єкції, вилучені для цієї сесії. Поверніть
  `prependContext` або `appendContext`.
- `before_prompt_build`: отримує поточний запит і повідомлення сесії.
  Поверніть `prependContext`, `appendContext`, `systemPrompt`,
  `prependSystemContext` або `appendSystemContext`.
- `heartbeat_prompt_contribution`: виконується лише для ходів Heartbeat і повертає
  `prependContext` або `appendContext`. Він призначений для фонових моніторів,
  яким потрібно підсумовувати поточний стан без зміни ходів, ініційованих користувачем.

`before_agent_start` лишається для сумісності. Віддавайте перевагу явним хукам вище,
щоб ваш плагін не залежав від застарілої комбінованої фази.

`before_agent_start` і `agent_end` містять `event.runId`, коли OpenClaw може
визначити активний запуск. Те саме значення також доступне в `ctx.runId`.
Запуски, керовані Cron, також надають `ctx.jobId` (ідентифікатор початкового завдання Cron), щоб
хуки плагінів могли прив’язувати метрики, побічні ефекти або стан до конкретного запланованого
завдання.

`agent_end` — це хук спостереження, який виконується fire-and-forget після ходу. Runner хука
застосовує тайм-аут 30 секунд, щоб завислий плагін або endpoint embedding
не міг залишити promise хука в очікуванні назавжди. Тайм-аут журналюється, і
OpenClaw продовжує роботу; він не скасовує мережеву роботу, якою володіє плагін, якщо
плагін також не використовує власний сигнал переривання.

Використовуйте `model_call_started` і `model_call_ended` для телеметрії викликів провайдера,
яка не має отримувати сирі запити, історію, відповіді, заголовки, тіла запитів
або ідентифікатори запитів провайдера. Ці хуки містять стабільні метадані, як-от
`runId`, `callId`, `provider`, `model`, необов’язкові `api`/`transport`, термінальні
`durationMs`/`outcome` і `upstreamRequestIdHash`, коли OpenClaw може вивести
обмежений хеш ідентифікатора запиту провайдера.

`before_agent_finalize` виконується лише тоді, коли harness збирається прийняти природну
фінальну відповідь асистента. Це не шлях скасування `/stop`, і він не
виконується, коли користувач перериває хід. Поверніть `{ action: "revise", reason }`, щоб попросити
harness зробити ще один прохід моделі перед фіналізацією, `{ action:
"finalize", reason? }`, щоб примусово фіналізувати, або не повертайте результат, щоб продовжити.
Нативні хуки Codex `Stop` ретранслюються в цей хук як рішення OpenClaw
`before_agent_finalize`.

Невбудовані плагіни, яким потрібні `llm_input`, `llm_output`,
`before_agent_finalize` або `agent_end`, мають задати:

```json
{
  "plugins": {
    "entries": {
      "my-plugin": {
        "hooks": {
          "allowConversationAccess": true
        }
      }
    }
  }
}
```

Хуки, що змінюють запит, і довговічні ін’єкції наступного ходу можна вимкнути для окремого плагіна
за допомогою `plugins.entries.<id>.hooks.allowPromptInjection=false`.

### Розширення сесій та ін’єкції наступного ходу

Плагіни робочих процесів можуть зберігати невеликий JSON-сумісний стан сесії за допомогою
`api.registerSessionExtension(...)` і оновлювати його через метод Gateway
`sessions.pluginPatch`. Рядки сесій проєктують зареєстрований стан розширення
через `pluginExtensions`, дозволяючи Control UI та іншим клієнтам рендерити
статус, яким володіє плагін, без знання внутрішніх деталей плагіна.

Використовуйте `api.enqueueNextTurnInjection(...)`, коли плагіну потрібен довговічний контекст, щоб
дістатися наступного ходу моделі рівно один раз. OpenClaw вилучає поставлені в чергу ін’єкції перед
хуками запиту, відкидає прострочені ін’єкції та дедуплікує за `idempotencyKey`
для кожного плагіна. Це правильна точка для відновлення після схвалень, підсумків політик,
дельт фонових моніторів і продовжень команд, які мають бути видимі для
моделі на наступному ході, але не мають ставати постійним текстом системного запиту.

Семантика очищення є частиною контракту. Колбеки очищення розширень сесії та
життєвого циклу runtime отримують `reset`, `delete`, `disable` або
`restart`. Хост видаляє постійний стан розширення сесії власного плагіна
та очікувані ін’єкції наступного ходу для reset/delete/disable; restart зберігає
довговічний стан сесії, тоді як колбеки очищення дають плагінам змогу звільнити завдання планувальника,
контекст запуску та інші позасмугові ресурси для старої генерації runtime.

## Хуки повідомлень

Використовуйте хуки повідомлень для маршрутизації на рівні каналу та політики доставки:

- `message_received`: спостерігати за вхідним вмістом, відправником, `threadId`, `messageId`,
  `senderId`, необов’язковою кореляцією запуску/сесії та метаданими.
- `message_sending`: переписати `content` або повернути `{ cancel: true }`.
- `message_sent`: спостерігати за фінальним успіхом або помилкою.

Для аудіовідповідей TTS без тексту `content` може містити приховану озвучену стенограму
навіть тоді, коли payload каналу не має видимого тексту/підпису. Перезапис цього
`content` оновлює лише стенограму, видиму для хука; вона не відображається як
підпис до медіа.

Контексти хуків повідомлень надають стабільні поля кореляції, коли вони доступні:
`ctx.sessionKey`, `ctx.runId`, `ctx.messageId`, `ctx.senderId`, `ctx.trace`,
`ctx.traceId`, `ctx.spanId`, `ctx.parentSpanId` і `ctx.callDepth`. Надавайте
перевагу цим полям першого класу перед читанням застарілих метаданих.

Надавайте перевагу типізованим полям `threadId` і `replyToId` перед використанням
метаданих, специфічних для каналу.

Правила ухвалення рішень:

- `message_sending` із `cancel: true` є термінальним.
- `message_sending` із `cancel: false` трактується як відсутність рішення.
- Перезаписаний `content` продовжує передаватися хукам нижчого пріоритету, якщо пізніший хук
  не скасує доставку.

## Встановлення хуків

`before_install` виконується після вбудованого сканування для встановлень Skills і плагінів.
Поверніть додаткові знахідки або `{ block: true, blockReason }`, щоб зупинити
встановлення.

`block: true` є термінальним. `block: false` трактується як відсутність рішення.

## Життєвий цикл Gateway

Використовуйте `gateway_start` для сервісів плагінів, яким потрібен стан, керований Gateway. Контекст
надає `ctx.config`, `ctx.workspaceDir` і `ctx.getCron?.()` для
перевірки й оновлення cron. Використовуйте `gateway_stop` для очищення довготривалих
ресурсів.

Не покладайтеся на внутрішній хук `gateway:startup` для runtime-сервісів, що належать плагіну.

`cron_changed` спрацьовує для подій життєвого циклу cron, керованих gateway, із типізованим
payload події, що охоплює причини `added`, `updated`, `removed`, `started`, `finished`
і `scheduled`. Подія переносить знімок `PluginHookGatewayCronJob`
(зокрема `state.nextRunAtMs`, `state.lastRunStatus` і
`state.lastError`, якщо вони наявні), а також `PluginHookGatewayCronDeliveryStatus`
зі значенням `not-requested` | `delivered` | `not-delivered` | `unknown`. Події
видалення все одно містять знімок видаленого завдання, щоб зовнішні планувальники могли
узгодити стан. Використовуйте `ctx.getCron?.()` і `ctx.config` з runtime-контексту
під час синхронізації зовнішніх планувальників пробудження, і зберігайте OpenClaw як
джерело істини для перевірок готовності та виконання.

## Майбутні застарівання

Кілька поверхонь, суміжних із хуками, застаріли, але все ще підтримуються. Мігруйте
до наступного мажорного випуску:

- **Простотекстові оболонки каналів** у обробниках `inbound_claim` і `message_received`.
  Читайте `BodyForAgent` і структуровані блоки контексту користувача
  замість розбору плаского тексту оболонки. Див.
  [Простотекстові оболонки каналів → BodyForAgent](/uk/plugins/sdk-migration#active-deprecations).
- **`before_agent_start`** залишається для сумісності. Нові плагіни мають використовувати
  `before_model_resolve` і `before_prompt_build` замість об'єднаної
  фази.
- **`onResolution` у `before_tool_call`** тепер використовує типізований
  union `PluginApprovalResolution` (`allow-once` / `allow-always` / `deny` /
  `timeout` / `cancelled`) замість довільного `string`.

Повний список — реєстрація можливостей пам'яті, профіль мислення провайдера,
зовнішні провайдери автентифікації, типи виявлення провайдерів, аксесори runtime завдань
і перейменування `command-auth` → `command-status` — див.
[Міграція Plugin SDK → Активні застарівання](/uk/plugins/sdk-migration#active-deprecations).

## Пов'язане

- [Міграція Plugin SDK](/uk/plugins/sdk-migration) — активні застарівання та графік видалення
- [Створення плагінів](/uk/plugins/building-plugins)
- [Огляд Plugin SDK](/uk/plugins/sdk-overview)
- [Точки входу Plugin](/uk/plugins/sdk-entrypoints)
- [Внутрішні хуки](/uk/automation/hooks)
- [Внутрішня архітектура Plugin](/uk/plugins/architecture-internals)
