33 KiB
Ты — senior AI systems engineer и principal backend architect.
Твоя задача: спроектировать и реализовать полноценный локальный multi-model AI agent runtime.
Это НЕ чат-бот. Это НЕ demo script. Это НЕ один большой файл с вызовами моделей и shell.
Это автономная локальная система исполнения задач с:
- central runtime loop
- несколькими локальными GGUF-моделями с жёсткими ролями
- tools
- planning
- critic loop
- долговременной memory
- permission gating
- event bus
- state persistence
- streaming
- конфигурируемым runtime
Система должна быть расширяемой, тестируемой, отказоустойчивой и пригодной для дальнейшего развития.
==================================================
- PRODUCT GOAL ==================================================
Построить локальный AI runtime, который:
- принимает пользовательскую задачу
- извлекает релевантную память
- собирает контекст
- принимает orchestration-решение
- при необходимости строит план
- исполняет шаги через tools и coder
- оценивает результаты через critic
- сохраняет полезные результаты в memory
- публикует события исполнения
- поддерживает streaming клиенту
- требует подтверждения на опасные действия
- умеет восстанавливаться после сбоя
- полностью управляется через конфиги
Система должна быть local-first.
================================================== 2. NON-GOALS
На первом этапе НЕ нужно:
- строить UI frontend
- делать distributed execution
- делать multi-user auth
- делать Kubernetes deployment
- делать сложный scheduler для множества параллельных задач
- делать self-modifying runtime
Telegram bot допускается только как thin stub.
================================================== 3. CENTRAL ARCHITECTURAL PRINCIPLE
Центр системы — Runtime Loop Controller.
Не router. Не отдельная LLM. Не execution engine.
Именно runtime loop замыкает полный цикл:
task -> state load -> context build -> orchestrator -> plan/decision -> execute -> critic -> memory policy -> state checkpoint -> next step
Целевая форма архитектуры:
Runtime Loop Controller
-> State Store / Checkpoints
-> Context Builder
-> Orchestrator / Planner
-> Router (policy + decision suggestion)
-> Execution Engine / Scheduler
-> Tools / Coder / Critic
-> Memory System
-> Event Bus / Event Store
-> Streaming Projection
-> back into Runtime Loop
Любой critical transition должен проходить через runtime loop.
================================================== 4. MODELS AND HARD ROLES
Используй отдельные модели с жёстким разделением ответственности.
4.1 Orchestrator / Planner
Модель:
- LLaMA-family GGUF
Роль:
- orchestration reasoning
- decomposition of user task
- decision whether planning is needed
- plan generation in strict JSON format
- next-step suggestion
Ограничения:
- не выполняет tools напрямую
- не пишет итоговый код, кроме инструкций для coder
- не оценивает финальную корректность результата
4.2 Coder
Модель:
- X-CODER GGUF
Роль:
- generate_code
- fix_code
- refactor_code
- generate helper scripts when explicitly requested by runtime
Ограничения:
- не принимает orchestration-решения
- не строит execution plan
- не вызывает tools напрямую
4.3 Critic
Модель:
- Gemma-family GGUF
Роль:
- оценивает результаты tools
- оценивает результаты coder
- предлагает memory usefulness score
- предлагает safety/usefulness judgment
Ограничения:
- не планирует
- не исполняет действия
- не принимает финальное решение о memory write
4.4 Embeddings Engine
Модель:
- MiniLM или совместимая embeddings model
Роль:
- embeddings generation
- semantic retrieval
Ограничения:
- не участвует в reasoning
- не участвует в planning
================================================== 5. GLOBAL RULES
Обязательные правила:
- Все execution transitions проходят через runtime loop controller.
- Все tool calls проходят через execution layer, permission layer и sandbox layer.
- Все prompts и model settings вынесены в
config/. - Все межмодульные контракты оформлены через типы/Pydantic models/dataclasses.
- Все важные действия публикуются как события.
- Task lifecycle не должен храниться только in-memory.
- Система должна корректно деградировать при сбое отдельных подсистем.
Hard decision rule:
- Все decision-producing components должны возвращать только структурированные decision objects.
- Ни один decision-producing component не должен напрямую исполнять tools.
- Ни один decision-producing component не должен напрямую мутировать task state.
- Ни один decision-producing component не должен неявно вызывать другие компоненты в обход runtime loop.
Обязательная деградация:
- если critic недоступен, runtime продолжает работу по fallback policy
- если memory retrieval недоступен, задача выполняется без retrieval
- если streaming недоступен, система возвращает sync response
- если planner вернул невалидный план, runtime делает controlled replan или graceful fail
================================================== 6. IMPLEMENTATION ORDER
Реализация должна идти итерациями в таком порядке:
- project skeleton
- typed contracts
- runtime loop skeleton
- event bus + event schema
- state persistence + checkpoints
- config loader
- context builder skeleton
- FastAPI skeleton
- router
- execution engine / scheduler
- permission system
- tool sandbox layer
- local tools
- coder integration
- critic integration
- memory system
- memory write policy engine
- streaming projection
- CLI
- optional Telegram stub
После каждого шага ты обязан:
- показать изменённые файлы
- показать структуру директорий
- кратко объяснить, что уже работает
- явно указать, что ещё stub
================================================== 7. MVP BOUNDARY
Первая рабочая версия обязана поддерживать end-to-end сценарий:
- пользователь отправляет задачу
- runtime loop создаёт task state
- context builder собирает контекст
- orchestrator решает direct action или planning
- execution engine исполняет шаги
- shell/file tools реально работают
- опасная команда требует подтверждения
- critic оценивает результат
- memory policy принимает решение о записи
- события пишутся в event store
- task state чекпоинтится
- клиент получает streaming или sync результат
Минимальный набор tools для MVP:
shell_execfile_readfile_write
Второй приоритет:
web_searchweb_fetch
================================================== 8. REQUIRED PROJECT STRUCTURE
Ожидаемая структура:
ducklm/
app/
api/
core/
runtime/
events/
state/
tools/
memory/
permissions/
streaming/
cli/
models/
services/
config/
models.json
prompts.json
permissions.json
runtime.json
data/
memory/
state/
events/
permissions/
tests/
main.py
Допускается разумная адаптация, но separation of concerns обязателен.
================================================== 9. REQUIRED DOMAIN CONTRACTS
Сначала зафиксируй typed contracts.
Минимально обязательны:
9.1 UserTask
{
"task_id": "uuid",
"session_id": "uuid",
"input": "string",
"context": {},
"created_at": "iso-datetime"
}
9.2 PlanStep
{
"id": "step-1",
"kind": "tool|coder|memory|respond",
"tool": "shell_exec",
"args": {},
"description": "human readable step description",
"requires_confirmation": false,
"depends_on": []
}
Rules:
kindобязателенargsвсегда объектdepends_onобязателен, даже если пустойtoolобязателен только дляkind=tool
9.3 ToolCall
{
"tool": "shell_exec",
"args": {},
"task_id": "uuid",
"step_id": "step-1"
}
9.4 ToolResult
{
"tool": "shell_exec",
"ok": true,
"output": "stdout/stderr/parsed data",
"error": null,
"metadata": {
"exit_code": 0,
"duration_ms": 120
}
}
9.5 CoderRequest
{
"mode": "generate|fix|refactor",
"instruction": "string",
"context": {},
"task_id": "uuid"
}
9.6 CriticScore
{
"correctness": 0.0,
"usefulness": 0.0,
"safety": 0.0,
"memory_store": true,
"weight": 0.0,
"explanation": "string"
}
Rules:
- все numeric scores в диапазоне
0..1 weightиспользуется как сигнал, а не как безусловная команда записи
9.7 MemoryEntry
{
"id": "uuid",
"text": "string",
"kind": "tool_result|plan|critique|fact|summary|user_preference",
"source": "tool|critic|user|system",
"weight": 0.85,
"task_id": "uuid",
"session_id": "uuid",
"metadata": {},
"created_at": "iso-datetime",
"embedding_model": "string",
"embedding_dim": 384
}
9.8 PermissionDecision
{
"action_type": "shell_command",
"pattern": "rm",
"decision": "allow_once|allow_always|deny|ask_always",
"created_at": "iso-datetime"
}
9.9 RuntimeEvent
{
"event_id": "uuid",
"task_id": "uuid",
"session_id": "uuid",
"sequence": 42,
"type": "task_received",
"timestamp": "iso-datetime",
"payload": {},
"causation_id": "uuid|null",
"correlation_id": "uuid"
}
9.10 TaskCheckpoint
{
"task_id": "uuid",
"status": "executing_step",
"active_step_id": "step-2",
"plan_snapshot": {},
"context_snapshot": {},
"updated_at": "iso-datetime"
}
9.11 ExecutionDirective
{
"type": "plan|tool|coder|respond|replan|store_memory|request_permission|complete|fail|noop",
"payload": {},
"requires_permission": false,
"confidence": 0.0,
"reason": "string"
}
Rules:
- все decision-producing components должны возвращать либо
ExecutionDirective, либо коллекцию совместимых директив confidenceнаходится в диапазоне0..1payloadвсегда объект- директива описывает намерение, а не исполняет действие сама
================================================== 10. RUNTIME LOOP CONTROLLER
Создай:
app/runtime/runtime_loop.pyapp/runtime/runtime_controller.py
Runtime Loop Controller — heart of system.
Он обязан:
- принять task
- загрузить или создать task state
- опубликовать стартовые события
- инициировать context assembly
- вызвать orchestrator
- определить
direct action / planning / replan / fail - передать исполнение в execution engine
- принять результаты tools/coder
- вызвать critic
- передать результат в memory write policy engine
- сохранить checkpoint
- опубликовать события
- решить
continue / replan / complete / fail
Runtime loop не должен:
- собирать prompts inline вручную
- содержать raw tool logic
- подменять собой router
- подменять собой execution engine
- принимать policy-level решения вместо других компонентов
Runtime loop обязан:
- применять уже возвращённые decision objects
- переводить систему между состояниями
- координировать вызовы между компонентами
Runtime loop не должен содержать скрытую бизнес-логику policy-уровня.
================================================== 11. CONTEXT BUILDER
Создай:
app/core/context_builder.py
Context builder обязан собирать:
- user input
- session context
- retrieved memory
- current task state
- current plan or active step
- recent tool results
- permission state
- runtime constraints and safety limits
Rules:
- любой вызов orchestrator/planner идёт только через context builder
- context builder должен быть token-budget aware
- low-priority context должен отбрасываться при переполнении
- prompt assembly не должна дублироваться по проекту
Минимальный результат:
{
"system_prompt": "string",
"task_summary": "string",
"memory_context": [],
"execution_context": {},
"tool_context": [],
"safety_context": {},
"constraints": {}
}
================================================== 12. ORCHESTRATION, PLANNING, ROUTER
Planning — это режим orchestration model, а не отдельная модель.
Router должен быть только:
- policy evaluator
- decision suggester
Создай:
app/core/router.py
Router обязан определять:
- нужен ли retrieval
- нужен ли planning
- direct step vs multi-step flow
- когда нужен coder
- когда нужен critic
- когда нужен replan
- когда требуется permission gate
Rules:
- router должен быть pure function по контракту
- router принимает input state + assembled context
- router возвращает только structured decision object
- router не имеет side effects
- router не мутирует state
- router не вызывает tools
- router не управляет execution lifecycle
- router не владеет task lifecycle
- router не исполняет шаги
- runtime loop применяет router decisions
Planner rules:
- planner mode возвращает только строгий JSON
- невалидный план не исполняется
- runtime делает bounded retry или graceful fail
================================================== 13. TASK GRAPH MODEL
План не должен жить только как список шагов.
Даже если MVP исполняет шаги последовательно, внутренняя модель должна быть graph-compatible.
Используй внутреннюю task graph representation:
{
"nodes": [
{
"id": "step-1",
"kind": "tool",
"tool": "shell_exec",
"args": {"command": "hostnamectl"},
"depends_on": []
},
{
"id": "step-2",
"kind": "respond",
"depends_on": ["step-1"]
}
]
}
Rules:
- scheduler валидирует отсутствие циклов
- planner может возвращать
PlanStep[]как transport format - после валидации план преобразуется во внутренний task graph
- MVP может использовать sequential DAG scheduler
================================================== 14. EXECUTION ENGINE AND SCHEDULER
Создай:
app/core/execution_engine.pyapp/core/execution_scheduler.py
Execution engine работает под управлением runtime loop.
Execution engine обязан:
- принимать валидированный task graph
- поддерживать execution cursor
- выбирать следующий исполнимый шаг
- учитывать зависимости шагов
- вызывать tools/coder через adapters
- возвращать структурированные результаты в runtime loop
- публиковать execution events
Минимальные состояния:
receivedretrieving_memoryorchestratingplanningawaiting_permissionexecuting_stepcritic_evaluatingstoring_memorycompletedfailed
Execution engine не должен заменять runtime loop.
================================================== 15. EVENT BUS, EVENT STORE, REPLAY
Streaming events недостаточно. Нужен внутренний event backbone.
Создай:
app/events/event_bus.pyapp/events/event_types.pyapp/events/event_store.py
EventBus обязан:
- принимать runtime domain events
- гарантировать ordering per task
- выдавать monotonic sequence number per task
- публиковать события подписчикам
- писать события в durable store
- поддерживать projection в streaming layer
Delivery guarantees:
- ordering guarantee per task обязателен
- delivery model минимально
at least once - consumer-side idempotency обязательна
- deduplication key:
task_id + sequence - replay не должен ломать состояние при повторном применении уже известных событий
Минимальные event types:
task_receivedcontext_builtllm_calledllm_result_receivedplan_createdstep_startedtool_calledtool_completedcoder_calledcoder_completedcritic_calledcritic_completedmemory_write_suggestedmemory_write_decidedmemory_writtenpermission_requestedpermission_resolvedcheckpoint_savedtask_completedtask_failed
Event sourcing baseline:
- каждое значимое действие должно порождать событие
- execution history должна быть воспроизводимой
- должна быть replay capability step-by-step
Каждое событие должно быть idempotent и deduplicatable по:
task_id + sequence
Streaming transport не является source of truth.
================================================== 16. STATE PERSISTENCE AND CHECKPOINTING
In-memory only state запрещён для autonomous mode.
Создай:
app/state/task_state_store.pyapp/state/checkpoint_store.py
Используй:
- SQLite как минимум для MVP
State persistence layer обязан поддерживать:
- task creation
- current task status
- active step
- current plan/task graph snapshot
- latest context summary
- latest safe checkpoint
- resume after restart/crash
Обязательные правила:
- checkpoint после critical transitions
- periodic checkpointing
- resume from last valid checkpoint
================================================== 17. ASYNC EXECUTION ISOLATION
Нужна явная изоляция между LLM loop и tool execution.
Обязательные требования:
- долгие tool operations не должны блокировать runtime loop
- блокирующие операции должны идти через async adapter / isolated runner
- streaming и event publishing должны продолжаться во время исполнения tool
Минимум:
- async tool runner
- timeout wrapper
- cancellation handling
- bounded concurrency policy
================================================== 18. TOOL SANDBOX LAYER
Помимо permission checks нужен sandbox layer.
Особенно для:
shell_execweb_fetchwith browser fallback- generated helper scripts
Минимальные требования:
- execution context isolation
- resource caps
- timeout enforcement
- working directory restrictions
- optional environment variable allowlist
Для shell нужно предусмотреть:
- CPU / wall time limits
- path restrictions where possible
- запрет неявного escalation
================================================== 19. TOOLS SYSTEM
Нужен tool registry и единый tool interface.
Обязательные tools для MVP:
shell_execfile_readfile_write
Второй этап:
web_searchweb_fetch
Требования:
- единый base tool interface
- единый
ToolResult - централизованный logging
- timeout/error isolation
- tool execution только через tool layer
================================================== 20. TOOL SAFETY AND PERMISSIONS
Перед потенциально опасным действием система обязана проверить policy.
Источники policy:
config/permissions.json- persistent store пользовательских решений
Поддерживаемые режимы:
allow_onceallow_alwaysdenyask_always
Минимум опасных shell patterns:
rmmvв sensitive pathschmodchown- package managers
curl | bashsudoshutdownreboot
Rules:
- опасная команда не исполняется до решения пользователя
- решения пользователя сохраняются
- execution layer получает уже разрешённое или отклонённое действие
================================================== 21. MEMORY SYSTEM
JSON file не использовать как primary memory store.
Используй:
- SQLite как primary metadata store
- FAISS или hnswlib как vector index
Memory обязана поддерживать:
- insert
- semantic search
- delete
- update weight
- filtering by kind/session/task/source
- embedding versioning
- reindex
Минимальные таблицы или эквивалент:
memory_items
- id
- text
- kind
- source
- weight
- task_id
- session_id
- metadata_json
- created_at
- updated_at
embeddings_index_map
- memory_id
- embedding_model
- embedding_dim
- vector_slot
- created_at
Rules:
- retrieval учитывает semantic score и memory weight
- low-value memories не должны загрязнять context
- смена embedding model требует reindex path
================================================== 22. MEMORY WRITE POLICY ENGINE
Critic только предлагает. Memory write policy engine решает.
Создай:
app/memory/write_policy.py
Policy engine должен учитывать:
- critic score
- thresholds из config
- kind/source memory candidate
- deduplication signals
- session/task scope
- safety constraints
- runtime weight modifiers
Решения policy engine:
storestore_with_weightskipmerge_with_existing
Policy engine должен быть детерминированной функцией.
Минимальная форма:
(critic_score + memory_type + runtime_weight + dedup_state + safety_state) -> decision
Нельзя ограничиваться примитивным правилом вида:
if score > 0.7 then store
Нужно зафиксировать:
- threshold model
- scoring formula or weighted rule set
- conflict resolution for near-duplicate memories
- merge policy for same-fact updates
================================================== 23. CRITIC LOOP
Critic получает:
- tool result
- coder output
- optional execution context
Возвращает:
{
"correctness": 0.91,
"usefulness": 0.77,
"safety": 1.0,
"memory_store": true,
"weight": 0.84,
"explanation": "Result is correct and safe, useful for future similar tasks"
}
Critic должен вызываться:
- после tool execution
- после coder output
- перед memory write suggestion
Critic failure не должен ломать execution path. Critic возвращает suggestion, а не final write decision.
================================================== 24. RETRY AND RECOVERY POLICY
Нужна явная retry/recovery стратегия.
Обязательные политики:
Planning retry:
- ограниченное число replan attempts
- каждый retry логируется как событие
Tool retry:
- только для idempotent operations или явно разрешённых tools
- policy зависит от типа ошибки
Partial failure recovery:
fail taskretry stepskip stepreplan
Critic recovery:
- critic failure переводится в fallback policy
Минимальные поля в config/runtime.json:
planner_retry_limittool_retry_limitreplan_limitstep_timeout_mstask_timeout_msallow_recovery_replancheckpoint_policyevent_retention_policy
================================================== 25. STREAMING SYSTEM
Требуется FastAPI WebSocket streaming.
Но streaming должен быть projection from event bus, а не отдельным источником правды.
Минимальные внешние события:
{ "type": "status", "data": "planning" }
{ "type": "token", "data": "..." }
{ "type": "plan", "data": [...] }
{ "type": "tool_start", "tool": "shell_exec", "step_id": "step-1" }
{ "type": "tool_result", "tool": "shell_exec", "data": {...} }
{ "type": "critic", "data": {...} }
{ "type": "permission_required", "data": {...} }
{ "type": "final", "data": {...} }
================================================== 26. CONFIG SYSTEM
Всё должно жить в config/.
Обязательные файлы:
config/models.json
- model paths
- model roles
- inference params
- context sizes
config/prompts.json
- orchestration prompt
- planning prompt
- coder prompt
- critic prompt
config/permissions.json
- dangerous command policies
- sensitive paths
- default approval behavior
config/runtime.json
- timeouts
- streaming settings
- critic fallback policy
- memory thresholds
- retrieval top_k
- replan limits
- max execution steps
- checkpoint policy
- event retention policy
Hard rule:
- никаких хардкодов prompts и critical thresholds в коде
================================================== 27. API SERVER
Сделай FastAPI backend.
Минимальные endpoints:
POST /chatWS /streamPOST /tool/executeGET /memory/searchDELETE /memory/item/{id}GET /health
Требования:
- Pydantic request/response models
- единый error handling
- dependency injection where разумно
================================================== 28. CODER MODULE
Создай:
app/core/coder.py
Минимальный интерфейс:
generate_code()fix_code()refactor_code()
Используется только coder model.
================================================== 29. CLI
Добавить CLI для локального использования.
Минимум:
- отправить задачу
- получить sync result
- показать streaming mode
- выполнить memory search
================================================== 30. TELEGRAM BOT
Только optional stub.
Если реализуешь:
- не связывай core runtime с Telegram-specific code
- делай только thin adapter layer
================================================== 31. RELIABILITY AND TESTING
Обязательные инженерные требования:
- structured logging
- typed exceptions
- timeout handling
- graceful failures
- no silent pass
- no giant mixed-responsibility files
Минимальные тесты:
- runtime loop transitions
- event ordering
- checkpoint save/load
- replay path
- plan validation
- permission policy checks
- tool registry
- shell safety path
- memory insert/search
- memory write policy
- router basic flow
================================================== 32. FORBIDDEN SHORTCUTS
Запрещено:
- single-model architecture
- hardcoded prompts in code
- bypassing runtime loop
- bypassing router for policy decisions
- tool execution outside tool layer
- dangerous command execution without permission check
- JSON file as primary memory store
- in-memory-only task lifecycle for autonomous mode
- direct streaming transport as substitute for event bus
- critic-only memory write decision path
- accepting invalid planner JSON as-is
- giant monolithic runtime file
================================================== 33. DEFINITION OF DONE
Работа считается выполненной, если:
- Есть модульная структура проекта.
- Есть typed contracts для core entities.
- Есть Runtime Loop Controller как центральный control loop.
- Есть Context Builder.
- Есть Router как policy evaluator / decision suggester.
- Есть Execution Engine / Scheduler.
- Есть EventBus + EventStore + replay-capable history.
- Есть state persistence + checkpointing + resume.
- Есть permission-gated tools.
- Есть tool sandbox layer.
- Есть coder integration.
- Есть critic integration.
- Есть memory на SQLite + vector index.
- Есть memory write policy engine.
- Есть FastAPI API.
- Есть streaming как projection от event bus.
- Есть CLI.
- Есть базовые тесты critical path.
================================================== 34. REQUIRED DELIVERY STYLE
Работай итеративно.
После каждого шага:
- показывай код
- показывай структуру файлов
- кратко объясняй решение
- явно отмечай допущения
- прямо помечай stubs
Не перескакивай к финальному “всё готово”, если каркас ещё не выстроен.
Начни с:
- project structure
- typed contracts
- runtime loop skeleton
- event bus skeleton
- state persistence skeleton
- config loader
- context builder skeleton
- FastAPI skeleton
- router
- execution engine / scheduler
Сначала построй правильный каркас. Потом наполняй его логикой.
КОНЕЦ ЗАДАНИЯ.