Luminarys AI
Luminarys AI

Модульная платформа для запуска AI-агентов, где каждый навык работает в WebAssembly-песочнице, агенты масштабируются на кластер из разнородных машин, а навыки пишутся на Go, Rust или AssemblyScript.

Привет, Хабр.

Последние полгода мы работаем с AI-агентами в продакшене и раз за разом сталкиваемся с одними и теми же архитектурными ограничениями. Инструменты либо получают полный доступ к системе, либо вынуждают постоянно подтверждать каждое действие вручную — гранулярные правила в конфигах помогают, но не дают рантаймовой изоляции: навык всё равно физически способен выйти за заявленные границы, если код написан неправильно. Масштабирование на гетерогенные машины — x86, ARM, IoT, edge — остаётся нерешённой задачей: существующие инструменты параллелят агентов внутри одного репозитория, но не умеют маршрутизировать вызовы к нодам на разных архитектурах. А скиллы и плагины привязаны к одному языку платформы — нет способа написать один навык на Rust для производительности, другой на TypeScript для удобства, и запустить их рядом в одном хосте. Мы решили решить эти проблемы на архитектурном уровне.

Готовых решений на архитектурном уровне мы не нашли — и решили построить платформу с нуля. Назвали её Luminarys AI. В этой статье расскажу, что она умеет и какие задачи закрывает.

Проблема первая: навык делает что хочет

В большинстве агентских фреймворков tool — это функция с полным доступом к системе. Хочет — читает любой файл, хочет — ходит на произвольный URL, хочет — выполняет команды. Единственная защита — ручное подтверждение каждого действия. LLM комбинирует команды, формирует новые аргументы — и пользователь вынужден снова и снова выдавать разрешения, не всегда понимая, что именно он разрешает. Автономная работа при такой модели невозможна.

Это работает в прототипах. В продакшене — нет.

Наше решение: каждый навык компилируется в WebAssembly и выполняется в изолированной песочнице. Он физически не может выйти за пределы разрешений, объявленных в его конфигурации. Хочет HTTP? Только URL из белого списка. Хочет файлы? Только в указанных директориях. Хочет выполнить команду? Только из разрешённого набора, без возможности объединять команды в цепочки.

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

# Пример: навык для работы с оборудованием
id: hardware-monitor
permissions:
  fs:
    enabled: true
    dirs:
      - "/sys/class:ro"               # чтение sysfs (датчики, устройства)
      - "/dev/serial:rw"              # доступ к serial-портам
  shell:
    enabled: true
    allowlist:
      - "lsusb **"                    # только перечисленные команды
      - "i2cget **"
      - "cat /proc/cpuinfo"
    allowed_dirs:
      - "/tmp/hw-monitor"

Навык для мониторинга температуры CPU видит только /sys/class/thermal. Навык для управления GPIO на Raspberry Pi — только /sys/class/gpio. Навык для чтения I2C-датчиков — только i2cget. Каждый получает ровно тот доступ, который ему нужен — и ни байтом больше.

При загрузке навыка платформа проверяет, что его код соответствует объявленным требованиям. Если навык запрашивает доступ к ресурсу, которого нет в конфигурации — он просто не загрузится.

Проблема вторая: один язык для всех навыков

Есть задачи, с которыми LLM не справится сама: парсинг бинарных форматов (protobuf, PCAP, ELF), OCR и распознавание документов, точные математические и инженерные вычисления, работа с AST исходного кода, ML-inference на специализированных моделях. Для каждой такой задачи разработчикам приходится создавать отдельный MCP-сервер — со своим процессом, конфигурацией, деплоем.

Мы предлагаем другой подход: платформа — это конструктор, где каждая такая задача решается навыком. Навыки устанавливаются из магазина (в разработке) или пишутся с нуля за минимальное время с помощью SDK. Один хост, один процесс, любое количество навыков на разных языках.

Наше решение: навыки можно писать на разных языках. Сейчас поддерживаются Go, Rust и AssemblyScript. Планируются C/C++ и другие языки.

Каждый SDK подходит для своих задач:

  • AssemblyScript — лучший выбор для большинства навыков. Компактные модули (~100 KB), знакомый TypeScript-синтаксис, быстрая компиляция. Идеален для файловых операций, HTTP, работы с текстом.

  • Rust — для навыков, требующих максимальной производительности или подключения нативных библиотек. Парсинг бинарных протоколов, ML-inference (ONNX), AST-анализ через tree-sitter.

  • Go — когда нужна богатая стандартная библиотека Go или встраивание скриптовых языков (JavaScript VM, Python engine).

Разработчик пишет только бизнес-логику с аннотациями. Кодогенератор создаёт весь служебный код — маршрутизацию методов, сериализацию, валидацию параметров:

# Разработчик пишет один файл:
skill.go    (или skill.rs, или skill.ts)

# Кодогенератор создаёт:
lmsk generate -lang go .

# Результат:
skill.wasm  → подписывается → skill.skill — готовый модуль

Один и тот же хост загружает навыки на разных языках одновременно — они работают рядом, вызывают друг друга, делят состояние.

Пример навыка: Go

// @skill:id      ai.example.hello
// @skill:name    "Hello Skill"
// @skill:version 1.0.0
// @skill:desc    "Simple greeting skill."
package main

import sdk "github.com/LuminarysAI/sdk-go"

// @skill:method greet "Return a greeting."
// @skill:param  name required "Person name"
// @skill:result "Greeting string"
func Greet(_ *sdk.Context, name string) (string, error) {
    return "Hello, " + name + "!", nil
}

Пример навыка: Rust

/// @skill:id      ai.example.hello
/// @skill:name    "Hello Skill"
/// @skill:version 1.0.0
/// @skill:desc    "Simple greeting skill."

use luminarys_sdk::prelude::*;

/// @skill:method greet "Return a greeting."
/// @skill:param  name required "Person name"
/// @skill:result "Greeting string"
pub fn greet(_ctx: &mut Context, name: String) -> Result<String, SkillError> {
    Ok(format!("Hello, {}!", name))
}

Пример навыка: AssemblyScript

/**
 * @skill:id      ai.example.hello
 * @skill:name    "Hello Skill"
 * @skill:version 1.0.0
 * @skill:desc    "Simple greeting skill."
 */
import { Context } from "@luminarys/sdk-as";

// @skill:method greet "Return a greeting."
// @skill:param  name required "Person name"
// @skill:result "Greeting string"
export function greet(_ctx: Context, name: string): string {
  return "Hello, " + name + "!";
}

Аннотации одинаковы во всех языках — @skill:method, @skill:param, @skill:result. Кодогенератор lmsk парсит их и генерирует dispatch-код, описание для MCP, валидацию параметров.

А для любителей вайбкодинга — в каждом SDK лежит AGENTS.md с полным описанием API на нужном языке. Скормите его вашему любимому AI-ассистенту, и он напишет навык за вас. Мы проверяли — справляется.

Проблема третья: один сервер, одна машина

Типичный AI-агент работает на одной машине. Нужно отлаживать код на ARM? Запускать на edge-устройствах? Мониторить парк IoT? Один сервер не справится.

Наше решение: встроенная кластеризация. Master-нода принимает подключения клиентов, slave-ноды выполняют навыки. Навыки не знают, что работают в кластере — для них всё выглядит локально. Платформа сама маршрутизирует вызовы к нужной ноде.

Luminarys Cluster
Luminarys Cluster

Реальные сценарии:

  • CI/CD: агент запускает тесты на Linux-slave, собирает Windows-бинарник на Windows-slave, результаты собирает master

  • Работа с оборудованием: slave на Raspberry Pi читает I2C-датчики, slave на Jetson Nano обрабатывает видео с камеры, slave на x86-сервере управляет промышленным контроллером через serial-порт — для агента это единый набор инструментов

  • IoT-парк: master в облаке, десятки slave на edge-устройствах. Каждый slave предоставляет навыки для своего оборудования — GPIO, SPI, UART, USB. Агент видит весь парк как одну систему

  • Мониторинг инфраструктуры: навыки для чтения sysfs, SMART-данных дисков, температуры CPU/GPU, состояния сети — каждый в своей песочнице с минимальными правами

  • Гетерогенные архитектуры: x86, ARM, RISC-V, MIPS — slave на любой платформе, master объединяет всё в единое пространство навыков

При отключении slave нода уведомляет кластер, master мгновенно обновляет список доступных инструментов для подключённых клиентов. При рестарте master — slaves автоматически переподключаются и перерегистрируют свои навыки.

Между нодами работает передача файлов через встроенный relay-сервер с аутентификацией, шифрованием и проверкой целостности.

Проблема четвёртая: одна модель на все задачи

GPT-4 отлично генерирует текст, но для кода лучше подойдёт специализированная модель. Для SQL — модель, обученная на схемах БД. Для Rust — модель, знающая borrow checker.

Наше решение (в разработке): мульти-LLM роутинг. Платформа автоматически выбирает модель по типу задачи, языку программирования и проекту. Навыки не знают, какая модель работает — они запрашивают «сгенерируй код», а платформа решает, кого спросить.

Конфигурация моделей — в одном файле, без рестарта:

models:
  code_default: "deepseek-coder"
  language_overrides:
    rust: "rust-specialist"
    sql:  "sql-specialist"
  general: "claude-sonnet"

Совместимость: MCP

Платформа говорит на Model Context Protocol — открытом стандарте от Anthropic. Это значит:

  • Claude Desktop, Claude Code, Cursor, Qwen Code — подключаются из коробки

  • MCP Inspector работает для отладки

  • Любой MCP-совместимый клиент видит навыки как инструменты

  • Поддерживаются все транспорты: Streamable HTTP (/mcp), Legacy SSE (/sse), stdio

  • Для Open WebUI и подобных систем доступен OpenAPI-эндпоинт (/openapi.json)

Не нужно писать адаптеры — стандартный протокол, стандартные инструменты.

Агентский режим (в разработке)

Мы проектируем агентскую систему с учётом реальных рабочих нагрузок, а не только интерактивного диалога «вопрос → один инструмент → ответ».

Батчевое выполнение

Агент может вызывать несколько инструментов за один шаг — синхронно или асинхронно:

  • Синхронный батч: «прочитай три файла и верни результат когда все готовы». Платформа выполняет вызовы параллельно, собирает результаты и возвращает их агенту одним пакетом.

  • Асинхронный батч: «запусти сборку на трёх нодах, мне не нужно ждать». Платформа запускает вызовы в фоне, агент продолжает работу. Результаты возвращаются по мере готовности.

Автономный режим

Платформа поддерживает callback-модель: навык регистрирует обработчик на событие (входящие данные из сети, таймер, сообщение от другого навыка, сигнал от оборудования), и платформа вызывает его когда событие наступает.

Это позволяет строить автономных агентов, которые:

  • Следят за состоянием оборудования и инфраструктуры в реальном времени

  • Реагируют на данные с датчиков и внешних устройств

  • Обрабатывают входящие сообщения (WebSocket, TCP, serial, MQTT через навык)

  • Запускают цепочки действий при наступлении условий

Навыки при этом остаются в песочнице — callback не даёт навыку больше прав, чем объявлено в его конфигурации.

Межнавыковое взаимодействие

Навык может вызвать другой навык — через оркестратор, с проверкой политик. Цепочки вызовов контролируются: глубина ограничена, тайм-ауты применяются на всю цепочку, циклы детектируются.

Безопасность

Безопасность заложена на уровне архитектуры, а не добавлена поверх. Каждый навык работает в WebAssembly-песочнице и не может выйти за пределы объявленных разрешений — доступ к файлам, URL, shell-командам контролируется рантаймом, а не кодом навыка. Shell-команды проверяются на цепочки, пайпы и перенаправления — LLM не сможет собрать опасную конструкцию, даже если попытается. Сетевое взаимодействие поддерживает TLS и аутентификацию. В планах — подпись пакетов навыков для верификации автора при установке из магазина.

Текущее состояние и что дальше

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

Рантайм и инфраструктура — WebAssembly-песочница, 30+ системных функций (файлы, HTTP, TCP, WebSocket, shell, архивы, системная информация, LLM-контекст), MCP-сервер (Streamable HTTP, SSE, stdio), кластеризация через NATS, передача файлов между нодами, авторизация, сборка под Linux, Windows и macOS.

SDK — три языка с полной реализацией: Go, Rust, AssemblyScript. Все три опубликованы и доступны через стандартные менеджеры пакетов. C/C++ SDK — в планах.

Примеры навыков — 15+ навыков на трёх языках. От стандартных (файловая система, git, HTTP, архивирование) до продвинутых: Python Engine (встроенный RustPython), JavaScript Engine (встроенный Goja), Tree-sitter (AST-парсинг на 10+ языках), Intent Classifier (ONNX-модель для классификации намерений). Все доступны в skill-examples.

В разработке:

  • Полноценный агентский цикл — батчевое выполнение, автономный режим, callback’и

  • Мульти-LLM роутинг — автоматический выбор модели под задачу

  • Магазин навыков — marketplace с подписью пакетов и версионированием

  • Интеграция с IDE через Agent Client Protocol

  • Мульти-агентный режим с профилями доступа

  • C/C++ SDK

Попробовать

Мы подготовили demo-кластер, который запускается одной командой через Docker Compose. Два узла (master + slave), 10 навыков, готовое задание для AI-агента:

git clone https://github.com/LuminarysAI/mcp-demo-cluster.git
cd mcp-demo-cluster
docker compose up -d

После старта подключите MCP-клиент (Claude Code, Cursor, Qwen CLI — конфиги уже включены в репозиторий) и дайте агенту задание из task/task.md. Агент самостоятельно напишет Go-приложение на slave-ноде, соберёт, протестирует, проверит эндпоинты с master-ноды и доставит архив с результатом на хост-машину.

SDK, примеры навыков и demo-кластер — на GitHub, документация — на luminarys.ai.

Где мы это применяем

Сейчас мы используем платформу для задач, где LLM-агент работает с большими объёмами данных, не помещающимися в контекст. Типичный сценарий: парсинг корпоративной документации (docx, PDF), формирование структурированного технического задания для LLM, выполнение и тестирование этого задания в изолированном окружении (slave-нода в Docker-контейнере со своим стеком — Go, Node.js, Python — без необходимости устанавливать что-либо на хост), сборка результатов в архив и доставка на master. Каждый этап — отдельный навык в песочнице, каждый — на нужной ноде.

Но архитектура не привязана к этому сценарию. Те же механизмы работают для автоматизации разработки (агент пишет код, запускает тесты, управляет Git), IoT (кластер на edge-устройствах), мониторинга инфраструктуры (навыки для sysfs, SMART, температуры), CI/CD (сборка на разных платформах), enterprise-автоматизации (оффлайн, собственные LLM, контроль данных).

Если вы строите AI-агентов и вам важна изоляция, масштабирование или мультиязычность — попробуйте. SDK открыт, demo запускается за минуту.

Итого

Мы решаем проблемы, с которыми сталкиваются разработчики AI-агентов: изоляция навыков, мультиязычность, масштабирование на несколько машин — уже работают. Мульти-LLM роутинг, магазин навыков, агентский цикл — в активной разработке.

Проект на стадии разработки. SDK открыт, demo доступен. Будем рады обратной связи — пишите в комментариях или на contacts@luminarys.ai.