
Когда я писал первую статью на Хабр про openLight в марте, проект состоял из одного коммита, одной Raspberry Pi и одного Telegram-бота.
У меня был Pi с Tailscale, маленький Matrix-сервер и несколько сервисов, за которыми хотелось приглядывать. Я устал печатать ssh pi@raspberrypi.local && systemctl status ... с телефона, поэтому написал небольшой Go-бинарь: Telegram-бот, SQLite и локальный Ollama как fallback, если обычный роутер не понимал запрос.
Прошло два месяца. Бинарь всё ещё весит около 25 МБ. Всё ещё один YAML-конфиг. Всё ещё SQLite. Но под капотом почти всё переписано хотя бы один раз.
И главное, изменилось понимание того, чем вообще стал проект.
openLight - это легковесный операционный слой для личных серверов, а не очередной AI-ассистент общего назначения.
В марте я бы так не сформулировал. Чтобы прийти к этому, понадобилось несколько месяцев реального использования, переписываний и откатов назад.
Это ретроспектива о том:
что сработало
что оказалось ошибкой
и почему я всё больше верю в маленькие локальные системы вместо “автономных AI-агентов”
Пять моментов, ради которых всё это

Поздний вечер, я не дома. Synapse упал на VPS. Я нажимаю
Restartпрямо в Telegram. Сервис поднимается. Ноутбук даже не открывал.Очередь в магазине. Tailscale начал сыпать warning’ами. Нажимаю
Logs, вижу знакомую проблему с peer’ом, ставлюIgnoreна 15 минут.Перелёт. Watch-цикл продолжает работать сам. Когда я приземляюсь, в чате уже лежат сообщения
resolved— всё восстановилось без меня.Mac mini дома. На нём Ollama и несколько Docker-сервисов. Watch на CPU > 90% срабатывает из-за моего же фонового джоба, о котором я уже забыл.
Удалённая машина.
/restart matrixс телефона уходит в docker-compose на VPS. Для меня это выглядит так же, как локальная Raspberry Pi.
Вся архитектура ниже существует только потому, что такие сценарии реально происходят.
Что изменилось технически
Роутинг: от плоского к deterministic-first
Изначально роутер был очень простым:
попробовать slash-команду
попробовать regex
если ничего не подошло, то отправить запрос в Ollama
Этого хватает примерно на неделю.
Потом начинаешь замечать:
половина задержки - это запуск модели на Pi
модель иногда выбирает “почти правильный”, но не тот tool
а “не понимаю запрос” и “уверен на 51%, выполняю” - это две очень разные ситуации

Сейчас перед LLM есть несколько полностью детерминированных слоёв:
slash-команды
aliases
нормализация
rule-based parsing
semantic mapping
И только если всё это не сработало, подключается модель.

Скриншот выше, тот же самый skill /status, но без LLM-вызова: русская фраза детерминированно нормализовалась.

skills, watch list, notes против agent.test.yaml.CLI теперь работает через тот же runtime, что и Telegram-бот:
тот же registry
тот же router
тот же auth
те же skill’ы
Это позволило использовать его и для smoke-тестов, и для локальной отладки.
От localhost к SSH-нодам
Первая версия openLight умела работать только с той машиной, на которой была запущена.
Но быстро стало понятно, если у тебя есть VPS, Mac mini, Raspberry Pi и ещё пара коробок, то нужен единый интерфейс. Так появилась идея:
один openLight
много SSH-нод
Нода - это просто именованный SSH-target в конфиге.
Сервис может выглядеть так:
node:vps:compose:/opt/matrix/docker-compose.yml:synapse
Для пользователя это всё ещё просто:
/restart matrix

Но внутри это может быть:
systemd
docker
docker compose
локально
удалённо через SSH
Самое важное, пользователь этого не видит. Есть:
один skill
один allowlist
один audit path
Именно так и должно быть.
От request-response к monitoring loop
Самое большое изменение - система watch’ей. v0.0.1 был полностью реактивным: я что-то спрашивал, агент отвечал. v0.1.0 добавил monitoring loop:
правила
polling
incidents
cooldown’ы
и Telegram-алерты с кнопками
Restart, Logs, Status, Ignore.
Но самая важная часть не в polling’е. А в том, что кнопки используют тот же самый skill path, что и ручные команды. Когда я нажимаю Restart в alert’е, вызывается тот же service_restart, что и при обычной команде.
тот же allowlist
тот же audit
тот же logging path
Нет отдельного “режима автоматизации”.

Наверное, это решение нравится мне больше всего. И оно почти противоположно тому, куда движется большая часть AI-agent tooling. Сейчас популярная идея:
дать модели shell
дать sandbox
дать autonomy
и надеяться на лучшее
Но для инфраструктуры это выглядит опасно. Инфраструктуре нужен не “автономный агент”. Ей нужен понятный, проверяемый execution path. Автоматизация - это кнопка поверх уже существующего безопасного механизма, а не отдельный уровень привилегий.
Что изменилось стратегически
Skill’ы — единственная настоящая граница безопасности
В ранних версиях у меня был mutating_execute_threshold - порог уверенности для действий, которые меняют состояние. Потом я понял, что это неправильная модель. Правильная модель гораздо проще:
LLM может выбирать только из уже существующих skill’ов, а сами skill’ы обеспечивают безопасность на уровне Go-кода.
Либо функция существует и проходит allowlist-проверки. Либо нет. Модель - это классификатор намерения, а не носитель привилегий.
Core vs Optional
В какой-то момент я заметил странную вещь. Каждый раз, когда я добавлял:
vision,
browser,
voice,
OCR,
мне хотелось включить это по умолчанию. Потому что демо выглядит круто. А потом через пару недель я дебажил:
память,
Playwright,
лишние зависимости,
latency,
и весь тот “AI assistant creep”, которого изначально хотел избежать.
Поэтому сейчас в проекте есть чёткое разделение:
core modules,
optional modules.
Если убрать optional-модули, то openLight всё ещё останется openLight. Если убрать core, то проект потеряет идентичность.

Один и тот же реестр виден LLM-классификатору и в ответе на пользовательский /skills. Никакой параллельной поверхности нет.
От Raspberry Pi к personal infrastructure
Где-то на третьем или четвёртом крупном рефакторе я понял, что openLight уже не про Raspberry Pi. Pi был просто самой маленькой машиной, которая оказалась под рукой. На самом деле меня начала интересовать другая категория:
маленькие always-on компьютеры
локальные серверы
Mac mini
старые ThinkPad
NUC
Raspberry Pi
домашние ARM-машины
Все они живут в странном промежутке:
это уже не ноутбук
но ещё и не “облако”
Для них плохо подходит mainstream tooling. Kubernetes здесь почти всегда избыточен. Datadog - тоже. Большие AI-agent frameworks - тем более. Этим машинам нужен:
маленький
понятный
дешёвый
repairable слой управления
Mac mini особенно сильно изменил моё восприятие проекта. M1 спокойно тянет:
Ollama
несколько Docker-сервисов
monitoring
Telegram-agent
и при этом потребляет смешное количество энергии
В какой-то момент openLight перестал быть “ботом для Raspberry Pi”. Он стал агентом для personal infrastructure, который просто использует Telegram как интерфейс. И мне кажется, что в ближайшие годы вокруг этой категории появится очень много интересного софта.
Что оказалось ошибкой
Фрейминг “альтернатива OpenClaw”
В первых README я слишком сильно определял проект через: “мы не такие как X” Это плохая идея. Во-первых, если человек не знает OpenClaw, ему всё равно. Во-вторых, решения начинают приниматься “от противного”: “они делают так, значит мы должны наоборот”. Это не архитектурный принцип.
“Structured tool calling” в раннем roadmap
Тогда мне казалось, что проблема решается более сложным tool-calling. Сейчас я думаю наоборот: проблема решается более сильным deterministic routing. Большая часть запросов вообще не должна доходить до LLM.
Полный registry в prompt
Ранний classifier видел:
все skill’ы
все описания
весь registry
Это:
раздувало prompt
замедляло routing
и ухудшало качество
Двухстадийная классификация решила проблему:
сначала только группы
потом только skill’ы внутри группы
LLM input budget - это тоже архитектурное ограничение.
Что подтвердилось практикой
Telegram - отличный интерфейс для homelab
Я пробовал:
Slack
web UI
dashboard’ы
Но всё проигрывало сценарию:
“я не дома, сервис упал, достал телефон, нажал Restart”.
SQLite хватает
Watch’и
Incidents
History
Settings
Skill calls
Всё живёт в одном SQLite-файле. Backup - это literally cp. И мне это нравится.
Один Go-бинарь — правильная форма
Без:
Redis,
Postgres,
service mesh,
Helm,
runtime dependency zoo.
scp + systemd/launchd - и всё работает.
Локальные LLM уже достаточно хороши
Qwen 0.5B на Raspberry Pi хватает для routing/classification. Мне не нужен GPT-4, чтобы понять:
“что там сломалось?”
Модель здесь не “думает”. Она помогает выбрать intent. И маленькие модели surprisingly хороши в этом.
Почему мне кажется, что это направление важно
Сейчас вся AI-индустрия движется в сторону:
огромных cloud-agent systems
autonomous workflows
giant tool ecosystems
generalized assistants
Но чем дольше я работаю над openLight, тем сильнее мне кажется:
самая полезная AI-инфраструктура ближайших лет будет не гигантской, а маленькой.
Не cloud-first. А local-first.
Не “autonomous”. А deterministic by default.
Не opaque. А observable.
Не “умной”. А repairable.
openLight - это очень маленький проект. Но для меня он стал способом исследовать именно эту идею. Он не пытается заменить инженера. Он пытается уменьшить трение между инженером и теми маленькими системами, которыми этот инженер уже управляет.
Код лежит на github.com/evgenii-engineer/openLight.
Если у тебя дома есть:
Raspberry Pi
Mac mini
VPS
homelab
или просто несколько always-on машин
возможно, openLight тебе пригодится.
