В марте я уже выкладывал материал про свой ранний проект — AAF (Autonomous Agent Framework). Это был базовый эксперимент, на котором я обкатывал концепции локального контекста и вызова инструментов. За прошедшие месяцы я переписал архитектуру с нуля, учтя накопленный опыт, и сформировал новый фреймворк — JAWL (Just A While Loop).
Если посмотреть на актуальный ландшафт опенсорсных автономных агентов, выделяются два интересных проекта: OpenClaw (созданный Питером Штайнбергером) и Hermes Agent (от Nous Research).
-
OpenClaw — это готовое локальное приложение-ассистент на Node.js. Оно выступает гейтвеем между мессенджерами и вашим ПК, закрывая вопросы привязки сессий (Pairing) и авторизации пользователей. Но это монолитный пользовательский софт, который, к тому же, часто страдает от проблем с безопасностью.
-
Hermes Agent — продвинутый ассистент на Python с механизмом самообучения и формированием профиля пользователя. Однако его память базируется преимущественно на логах сессий и плоском векторном поиске, без жесткой реляционной структуры и графов знаний.
JAWL решает задачу с точки зрения системной инженерии на Python. Это полностью асинхронный фреймворк, работающий через механизм Event-Driven ReAct Loop, предоставляющий агенту гибридную векторно-графовую память Vector-Graph RAG, дедукцию по теореме Байеса, делегирование задач фоновым воркерам и транзакционную самомодификацию кода с автоматическим откатом.
🏗 Архитектура слоев (L0 — L3)
Система спроектирована с четким разграничением ответственности по слоям (SOLID):
┌─────────────────────────────────────────────────────────────┐│ 🔴 L3: AGENT CORE (ReAct Loop, Heartbeat, LLM Executor) │└──────────────────────────────┬──────────────────────────────┘ │ (вызовы инструментов + сбор контекста)┌──────────────────────────────▼──────────────────────────────┐│ 🟠 L2: INTERFACES (Host OS, Telegram, GitHub, Web, Voice) │└──────────────────────────────┬──────────────────────────────┘ │ (пассивные хранилища данных)┌──────────────────────────────▼──────────────────────────────┐│ 🟢 L0: STATE LAYER (Пассивные кэши интерфейсов) │└──────────────────────────────┬──────────────────────────────┘ │ (Долгосрочная память)┌──────────────────────────────▼──────────────────────────────┐│ 🟡 L1: DATABASES (SQLite + Qdrant + KuzuDB) │└─────────────────────────────────────────────────────────────┘
-
L0 State: Пассивный кэш данных. Они хранят “снимки состояния” интерфейсов (сообщения, метрики хост-ПК, открытые файлы) в памяти. Задумка L0: стейты не выполняют I/O операций при каждой сборке промпта, что устраняет задержки на сетевые запросы при каждом запросе к модели.
-
L1 Databases Layer: Гибридная память.
-
SQL DB (SQLite): Матрица Эйзенхауэра для рабочих задач, гипотезы Байеса, встроенные математические мотиваторы, заметки и CRM субъектов.
-
Vector DB (Qdrant + FastEmbed): Семантическая память: Knowledge (знания) и Thoughts (фоновая рефлексия).
-
Graph DB (KuzuDB): Граф знаний и граф навигации по кодовой базе (Code Graph).
-
-
L2 Interfaces Layer: Изолированные плагины взаимодействия с внешним миром (Host OS, Telegram, GitHub, Email, Web, Voice, Calendar и др.). Собираются динамически через паттерн Plugin Discovery.
-
L3 Agent Layer: Вся высокоуровневая логика (
ReactLoop,Heartbeat,LLMExecutorс ротацией ключей,SwarmManager,SubconsciousOrchestrator).
⚡ Событийно-управляемый Heartbeat
Агент в JAWL, как и во многих других фреймворках, крутится в ReAct цикле. Для того, чтобы уменьшить затраты на запросы к модели, я написал локальный Event Bus, который менеджерит просыпания модели. Все L2-интерфейсы подключены к единой асинхронной шине событий (EventBus). Каждое входящее событие имеет свой уровень приоритета (от BACKGROUND и LOW до CRITICAL). Heartbeat на лету умножает оставшееся время сна на коэффициент ускорения:
Если поступает событие уровня CRITICAL (например, прямое сообщение от пользователя или вебхук), коэффициент равен 0.0 — остаток времени мгновенно обнуляется, и агент просыпается без задержки.
[Сон Heartbeat: 600 сек] │ Входящий ивент (MEDIUM, x0.6) │ [Сон сокращен: 360 сек] │ Входящий ивент (CRITICAL, x0.0) │ ⚡ МОМЕНТАЛЬНЫЙ ВЫЗОВ
🧠 Гибридный Vector-Graph RAG
Векторный поиск отлично ищет похожие по смыслу фрагменты текста, но не способен отслеживать жесткие логические цепочки. Графовая база (KuzuDB) хранит причинно-следственные связи и структуры.
В JAWL реализован гибридный поиск:
-
Из текста вызова извлекаются ключевые сущности.
-
Параллельно запрашиваются векторы из Qdrant и связанные узлы из KuzuDB.
-
Кросс-резолвинг: Найденный векторный факт проверяет наличие своих узлов в графе и подтягивает их соседние связи. И наоборот — текстовые описания найденных графовых узлов отправляются в новый векторный поиск.
Для корректной работы с русским языком и падежами в систему встроен поиск сущностей на базе RapidFuzz и алгоритма Ахо-Корасик FlashText.
🐝 Оркестрация субагентами
Выполнять тяжелые и рутинные задачи (парсинг 20 сайтов, глубокий рефакторинг кода) именно основной, дорогой моделью давно стало признаком плохого распределения токенов. В JAWL, как и в некоторых других агентских фреймворках главный агент выступает в роли оркестратора. Он формулирует ТЗ и спавнит фоновых субагентов со специализированными ролями (CODER, WEB_RESEARCHER, ARCHIVIST, QA_ENGINEER, SYSADMIN):
┌────────────────────────┐ │ Main Agent │ └───────────┬────────────┘ │ Делегирование рутины ┌─────────┼─────────┐ ▼ ▼ ▼ │ Subagents │ │ │ │ └─────────┴─────────┘ │ Отформатированные Markdown репорты ▼ [SUBAGENT_TASK_COMPLETED] -> Пробуждение главного агента
Субагенты работают в изолированных Stateless ReAct циклах на более дешевых и быстрых моделях (например, Gemini 3.5 Flash Lite). Они не имеют доступа к основной памяти и возвращают результат в виде итогового Markdown-отчета. Нагрузка на API регулируется через asyncio.Semaphore.
🛡 Безопасная самомодификация
При наличии уровня доступа OPERATOR агент имеет право модифицировать исходный код самого фреймворка. Чтобы защитить систему от падения в незапускаемое состояние, внедрен механизм под названием Deploy Sessions:
-
Перед правками агент открывает деплой-сессию.
-
Система создает транзакционный Copy-on-Write бэкап всех изменяемых файлов и ведут манифест новых файлов.
-
При коммите сессии принудительно запускаются синтаксический анализатор
compileallи набор тестовpytest. -
Если тесты провалены, агент получает Traceback ошибки и списывает одну попытку.
-
Если лимит попыток исчерпан, система автоматически выполняет Rollback — восстанавливает исходные файлы из бэкапа и удаляет части нерабочего кода.
🚀 Заключение
Фреймворк распространяется под лицензией MIT. Исходный код, архитектурные схемы и документация доступны на GitHub:
👉 GitHub: https://github.com/th0r3nt/JAWL
Буду рад отзывам и пулл-реквестам в репозитории.
ссылка на оригинал статьи https://habr.com/ru/articles/1079990/