Часть 17. Хуки Qwen Code: автоматизация рабочего процесса
Хуки Qwen Code — это сценарии, которые запускаются в заранее определённые моменты сессии: при старте, после пользовательского запроса, перед использованием инструмента, после использования инструмента, при ошибке инструмента или перед завершением ответа.
В SDD хуки нужны не для того, чтобы заменить спецификации. Они нужны, чтобы сделать процесс менее зависимым от памяти человека: напомнить агенту о правилах, записать важное событие, остановить опасную команду, добавить короткий контекст или собрать следы для последующей проверки.
Базовая схема:
flowchart TD
A["Событие Qwen Code"] --> B["Фильтр matcher"]
B --> C["Хук<br/>command или http"]
C --> D{"Можно продолжать?"}
D -- "да" --> E["Qwen Code продолжает работу"]
D -- "нет" --> F["Qwen Code показывает причину остановки"]
C --> G["Дополнительный контекст"]
G --> EКогда хуки уместны
Хук уместен, если действие должно происходить регулярно и одинаково:
- записать факт использования инструмента;
- добавить короткую SDD-памятку после
/clear; - проверить потенциально опасную команду перед запуском;
- сохранить ошибку инструмента для ретроспективы;
- отправить событие во внутренний журнал;
- добавить в контекст ссылку на актуальную спецификацию;
- запустить лёгкую фоновую проверку после изменения файла.
Хук не нужен, если правило достаточно записать в QWEN.md. Например, «сначала читай спецификации» лучше оставить как правило поведения. А вот «каждый запуск Bash с опасной командой должен быть остановлен» уже подходит для хука.
События, которые чаще всего нужны
Для учебного процесса достаточно понимать несколько событий.
| Событие | Когда срабатывает | Типичный смысл в SDD |
|---|---|---|
SessionStart | при старте или возобновлении сессии | добавить короткое напоминание о проекте |
UserPromptSubmit | после пользовательского запроса | проверить запрос и добавить релевантный контекст |
PreToolUse | перед использованием инструмента | остановить опасное действие |
PostToolUse | после успешного использования инструмента | записать факт, запустить лёгкую фоновую проверку |
PostToolUseFailure | после ошибки инструмента | сохранить ошибку для анализа |
Stop | перед завершением ответа агента | записать итог сессии или напомнить о проверке |
| PreCompact | перед сжатием контекста | сохранить важные выводы перед потерей деталей |
Не нужно подключать всё сразу. Начните с одного или двух событий, иначе процесс станет непрозрачным.
Типы хуков
Qwen Code поддерживает несколько типов исполнителей.
command запускает локальную команду. Это основной вариант для проектных хуков: Python-скрипт, скрипт оболочки или маленькая утилита.
http отправляет событие на HTTP-адрес. Это удобно для централизованного журнала или внутренней системы аудита, но требует аккуратной настройки секретов и разрешённых адресов.
function предназначен для внутренних JavaScript-функций на уровне сессии. Для обычного проекта почти всегда достаточно command или http.
Что получает хук
Командный хук получает JSON через стандартный ввод. В нём есть общие поля: идентификатор сессии, текущая директория, имя события, время события. Для событий инструментов добавляются имя инструмента, входные данные инструмента, результат или ошибка.
Хук может вернуть JSON через стандартный вывод. Чаще всего он делает одно из трёх:
- ничего не меняет и просто завершает работу;
- добавляет
additionalContext, чтобы Qwen Code увидел короткое сообщение в следующем шаге; - запрещает действие перед использованием инструмента и объясняет причину.
Код завершения тоже важен. 0 означает успешную работу хука. 2 используется для блокирующей ошибки. Другие коды считаются неблокирующей ошибкой: основной ход Qwen Code продолжается, а детали видны в отладке.
Минимальный комплект файлов
Примеры вынесены из урока в отдельные файлы:
- examples/hooks/settings-workflow.example.json — пример подключения хуков;
- examples/hooks/pre_tool_guard.py — защитный хук перед опасными командами;
- examples/hooks/log_tool_result.py — журналирование успешных и неуспешных вызовов инструментов;
- examples/hooks/inject_sdd_context.py — добавление короткого SDD-контекста;
- examples/hooks/README.md — краткое описание примеров.
Подключение в учебном проекте:
mkdir -p .qwen/hooks
cp sdd-qwen-code-ru/examples/hooks/pre_tool_guard.py .qwen/hooks/pre_tool_guard.py
cp sdd-qwen-code-ru/examples/hooks/log_tool_result.py .qwen/hooks/log_tool_result.py
cp sdd-qwen-code-ru/examples/hooks/inject_sdd_context.py .qwen/hooks/inject_sdd_context.py
chmod +x .qwen/hooks/*.py
Пример настроек скопируйте отдельно и объедините с уже существующим .qwen/settings.json вручную:
cp sdd-qwen-code-ru/examples/hooks/settings-workflow.example.json .qwen/settings-hooks.example.json
Не перезаписывайте рабочие настройки модели, авторизации и MCP-серверов.
Защитный хук перед инструментом
PreToolUse подходит для действий, которые должны быть проверены до выполнения. Самый понятный пример — команды оболочки.
Файл examples/hooks/pre_tool_guard.py проверяет вход Bash на несколько опасных шаблонов: удаление корня или домашней директории, git reset --hard, git clean -fd, запуск скачанного скрипта через командную оболочку. Это не полноценная песочница. Это последняя проверка перед очевидно рискованным действием.
Важно: защитный хук должен объяснять причину остановки. Если агент видит только «команда запрещена», он начнёт угадывать обходной путь. Если он видит конкретную причину, он может предложить безопасный вариант.
Журналирование инструментов
PostToolUse и PostToolUseFailure подходят для журнала событий. В SDD такой журнал полезен не сам по себе, а как источник ретроспективы:
- какие команды часто падали;
- какие файлы агент менял перед ошибкой;
- какие проверки запускались вручную;
- какие действия стоит перенести в
validation.md; - какие правила стоит записать в
QWEN.md.
Файл examples/hooks/log_tool_result.py пишет компактные записи в .qwen/hooks/logs/tool-events.jsonl. Это локальный технический журнал. Не храните там секреты, большие ответы модели и полные дампы окружения.
Для журналирования обычно включают асинхронный режим, чтобы основной ход работы не ждал запись в журнал.
Добавление SDD-контекста
SessionStart и UserPromptSubmit подходят для короткого добавления контекста. Это особенно полезно после /clear: история чата очищена, но проектный процесс должен остаться видимым.
Файл examples/hooks/inject_sdd_context.py не читает весь проект. Он проверяет наличие QWEN.md, specs/mission.md, specs/tech-stack.md и specs/roadmap.md, затем добавляет короткую памятку. Такой хук не должен превращаться в скрытую спецификацию. Он только направляет агента к файлам, где живёт источник истины.
Хуки и проверки
Есть соблазн запускать npm test после каждого изменения файла. Обычно это плохая идея: агент станет медленным, а ошибки будут приходить в неподходящий момент. Лучше разделить проверки:
- лёгкие проверки можно запускать автоматически и асинхронно;
- тяжёлые проверки запускаются по явному шагу из
validation.md; - блокирующие хуки используют только для опасных действий;
- результаты автоматических проверок должны попадать в отчёт или журнал, а не теряться в шуме.
Если хук запускает проверку, он должен отвечать на один вопрос. Например: «после изменения TypeScript-файла упала ли быстрая проверка типов?» Не надо превращать один хук в полный процесс слияния ветки.
Правила безопасности
Хуки выполняются в вашей среде и с вашими правами. Поэтому относитесь к ним как к обычному коду автоматизации.
Минимальные правила:
- храните проектные хуки в репозитории и ревьюйте их как код;
- задавайте
timeout, чтобы зависший хук не блокировал сессию; - используйте асинхронный режим для журналов и фоновых проверок;
- не передавайте секреты в командную строку;
- для HTTP-хуков задавайте список разрешённых переменных окружения;
- не отправляйте исходники и промпты во внешние сервисы без явного решения команды;
- не пишите хуки, которые молча меняют файлы проекта;
- добавляйте понятное сообщение при блокировке действия.
Проектные хуки стоит включать только в доверенной директории. Если вы открыли чужой репозиторий, сначала прочитайте .qwen/settings.json и .qwen/hooks/, а уже потом разрешайте автоматический запуск.
Что не стоит автоматизировать
Плохие идеи:
- автоматически исправлять код после каждой ошибки инструмента;
- блокировать любые команды, которые не входят в заранее составленный список;
- добавлять в контекст большие фрагменты спецификаций на каждый запрос;
- записывать полные ответы модели в постоянный журнал;
- смешивать память, проверку, форматирование и безопасность в одном скрипте;
- использовать хуки как скрытую замену
requirements.md,plan.mdиvalidation.md.
Хук должен быть маленьким и понятным. Если вы не можете объяснить его назначение одной фразой, скорее всего, он делает слишком много.
Практическое упражнение
- Скопируйте примеры хуков в учебный проект.
- Подключите
pre_tool_guard.pyтолько кPreToolUseдляBash. - Подключите
log_tool_result.pyкPostToolUseиPostToolUseFailure. - Подключите
inject_sdd_context.pyкSessionStartиUserPromptSubmit. - Запустите Qwen Code в проекте и выполните
/clear. - Попросите агента прочитать дорожную карту и предложить следующую фичу без изменения файлов.
- Проверьте, что журнал появился в
.qwen/hooks/logs/tool-events.jsonl. - Попробуйте опасную команду в безопасном тестовом виде и убедитесь, что защитный хук объясняет блокировку.
После упражнения ответьте письменно:
- какой хук реально помог процессу;
- какой хук оказался шумным;
- что лучше перенести в
QWEN.md; - что лучше оставить ручным шагом в
validation.md.
Связь со следующими частями
В следующей части хуки рассматриваются с точки зрения безопасности: они могут защищать процесс, но сами требуют ревью. После этого в части про SQLite-память тот же механизм используется для сбора событий, фонового обобщения и добавления короткой памяти в новые сессии.