Cairn — движок поиска решений по графу фактов для AI-агентов

· 6 мин чтения
ai-agents multi-agent orchestration security python
📂 Исходный код на GitHub

Движок общего назначения для поиска пути в пространстве состояний: граф фактов и намерений, цикл OODA у воркеров, сервер и диспетчер, поддержка Claude Code, Codex и Pi, запуск в Docker или локально без него. Python, лицензия AGPL-3.0.

Cairn — движок поиска решений по графу фактов для AI-агентов

Cairn — движок поиска решений по графу фактов

Cairn — это движок решения задач, в котором нет ни заранее заданных ролей, ни заранее прописанного сценария работы. Ему передают начальную точку и цель, а он ищет путь через неизвестное пространство состояний. Первая область, где это проверено на практике, — автономное пентестирование. Но задумывается движок гораздо шире.

Проект написан на Python (FastAPI и uvicorn), распространяется под лицензией AGPL-3.0. Репозиторий: https://github.com/oritera/Cairn

Какую задачу решает Cairn

Пентест — это направленный поиск по почти бесконечному пространству состояний:

  • Начало — известно: адрес цели или сама система.
  • Цель — задана: получить shell, забрать флаг.
  • Путь — неизвестен.

Такая же структура есть у множества других задач. Исследование уязвимостей, математическое доказательство, CTF — везде, где есть ясная стартовая точка, ясное условие успеха и неизвестный путь между ними, задача устроена одинаково. Cairn построен именно для таких задач, а пентестирование — первая область, где его проверили.

Три сущности: факт, намерение, подсказка

В основе движка лежит архитектура чёрной доски в современной переработке. Это когда несколько участников работают с общей доской: каждый читает текущее состояние, каждый добавляет на доску своё новое знание, а центрального планировщика нет. Классический пример такой архитектуры — система Hearsay-II из CMU, 1970 год.

В Cairn на доске живут всего три сущности:

Сущность Что это
Факт Подтверждённая объективная находка, записанная на доску
Намерение Объявленное направление разведки, которое ещё не выполнено
Подсказка Решение человека, добавленное в любой момент; агенты подхватывают его при следующем чтении

Граф растёт от origin к goal. Каждый новый факт — это очередной камень в cairn, а cairn по-английски как раз означает «пирамидка из камней», по которой альпинисты оставляют путь для следующих. Отсюда и название проекта.

Факты только добавляются и никогда не меняются. Изменение состояния выражается новым фактом. Например, в ходе разведки сети появляются три записи: f003 — «получен root shell на host-A», f007 — «через host-A найдена внутренняя сеть 10.0.2.0/24», f025 — «shell на host-A отвалился». Сам факт «shell отвалился» — объективная находка, поэтому он тоже попадает в граф. Агент, прочитавший граф, сам делает вывод о текущей достижимости и объявляет следующее намерение: восстановить shell или сменить опорную точку. Переписывать историю не нужно, и помечать старые факты как устаревшие тоже не нужно — сам порядок фактов уже несёт информацию об изменениях.

Намерение в графе — это ребро. При этом у одного намерения может быть несколько исходных фактов: несколько известных находок совместно поддерживают одну разведку, и все они сохраняются в связях, а не теряются.

Агенты без ролей

Воркеры Cairn работают по циклу OODA: Observe — наблюдают полный граф, Orient — сориентировались в текущем состоянии, Decide — решили, что делать дальше, Act — выполнили разведку. Находки записываются обратно на доску как новые факты.

У воркеров нет фиксированных ролей. Задачи рождаются на ходу из текущего состояния графа, а не из заранее написанных должностей вроде «разведчик» или «аналитик».

Всего есть три типа задач, и выполняет их один и тот же воркер:

Задача Что делает Результат
Bootstrap В начале проекта пробует решить задачу напрямую Факт и, возможно, отметка о завершении
Reason Читает весь граф: цель достигнута? что исследовать дальше? Завершение, новые намерения или ничего
Explore Берёт одно намерение, выполняет разведку, отчитывается Один факт

Агенты не общаются друг с другом напрямую. Единственный канал связи — общая доска. Один агент оставил на ней факт, другой увидел этот факт и на его основе принял решение. Такой способ координации в биологии называют стигмергией: муравьи выстраивают маршруты, оставляя на земле следы, и никто не говорит никому, куда идти.

Архитектура

Cairn Server хранит граф и следит только за его согласованностью. Никакой логики и никаких решений он не принимает.

Cairn Dispatcher читает граф, планирует задачи, поднимает и останавливает контейнеры воркеров. Это единственный компонент, который пишет в протокол.

Worker Container — свой на каждый проект, внутри него одновременно работает несколько воркеров. Воркер получает промпт и возвращает структурированный ответ.

Поддерживаются три бэкенда воркеров: Claude Code, Codex и Pi. Модель для каждого бэкенда задаётся в конфиге, поэтому один и тот же движок можно гонять на разных моделях.

Воркеры могут работать и напрямую на машине диспетчера, без контейнеров — об этом ниже.

Требования и запуск

Нужны macOS или Linux, Python не ниже 3.12 и Docker (в локальном режиме Docker не нужен).

Сначала скачивается образ контейнера с воркером:

docker pull --platform=linux/amd64 ghcr.io/oritera/cairn-worker-container:latest

Дальше создаётся конфиг диспетчера — его нужно заполнить адресами и ключами доступа к моделям. Пример лежит в репозитории: dispatch.example.yaml.

cp dispatch.example.yaml dispatch.yaml

Запуск через Docker Compose:

docker pull ghcr.io/astral-sh/uv:python3.13-trixie
docker compose up --build

Сервер поднимается на порту 8000, диспетчер стартует после того, как сервер пройдёт проверку состояния. Данные сохраняются в каталог ./datas/cairn/.

Запуск вручную, без Docker Compose:

# Запустить сервер
uv run --project cairn cairn serve

# Запустить диспетчер
uv run --project cairn cairn dispatch --config dispatch.yaml

В конфиге есть полезные ограничители. max_workers — общий предел числа одновременно работающих воркеров, max_running_projects — сколько проектов допустимо вести параллельно, max_project_workers — защита от того, чтобы один проект занял весь диспетчер, а tasks.reason.max_intents ограничивает, сколько новых намерений может породить один шаг Reason.

Локальный режим без Docker

Отдельный режим запускает воркеров как обычные процессы на машине диспетчера. Они используют уже настроенные и залогиненные CLI-инструменты claude, codex или pi — Docker не нужен, и ключи в конфиге тоже не нужны.

cp dispatch.local.example.yaml dispatch.yaml

uv run --project cairn cairn serve
uv run --project cairn cairn dispatch --config dispatch.yaml

Режим включается параметром runtime.execution: local в dispatch.local.example.yaml. Каждому проекту достаётся отдельный рабочий каталог внутри local.workspace_root.

Важное ограничение: в этом режиме агенты работают с правами вашего пользователя и без песочницы. Диспетчер надо запускать прямо на хосте, а не внутри контейнера, и только в тех окружениях, где у вас есть разрешение на работу.

Результаты

Cairn показал себя на хакатоне Tencent Cloud Hackathon, второе издание, в челлендже по AI-пентестингу. В соревновании участвовали 610 команд и 1345 человек из ведущих университетов и компаний по безопасности.

  • Решено задач: 54 из 54 — единственная команда, взявшая максимум.
  • Итоговое место: 3-е.

Систему до соревнования не тестировали. Полный конвейер подняли впервые в 4 часа ночи в день старта. Без предварительного обучения, без настройки, без профильных инструментов. Ноль MCP-инструментов, ноль RAG, ноль заранее прописанных ролей агентов.

Документация, лицензия и ответственность

Подробная спецификация протокола лежит в docs/specs/server-protocol.md, описание работы диспетчера — в docs/specs/dispatcher-design.md.

Лицензия — GNU AGPLv3, подробности в файле LICENSE. Для коммерческого или закрытого использования автор предлагает отдельную платную лицензию: нужно написать ему напрямую. Отправляя pull request, вы соглашаетесь с тем, что ваш вклад может использоваться и по AGPL-3.0, и по коммерческой лицензии проекта.

Авторы отдельно предупреждают: инструмент предназначен только для тех окружений, где у вас есть явное разрешение на работу. Использовать Cairn против чужих сетей, приложений и данных без разрения владельца незаконно. Ответственность за применение лежит на пользователе.

Источник: https://github.com/oritera/Cairn