🤖 AI-агенты для бизнеса

14. Внутренности ядра

⚫ Документ для тех, кто пишет или меняет сам код ядра. Полная спецификация — в SPEC.md (англ., источник истины); здесь — краткая карта. Семантика — из исходников agent_os_core.


14.1 Модель

Ядро — это один async-рантайм (Tokio) с событийным циклом, который:

  1. хранит таблицу процессов (DashMap<Pid, AgentProcess>);
  2. каждый тик зовёт планировщик (schedule() → ScheduleDecision);
  3. диспатчит ходы (run_turn(pid)), вызывая провайдера и выполняя цикл tool-call'ов;
  4. ограничивает ресурсы (бюджеты, группы, лимит конкурентности) до диспатча;
  5. маршрутизирует IPC;
  6. посредничает в каждом tool-вызове;
  7. эмитит события слушателям;
  8. управляет сессиями (SessionRegistry).

Ядро держит опциональные сервисные ручки, подключаемые один раз при загрузке хостом (message_store, state_store, cron_service, workflow_service, provider, pricing) — если ручка не подключена, соответствующие syscall'ы отвечают «не настроено».

Цикл загрузки:

loop {
    decision = schedule()
    match decision {
        Run(pid)       → run_turn(pid)
        Idle           → sleep(50ms)
        AtConcurrencyLimit → sleep(50ms)
        Shutdown       → break
    }
}

14.2 Основные абстракции

Понятие ОС Эквивалент Модуль
Процесс AgentProcess — PID, машина состояний, контекст, инструменты, бюджет process.rs
Ядро Kernel — событийный цикл kernel.rs
CPU InferenceProvider — подключаемый LLM provider.rs
RAM ContextWindow — память с вытеснением context.rs
Устройство I/O Tool tool.rs
cgroups/ulimits TokenBudget / BudgetGroup budget.rs
Системный вызов Syscall syscall.rs
Сигнал Signal ipc.rs
fork() fork() — COW-контекст, наследование группы process.rs
Таблица процессов DashMap<Pid, AgentProcess> kernel.rs
Драйвер ToolHandler tool.rs

Машина состояний процесса

spawn → Created → (init) → Ready ⇄ Running → (exit) → Terminated
                              │
                              └→ Blocked{reason} → (unblock) → Ready

Ход и цикл tool-call'ов

  1. Ядро выбирает процесс P.
  2. Отправляет контекст P + последние tool-результаты провайдеру.
  3. Провайдер стримит токены.
  4. Если LLM просит tool-call, ядро ставит стрим на паузу, валидирует вызов, выполняет обработчик (с дедлайном), добавляет результат как сообщение tool и возобновляет инференс.
  5. Ход завершается, когда агент yield'ится, блокируется, истекает квант или исчерпан бюджет.

Конкурентность метрится Semaphore только вокруг provider.stream — tool-вызовы и хуки идут без пермита, поэтому медленный инструмент не «голодает» другие сессии.

Контекстное окно

ContextWindow { max_tokens, messages, eviction, summary }. Политики вытеснения: Fifo (дроп старых), SummaryFirst { keep } (свернуть старые в summary, по умолчанию keep=8), SlidingWindow { n }. Вытеснение чистит и осиротевшие tool-результаты, чей родительский assistant-сообщение удалён.

Бюджеты

TokenBudget { max_per_turn, bucket: TokenBucket, max_total, … }. TokenBucket — классический leaky bucket (capacity + refill_rate). Группа BudgetGroup добавляет два опциональных слоя: per-user (под-ведро на user_id) и per-session. Проверка до диспатча: группа → per-user → per-session (can_consume_for); исчерпанный слой — BudgetLevel::{Group,User,Session}.

IPC и syscall'ы

MessagePayload: Text, Json, Signal (Terminate/Pause/Resume/Interrupt), SpawnRequest, SpawnResult.

Syscall'ы: Spawn, Fork, Kill, Yield, Send/Recv, ToolCall, SetState/GetState/DeleteState, Checkpoint/Restore.

Хуки

HookHandler с точками before_user_message (transform/inject/suppress/reply/ notice), after_turn (пост-ходовое notice), after_loop. Плюс merge_user (слияние идентичностей), memory_inspect (инспекция), apply_feedback (like/dislike). HookOutcome { inject, replace_message, reply, notice, suppress }.


14.3 Планировщик

SchedulingPolicy: RoundRobin (по умолч.), PriorityPreemptive, FairShare, DeadlineDriven. Scheduler { policy, time_slice, max_concurrent }. ScheduleDecision: Run(pid) | Idle | AtConcurrencyLimit | Shutdown.


14.4 Провайдер инференса

trait InferenceProvider {
    fn provider_type(&self) -> &str;
    async fn stream(&self, request) -> Result<Box<dyn Stream<Item=Result<InferenceEvent, InferenceError>>>>;
}
enum InferenceEvent { Token(String), ToolCall(ToolCallRequest), Done(InferenceStats) }

Конкретная реализация — OpenAiProvider (reqwest + SSE). Pricing оценивает стоимость из статистики.


14.5 Подсистемы хранения

Слой Где Источник истины для
Текстовые логи (tracing) stdout → agent_os.log операционный просмотр
Event store (EventDb) logs/events.db аудит (одна строка на событие)
Message store logs/messages.db транскрипты + FAQ-кэш, полнотекстовый поиск
JSONL-трейсы logs/process-{pid}.jsonl сырой поток событий процесса
State store logs/state.db scoped key-value (session/user/agent)
Checkpoints CheckpointStore восстановление/миграция

14.6 События и слушатели

Ядро эмитит типизированные ProcessEvent через шину: TurnStart, Token, ToolCall, ToolResult, ToolProgress, TurnEnd, StateChange, Error, Spawned, Terminated, BudgetConsumed, BudgetExhausted, RateLimited, ScheduleBlocked, события жизненного цикла сессий, Cost, шаги воркфлоу. Слушатели реализуют ProcessListener (все методы no-op по умолчанию).


14.7 Загрузка

  1. Хост грузит конфиг и строит Kernel.
  2. ToolRegistry регистрирует встроенные и пользовательские инструменты; HookRegistry — хуки.
  3. InferenceProvider подключается к LLM.
  4. Подключаются сервисные ручки (message_store, state_store, cron_service, workflow_service, pricing).
  5. Грузятся шаблоны агентов (встроенные + YAML).
  6. Bootstrap-агенты спавнятся (или лениво по первому запросу сессии).
  7. Стартует цикл планировщика.
  8. Хост слушает внешние запросы (HTTP + SSE).

14.8 Дизайн-решения

  1. Кооперативная многозадачность по умолчанию; вытеснение опционально.
  2. spawn и fork — оба поддержаны; fork всегда наследует бюджетную группу.
  3. Учёт стоимости на уровне инструментов — каждый ToolResult несёт ToolCost.
  4. I/O через ядро — агенты никогда не зовут инструменты напрямую.
  5. Opt-in подсистемы — при неподключении отвечают «не настроено», а не падают.

14.9 Не-цели

Мультитенантность (один инстанс = один тенант), распределённый планировщик, fine-tuning, graph-воркфлоу в ядре (это серверный слой), real-time гарантии.


14.10 Карта исходников

Забота Модуль
Ядро, цикл хода agent_os_core/src/kernel.rs
Процесс, spec, fork agent_os_core/src/process.rs
Машина состояний agent_os_core/src/state.rs
Контекст, вытеснение agent_os_core/src/context.rs
Бюджеты, группы, стоимость agent_os_core/src/budget.rs
Планировщик agent_os_core/src/scheduler.rs
Провайдер (trait) agent_os_core/src/provider.rs
OpenAI-провайдер agent_os_core/src/openai_provider.rs
Инструменты agent_os_core/src/tool.rs
Хуки agent_os_core/src/hook.rs, hooks/
IPC, сигналы agent_os_core/src/ipc.rs
Syscall'ы agent_os_core/src/syscall.rs
State store agent_os_core/src/state_store.rs
Message store agent_os_core/src/message_store.rs
События, слушатели agent_os_core/src/event.rs, listener.rs
Event DB agent_os_core/src/event_db.rs
Чекпоинты agent_os_core/src/checkpoint.rs
JSONL-логгер agent_os_core/src/jsonl_logger.rs
Субагенты agent_os_core/src/subagent.rs
Cron agent_os_core/src/cron.rs
Воркфлоу agent_os_core/src/workflow.rs
Прайсинг agent_os_core/src/pricing.rs
Загрузчик конфига agent_os_core/src/config.rs
Скриптовые рантаймы agent_os_core/src/script_engine/, js_runtime/

14.11 Сборка и тесты

Cargo-воркспейс из трёх крейтов:

Крейт Назначение
agent_os_core ядро: процессы, планировщик, бюджеты, события, провайдер-абстракция, хуки, message store. Без HTTP и конкретного провайдера
agent_os_tools реализации инструментов (скраперы, архив, RSS, PDF, JSON, скрипты) и встроенные
agent_web_bot HTTP-сервер (axum), OpenAI-провайдер, виджет, админ-UI, прокси, Telegram-боты, загрузчик конфига
cargo build                       # debug-сборка всех бинарников
cargo run --bin agent_web_bot     # запуск сервера (грузит config/server.yaml)

cargo test -p agent_os_core       # юнит-тесты ядра/инструментов/хуков
cargo test -p agent_web_bot       # тесты сервера, auth, proxy, login, sessions
cargo test -p agent_web_bot --lib # HTTP-слой (роутинг, auth, login, access-лог)

Виджет в widget/ собирается автоматически build.rs у agent_web_bot (через npm) — отдельный npm run build не нужен. Интеграционные тесты agent_web_bot/tests/ требуют живой ключ LLM и по умолчанию не запускаются.