Не система склеенных частей, а одна сущность: один мозг, четыре контура памяти, руки-инструменты, внутренний цикл воли и автономный демон. Только стандартная библиотека Python 3.10+ — ноль внешних зависимостей.
┌──────────────────────────────────────────────────────────────┐
│ СЛОЙ 4 · ВОЛЯ run_daemon(): очередь задач → solve() │
├──────────────────────────────────────────────────────────────┤
│ СЛОЙ 3 · ПАМЯТЬ рабочая | эпизодическая | семантическая│
│ | процедурная (SQLite + FTS5) │
├──────────────────────────────────────────────────────────────┤
│ СЛОЙ 2 · РУКИ реестр @tool: read/write/list/exec/ │
│ web_search/remember/recall │
├──────────────────────────────────────────────────────────────┤
│ СЛОЙ 1 · ЦИКЛ solve(): АНАЛИЗ→ПЛАН→ДЕЙСТВИЕ→РЕФЛ. │
│ JSON-протокол, бюджет шагов, ремонт │
├──────────────────────────────────────────────────────────────┤
│ СЛОЙ 0 · МОЗГ LLMCore (модель-агностик, OpenAI API) │
└──────────────────────────────────────────────────────────────┘
# 1. Ядро — любой OpenAI-совместимый рантайм
export UA_LLM_BASE_URL="http://localhost:11434/v1" # Ollama
export UA_LLM_MODEL="qwen3:30b-a3b"
# 2. Разовая задача
python universal_agent.py task --task "Изучи каталог workspace и напиши инвентаризацию"
# 3. Автономная жизнь (демон воли)
python universal_agent.py daemon &
echo "Найди в workspace все TODO и сведи в список" >> task_queue.txtПоддержанные рантаймы (диалект один и тот же):
| Рантайм | UA_LLM_BASE_URL |
|---|---|
| Ollama | http://localhost:11434/v1 |
| vLLM | http://localhost:8000/v1 |
| LM Studio | http://localhost:1234/v1 |
| Облако | URL провайдера + UA_LLM_API_KEY |
Смена мозга — две переменные окружения. Тело агента не меняется.
# из исходников (ноль зависимостей)
pip install -e .
universal-agent task --task "текст задачи" # точка входа из pyproject
# или Docker (изолированный non-root рантайм)
docker build -t universal-agent .
docker run --rm universal-agent task --task "текст задачи"Инструменты разработчика:
| Команда | Действие |
|---|---|
make verify |
канон: check.py (компиляция + тесты + гигиена + манифест) |
make test |
unittest-набор подробно |
make lint |
ruff check |
make manifest |
пересборка release/manifest_sha256.txt |
make run TASK="..." |
разовая задача |
make daemon |
автономная жизнь |
| Переменная | По умолчанию | Смысл |
|---|---|---|
UA_LLM_BASE_URL |
http://localhost:11434/v1 |
адрес мозга |
UA_LLM_MODEL |
qwen3:30b-a3b |
имя модели |
UA_LLM_API_KEY |
ollama |
ключ (для облаков) |
UA_MAX_STEPS |
12 |
бюджет шагов на задачу |
UA_MAX_OBSERVATION_CHARS |
4000 |
усечение наблюдений |
UA_RECALL_TOP_K |
6 |
воспоминаний на задачу |
UA_MEMORY_HALFLIFE_DAYS |
14.0 |
полураспад новизны |
UA_EXEC_TIMEOUT_SEC |
60 |
потолок времени кода |
UA_EXEC_CPU_SEC |
10 |
RLIMIT_CPU |
UA_EXEC_MEM_MB |
512 |
RLIMIT_AS |
UA_EXEC_NET_ISOLATE |
false |
unshare -n (нужны namespaces) |
UA_DAEMON_POLL_SEC |
5 |
такт демона |
UA_QUEUE_PATH |
./task_queue.txt |
очередь воли |
UA_WORKSPACE_ROOT |
./workspace |
рабочее тело |
UA_MEMORY_DB |
./memory/agent.db |
эпизоды + индекс |
UA_KNOWLEDGE_DIR |
./knowledge |
карточки уроков |
UA_RESULTS_LOG |
./results.log |
итоговый журнал |
Каждый ход агента — строго JSON (ReAct-дисциплина):
{"thought": "краткая мысль шага",
"action": {"name": "execute_python", "params": {"code": "print(2+2)"}}}Завершение — инструмент finish с финальным отчётом. Нарушение формата не
валит цикл: парсер ремонтирует ограждения/обвязку, при полном провале агент
получает «НАРУШЕНИЕ ПРОТОКОЛА» и повторяет ход. Ошибка любого инструмента —
наблюдение, а не крах: мозг видит текст ошибки и корректирует план.
| Контур | Реализация |
|---|---|
| Рабочая | история сообщений с усечением наблюдений |
| Эпизодическая | таблица events (задачи, действия, наблюдения, отчёты) |
| Семантическая | FTS5-индекс (фолбэк — LIKE-режим) + knowledge/*.md |
| Процедурная | дистилляция уроков после каждой задачи |
Выборка — гибридный скоринг (Park et al., 2023 / кривая Эббингауза):
score = (1/(1+позиция_BM25)) × ( exp(−возраст/полураспад) + значимость )
Ничего не удаляется никогда — меняется лишь вес доходимости. После завершения
задачи мозг отвечает себе, пригодится ли техника другим задачам; если да —
карточка урока пишется в knowledge/ и индексируется с значимостью 0.95.
execute_python ограничен: RLIMIT_CPU, RLIMIT_AS, потолок времени,
убийство всей группы процессов по таймауту, cwd = workspace, отсечение
параметров вне схемы. Опционально UA_EXEC_NET_ISOLATE=true добавляет
unshare -n (сетевая изоляция, нужны user namespaces).
Контейнерная песочница (фаза II, «Крепость»): UA_EXEC_DOCKER=1
поднимает границу на уровне ядра — каждый вызов исполняется в отдельном
контейнере с --network none (сеть отрезана), cgroup-лимитами
(UA_EXEC_MEM_MB → --memory, UA_EXEC_DOCKER_CPUS → --cpus,
UA_EXEC_DOCKER_PIDS → --pids-limit, swap-побег закрыт),
--read-only корнем ФС, сбросом capabilities (--cap-drop ALL),
запретом повышения привилегий и не-root пользователем; workspace
монтируется внутрь, по таймауту контейнер снимается docker kill.
Образ задаётся UA_EXEC_DOCKER_IMAGE (по умолчанию python:3.12-alpine).
Если docker недоступен — автоматический откат на локальные RLIMIT-лимиты
с пометкой в наблюдении; агент не останавливается.
Честное предупреждение: RLIMIT-песочница — не жёсткая граница безопасности.
Для враждебного ввода включайте UA_EXEC_DOCKER=1; ещё жёстче — gVisor/nsjail
поверх данного каркаса.
python -m unittest discover -s tests -vПокрыто: экстрактор JSON и приведение типов; память (BM25-ранжирование, новизна, значимость, LIKE-фолбэк); границы workspace и дисциплина dispatch; файловые руки и песочница (stdout/exit, syntax error, TIMEOUT, RLIMIT_AS); контейнерная песочница на фейковом docker CLI (жёсткость флагов, видимость workspace, снятие по таймауту, откат при недоступном docker, конфиг из env); A2A Agent Card (валидность, версия с pyproject, зелёный healthcheck, красный при расхождении); три сквозных сценария (полный цикл с консолидацией урока, ремонт протокола, честный частичный итог при исчерпании бюджета).
agent-card.json — манифест агента по спецификации A2A (protocolVersion 1.0):
identity, capabilities, шесть навыков, каждый из которых — реальное поведение
тела (руки _TOOLBOX, режимы CLI task/daemon).
make health # rc=0 — карточка честна; rc=2 — расхождение = красныйЧто сверяется (честность вслух): обязательные поля и типы схемы A2A v1.0;
version карточки == pyproject.toml; каждый навык ↔ существующие руки
(объявил несуществующую руку или скрыл живую — красный); режимы CLI существуют;
streaming/pushNotifications = false — потому что их правда нет. При заданном
AGENT_HEALTH_URL карточка скачивается с {URL}/.well-known/agent-card.json
и сверяется с объявленной — живое расхождение = красный.
scripts/check.py— верификатор канона: компиляция, тесты, скан секретов, сходимостьrelease/manifest_sha256.txt, комплектность. Строка# Result:— пропуск на пуш.- Conventional Commits + DCO (
git commit -s), PR = 24ч → squash (см. CONTRIBUTING.md). make manifest— SHA-256-манифест ключевых файлов релиза.
- Фаза I — Жизнь: подключить реальный рантайм, 10 бытовых задач, ≥8/10 до finish.
- Фаза II — Крепость: ✅ docker-песочница (
UA_EXEC_DOCKER=1); далее — failover-ядро, полноценный поисковый API. - Фаза III — Глубина памяти: эмбеддинги + sqlite-vec поверх FTS5, ночная консолидация (схлопывание дублирующихся уроков).
- Фаза IV — Метапознание: телеметрия сбоев, самоограничения в
knowledge/constraints.md, интерфейсы воли (Telegram/CLI/Web).
git init && git add . && git commit -m "ЦУА v2.1"
git remote add origin git@github.com:you/universal-agent.git
git push -u origin mainНикогда не кладите токены и ключи в файлы репозитория и в файлы задач —
ключи живут только в переменных окружения (UA_LLM_API_KEY, деплой-секреты).
Утёкший в текст/чат ключ считается скомпрометированным: отзыв немедленно.

