Скрипты
Общее описание
Скрипт — исполняемый файл, в котором реализована логика активного действия. Скрипт выполняется на узле Smart Monitor с помощью интерпретатора, указанного в его настройках.
Помимо кода у скрипта есть контракт — описание того, какие данные он принимает и какие возвращает:
- входные параметры — значения, которые нужны скрипту для работы
- возвращаемые параметры — результат работы, который скрипт отдает после выполнения
Контракт делает скрипт независимым от места вызова: скрипт не знает, кто его запустил — аналитик из карточки инцидента, поисковое задание или переход рабочего процесса. Источник значений параметров определяется в активном действии и в месте применения.
Список скриптов
Чтобы открыть список скриптов, перейдите в Навигационное меню - Активные действия - Скрипты.

Настройка скрипта
Настройка скрипта содержит две вкладки:
Общее— параметры исполнения, контракт скрипта и связанные активные действияКод— содержимое файла скрипта
Параметры исполнения
Идентификатор— уникальное имя скрипта. Код скрипта автоматически сохраняется в файл с названием из идентификатора и расширения, соответствующего интерпретаторуИнтерпретатор— среда выполнения скрипта, выбирается из справочника интерпретаторов. В текущей версии поддерживается только PythonТаймаут выполнения, с— максимальное время работы скрипта. Если скрипт не завершился вовремя, Smart Monitor перестает ожидать результат, а запуск получает статус с неизвестным результатомПередавать полный контекст— если флажок установлен, помимо объявленных входных параметров скрипт получает набор данных запуска: в Планировщике задач — результаты поиска, в Менеджере инцидентов — инцидент

В справочнике интерпретаторов указываются путь к исполняемому файлу среды выполнения на узле исполнения скриптов и тип среды.
Скрипт использует сторонние библиотеки из окружения своего интерпретатора.
Входные параметры
Входные параметры описывают данные, которые скрипт ожидает получить. Для каждого параметра задаются:
ИдентификаторТип—Строка,Число,ЛогическийилиСекретМассив— признак того, что скрипт получает не одно значение, а список значений указанного типа. Подробнее — в разделе Параметры-массивыЗначение по умолчанию— значение, которое подставляется в скрипт по умолчанию. Тип значения должен совпадать с типом параметра: у параметра типаЧисло— число, у параметра типаЛогический—trueилиfalseОбязательный— признак того, что без этого параметра скрипт не может выполнитьсяТехническое описание— пояснение назначения параметра
Параметр типа Секрет используют для паролей, токенов и других подобных значений. Его значение хранится в хранилище ключей (keystore).
Идентификаторы входных параметров должны быть уникальными.
При запуске скрипт получает все объявленные входные параметры. Значение каждого параметра определяется так:
- Значение, заданное для запуска. Приоритет значений убывает в таком порядке: введенное пользователем, заданное в месте применения, заданное в карточке действия
- Если значение нигде не задано — берется значение по умолчанию из настроек скрипта
- Если нет и его — пустое значение (
None)

Параметры-массивы
Флажок Массив доступен только у параметров типа Строка и Число:
| Тип параметра | Флажок Массив | Значение по умолчанию |
|---|---|---|
Строка | доступен | флажок снят — одна строка; флажок установлен — список строк |
Число | доступен | флажок снят — одно число; флажок установлен — список чисел |
Логический | недоступен | одно значение |
Секрет | недоступен | одно значение |
В карточке активного действия параметр-массив заполняется с помощью поля типа Мульти-выбор; в скрипт он передается как список (list).
Возвращаемые параметры
Возвращаемые параметры описывают результат, который скрипт отдает после выполнения. Для каждого параметра задаются путь в контексте, тип и описание.

Связанные активные действия
В блоке перечислены активные действия, созданные на основе скрипта, и места их вызова.
Перед изменением или удалением скрипта проверьте этот блок: если на скрипте создано хотя бы одно активное действие, часть изменений запрещена. Подробнее — в разделе Изменение используемого скрипта.

Код скрипта
На вкладке Код отображается содержимое файла скрипта, его имя и время последнего изменения. Код можно отредактировать в интерфейсе и сохранить.

Изменение используемого скрипта
Скрипт считается используемым, если на его основе создано хотя бы одно активное действие. Такой скрипт можно изменять только так, чтобы уже настроенные действия продолжали ему соответствовать.
Запрещенные изменения
| Место | Запрещенное изменение |
|---|---|
| Входной параметр | Удалить или переименовать |
| Входной параметр | Изменить тип |
| Входной параметр | Установить или снять флажок Массив |
| Входной параметр | Добавить обязательный параметр без значения по умолчанию |
| Входной параметр | Сделать параметр обязательным, если у него нет значения по умолчанию |
| Входной параметр | Удалить значение по умолчанию у обязательного параметра |
| Возвращаемый параметр | Удалить, переименовать или изменить тип |
| Скрипт | Удалить скрипт, в том числе в составе массового удаления |
Изменение значения по умолчанию и описания параметра в скрипте не распространяется на поля уже созданных действий.
Контракт скрипта
Скрипт — это один файл на Python с классом-наследником ScriptAction из библиотеки sm_actions. В классе описывается только логика действия. Чтение входных параметров, передачу результата в Smart Monitor и определение исхода запуска выполняет загрузчик на узле исполнения скриптов.
Требования к файлу скрипта:
- в файле объявлен ровно один класс, наследующий
ScriptAction. Если таких классов нет или их несколько, скрипт не загрузится - скрипт не может импортировать соседние модули и другие скрипты: весь код размещается в одном файле. Общий код оформляется библиотекой в окружении интерпретатора
- доступны только библиотеки, которые администратор установил в окружение интерпретатора
Структура скрипта
from sm_actions import ScriptAction, ScriptFailure, UnknownEffect
class Action(ScriptAction):
def setup(self):
"""Необязательный. Выполняется один раз на процесс:
импорты, клиенты, загрузка моделей. Не зависит от параметров вызова."""
import requests
self.http = requests.Session()
def validate(self, params):
"""Необязательный. Проверка параметров до каких-либо внешних эффектов."""
if params["threshold"] < 0:
raise ScriptFailure("threshold must be >= 0")
def run(self, ctx):
"""Обязательный. Выполняет действие и возвращает словарь возвращаемых параметров."""
resp = self.http.post("https://…", json=ctx.payload, timeout=ctx.remaining())
if resp.status_code >= 500:
raise UnknownEffect(f"API returned {resp.status_code}")
return {"verdict": resp.json()["verdict"]}
def teardown(self):
"""Необязательный. Выполняется один раз при остановке процесса:
закрыть то, что открыл setup."""
self.http.close()
Методы класса:
| Метод | Обязательный | Назначение |
|---|---|---|
setup() | нет | Подготовка, которая не зависит от параметров вызова: импорты, клиенты внешних систем, загрузка моделей. Выполняется один раз на процесс |
validate(params) | нет | Проверка входных параметров до обращения к внешним системам. Ошибка на этом этапе гарантирует, что действие ничего не изменило |
run(ctx) | да | Основная работа действия. Возвращает словарь возвращаемых параметров |
teardown() | нет | Освобождение ресурсов, открытых в setup. Выполняется один раз при остановке процесса. Вызов не гарантирован (процесс могут прервать по сроку или при сбое) и не влияет на результат запуска, поэтому внешних эффектов здесь быть не должно |
Создавайте временные файлы только в ctx.temp_dir().
Контекст вызова
Метод run получает контекстный объект ctx со следующими данными:
| Атрибут | Что содержит |
|---|---|
ctx.params | Все объявленные входные параметры, приведенные к типам. |
ctx.element | Элемент, на котором вызван скрипт при обработке по одному элементу: запись record, ее номер в наборе position (с нуля) и размер набора set_size. При обработке набора целиком — None |
ctx.set | Набор, на котором вызван скрипт при обработке набора целиком: список записей records. При обработке по одному элементу — None |
ctx.payload | Набор данных запуска — список сырых документов, по которым запущено действие. Заполняется, только если у скрипта установлен флажок Передавать полный контекст, иначе None. Для большего удобства используйте ctx.element или ctx.set. |
ctx.run | Сведения о запуске: идентификатор запуска run_id, идентификатор действия action_id и срок завершения deadline (UTC, вычисляется по таймауту) |
ctx.meta | Метаданные запуска: кто, откуда и на чем запустил действие. Состав — в разделе Метаданные |
ctx.remaining() | Количество секунд до срока завершения. Используйте его как таймаут обращений к внешним системам, чтобы скрипт укладывался в срок сам |
ctx.log | Журнал скрипта. Записи попадают в диагностику запуска |
ctx.temp_dir() | Временный каталог вызова. Создается при первом обращении и удаляется после завершения вызова |
Из ctx.element и ctx.set всегда задан ровно один — по нему скрипт определяет режим обработки. Содержимое записей (ctx.element.record, ctx.set.records) передается, только если у скрипта установлен флажок Передавать полный контекст, иначе оно равно None. Режим и место элемента в наборе (position, set_size) передаются всегда.
Входные параметры в ctx.params
ctx.params — словарь всех входных параметров, объявленных в скрипте, в порядке объявления. Тот же словарь передается в validate(params). Каждый объявленный параметр присутствует в словаре всегда, поэтому проверять наличие ключа не нужно.
Значения приведены к объявленному типу:
| Тип параметра | Значение в Python |
|---|---|
Строка | str |
Число | int, если значение целое, иначе float |
Логический | bool |
Секрет | str из хранилища ключей (keystore) или None |
| Массив | list значений типа параметра |
Значение секретного параметра подставляется из хранилища ключей на узле, где выполняется скрипт. Если не задан обязательный секретный параметр, скрипт не запускается.
Не записывайте значения секретных параметров в журнал скрипта и в текст исключений: и то, и другое попадает в историю запуска.
Передавайте ctx.remaining() в таймауты сетевых запросов. Тогда при медленном ответе внешней системы скрипт сам завершится с понятной ошибкой, а не будет прерван по таймауту выполнения с неизвестным исходом.
Метаданные
ctx.meta содержит три атрибута:
| Атрибут | Что содержит |
|---|---|
ctx.meta.call | Место и время вызова: scope — место вызова (INCIDENT_MANUAL_SCOPE, INCIDENT_WORKFLOW_SCOPE, INCIDENT_SLA_SCOPE, JOB_SCHEDULER_SCOPE), time — логическое время вызова (datetime, UTC) |
ctx.meta.run_as | От чьего имени выполняется действие: имя пользователя name, список ролей roles и режим mode (AS_INITIATOR, AS_STORED_ROLES, AS_SYSTEM). None, если место вызова его не передало |
ctx.meta.object | Объект, на котором запущено действие: тип type, идентификатор id и название title. None, если место вызова его не передало |
Метаданные носят справочный характер: отсутствующее или некорректное значение передается как None и не прерывает вызов.
Исход запуска
Исход запуска определяется тем, как завершился скрипт:
| Как завершился скрипт | Исход | Что это значит |
|---|---|---|
run вернул словарь или None | Успех | Действие выполнено. None означает пустой результат |
Исключение при импорте, в setup или validate (в том числе прерывание по сроку в validate) | Ошибка (FAILED) | До run дело не дошло, внешних эффектов не было |
run вызвал ScriptFailure | Ошибка (FAILED) | Скрипт гарантирует, что ничего не изменил во внешней системе. Запуск можно безопасно повторить |
run вызвал UnknownEffect | Неизвестно (UNKNOWN) | Действие во внешней системе могло произойти. Перед повтором результат проверяет человек |
run вызвал любое другое исключение или sys.exit() | Неизвестно (UNKNOWN) | run мог упасть уже после обращения к внешней системе |
run прерван по сроку или процесс завершен по таймауту | Неизвестно (UNKNOWN) | Действие могло успеть выполниться |
run вернул не словарь или значение, которое нельзя преобразовать в JSON | Неизвестно (UNKNOWN) | Действие выполнено, но результат не прочитан |
run вернул необъявленный ключ или значение другого типа | Ошибка (FAILED) | Результат не соответствует контракту скрипта |
Сообщение исключения сохраняется как причина исхода в истории запуска.
run возвращает словарь, в котором ключ — идентификатор возвращаемого параметра, а значение — значение объявленного типа.
Скрипт должен вернуть все параметры, объявленные в его карточке: последующие действия и места применения используют каждый из них. Вместо словаря можно вернуть None, только если у скрипта нет возвращаемых параметров.
Требования к словарю:
- ключи плоские и в точности совпадают с идентификаторами параметров, включая точки: параметр
ticket.idвозвращается как{"ticket.id": 42}, а не как{"ticket": {"id": 42}} - строка —
str, число —intилиfloat, логическое значение —bool; списки и словари в качестве значений не допускаются - значения должны сериализоваться в JSON стандартными средствами Python;
datetime,Decimalиbytesпредварительно преобразуйте в строку или число - размер результата не должен превышать лимит узла исполнения (по умолчанию 10 МБ)
Выбирайте исключение с учетом того, произошло ли действие во внешней системе. Используйте ScriptFailure, только если точно известно, что действие не выполнено: например, параметры не прошли проверку или получен ответ внешней системы, гарантирующий, что действие не выполнено. Если запрос мог быть выполнен, но ответ не получен, используйте UnknownEffect: перед повторным запуском результат должен проверить человек.
Срок выполнения и журнал
Незадолго до истечения таймаута загрузчик прерывает validate или run исключением sm_actions.DeadlineExceeded. Оно наследуется от BaseException, поэтому except Exception его не перехватывает. Не перехватывайте его в коде: блоки finally и with при прерывании успевают выполниться. Прерванный run получает исход UNKNOWN, а если срок истек полностью, процесс скрипта завершается принудительно. Прерывание по сроку не заменяет таймауты внешних вызовов — используйте ctx.remaining().
ctx.log — стандартный logging.Logger, который пишет в stderr процесса. Последние записи stderr (до 64 КБ) и stdout попадают в диагностику запуска: при успешном исходе — с уровнем INFO, иначе — с уровнем ERROR.
Отладка скрипта
Скрипт можно запустить локально, без Smart Monitor, передав входные данные из JSON-файла:
Файлы скриптов хранятся на узлах с плагином sm-actions в каталоге /app/opensearch/scripts.
PYTHONPATH=<каталог loaders/python из sme-re> python3 -m sm_actions.run script.py input.json
Пример input.json:
{
"contractVersion": 1,
"run": { "runId": "local-1", "actionId": "local", "deadline": "2030-01-01T00:00:00Z" },
"params": { "threshold": 5, "host": "srv-1", "token": "dev-token" },
"payload": [ { "user": "ivanov", "ip": "10.0.0.1" } ],
"meta": {
"call": { "scope": "INCIDENT_MANUAL_SCOPE", "time": "2026-10-21T09:15:03Z" },
"runAs": { "name": "ivanov", "roles": ["analyst"], "mode": "AS_INITIATOR" },
"object": { "type": "incident", "id": "inc-42", "title": "Подбор пароля на srv-1" }
}
}
Имена полей в input.json записываются в camelCase, а в ctx те же поля доступны в snake_case: runId — ctx.run.run_id, runAs — ctx.meta.run_as.
Загрузчик последовательно выполняет setup, validate, run и teardown и выводит результат в stdout: {"outputs": {...}} или {"error": {"message": ..., "effect": ...}}. При локальном запуске прерывания по сроку нет.
Настройки узла OpenSearch, связанные с выполнением скриптов
| Настройка | По умолчанию | Тип | Описание |
|---|---|---|---|
sm.actions.script.deadline_margin | 2s | Статическая | Насколько срок процесса скрипта короче срока вызова: SME RE убивает процесс раньше, чем плагин отменит запрос. |
sm.actions.per_element.max_elements | 100 | Динамическая | Предел элементов набора при вызове по элементу, одна настройка на все типы действий. |
API справочника интерпретаторов
Интерпретаторы создаются, изменяются и удаляются через API, например в консоли Dev Tools. Запись интерпретатора содержит поля:
| Поле | Тип | Обязательное при создании | Ограничение | Описание |
|---|---|---|---|---|
name | строка | да | до 256 символов | Название интерпретатора, которое отображается в настройке скрипта |
path | строка | да | до 1024 символов | Путь к исполняемому файлу среды выполнения на узле исполнения скриптов |
type | строка | да | до 1024 символов | Тип среды выполнения. От типа зависит расширение файла скрипта. В текущей версии — python |
Идентификатор интерпретатора задается в пути запроса при создании и не изменяется. По этому идентификатору на интерпретатор ссылаются скрипты.
Для запросов требуются отдельные права доступа к интерпретаторам. Они перечислены в разделе Права доступа.
Получение интерпретаторов
Список всех интерпретаторов:
GET _core/script_interpreters
Один интерпретатор по идентификатору:
GET _core/script_interpreters/<идентификатор>
Создание интерпретатора
Все поля обязательны:
POST _core/script_interpreters/python3
{
"name": "Python 3",
"path": "/usr/bin/python3",
"type": "python"
}
Изменение интерпретатора
Передаются только изменяемые поля, остальные остаются без изменений. Переданное поле не может быть пустой строкой.
PUT _core/script_interpreters/python3
{
"path": "/opt/python3.11/bin/python3"
}
Изменение пути или типа применяется ко всем скриптам, которые используют интерпретатор.
Удаление интерпретатора
Удаление одного интерпретатора:
DELETE _core/script_interpreters/python3
Массовое удаление:
POST _core/script_interpreters/bulk_update/delete
{
"ids": {
"user": ["python3", "python3_legacy"]
}
}
Интерпретатор, который используется хотя бы одним скриптом, удалить нельзя: запрос вернет ошибку 400 с текстом Interpreters [<идентификатор>] are used by scripts: move the scripts to another interpreter before deleting. При массовом удалении запрос отклоняется, если используется хотя бы один из перечисленных интерпретаторов. Перед удалением переведите скрипты на другой интерпретатор.
Права доступа
Доступ можно настроить как для отдельных скриптов, так и для всех сразу.
Для отдельных скриптов доступы настраиваются по кнопке Разрешения.
Для просмотра сразу всех скриптов нужно выдать кластерное разрешение cluster:admin/sm/adhoc_scripts/read_all, для создания — cluster:admin/sm/adhoc_scripts/create, для изменения и удаления — cluster:admin/sm/adhoc_scripts/write_all.
Чтобы создать активное действие на основе скрипта, помимо прав на активные действия требуется право на чтение этого скрипта или всех скриптов (cluster:admin/sm/adhoc_scripts/read_all).
Доступ для интерпретаторов проверяется собственными кластерными правами. Он выдается сразу на все интерпретаторы, права на отдельный интерпретатор не настраиваются:
| Право | Что разрешает |
|---|---|
cluster:admin/sm/script_interpreters/read | Просмотр интерпретаторов |
cluster:admin/sm/script_interpreters/create | Создание интерпретаторов |
cluster:admin/sm/script_interpreters/write | Изменение и удаление интерпретаторов |
Чтобы пользователь мог создать скрипт, ему нужно выдать доступ на просмотр интерпретаторов (cluster:admin/sm/script_interpreters/read) и создание скриптов (cluster:admin/sm/adhoc_scripts/create).