title: Архитектура description: “Как работают обработчик крючков, загрузка конфигурации и оценка политик” icon: sitemap
Этот документ объясняет внутреннее устройство failproofai: как система крючков перехватывает вызовы инструментов агента, как загружается и объединяется конфигурация, как оцениваются политики и как панель мониторинга отслеживает активность агента.Обзор
failproofai состоит из двух независимых подсистем:- Обработчик крючков — быстрый CLI подпроцесс, который Claude Code вызывает при каждом вызове инструмента агента. Оценивает политики и возвращает решение.
- Монитор агента (Панель) — веб-приложение Next.js для мониторинга сеансов агента и управления политиками.
~/.failproofai/ и в директории проекта .failproofai/, но работают как отдельные процессы и взаимодействуют только через файловую систему.
Обработчик крючков
Интеграция с Claude Code
Когда вы выполняетеfailproofai policies --install, он записывает записи вроде этой в ~/.claude/settings.json:
failproofai --hook PreToolUse как подпроцесс перед каждым вызовом инструмента, передавая JSON-полезную нагрузку на stdin.
Формат полезной нагрузки
PostToolUse полезная нагрузка также содержит tool_result с выводом инструмента.
Обработчик применяет лимит stdin в 1 МБ. Полезные нагрузки, превышающие это значение, отбрасываются и все политики неявно разрешают операцию.
Формат ответа
Запретить (PreToolUse):- Код выхода:
2 - Причина записывается в stderr (не в stdout)
- Код выхода:
0 - Пустой stdout
allow(message) позволяет политике отправить информационный контекст обратно Claude даже когда операция разрешена. Обработчик крючков записывает следующий JSON в stdout (не в файл конфигурации — это ответ обработчика на Claude Code, так же как запрет и инструкции выше):
- Код выхода:
0(операция разрешена) - Когда несколько политик возвращают
allowс сообщением, их сообщения объединяются новыми строками в одну строкуadditionalContext - Если ни одна политика не предоставляет сообщение, stdout пустой (как и раньше)
Конвейер обработки
src/hooks/handler.ts реализует полный конвейер:
Загрузка конфигурации
src/hooks/hooks-config.ts реализует загрузку конфигурации с тремя уровнями видимости.
enabledPolicies— дедублицированное объединение всех трех файловpolicyParams— ключ для каждой политики, первый файл, который его определяет, полностью побеждаетcustomPoliciesPath— первый файл, который его определяет, побеждаетllm— первый файл, который его определяет, побеждает
readHooksConfig() (только глобальное) для чтения и записи, так как она не вызывается с cwd проекта.
Оценка политик
src/hooks/policy-evaluator.ts запускает политики по порядку.
Для каждой политики:
- Найти схему
paramsполитики (если она есть). - Прочитать
policyParams[policy.name]из объединенной конфигурации. - Объединить предоставленные пользователем значения со значениями по умолчанию схемы для получения
ctx.params. - Вызвать
policy.fn(ctx)с разрешенным контекстом. - Если результат
deny, остановиться немедленно и вернуть это решение. - Если результат
instruct, накопить сообщение и продолжить. - Если результат
allow, перейти к следующей политике.
- Если возвращен какой-либо
deny, выдать ответ с запретом. - Если собраны какие-либо
instruct, выдать единый ответ с инструкцией со всеми сообщениями, объединенными вместе. - В противном случае выдать ответ с разрешением (пустой stdout, выход 0).
Встроенные политики
src/hooks/builtin-policies.ts определяет все 39 встроенных политик как объекты BuiltinPolicyDefinition:
params, объявляют PolicyParamsSchema с типами и значениями по умолчанию для каждого параметра. Оценщик политик внедряет разрешенные значения в ctx.params перед вызовом fn. Функции политик читают ctx.params без проверок на null, потому что значения по умолчанию всегда применяются первыми.
Сопоставление шаблонов внутри политик использует разобранные токены команд (argv), а не прямое сопоставление строк. Это предотвращает обход через инъекции операторов оболочки (например, шаблон для sudo systemctl status * не может быть обойден путем добавления ; rm -rf / к команде).
Пользовательские политики
src/hooks/custom-hooks-registry.ts реализует реестр на основе globalThis:
src/hooks/custom-hooks-loader.ts загружает файл политик пользователя:
- Прочитать
customPoliciesPathиз конфигурации; пропустить если отсутствует. - Разрешить абсолютный путь; проверить существование файла.
- Переписать все импорты
from "failproofai"на фактический путь dist, чтобыcustomPoliciesразрешился на тот же реестрglobalThis. - Рекурсивно переписать переходные локальные импорты для обеспечения совместимости ESM.
- Записать временные файлы
.mjsиimport()файл точки входа. - Вызвать
getCustomHooks()для получения зарегистрированных крючков. - Очистить все временные файлы в блоке
finally.
~/.failproofai/hook.log и загрузчик возвращает пустой массив. Встроенные политики не затрагиваются.
Пользовательские политики оцениваются после всех встроенных политик. Пользовательская политика deny по-прежнему короткозамыкает дальнейшие пользовательские политики (но все встроенные уже были выполнены к этому моменту).
Логирование активности
После каждого события крючка обработчик добавляет строку JSONL в~/.failproofai/hook-activity.jsonl:
Архитектура панели
Панель — это приложение Next.js 16, использующее App Router с React Server Components и Server Actions.- Компоненты страниц вызывают
lib/projects.tsиlib/log-entries.tsдля прямого чтения данных проекта/сеанса из файловой системы (нет API слоя для чтения). - Страница Политик использует Server Actions для всех мутаций (переключение, обновление параметров, установка/удаление).
- Средство просмотра сеансов анализирует формат JSONL-транскрипта Claude и отображает временную шкалу сообщений и вызовов инструментов.
- Нет базы данных — все постоянное состояние находится в простых файлах (
~/.failproofai/,~/.claude/projects/). - Server Actions для мутаций — не требуется REST API для операций CRUD.
- React Server Components для страниц чтения — быстрая первоначальная загрузка, нет клиентского пакета для выборки данных.
- Клиентские компоненты только где нужна интерактивность (переключатели политик, поиск активности, средство просмотра логов).

