HOOK.md для командных событий и событий Gateway, таких как
/new, /reset, /stop, agent:bootstrap или gateway:startup.
Быстрый старт
Регистрируйте типизированные хуки Plugin черезapi.on(...) из точки входа Plugin:
priority. Хуки с одинаковым приоритетом
сохраняют порядок регистрации.
api.on(name, handler, opts?) принимает:
priority— порядок обработчиков (большее значение выполняется раньше).timeoutMs— необязательный бюджет на хук. Когда он задан, раннер хуков прерывает этот обработчик после истечения бюджета и продолжает со следующим, вместо того чтобы позволять медленной настройке или извлечению из памяти расходовать настроенный вызывающей стороной тайм-аут модели. Не указывайте его, чтобы использовать стандартный тайм-аут наблюдения/решения, который раннер хуков применяет обобщенно.
hooks.timeouts.<hookName> переопределяет hooks.timeoutMs, который переопределяет
значение api.on(..., { timeoutMs }), заданное автором Plugin. Каждое настроенное значение должно
быть положительным целым числом не больше 600000 миллисекунд. Предпочитайте переопределения
для отдельных хуков, когда известны медленные хуки, чтобы один Plugin не получал увеличенный бюджет
везде.
Каждый хук получает event.context.pluginConfig — разрешенную конфигурацию для
Plugin, зарегистрировавшего этот обработчик. Используйте ее для решений хуков, которым нужны
текущие параметры Plugin; OpenClaw внедряет ее отдельно для каждого обработчика, не изменяя
общий объект события, видимый другим Plugin’ам.
Каталог хуков
Хуки сгруппированы по поверхности, которую они расширяют. Имена, выделенные жирным, принимают результат-решение (блокировка, отмена, переопределение или запрос подтверждения); все остальные предназначены только для наблюдения. Ход агентаbefore_model_resolve— переопределить провайдера или модель до загрузки сообщений сессииagent_turn_prepare— обработать поставленные в очередь вставки хода Plugin и добавить контекст того же хода перед хуками промптаbefore_prompt_build— добавить динамический контекст или текст системного промпта перед вызовом моделиbefore_agent_start— объединенная фаза только для совместимости; предпочитайте два хука вышеbefore_agent_run— проверить финальный промпт и сообщения сессии перед отправкой в модель и при необходимости заблокировать запускbefore_agent_reply— досрочно завершить ход модели синтетическим ответом или молчаниемbefore_agent_finalize— проверить естественный финальный ответ и запросить еще один проход моделиagent_end— наблюдать финальные сообщения, состояние успеха и длительность запускаheartbeat_prompt_contribution— добавить контекст только для Heartbeat для фонового монитора и Plugin’ов жизненного цикла
model_call_started/model_call_ended— наблюдать очищенные метаданные вызова провайдера/модели, тайминг, результат и ограниченные хэши идентификатора запроса без содержимого промпта или ответаllm_input— наблюдать вход провайдера (системный промпт, промпт, историю)llm_output— наблюдать выход провайдера, использование и разрешенныйcontextTokenBudget, когда он доступен
before_tool_call— переписать параметры инструмента, заблокировать выполнение или запросить подтверждениеafter_tool_call— наблюдать результаты инструмента, ошибки и длительностьresolve_exec_env— добавить переменные окружения, принадлежащие Plugin, вexectool_result_persist— переписать сообщение ассистента, созданное из результата инструментаbefore_message_write— проверить или заблокировать выполняющуюся запись сообщения (редко)
inbound_claim— забрать входящее сообщение до маршрутизации агенту (синтетические ответы)message_received— наблюдать входящее содержимое, отправителя, поток и метаданныеmessage_sending— переписать исходящее содержимое или отменить доставкуreply_payload_sending— изменить или отменить нормализованную полезную нагрузку ответа перед доставкойmessage_sent— наблюдать успех или сбой исходящей доставкиbefore_dispatch— проверить или переписать исходящую отправку перед передачей каналуreply_dispatch— участвовать в финальном конвейере отправки ответа
session_start/session_end— отслеживать границы жизненного цикла сессии.reasonсобытия имеет одно из значений:new,reset,idle,daily,compaction,deleted,shutdown,restartилиunknown. Значенияshutdownиrestartсрабатывают из финализатора завершения Gateway, когда процесс остановлен или перезапущен, пока сессии еще активны, чтобы нижестоящие Plugin’ы (например, хранилища памяти или расшифровок) могли финализировать призрачные строки, которые иначе остались бы в открытом состоянии между перезапусками. Финализатор ограничен по времени, поэтому медленный Plugin не может заблокировать SIGTERM/SIGINT.before_compaction/after_compaction— наблюдать или аннотировать циклы Compactionbefore_reset— наблюдать события сброса сессии (/reset, программные сбросы)
subagent_spawned/subagent_ended— наблюдать запуск и завершение субагента.subagent_delivery_target— хук совместимости для доставки завершения, когда базовая привязка сессии ядра не может спроецировать маршрут.subagent_spawning— устаревший хук совместимости. Теперь ядро подготавливает привязки субагентовthread: trueчерез адаптеры привязки сессий каналов до срабатыванияsubagent_spawned.subagent_spawnedвключаетresolvedModelиresolvedProvider, когда OpenClaw разрешил нативную модель дочерней сессии перед запуском.subagent_endedнесетtargetSessionKey(идентичность — это соответствуетsubagent_spawned.childSessionKey),targetKind("subagent"или"acp"),reason, необязательныйoutcome("ok","error","timeout","killed","reset"или"deleted"), необязательныеerror,runId,endedAt,accountIdиsendFarewell. Он не включаетagentIdилиchildSessionKey; используйтеtargetSessionKey, чтобы сопоставить его с соответствующим событиемsubagent_spawned.
gateway_start/gateway_stop— запускать или останавливать сервисы, принадлежащие Plugin, вместе с Gatewaydeactivate— устаревший псевдоним совместимости дляgateway_stop; используйтеgateway_stopв новых Plugin’ахcron_changed— наблюдать изменения жизненного цикла Cron, принадлежащего Gateway (добавлен, обновлен, удален, запущен, завершен, запланирован)before_install— проверить подготовленные материалы установки Skills или Plugin из загруженного рантайма Plugin
Отладка хуков рантайма
Используйтеbefore_model_resolve, когда Plugin должен переключить провайдера или модель
для хода агента. Он выполняется до разрешения модели; llm_output выполняется только после того,
как попытка модели создает выход ассистента.
Чтобы подтвердить эффективную модель сессии, проверьте регистрации рантайма, затем
используйте openclaw sessions или поверхности сессий/статуса Gateway. При отладке
полезных нагрузок провайдера запускайте Gateway с --raw-stream и
--raw-stream-path <path>; эти флаги записывают сырые события потока модели в jsonl
файл.
Политика вызовов инструментов
before_tool_call получает:
event.toolNameevent.params- необязательные
event.toolKindиevent.toolInputKind— авторитетные со стороны хоста дискриминаторы для инструментов, которые намеренно имеют общие имена; например, внешние вызовыexecв режиме кода используютtoolKind: "code_mode_exec"и включаютtoolInputKind: "javascript" | "typescript", когда язык входных данных известен - необязательный
event.derivedPaths, содержащий best-effort подсказки целевых путей, выведенные хостом, для известных оболочек инструментов, таких какapply_patch; при наличии эти пути могут быть неполными или могут завышать то, чего инструмент фактически коснется (например, при некорректных или частичных входных данных) - необязательный
event.runId - необязательный
event.toolCallId - поля контекста, такие как
ctx.agentId,ctx.sessionKey,ctx.sessionId,ctx.runId,ctx.jobId(задается для запусков, управляемых Cron),ctx.toolKind,ctx.toolInputKindи диагностическийctx.trace
block: trueявляется терминальным и пропускает обработчики с более низким приоритетом.block: falseтрактуется как отсутствие решения.paramsпереписывает параметры инструмента для выполнения.requireApprovalприостанавливает запуск агента и запрашивает пользователя через подтверждения Plugin. Команда/approveможет подтверждать как exec, так и подтверждения Plugin. В нативных ретрансляцияхPreToolUseрежима отчета app-server Codex это откладывается до соответствующего запроса подтверждения app-server; см. рантайм Codex harness.block: trueс более низким приоритетом все еще может заблокировать после того, как хук с более высоким приоритетом запросил подтверждение.onResolutionполучает разрешенное решение подтверждения —allow-once,allow-always,deny,timeoutилиcancelled.
requireApproval вместо
необязательных инструментов или подтверждений exec.
Plugin’ы, которым нужна политика уровня хоста, могут регистрировать доверенные политики инструментов через
api.registerTrustedToolPolicy(...). Они выполняются до обычных хуков
before_tool_call и до обычных решений хуков. Встроенные доверенные
политики выполняются первыми; доверенные политики установленных Plugin’ов выполняются далее в порядке загрузки
Plugin; обычные хуки before_tool_call выполняются после них. Встроенные Plugin’ы сохраняют
существующий путь доверенных политик. Установленные Plugin’ы должны быть явно включены
и объявлять каждый идентификатор политики в contracts.trustedToolPolicies; необъявленные идентификаторы
отклоняются до регистрации. Идентификаторы политик ограничены областью регистрирующего
Plugin, поэтому разные Plugin’ы могут повторно использовать один и тот же локальный идентификатор. Используйте этот уровень только
для доверенных хостом ограничителей, таких как политика рабочей области, контроль бюджета или
безопасность зарезервированных рабочих процессов.
Хук окружения Exec
resolve_exec_env позволяет Plugin’ам добавлять переменные окружения в вызовы инструмента exec
после построения базового окружения exec и до запуска команды. Он получает:
event.sessionKeyevent.toolName, сейчас всегда"exec"event.host, одно из"gateway","sandbox"или"node"- поля контекста, такие как
ctx.agentId,ctx.sessionKey,ctx.messageProviderиctx.channelId
Record<string, string>, чтобы объединить его с окружением exec. Обработчики
выполняются в порядке приоритета, а результаты более поздних хуков переопределяют результаты более ранних хуков для
одного и того же ключа.
Вывод hook фильтруется через политику ключей среды выполнения host перед
объединением. Недопустимые ключи, PATH и опасные ключи переопределения host,
такие как LD_*, DYLD_*, NODE_OPTIONS, переменные прокси и переменные
переопределения TLS, отбрасываются. Отфильтрованная среда Plugin включается в
метаданные подтверждения/аудита Gateway и пересылается в запросы выполнения
node-host.
Сохранение результатов инструментов
Результаты инструментов могут включать структурированныеdetails для
рендеринга UI, диагностики, маршрутизации медиа или метаданных, принадлежащих
Plugin. Рассматривайте details как метаданные runtime, а не как содержимое
промпта:
- OpenClaw удаляет
toolResult.detailsперед повторным воспроизведением у провайдера и входом Compaction, чтобы метаданные не стали контекстом модели. - Сохраненные записи сессий хранят только ограниченные
details. Слишком большие details заменяются компактной сводкой иpersistedDetailsTruncated: true. tool_result_persistиbefore_message_writeвыполняются до финального ограничения сохранения. Hooks все равно должны держать возвращаемыеdetailsнебольшими и не размещать текст, важный для промпта, только вdetails; видимый модели вывод инструмента помещайте вcontent.
Hooks промпта и модели
Используйте hooks, специфичные для фазы, в новых plugins: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 остается для совместимости. Предпочитайте явные hooks выше,
чтобы ваш plugin не зависел от устаревшей объединенной фазы.
before_agent_run выполняется после построения промпта и до любого входа
модели, включая загрузку изображений, локальных для промпта, и наблюдение
llm_input. Он получает текущий пользовательский ввод как prompt, а также
загруженную историю сессии в messages и активный системный промпт. Возвращайте
{ outcome: "block", reason, message? }, чтобы остановить запуск до того, как
модель сможет прочитать промпт. reason является внутренним; message — это
замена, видимая пользователю. Поддерживаются только outcomes pass и block;
неподдерживаемые формы решений завершаются закрытым отказом.
Когда запуск блокируется, OpenClaw сохраняет только текст замены в
message.content плюс нечувствительные метаданные блокировки, такие как id
блокирующего plugin и timestamp. Исходный пользовательский текст не сохраняется
в transcript или будущем контексте. Внутренние причины блокировки считаются
чувствительными и исключаются из payloads transcript, history, broadcast, log и
diagnostics. Наблюдаемость должна использовать очищенные поля, такие как id
блокировщика, outcome, timestamp или безопасную категорию.
before_agent_start и agent_end включают event.runId, когда OpenClaw может
идентифицировать активный запуск. То же значение также доступно в ctx.runId.
Запуски, управляемые Cron, также раскрывают ctx.jobId (id исходного задания
Cron), чтобы hooks plugin могли привязывать метрики, побочные эффекты или
состояние к конкретному запланированному заданию.
Для запусков, исходящих из канала, ctx.channel и ctx.messageProvider
идентифицируют поверхность провайдера, например discord или telegram, а
ctx.channelId является идентификатором целевой беседы, когда OpenClaw может
вывести его из ключа сессии или метаданных доставки.
Когда доступна идентичность отправителя, контексты hooks агента также включают:
ctx.senderId— ограниченный каналом ID отправителя (например, Feishuopen_id, ID пользователя Discord). Заполняется, когда запуск исходит из пользовательского сообщения с известными метаданными отправителя.ctx.chatId— транспортно-нативный идентификатор беседы (например, Feishuchat_id, Telegramchat_id). Заполняется, когда исходный канал предоставляет нативный ID беседы.ctx.channelContext.sender.id— тот же ID отправителя, что иctx.senderId, под объектом, принадлежащим каналу, который plugins могут расширять специфичными для канала полями.ctx.channelContext.chat.id— тот же ID беседы, что иctx.chatId, под объектом, принадлежащим каналу, который plugins могут расширять специфичными для канала полями.
id. Channel plugins, которые передают
более богатые метаданные отправителя или чата через inbound helper, могут
дополнять PluginHookChannelSenderContext или PluginHookChannelChatContext из
openclaw/plugin-sdk/channel-inbound:
ctx.senderExternalId остается устаревшим полем совместимости с исходным кодом
для старых plugins. Core его не заполняет; новые специфичные для канала
идентичности отправителей должны находиться под ctx.channelContext.sender
через module augmentation.
agent_end — это hook наблюдения. Gateway и пути persistent harness запускают
его fire-and-forget после хода, тогда как краткоживущие one-shot пути CLI ждут
promise hook перед очисткой процесса, чтобы доверенные plugins могли сбросить
терминальную наблюдаемость или захватить состояние. Runner hook применяет
тайм-аут 30 секунд, чтобы зависший plugin или embedding endpoint не мог оставить
promise hook в ожидании навсегда. Тайм-аут логируется, и OpenClaw продолжает
работу; он не отменяет сетевую работу, принадлежащую plugin, если сам plugin не
использует собственный abort signal.
Используйте model_call_started и model_call_ended для телеметрии вызовов
провайдера, которая не должна получать raw prompts, history, responses, headers,
request bodies или provider request IDs. Эти hooks включают стабильные
метаданные, такие как runId, callId, provider, model, необязательные
api/transport, терминальные durationMs/outcome и
upstreamRequestIdHash, когда OpenClaw может вывести ограниченный hash request
id провайдера. Когда runtime разрешил метаданные context-window, событие hook и
контекст также включают contextTokenBudget, эффективный token budget после
ограничений модели/config/agent, а также contextWindowSource и
contextWindowReferenceTokens, когда был применен более низкий cap.
before_agent_finalize выполняется только когда harness собирается принять
естественный финальный ответ ассистента. Это не путь отмены /stop, и он не
выполняется, когда пользователь прерывает ход. Возвращайте { action: "revise", reason }, чтобы запросить у harness еще один проход модели перед финализацией,
{ action: "finalize", reason? }, чтобы принудительно финализировать, или
опустите результат, чтобы продолжить. Нативные hooks Codex Stop ретранслируются
в этот hook как решения OpenClaw before_agent_finalize.
При возврате action: "revise" plugins могут включать метаданные retry, чтобы
дополнительный проход модели был ограниченным и безопасным для повторного
воспроизведения:
instruction добавляется к причине ревизии, отправляемой в harness.
idempotencyKey позволяет host считать retries для одного и того же запроса
plugin среди эквивалентных решений finalize, а maxAttempts ограничивает,
сколько дополнительных проходов host разрешит перед продолжением с естественным
финальным ответом.
Не входящие в комплект plugins, которым нужны raw conversation hooks
(before_model_resolve, before_agent_reply, llm_input, llm_output,
before_agent_finalize, agent_end или before_agent_run), должны задать:
plugins.entries.<id>.hooks.allowPromptInjection=false.
Расширения сессии и внедрения следующего хода
Workflow plugins могут сохранять небольшое JSON-совместимое состояние сессии с помощьюapi.registerSessionExtension(...) и обновлять его через метод Gateway
sessions.pluginPatch. Строки сессии проецируют зарегистрированное состояние
расширения через pluginExtensions, позволяя Control UI и другим клиентам
отображать статус, принадлежащий plugin, без знания внутреннего устройства
plugin.
Используйте api.enqueueNextTurnInjection(...), когда plugin нужен долговечный
контекст, который должен попасть в следующий ход модели ровно один раз.
OpenClaw извлекает поставленные в очередь внедрения перед prompt hooks,
отбрасывает истекшие внедрения и дедуплицирует по idempotencyKey для каждого
plugin. Это правильный seam для возобновлений подтверждений, сводок политик,
дельт фонового мониторинга и продолжений команд, которые должны быть видимы
модели на следующем ходе, но не должны становиться постоянным текстом
системного промпта.
Семантика очистки является частью контракта. Cleanup расширений сессии и
callbacks cleanup жизненного цикла runtime получают reset, delete, disable
или restart. Host удаляет принадлежащее plugin постоянное состояние расширения
сессии и ожидающие внедрения следующего хода для reset/delete/disable; restart
сохраняет долговечное состояние сессии, а callbacks cleanup позволяют plugins
освобождать scheduler jobs, run context и другие out-of-band ресурсы старого
поколения runtime.
Hooks сообщений
Используйте message hooks для маршрутизации на уровне канала и политики доставки:message_received: наблюдает входящий контент, отправителя,threadId,messageId,senderId, необязательную корреляцию run/session и метаданные.message_sending: переписываетcontentили возвращает{ cancel: true }.reply_payload_sending: переписывает нормализованные объектыReplyPayload(включаяpresentation,delivery, media refs и text) или возвращает{ cancel: true }.message_sent: наблюдает финальный успех или сбой.
content может содержать скрытую spoken transcript,
даже когда payload канала не имеет видимого текста/caption. Переписывание этого
content обновляет только transcript, видимый hook; он не рендерится как media
caption.
События reply_payload_sending могут включать usageState, best-effort live
snapshot model/usage/context для текущего хода. Durable delivery, recovered
replay и replies без точной корреляции run его опускают.
Контексты message hook раскрывают стабильные поля корреляции, когда они
доступны: ctx.sessionKey, ctx.runId, ctx.messageId, ctx.senderId,
ctx.trace, ctx.traceId, ctx.spanId, ctx.parentSpanId и ctx.callDepth.
Inbound и контексты before_dispatch также раскрывают метаданные reply, когда
канал имеет отфильтрованные по видимости данные цитируемого сообщения:
replyToId, replyToIdFull, replyToBody, replyToSender и
replyToIsQuote. Предпочитайте эти первоклассные поля чтению legacy metadata.
Предпочитайте типизированные поля threadId и replyToId перед использованием
специфичных для канала метаданных.
Правила принятия решений:
message_sendingсcancel: trueявляется терминальным.message_sendingсcancel: falseтрактуется как отсутствие решения.- Переписанное
contentпродолжает передаваться хукам с более низким приоритетом, если последующий хук не отменит доставку. reply_payload_sendingвыполняется после нормализации полезной нагрузки и перед доставкой в канал, включая ответы, направляемые обратно в исходный канал. Обработчики выполняются последовательно, и каждый обработчик видит последнюю полезную нагрузку, созданную обработчиками с более высоким приоритетом.- Полезные нагрузки
reply_payload_sendingне раскрывают маркеры доверия времени выполнения, такие какtrustedLocalMedia; плагины могут изменять форму полезной нагрузки, но не могут предоставлять доверие к локальным медиа. message_sendingможет возвращатьcancelReasonи ограниченныеmetadataвместе с отменой. Новые API жизненного цикла сообщений раскрывают это как результат подавленной доставки с причинойcancelled_by_message_sending_hook; устаревшая прямая доставка для совместимости продолжает возвращать пустой массив результатов.message_sentпредназначен только для наблюдения. Сбои обработчиков логируются и не изменяют результат доставки.
Хуки установки
Используйтеsecurity.installPolicy для решений оператора о разрешении/блокировке. Эта
политика выполняется из конфигурации OpenClaw, охватывает пути установки и обновления CLI
и при включении, но недоступности, завершает выполнение с отказом при сбое.
before_install — это хук жизненного цикла среды выполнения плагинов. Он выполняется после
security.installPolicy только в процессе OpenClaw, где хуки плагинов уже
загружены, например в потоках установки на основе Gateway. Он полезен для
наблюдений, предупреждений и проверок совместимости, принадлежащих плагинам, но не является
основной корпоративной или хостовой границей безопасности для установок. Поле builtinScan
остается в полезной нагрузке события для совместимости, но OpenClaw больше не
выполняет встроенную блокировку опасного кода во время установки, поэтому это пустой результат
ok. Верните дополнительные находки или { block: true, blockReason }, чтобы остановить
установку в этом процессе.
block: true является терминальным. block: false трактуется как отсутствие решения.
Сбои обработчиков блокируют установку с отказом при сбое.
Жизненный цикл Gateway
Используйтеgateway_start для сервисов плагинов, которым требуется состояние, принадлежащее Gateway.
Контекст предоставляет ctx.config, ctx.workspaceDir и ctx.getCron?.() для
проверки и обновления Cron. Используйте gateway_stop для очистки долгоживущих
ресурсов.
Не полагайтесь на внутренний хук gateway:startup для сервисов времени выполнения,
принадлежащих плагинам.
cron_changed срабатывает для событий жизненного цикла Cron, принадлежащих Gateway, с типизированной
полезной нагрузкой события, охватывающей причины added, updated, removed, started, finished
и scheduled. Событие содержит снимок PluginHookGatewayCronJob
(включая state.nextRunAtMs, state.lastRunStatus и
state.lastError, если они присутствуют), а также PluginHookGatewayCronDeliveryStatus
со значением not-requested | delivered | not-delivered | unknown. События удаления
по-прежнему содержат снимок удаленной задачи, чтобы внешние планировщики могли
сверить состояние. Используйте ctx.getCron?.() и ctx.config из контекста
времени выполнения при синхронизации внешних планировщиков пробуждения и оставляйте OpenClaw
источником истины для проверок наступления срока и выполнения.
Предстоящие устаревания
Некоторые поверхности, смежные с хуками, устарели, но все еще поддерживаются. Выполните миграцию до следующего мажорного выпуска:- Текстовые конверты каналов в обработчиках
inbound_claimиmessage_received. ЧитайтеBodyForAgentи структурированные блоки пользовательского контекста вместо разбора плоского текста конверта. См. Текстовые конверты каналов → BodyForAgent. before_agent_startостается для совместимости. Новым плагинам следует использоватьbefore_model_resolveиbefore_prompt_buildвместо объединенной фазы.subagent_spawningостается для совместимости со старыми плагинами, но новым плагинам не следует возвращать из него маршрутизацию потоков. Ядро подготавливает привязки подагентовthread: trueчерез адаптеры привязки сессий каналов до срабатыванияsubagent_spawned.deactivateостается устаревшим совместимым псевдонимом очистки до после 2026-08-16. Новым плагинам следует использоватьgateway_stop.onResolutionвbefore_tool_callтеперь использует типизированное объединениеPluginApprovalResolution(allow-once/allow-always/deny/timeout/cancelled) вместо свободногоstring.
command-auth → command-status — см. в
Миграция Plugin SDK → Активные устаревания.
Связанные материалы
- Миграция Plugin SDK - активные устаревания и график удаления
- Создание плагинов
- Обзор Plugin SDK
- Точки входа Plugin
- Внутренние хуки
- Внутренняя архитектура Plugin