Хуки Bot
Хуки позволяют Bot выполнять небольшие правила автоматизации вокруг инструментов, ходов разговора, памяти, активности рабочего пространства, подтверждений, сжатия контекста и субагентов. Они настраиваются для каждого Bot в файле рабочего пространства:
/data/.memoh/hooks.jsonОткройте страницу Detail Page нужного Bot и перейдите на вкладку Hooks, чтобы редактировать этот файл из UI.
Вкладка Hooks
Вкладка Hooks — это JSON-редактор конфигурации хуков Bot. Она умеет:
- показывать, существует ли
/data/.memoh/hooks.json - показывать, включена ли пользовательская конфигурация
- считать включённые хуки и действия
- выводить каталог поддерживаемых событий
- показывать, какие события подключены к среде выполнения
- перезагружать и сохранять JSON-конфигурацию
- вставлять стартовый шаблон
- прогонять синтетическое событие через действующую конфигурацию хуков
Если файла нет, UI и сервис создают пустую включённую конфигурацию:
{
"version": 1,
"enabled": true,
"hooks": []
}Визуального конструктора правил на вкладке нет. Редактируйте JSON напрямую.
Структура конфигурации
{
"version": 1,
"enabled": true,
"defaults": {
"timeout": "10s",
"on_error": "fail",
"max_output_bytes": 65536,
"trigger_nested_hooks": false
},
"env": {
"HOOK_LOG": "/data/.memoh/hooks.log"
},
"hooks": [
{
"name": "review shell commands",
"event": "PreToolUse",
"matcher": "^exec$",
"enabled": true,
"priority": 10,
"actions": [
{
"type": "command",
"command": "python3 /data/.memoh/review-command.py",
"timeout": "5s",
"on_error": "block"
}
]
}
]
}Поля верхнего уровня:
| Поле | Описание |
|---|---|
version | Обязательная версия схемы. Текущая версия — 1. |
enabled | Включает или выключает хуки в этой пользовательской конфигурации. По умолчанию true. |
defaults.timeout | Таймаут действия по умолчанию. Принимает длительности в стиле Go, такие как 10s, или целое число секунд. По умолчанию 10s. |
defaults.on_error | Поведение при ошибке по умолчанию: ignore, fail или block. По умолчанию fail. |
defaults.max_output_bytes | Максимум захватываемых байт stdout/stderr на одно действие типа command. По умолчанию 65536. |
defaults.trigger_nested_hooks | Разбирается схемой, по умолчанию false; отдельного элемента управления в UI хуков пока нет. |
env | Дополнительные переменные окружения для действий типа command из пользовательской конфигурации. |
hooks | Упорядоченный список правил. Сработавшие хуки выполняются по убыванию priority; при равном приоритете сохраняется порядок в файле. |
Поля хука:
| Поле | Описание |
|---|---|
name | Необязательное имя для отображения и отладки. |
event | Обязательное имя события из каталога. |
matcher | Необязательное регулярное выражение. Сопоставляется с наиболее подходящим целевым текстом запроса. |
enabled | Включает или выключает этот хук. По умолчанию true. |
priority | Большие числа выполняются первыми. |
actions | Действия, выполняемые при срабатывании хука. |
conditions | Присутствует в схеме для будущего расширения; сейчас при сопоставлении используются event, enabled и matcher. |
Цель для matcher выбирается из запроса хука в таком порядке:
tool.nameapproval.tool_namechannel.platformmemory.scopeextra.command,extra.path,extra.operationилиextra.scope- имя события
Типы действий
Поддерживаются два типа действий: command и tool.
Действие command
{
"type": "command",
"command": "mkdir -p .memoh && cat >> .memoh/hooks.log",
"work_dir": "/data",
"timeout": "10s",
"on_error": "ignore"
}Действие command выполняется внутри контейнера рабочего пространства Bot. Запрос хука передаётся как JSON на stdin, с завершающим переводом строки.
Рабочий каталог определяется так:
action.work_dir- текущий каталог рабочего пространства из запроса
/data
Переменные окружения включают:
envверхнего уровня из действующей конфигурацииMEMOH_HOOK_EVENTMEMOH_HOOK_NAMEMEMOH_BOT_IDMEMOH_SESSION_ID
Если stdout — это JSON, команда может вернуть:
{
"decision": "append_context",
"reason": "extra context added",
"append_context": "Use the production-safe command variant.",
"metadata": {
"source": "hook"
}
}Если stdout — не JSON, Memoh трактует действие как allow и сохраняет «сырой» stdout в метаданных действия. Ненулевой код выхода — это ошибка действия.
Действие tool
{
"type": "tool",
"tool": "record_event",
"input": {
"source": "hook"
},
"timeout": "10s",
"on_error": "fail"
}Действие tool вызывает доступный инструмент Bot по имени с настроенным input. Результаты инструмента могут вернуть decision, reason и append_context в объектном результате.
mcp_tool зарезервирован в кодовой базе, но сейчас отклоняется.
Решения и ошибки
Действия могут возвращать одно из таких решений:
| Решение | Эффект |
|---|---|
allow | Продолжить как обычно. |
deny | Запретить охраняемую операцию. Для PreToolUse это отклоняет вызов инструмента. |
ask_approval | Запросить подтверждение человека там, где среда выполнения поддерживает передачу на подтверждение. |
append_context | Добавить контекст там, где интеграция события потребляет append_context, например в потоках, связанных с промптом, моделью или памятью. |
on_error управляет тем, что происходит при сбое действия:
| Значение | Эффект |
|---|---|
ignore | Записать в лог и перейти к следующему действию. |
fail | Вернуть ошибку действия. Это значение по умолчанию. |
block | Превратить сбой в решение deny. |
Каталог событий
Вкладка Hooks загружает каталог событий из /bots/{bot_id}/hooks/events. События, помеченные как поддерживаемые средой выполнения, подключены к текущим путям исполнения. События «только в каталоге» принимаются разбором конфигурации и тестовыми запусками, но живой путь среды выполнения их пока не порождает.
| Событие | Область | Поддержано средой выполнения | Примечания |
|---|---|---|---|
PreToolUse | Инструменты | Да | Выполняется до решения о подтверждении вызова инструмента. Может запретить или запросить подтверждение. |
PostToolUse | Инструменты | Да | Выполняется после успешного вызова инструмента. |
ToolError | Инструменты | Да | Выполняется, когда вызов инструмента возвращает ошибку. |
SessionStart | Сессия | Да | Выполняется после создания сессии. |
UserMessageReceived | Разговор | Да | Выполняется после того, как резолвер разговора получил входящее сообщение пользователя. |
BeforePromptBuild | Промпт | Да | Выполняется до сборки промпта; append_context может добавляться в системный промпт. |
AfterPromptBuild | Промпт | Да | Выполняется после сборки промпта; append_context может добавляться в системный промпт. |
BeforeModelCall | Модель | Да | Выполняется перед шагами генерации модели; append_context может добавляться как сообщение пользователя. |
AfterModelCall | Модель | Да | Выполняется после шагов генерации модели. |
TurnEnd | Ход | Да | Выполняется по завершении хода. |
TurnError | Ход | Да | Выполняется при сбое хода. |
BeforeMemorySearch | Память | Да | Выполняется перед поиском в памяти. |
AfterMemorySearch | Память | Да | Выполняется после поиска в памяти; append_context может вливаться в контекст памяти. |
BeforeMemoryWrite | Память | Да | Выполняется перед записью памяти разговора. |
AfterMemoryWrite | Память | Да | Выполняется после записи памяти. |
MemoryExtracted | Память | Да | Выполняется после извлечения памяти и подготовки записи. |
WorkspaceStart | Рабочее пространство | Да | Выполняется после запуска рабочего пространства. |
WorkspaceStop | Рабочее пространство | Да | Выполняется при остановке рабочего пространства. |
BeforeWorkspaceCommand | Рабочее пространство | Да | Выполняется перед shell-командами рабочего пространства. Может запретить команду. |
AfterWorkspaceCommand | Рабочее пространство | Да | Выполняется после shell-команд рабочего пространства. |
BeforeFileWrite | Рабочее пространство | Да | Выполняется перед записью файлов и патчами. Может запретить запись. |
AfterFileWrite | Рабочее пространство | Да | Выполняется после записи файлов и патчей. |
BeforeApprovalCreate | Подтверждения | Да | Выполняется перед созданием запроса на подтверждение инструмента. |
ApprovalRequested | Подтверждения | Да | Выполняется после того, как подтверждение запрошено. |
ApprovalResolved | Подтверждения | Да | Выполняется после того, как по подтверждению принято решение. |
ApprovalTimeout | Подтверждения | Да | Выполняется, когда подтверждение истекает по таймауту. |
PreCompact | Сжатие | Да | Выполняется перед сжатием сессии. |
PostCompact | Сжатие | Да | Выполняется после сжатия сессии. |
SubagentStart | Субагенты | Да | Выполняется перед запуском задачи субагента. |
SubagentStop | Субагенты | Да | Выполняется после остановки задачи субагента. |
InboundMessageNormalized | Сообщения | Нет | Пока только в каталоге. |
BeforeOutboundMessage | Сообщения | Нет | Пока только в каталоге. |
AfterOutboundMessage | Сообщения | Нет | Пока только в каталоге. |
ChannelDeliveryFailed | Сообщения | Нет | Пока только в каталоге. |
Тестирование хуков
Используйте раздел Test на вкладке Hooks, чтобы прогнать синтетическое событие:
- Выберите событие.
- Отредактируйте JSON-нагрузку.
- Нажмите Run Test.
- Изучите возвращённый результат: сработавшие хуки, выполненные действия, решение, результаты действий и метаданные источника хуков.
Тестовый путь использует действующую конфигурацию и выполняет настоящие действия. Не включайте в тестовые нагрузки разрушительные команды и вызовы инструментов — если только это не то, что вы намерены проверить.
Замечания о безопасности
Хуки выполняются внутри рабочего пространства Bot. Относитесь к ним как к любому другому коду, который там работает.
- Просматривайте каждое действие типа command перед включением.
- Будьте осторожны с
PreToolUse,BeforeWorkspaceCommandиBeforeFileWrite: они могут заблокировать нормальную работу Bot. - Держите таймауты короткими и задавайте
on_errorосознанно. - Не храните долгоживущие секреты прямо в
hooks.json. - Для рискованных хуков предпочитайте узкие выражения
matcher. - Помните, что действия типа command получают запрос хука на stdin, а в нём могут быть текст сообщений, входные данные инструментов, пути и ошибки.