14. Внутренности ядра
⚫ Документ для тех, кто пишет или меняет сам код ядра. Полная спецификация —
в SPEC.md (англ., источник истины); здесь — краткая карта. Семантика — из
исходников agent_os_core.
14.1 Модель
Ядро — это один async-рантайм (Tokio) с событийным циклом, который:
- хранит таблицу процессов (
DashMap<Pid, AgentProcess>); - каждый тик зовёт планировщик (
schedule() → ScheduleDecision); - диспатчит ходы (
run_turn(pid)), вызывая провайдера и выполняя цикл tool-call'ов; - ограничивает ресурсы (бюджеты, группы, лимит конкурентности) до диспатча;
- маршрутизирует IPC;
- посредничает в каждом tool-вызове;
- эмитит события слушателям;
- управляет сессиями (
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
- Created — выделен, не инициализирован.
- Ready — ждёт планировщика (
is_runnable()). - Running — потребляет инференс.
- Blocked { reason } — ждёт внешнее событие (tool-результат, IPC, ввод).
- Terminated { exit_code } — завершён (0) или убит (≠0).
Ход и цикл tool-call'ов
- Ядро выбирает процесс P.
- Отправляет контекст P + последние tool-результаты провайдеру.
- Провайдер стримит токены.
- Если LLM просит tool-call, ядро ставит стрим на паузу, валидирует
вызов, выполняет обработчик (с дедлайном), добавляет результат как
сообщение
toolи возобновляет инференс. - Ход завершается, когда агент 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 Загрузка
- Хост грузит конфиг и строит
Kernel. ToolRegistryрегистрирует встроенные и пользовательские инструменты;HookRegistry— хуки.InferenceProviderподключается к LLM.- Подключаются сервисные ручки (
message_store,state_store,cron_service,workflow_service,pricing). - Грузятся шаблоны агентов (встроенные + YAML).
- Bootstrap-агенты спавнятся (или лениво по первому запросу сессии).
- Стартует цикл планировщика.
- Хост слушает внешние запросы (HTTP + SSE).
14.8 Дизайн-решения
- Кооперативная многозадачность по умолчанию; вытеснение опционально.
spawnиfork— оба поддержаны;forkвсегда наследует бюджетную группу.- Учёт стоимости на уровне инструментов — каждый
ToolResultнесётToolCost. - I/O через ядро — агенты никогда не зовут инструменты напрямую.
- 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 и по умолчанию не запускаются.