AcTrail: слежка за ИИ-агентом
Введение
ИИ-агенты уже давно перестали быть лабораторной игрушкой. Сегодня они пишут код, управляют файлами, ходят в интернет и принимают решения без подтверждения пользователя. Развернуть такого «помощника» можно где угодно: на выделенном сервере в дата-центре, в облачном контейнере — или прямо на собственном ноутбуке.
И вот тут начинается проблема, о которой не принято говорить в восторженных обзорах.
Агент с доступом к локальной файловой системе — это, по сути, процесс с привилегиями пользователя. Он читает, перемещает, перезаписывает и удаляет данные так же свободно, как это сделали бы вы сами. Ошибка в цепочке рассуждений, неверно интерпретированная команда, конфликт версий инструментов — и вот уже агент «оптимизирует» папку, в которой лежал единственный бэкап клиентского проекта или лезет «ломать» какой-то сетевой сервис. За действиями такого рода просто необходимо какое-то наблюдение. И вот про инструмент такого наблюдения и пойдёт речь в сегодняшней статье.
Сразу придётся сделать оговорку, что речь пойдёт именно про наблюдение над действиями агента, а не ограничение этих действий. То есть мы рассмотрим инструмент, который поможет разобраться «что же такого наделал ИИ-агент» уже после того как всё случилось 🙂
Что мы будем делать сегодня?
Мы разобьём эту статью на два раздела. В первом мы просто запустим локальную модель qwen и подключим к ней (уже типовой на данный момент) ИИ-агент openclaw. Всё будет работать локально, чтобы мы не зависели от каких-либо внешних сервисов и данный эксперимент можно было бы при желании повторить. А во втором разделе, мы установим инструментарий AcTrail для наблюдения за действиями ИИ-агента и продемонстрируем на простом примере как это работает.
Локальная установка qwen и openclaw
Для начала давайте опишем стенд, на котором мы будем проводить все наши действия.
Запускать всё это хозяйство мы будем на сервере Huawei 2288H V5, на его борту 2 процессора Intel(R) Xeon(R) Gold 5118 CPU @ 2.30GHz и 256 Гб ОП. Также в сервер установлены две карты Nvidia GV100GL (Tesla V100 PCIe 16GB).
Работает этот сервер под управлением ОС от нашего сообщества — openScaler 24.03 SP4 (версия ядра 6.6.0).
Так как мы заботимся о безопасности, то и модель и ИИ-агента мы будем запускать внутри контейнеров, а не напрямую на хосте. Для этого мы установили на наш сервер дополнительно:
-
драйвер NVIDIA driver 570+ (CUDA 12.8) (NVIDIA-Linux-x86_64-570.211.01.run)
-
Docker версии 29.7.2 (с плагином Compose)
-
NVIDIA Container Toolkit.
В docker был добавлен runtime nvidia, командой:
nvidia-ctk runtime configure —runtime=docker
Проверим драйвер nvidia на хосте:

Вывод nvidia-smi на хосте.
Если что, вот вывод карт nvidia в lspci:

Вывод команды lspci на хосте.
Для, проверки, что внутри контейнеров GPU доступен для использования, мы дадим команду:

Проверка доступности GPU внутри контейнера.
Запускать модель qwen мы будем при помощи ollama, а для запуска openclaw мы возьмём его официальный docker образ.
Создадим все необходимые каталоги для запуска:
mkdir -p ~/local-qwen/{ollama,openclaw-config,openclaw-workspace,openclaw-secrets}
перейдём в каталог ~/local-qwen и дальнейшие действия будут выполняться внутри этого каталога.
Чтобы запускать всё одной командой, мы создадим compose файл:
docker-compose.yml:
name: local-qwen
services:
ollama:
image: docker.io/ollama/ollama:latest
container_name: ollama
restart: unless-stopped
environment:
OLLAMA_HOST: "0.0.0.0:11434"
NVIDIA_VISIBLE_DEVICES: "all"
NVIDIA_DRIVER_CAPABILITIES: "compute,utility"
OLLAMA_KEEP_ALIVE: "30m"
volumes:
- ./ollama:/root/.ollama:Z
ports:
- "127.0.0.1:11434:11434"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
healthcheck:
test: ["CMD-SHELL", "ollama list >/dev/null 2>&1 || exit 1"]
interval: 15s
timeout: 10s
retries: 20
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
openclaw-gateway:
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
container_name: openclaw-gateway
restart: unless-stopped
depends_on:
ollama:
condition: service_healthy
env_file:
- .env
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
volumes:
- ${OPENCLAW_CONFIG_DIR:-./openclaw-config}:/home/node/.openclaw:Z
- ${OPENCLAW_WORKSPACE_DIR:-./openclaw-workspace}:/home/node/.openclaw/workspace:Z
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR:-./openclaw-secrets}:/home/node/.config/openclaw:Z
ports:
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT:-18789}:18789"
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
init: true
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND:-lan}",
"--port",
"18789",
]
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
openclaw-cli:
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
profiles:
- cli
env_file:
- .env
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
BROWSER: echo
volumes:
- ${OPENCLAW_CONFIG_DIR:-./openclaw-config}:/home/node/.openclaw:Z
- ${OPENCLAW_WORKSPACE_DIR:-./openclaw-workspace}:/home/node/.openclaw/workspace:Z
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR:-./openclaw-secrets}:/home/node/.config/openclaw:Z
network_mode: "service:openclaw-gateway"
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
stdin_open: true
tty: true
init: true
entrypoint: ["node", "dist/index.js"]
depends_on:
- openclaw-gateway
Необходимо сразу дать некоторые комментарии по этому файлу. Как вы видите, мы разделили агента на собственно постоянно запущенный агент (openclaw-gateway) и консоль управления им (openclaw-cli). Контейнер с консолью управления не запускается автоматически при помощи команды docker compose up, но доступен для запуска через docker compose run — это всё достигается применением profiles.
Теперь давайте создадим файл, в который поместим все необходимые для запуска приложений переменные среды:
cat > ~/local-qwen/.env <<'EOF'
# Ollama
OLLAMA_HOST=0.0.0.0:11434
# OpenClaw
OPENCLAW_IMAGE=ghcr.io/openclaw/openclaw:latest
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_CONFIG_DIR=./openclaw-config
OPENCLAW_WORKSPACE_DIR=./openclaw-workspace
OPENCLAW_AUTH_PROFILE_SECRET_DIR=./openclaw-secrets
OPENCLAW_TZ=Europe/Moscow
EOF
Для запуска openclaw нам понадобится создать токен:
echo "OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)" >> ~/local-qwen/.env
cat ~/local-qwen/.env
Создадим минимальный конфиг для запуска openclaw:
cat > ~/local-qwen/openclaw-config/openclaw.json <<'EOF'
{
"gateway": {
"mode": "local",
"bind": "lan"
}
}
EOF
И наконец, зададим нужные права для каталогов, в расчёте на то, что они должны быть доступны пользователю с UID 1000, под которым работает контейнер openclaw.
chown -R 1000:1000 ~/local-qwen/openclaw-config \
~/local-qwen/openclaw-workspace \
~/local-qwen/openclaw-secrets
ls -ld ~/local-qwen/openclaw-config \
~/local-qwen/openclaw-workspace \
~/local-qwen/openclaw-secrets
Отлично! Всё готово для первого запуска! Всё наше хозяйство мы запускаем привычной всем контейнероводам командой:

Запуск контейнеров.
Проверяем, что контейнеры успешно запустились:

Перечень запущенных контейнеров.
Отлично!
Теперь нам надо загрузить модель Qwen. Делать это мы будем командой:

Загрузка модели Qwen.
После
успешного выполнения, мы можем увидеть
скаченную модель командой:

Перечень скаченных моделей.
Сразу поясним, почему мы выбрали именно эту модель: а всё просто — она влезает в одну V100 16GB (Q4_K_M квант, ~9GB) и имеет хороший баланс скорости и качества.
Проверяем, что ollama доступна с хоста и загруженная модель есть в выводе:

Проверка, что ollama видит модель.
Мы должны увидеть вывод JSON со списком моделей, как это показано на нашем скриншоте.
Теперь нам осталась сущая малость, а именно настроить наш ИИ-агент для работы с нашей локальной моделью. Для этого дадим следующую команду:

Настройка агента openclaw.
Прошу заметить, что мы вручную отвечаем на вопросы, выбирая или вбивая ответ:
- Ollama mode →
Local only - Ollama base URL →
http://ollama:11434
И теперь нам осталось только установить установленную модель в качестве модели по умолчанию. Для этого мы даём следующие команды:

Установка модели Qwen в качестве модели по умолчанию.
Выполняем проверку, что наша модель qwen2.5:14b выбрана в качестве default:
Проверка настроенной модели по умолчанию.
Ну и теперь мы можем проверить работу ИИ-агента, задав ему какой-нибудь вопрос. Спросим у агента, знаком ли ему Марк Твен:
Тестовый запрос агенту.
В соседней вкладке мы можем увидеть нагрузку на GPU:
Нагрузка на GPU.
Так как нас больше всего заботит деятельность ИИ-агента, то давайте убедимся, что openclaw видит файлы в каталоге, который мы ему выделили (разумеется он должен видеть только то, что ему выделили при настройке контейнера).
Для этого мы просто попросим его их показать:
Перечень файлов, которые видит ИИ-агент.
Убеждаемся, что агент не врёт и мы видим эти же самые файлы в нашем локальном каталоге:
Файлы в каталоге на хосте.
Давайте теперь проверим, что агент может и сам создавать файлы по нашему запросу. Давайте попросим его об этом:
Запрос ИИ-агенту на создание файла.
Проверяем, что такой файл действительно появился:
Проверка созданного файла.
Отлично, промежуточной цели мы достигли — у нас теперь есть ИИ-агент, который использует локально запущенную модель Qwen для выполнения задач, которые мы ему поручим.
Переходим к разделу, посвящённому настройке наблюдений над его действиями.
Установка и настройка AcTrail
Для начала поясним, а что же такое AcTrail? AcTrail — система отслеживания активности для AI-агентов, работающая на уровне ядра (требования к ядру — версия не ниже 5.x, у нас в openScaler 24.03 SP4 ядро 6.6.0) и использование механизма eBPF. В отличие от обычных логов, которые пишет сам агент, AcTrail захватывает реальные действия процесса: какие команды он выполняет, к каким файлам обращается, какие сетевые соединения устанавливает, какой трафик передаёт (включая LLM-запросы/ответы).
На что нацелен проект AcTrail? Суть решаемой им проблемы и краткий ответ мы можем увидеть на следующей схеме:
Источник: https://raw.atomgit.com/openeuler/AcTrail/files/master/images/figure1-agent-log-gap-zh-cn.drawio.svg
Если быть кратким, то логи ИИ-агента рассказывают лишь то, что агент сам готов о себе рассказать; правда о его действиях лежит этажом ниже — в операционной системе. И вот мониторингом на этом «этаже» и занимается AcTrail.
Новаторство AcTrail именно в том, что вместо «дампа логов» он строит семантическую цепочку «факт → действие → ответ», превращая мониторинг в инструмент расследования инцидентов. После того как ИИ-агент «навел порядок» в файлах, вы можете постфактум восстановить: кто его запустил, что именно изменилось, куда ушли данные и как он расплодил дочерние процессы.
Все заинтересовавшиеся могут пройти по ссылке в репозиторий с исходными кодами этого проекта: https://atomgit.com/openeuler/AcTrail и самостоятельно ознакомится.
В нашем случае AcTrail покажет всё что OpenClaw будет выполнять на хосте, всё его общение с Ollama по HTTP. Можно будет увидеть дерево процессов: какие дочерние процессы запускает агент . Для удобства просмотра этой информации у AcTrail есть веб-интерфейс для визуализации трейсов.
Для установки AcTrail мы просто скачаем уже готовый rpm файл (собранный для openEuler) и установим его при помощи привычного dnf:
wget https://gitcode.com/openeuler/AcTrail/releases/download/v0.7.0/AcTrail-0.7.0-1.oe2403sp3.x86_64.rpm
dnf install ./AcTrail-0.7.0-1.oe2403sp3.x86_64.rpm
После установки нам надо инициализировать конфигурационный файл, дав команду:
actraild init
Конфигурационный файл создаётся по адресу /etc/actrail/actraild.conf
После этого мы можем запустить сервис командой
actraild start
По умолчанию сокеты, которые actraid создаём в каталоге /run/actrail/*.sock имеют права 660 (только root и группа). Но, мы запускаем нашего ИИ-агента в контейнере, к тому же внутри контейнера процесс OpenClaw работает под пользователем node (UID 1000). А для того, чтобы мы смогли наблюдать за деятельностью openclaw нам придётся запустить его при помощи actrailctl (который в свою очередь мы просто прокинем внутрь контейнера). Поэтому, чтобы пользователь с uid 1000 мог работать с этими сокетами, нам придётся поменять в конфигурационном файле actraild:
sed -i 's/socket_mode_octal = "660"/socket_mode_octal = "666"/; s/sync_socket_mode_octal = "660"/sync_socket_mode_octal = "666"/' \
/etc/actrail/actraild.conf
Чтобы наши изменения оказались активными, давайте перезапустим actraild:
actraild stop
actraild start
Останавливаем текущие контейнеры:
cd ~/local-qwen
docker compose down
И правим наш compose файл:
name: local-qwen
services:
ollama:
image: docker.io/ollama/ollama:latest
container_name: ollama
restart: unless-stopped
environment:
OLLAMA_HOST: "0.0.0.0:11434"
NVIDIA_VISIBLE_DEVICES: "all"
NVIDIA_DRIVER_CAPABILITIES: "compute,utility"
OLLAMA_KEEP_ALIVE: "30m"
volumes:
- ./ollama:/root/.ollama:Z
ports:
- "127.0.0.1:11434:11434"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
healthcheck:
test: ["CMD-SHELL", "ollama list >/dev/null 2>&1 || exit 1"]
interval: 15s
timeout: 10s
retries: 20
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
openclaw-gateway:
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
container_name: openclaw-gateway
restart: unless-stopped
depends_on:
ollama:
condition: service_healthy
env_file:
- .env
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
volumes:
- ${OPENCLAW_CONFIG_DIR:-./openclaw-config}:/home/node/.openclaw:Z
- ${OPENCLAW_WORKSPACE_DIR:-./openclaw-workspace}:/home/node/.openclaw/workspace:Z
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR:-./openclaw-secrets}:/home/node/.config/openclaw:Z
# AcTrail integration
- /run/actrail:/run/actrail:Z
- /etc/actrail:/etc/actrail:ro,Z
- /usr/bin/actrailctl:/usr/bin/actrailctl:ro,Z
- /usr/bin/libactrail_tls_payload_probe_sync.so:/usr/bin/libactrail_tls_payload_probe_sync.so:ro,Z
ports:
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT:-18789}:18789"
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
init: true
command:
[
"actrailctl",
"--config", "/etc/actrail/actraild.conf",
"--socket-path", "/run/actrail/control.sock",
"launch",
"--host-ebpf", "auto",
"--seccomp-notify", "auto",
"--name", "openclaw-gw",
"--",
"node",
"dist/index.js",
"gateway",
"--bind", "lan",
"--port", "18789",
]
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
openclaw-cli:
image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
profiles:
- cli
env_file:
- .env
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
BROWSER: echo
volumes:
- ${OPENCLAW_CONFIG_DIR:-./openclaw-config}:/home/node/.openclaw:Z
- ${OPENCLAW_WORKSPACE_DIR:-./openclaw-workspace}:/home/node/.openclaw/workspace:Z
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR:-./openclaw-secrets}:/home/node/.config/openclaw:Z
network_mode: "service:openclaw-gateway"
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
stdin_open: true
tty: true
init: true
entrypoint: ["node", "dist/index.js"]
depends_on:
- openclaw-gateway
Давайте сделаем краткие пояснения к тому, что мы изменили по сравнению с предыдущей версией нашего compose файла:
Были добавлены volumes для AcTrail:
-
/run/actrail:/run/actrail:Z— сокеты daemon’а (read-write, нужны для подключения) -
/etc/actrail:/etc/actrail:ro,Z— конфиг daemon’а (read-only) -
/usr/bin/actrailctl:/usr/bin/actrailctl:ro,Z— бинарь CLI (read-only) -
/usr/bin/libactrail_tls_payload_probe_sync.so:/usr/bin/libactrail_tls_payload_probe_sync.so:ro,Z— preload-библиотека для TLS-захвата (read-only)
Изменена команда запуска:
-
Было:
node dist/index.js gateway --bind lan --port 18789 -
Стало:
actrailctl --socket-path /run/actrail/control.sock launch --host-ebpf auto --seccomp-notify auto --name openclaw-gw -- node dist/index.js gateway --bind lan --port 18789
Снова убеждаемся что actraild запущен:
actraild status
Запускаем наши отредактированные контейнеры:
cd ~/local-qwen
docker compose up -d
Ждём 30-60 секунд. Проверяем статус:
docker compose ps
Проверяем, что actrail начал захват событий:
Запуск контейнеров и actrail.
запускаем в отдельном терминале:
Запуск веб-интерфейса actrail.
Заходим при помощи любого браузера по ссылке из вывода предыдущей команды и переходим на вкладку traces:
Веб-интерфейс actrail: вкладка traces.
и видим, что State в статусе Active. Всё нормально, можно начинать давать запросы агенту и наблюдать за его активностью.
Так как проще всего наблюдать за созданием и удалением файлов (мы же сами просим агента создать файл с заданным именем), то для базовой демонстрации это представляется самым удобным примером. Давайте дадим агенту в консоли следующий запрос.
Запрос ИИ-агенту на создание файла с заданным содержимым.
Проверяем созданный файл и его содержимое:
Проверка созданного файла.
А теперь идём в веб консоль actrail и на вкладке Files можем видеть запись (операция write) в указанный нами файл:
Операция write в веб-интерфейсе actrail
К слову, искать можно и среди всех событий на вкладке Events:
перечень Events в веб-интерфейсе actrail.
Если у нас много событий, то можно попробовать отфильтровать их при помощи поискового окна (вверху справа):
Использование фильтра в веб-интерфейсе — Timeline.
Использование фильтра в веб-интерфейсе — Events.
Использование фильтра в веб-интерфейсе — Files.
Собственно, для первого подхода к этому снаряду пока информации достаточно. В завершение покажу ещё пару скриншотов как actrail отображает команды и процессы ИИ-агента:
Команды ИИ-агента в веб-интерфейса actrail.
Дерево процессов ИИ-агента в веб-интерфейса actrail.
Подведём итоги
Появление AcTrail от openEuler — это своевременный и очень нужный ответ на стихийное размножение ИИ-агентов. Утилита предлагает современный подход (использование технологии eBPF) к системному трейсингу, позволяя в реальном времени детально отслеживать цепочки рассуждений помощника, его обращения к API и операции с файловой системой. Конечно, решение еще не лишено «детских болезней»: веб-интерфейс местами откровенно сыроват, к примеру, хотелось бы получить возможность фильтровать события по нескольким критериям. Однако в реалиях, где нейросети получают широкие права доступа, прозрачность и глубина логирования всегда важнее красивой обертки. AcTrail — это уверенный шаг к тому, чтобы перестать гадать, что творит ваш агент «под капотом», и наконец превратить ИИ из непредсказуемого «черного ящика» в безопасный и подконтрольный инструмент.
А по поводу системы накладывания ограничений на действия ИИ-агента мы поговорим в одной из наших следующей статей. Следите за анонсами!




















