Хуки для AI-сеансів: зробіть OpenClaw керованим workflow

ai · 2026-10-10

AI-агент часто поводиться як працівник, якому кожного разу треба усно нагадувати: «після зміни запусти перевірку», «не чіпай секрети», «повідом мене, коли закінчиш». Це не проблема формулювання промпту. Це відсутність подій життєвого циклу й детермінованих дій навколо моделі.

Хук — це обробник, який запускається на відомій події: початку сеансу, перед викликом інструмента, після редагування файла, під час стискання контексту або завершення роботи. Модель може вирішувати, що робити; хук гарантує, що необхідна операційна дія відбудеться. Для OpenClaw це корисний спосіб розділити міркування агента й контроль workflow.

Що вже роблять Claude Code, Codex і OpenCode

У Claude Code хуки — це команди, які виконуються у визначених точках життєвого циклу. Документація прямо пропонує використовувати їх для форматування після редагування, блокування команд до запуску, сповіщення про очікування відповіді та додавання контексту на старті. Окрім shell-команд, є HTTP-, MCP-, prompt- та agent-based хуки. Для повної схеми подій є окремий довідник hooks: серед важливих подій — SessionStart, PreToolUse, PostToolUse, Stop, PreCompact і PostCompact. Конфігурацію можна перевірити командою /hooks.

У Codex hooks модель розширення подібна, але добре видно ще один production-аспект: довіра до коду хуків. Codex шукає hooks.json або таблиці hooks у config.toml на рівнях користувача й проєкту, а також у плагінах. Не-керовані хуки треба переглянути й довірити; довіра прив’язана до хешу визначення, тому змінений хук знову потрапляє на перевірку. Командні хуки можуть виконуватися паралельно, а MCP-хук використовує вже підключений MCP-сервер. Важливе обмеження: тайм-аут або помилка callback не обов’язково блокують інструмент. Отже, хук — це guardrail, а не автоматично повна межа безпеки чи журнал відповідності.

В OpenCode хуки оформлені як JavaScript/TypeScript-плагіни. У первинному issue про parity lifecycle-подій перелічені tool.execute.before, tool.execute.after, session.idle, session.compacting і session.compacted, а також чесно описані прогалини API: наприклад, немає повної події помилки після інструмента й per-agent hooks. Плагін може змінити аргументи інструмента, заборонити читання .env, відправити сповіщення або додати власний інструмент. Цікавий для OpenClaw приклад — хук стискання, який додає до промпту список активних файлів, рішень і блокерів, щоб продовження сеансу не втратило робочий стан.

Різниця між продуктами не змінює головний принцип: інструкція в промпті просить, а lifecycle-хук примушує workflow пройти визначену точку контролю. Але хук потрібно версіонувати, обмежувати й тестувати так само, як production-код.

Контракт подій для OpenClaw

Не варто механічно переносити конфігурацію Claude Code чи Codex в OpenClaw. Спочатку зафіксуйте власний контракт подій — його можна реалізувати поверх наявних cron-задач, агентів, skills, task ledger і Telegram-нотифікацій.

lifecycle:
  session_start:
    - load_vault_context
    - create_run_record
  before_tool:
    - classify_risk
    - require_approval_for: [external_write, destructive, secret_access]
  after_tool:
    - capture_artifact
    - run_deterministic_checks
  session_stop:
    - write_receipt
    - notify_telegram

Це контракт, а не готові ключі конфігурації OpenClaw. Для кожної події визначте чотири речі:

  1. вхідні поля (run_id, агент, інструмент, аргументи, репозиторій);
  2. дію, яка не залежить від рішення моделі;
  3. результат (allow, deny, needs_approval, artifact);
  4. поведінку при помилці або тайм-ауті.

Останній пункт критичний. Для форматування чи сповіщення можна обрати fail-open: робота продовжується, а помилка потрапляє у звіт. Для доступу до production, секретів, зовнішнього запису або видалення — fail-closed: невідомий результат означає зупинку й ручне рішення.

П’ять практичних схем

1. Реєстр подій у vault замість довгого промпту

На session_start створюйте короткий Markdown-запис із run_id, метою, дозволеним scope та очікуваним артефактом. На after_tool додавайте лише факт, результат і посилання на артефакт; не копіюйте туди весь transcript.

---
run_id: run-2026-10-10-article
agent: researcher
status: running
scope: [official-docs, article-draft]
---

## Мета
Підготувати один матеріал про lifecycle-хуки для AI-сеансів.

## Події
- 11:02 session_start — завантажено правила й тему.
- 11:08 web_fetch — 4 джерела, усі відповіли успішно.

## Наступна дія
Перевірити посилання та зібрати фінальний файл.

На наступному сеансі агент читає цей компактний стан, а не тягне стару розмову. Перевага — відновлення після обриву й менше токенів. Компроміс — це ще один формат, який треба підтримувати; додайте TTL для тимчасових записів і не зберігайте секрети або повні відповіді інструментів.

2. Telegram як шина подій, а не канал кожного tool call

Розділіть topology на три ролі:

Telegram user bot -> router agent -> worker agent/skill -> verifier -> event writer
                                      \-> approval request -> Telegram ops chat

Основний бот приймає запит і повертає один фінальний receipt. Окремий ops-чат отримує лише needs_approval, failed і completed, а не кожен виклик shell або пошуковий результат. Router вирішує, який worker потрібен; skill містить детермінований runbook; verifier перевіряє артефакт; notifier нічого не вирішує.

Таке розділення прибирає спам і не дає моделі випадково перетворити звичайну відповідь на зовнішнє повідомлення. Для довгих задач зберігайте run_id у кожному повідомленні й дозволяйте команди /status run-id та /approve run-id, а не approval без ідентифікатора.

3. Pre-tool gate для ризикових дій

Замість інструкції «не видаляй production» зробіть вузький policy-wrapper. Він отримує нормалізовану назву інструмента й аргументи, повертає рішення та причину. Правила мають бути allowlist-орієнтованими: невідомий інструмент або відсутнє поле scope не проходять.

{
  "event": "before_tool",
  "run_id": "run-123",
  "tool": "shell",
  "args": {"command": "terraform apply", "environment": "staging"},
  "decision": "needs_approval",
  "reason": "external_write"
}

Для OpenClaw практичне правило таке: read-only пошук і локальна перевірка можуть проходити автоматично; зовнішній запис, зміна інфраструктури, робота із секретами та destructive-команди — тільки через approval. Валідуйте не текст промпту, а структуровані аргументи. Не покладайтеся на один хук як на єдиний захист: sandbox, IAM і права самого процесу мають залишатися нижчим рівнем оборони.

4. Post-tool verifier, який видає артефакт

Після дії запускайте детерміновану перевірку, а не просіть того самого агента сказати «здається, готово». Для статті це перевірка frontmatter, URL і Hugo; для коду — тести, lint і diff; для Terraform — plan та policy check. У ledger записуйте команду, exit code, тривалість і короткий результат.

after_tool:
  match:
    artifact: content/ai/*.md
  checks:
    - frontmatter.date_matches_schedule
    - links.http_status_is_200
    - hugo.build
  on_failure: keep_artifact_and_mark_failed

Worker не має права відправляти «успішно» напряму. Він повертає артефакт; verifier змінює стан на verified або failed; лише після цього notifier надсилає receipt. Це трохи збільшує затримку, зате розділяє створення й приймання результату.

5. Незвичний патерн: тіньовий event-sourced сеанс

Зробіть маленький локальний «дзеркальний» журнал: кожна lifecycle-подія спочатку додається як один рядок JSONL або короткий Markdown-блок, а вже потім агрегується у vault-сторінку. Агент не читає всі події автоматично. На session_start окремий summarizer будує 10–20 рядків стану; на session_stop зберігаються рішення, помилки й наступний крок.

{"ts":"2026-10-10T11:08:00+01:00","run_id":"run-123","event":"tool.finished","tool":"web_fetch","status":"ok","artifact":"source-04"}
{"ts":"2026-10-10T11:11:00+01:00","run_id":"run-123","event":"verify.failed","check":"link_status","status":"failed"}

Це корисно для нічних cron-задач і Telegram-команд /status: після збою можна відновити стан без replay всієї розмови. Ціна — складніша операційна модель, дублювання даних і ризик зберегти приватний контекст. Тому застосуйте redaction до запису, whitelist полів, ротацію та окрему політику доступу. Event log — не резервна копія transcript і не доказ аудиту, якщо ви не гарантували цілісність і повноту запису.

Як розкласти це на agents, skills і конфігурацію

Не створюйте окремого агента для кожної події. Агент володіє контекстом і приймає рішення в межах ролі: router, worker, verifier. Skill описує повторювану процедуру: як прочитати vault, як запустити перевірки, який формат receipt повернути. Хук або його аналог запускає процедуру на події й не містить бізнес-міркування.

Мінімальна структура може виглядати так:

workflow/
  contracts/events.yaml
  policies/tool-allowlist.yaml
  skills/article-publish/SKILL.md
  skills/article-publish/checks.sh
  agents/router.md
  agents/verifier.md
  runs/2026-10-10/run-123.md

Тримайте політики й skills версіонованими разом із проєктом, а персональні правила vault — окремо. Для кожного workflow задайте timeout, retry, on_error і approval_owner. Повторний запуск має бути ідемпотентним: однаковий run_id не повинен двічі публікувати статтю або надсилати два зовнішні запити.

Почніть з двох подій: before_external_write і after_artifact_created. Додайте журнал та Telegram receipt. Лише після цього розширюйте покриття на старт сеансу, compaction і subagents. Так ви побачите реальні точки відмови, а не побудуєте ще одну систему, яку всі обходять.

Джерела