DARK FACTORY · ТЕХ-АРХИТЕКТУРА
◆ Технический документ · v1.0 · май 2026

Техническая архитектура.

Как устроены агенты и их хостинг, нужны ли MCP-серверы, транспорт между агентами, Python vs Golang, векторные vs графовые БД и декомпозиция на сервисы.

9 доменов Go + Python NATS + Kafka vector → graph
Фундамент

6 принципов, из которых выводятся все решения

ПринципТехническое следствие
Граница процесса = граница доверияКаждый агент — отдельный процесс в отдельном namespace. Никакого in-process шаринга между задачами разных заказчиков.
Stateless compute, stateful storageВоркеры не хранят состояние локально. Всё — в Postgres/Redis/MinIO/Qdrant. Воркер можно убить и пересоздать в любой момент.
Язык под нагрузку, не под модуPython — LLM-экосистема и скорость разработки. Go — конкурентность, латентность, демоны. Rust — точечно для hot-path.
Один протокол наружу, много внутриНаружу — gRPC + REST + MCP (для IDE). Внутри — NATS/gRPC. Не плодим зоопарк.
Событие — источник истиныЖизненный цикл задачи — лог событий (event sourcing для критичного пути). Состояние — проекция.
Деградация, а не отказНет Qdrant → работаем без reuse; нет fine-tuned модели → fallback на base. Любой сервис умеет degraded-режим.
Декомпозиция · уровень 1

9 доменов (bounded contexts)

Каждый домен владеет своими данными (database-per-context). Кросс-доменное чтение — только через API/события, не через чужую БД.

D1

Intent

Discovery, SDD-builder, pattern-retriever

D2

Orchestration

Планирование, DAG-движок, dispatcher

D3

Agent Execution

Воркеры, sandbox, tool-broker

D4

Inference

vLLM, model-router, embeddings, registry

D5

Knowledge

Корпус, reuse-engine, fine-tune

D6

Fleet

Provisioner, scheduler, autoscaler

D7

Quality

Mockarty, evals, review, security

D8

Delivery

CI/CD, deploy, domain, SSL, CRM

D9

Platform

Auth, billing, metrics, audit, tenant

Декомпозиция · уровни 2 и 3

Наборы сервисов → сервисы → язык

ДоменНабор сервисовСервисы (процессы)Язык
D1 Intentintent-suitediscovery-api · sdd-builder · pattern-retrieverPython
D2 Orchestrationorchestratortask-planner · dag-engine · session-manager · dispatcherGo
D3 Agent Execagent-runtimesupervisor · worker · tool-broker · sandbox-controllerGo+Py
D4 Inferenceinference-planemodel-router · vllm-server · embedding-server · kv-cacheGo+vLLM
D5 Knowledgeknowledge-suitecorpus-api · embedding-pipeline · reuse-engine · finetuneGo+Py
D6 Fleetfleet-controlprovisioner · scheduler · health-monitor · cost-optimizerGo
D7 Qualityquality-suiteMockarty · eval-runner · review-agent · security-gateGo+Py
D8 Deliverydelivery-suiteci-orchestrator · deployer · domain-ssl-mgr · crm-connectorGo+Py
D9 Platformplatform-coreapi-gateway · billing · metrics · audit · tenant · authGo
Вместе деплоится → один набор. Масштабируется независимо → отдельный сервис. Граница языка = граница сервиса (не смешиваем Go и Python в одном процессе).
Агенты · модель исполнения

Агент — это эфемерный процесс, а не сервис

Мы не держим 1000 живых агентов. Мы держим пул warm-слотов на GPU и запускаем в них агентов под задачи.

1

Назначение

Получает SDD-фрагмент + контекст от оркестратора

2

Подъём

Стартует в изолированном sandbox на GPU-ноде

3

Reasoning

Петля LLM + tool-вызовы до завершения подзадачи

4

Результат

Отдаёт артефакт + Evidence, пишет в стор

5

Уничтожение

Либо warm-reuse в пуле для следующей задачи

Warm-старт воркера
<100мс
vs 2–4 сек холодный
Изоляция
gVisor
syscall-перехват, не трогает ядро
Модель в VRAM
грузится один раз на ноду
Агенты · хостинг

Двухуровневая модель: Supervisor + Worker

┌──────────────────────────────────────────────────────────────┐ │ GPU-НОДА │ │ │ │ ┌────────────────────┐ ┌──────────────────────────┐ │ │ │ agent-supervisor │ gRPC │ vllm-server (на этой │ │ │ │ (Go, 1 на ноду) │◄───────►│ же ноде, локальный) │ │ │ │ • lifecycle воркеров │ │ модель в VRAM │ │ │ │ • health/heartbeat │ └──────────────────────────┘ │ │ │ • resource limits │ ▲ локальный сокет │ │ │ • crash recovery │ │ (минимум latency) │ │ └─────────┬───────────┘ │ │ │ │ fork/exec в sandbox │ │ │ ┌────────▼────────┐ ┌────────────────┐ │ │ │ │ agent-worker #1 │ │ agent-worker #2 │─┘ │ │ │ (Python, gVisor) │ │ (Python, gVisor)│ │ │ │ reasoning loop │ │ reasoning loop │ │ │ └─────────────────┘ └────────────────┘ │ └──────────────────────────────────────────────────────────────┘
Supervisor · Go

Долгоживущий демон, один на ноду. Высокая конкурентность (десятки воркеров), низкий overhead, отличный supervision-паттерн.

Worker · Python

Эфемерный, под одну подзадачу. Reasoning I/O-bound (ждёт LLM) — GIL не мешает. Вся LLM-экосистема на Python.

Агенты · изоляция

6 слоёв sandbox-изоляции

СлойТехнологияЧто изолирует
ПроцессОтдельный PID/namespaceПамять, FD между воркерами
SyscallgVisor (runsc)Нет прямого доступа к ядру ноды
FSOverlayFS + ephemeral layerЧистый workspace, уничтожается после задачи
СетьNet namespace + egress-firewallТолько tool-broker и vllm; наружу — по allowlist (R-уровень)
Ресурсыcgroups v2CPU/RAM/PID limits per worker
TenantK8s namespace + sandboxЗадачи разных заказчиков физически не пересекаются
K8s управляет supervisor'ами и долгоживущими сервисами. Эфемерные воркеры — кастомный lightweight gVisor-spawner, а не pod-per-task: холодный старт пода — секунды, наш warm-старт — десятки мс.
Агенты · размещение

Affinity: какие агенты где живут

Роль агентаМодельГде живёт
Orchestrator-планировщикQwen 3.6 35B MoEОтдельная нода 2×A100, не делит с воркерами
Coder + Tester (одна задача)Qwen 3.6 27BОдна нода — общий warm KV-cache по проекту
ReviewerQwen 3 Coder 480BИзолированная нода 4×A100 (независимая валидация)
SecurityQwen 3 Coder 480BИзолирован от Coder (нет доступа к его workspace)
Docs / лёгкиеQwen 3.5 9BДешёвые ноды A10, высокая плотность воркеров
🔥

Warm KV-cache

Coder и Tester одной задачи делят префикс контекста — экономия инференса.

🛡️

Изоляция ролей

Reviewer и Security физически отделены от Coder — независимая оценка без доступа к его окружению.

Ключевое решение

MCP — да, но только на границе. Внутри — нет

✓ MCP нужен — внешняя граница
  • IDE-интеграция (Cursor, Claude Desktop, Windsurf) — де-факто стандарт. Mockarty уже отдаёт MCP.
  • Tool-источники заказчика — его CRM/API он отдаёт как MCP-сервер, мы подключаем как tool-source.
✗ MCP не нужен — внутри
  • JSON-RPC поверх stdio/SSE — медленно для высокого RPS.
  • Слабая типизация контрактов, нет стриминга бинарей.
  • Внутри tool-вызовы идут через наш gRPC tool-broker — типизированно, быстро, с Policy enforcement.
MCP — протокол внешней границы (IDE + интеграции заказчика). Внутренняя tool-шина — собственный gRPC tool-broker с мандатным Policy enforcement. Совместимость снаружи + производительность и контроль внутри.
Tool-шина

tool-broker — единая точка enforcement

agent-worker (Python) │ tool_call(name, args) — gRPC ▼ tool-broker (Go) │ ├─► Policy Hook check (R0–R5, guardrails, квоты) ◄── мандатно ├─► FS-tool (запись в sandbox workspace) ├─► Shell-tool (выполнение в gVisor) ├─► HTTP-tool (egress через allowlist доменов) ├─► Browser-tool (headless, отдельный pool) ├─► Mockarty-tool (мок внешних API) └─► MCP-adapter ───► внешние MCP-серверы (CRM заказчика и т.п.)
Агент физически не может вызвать tool в обход брокера — egress-firewall sandbox это гарантирует. Внешние MCP-серверы подключаются как один из бэкендов брокера через MCP-adapter, а не напрямую к агенту.
Транспорт

Два класса коммуникации, правильный инструмент под каждый

КлассПаттернТехнология
Команды/запросы (нужен ответ)request-responsegRPC
События/факты (fan-out)pub-subNATS JetStream
Тяжёлые задачи (durable, retry)work queueNATS JetStream / RabbitMQ
Поток high-volume (логи, метрики)streamKafka
NATS — нервная система

Control-plane: распределение задач, события жизненного цикла, heartbeat. Лёгкий, низколатентный, request-reply + work-queue + pub-sub в одном.

Kafka — кровеносная система

Data-plane high-throughput: лог reasoning-петель, per-task метрики, датасеты для Корпуса и fine-tune. Долгий retention, реплей.

Распределение задач

Путь одной задачи — через DAG, не A2A

1. SDD готов → task-planner (Go) строит DAG подзадач (Coder→Test→Review→Security→Docs) 2. dag-engine публикует готовые узлы → NATS "tasks.ready.<model>" 3. dispatcher (Go) спрашивает fleet-scheduler: "дай слот Qwen-27B с warm cache" 4. fleet-scheduler: bin-packing + affinity → node_id + worker_slot 5. dispatcher → gRPC к agent-supervisor: "spawn worker, вот контекст" 6. supervisor поднимает worker в sandbox, отдаёт задачу 7. worker гоняет reasoning-loop (LLM локально + tools через broker) 8. worker завершает → результат в стор + событие "tasks.done" 9. dag-engine разблокирует зависимые узлы → goto 2 10. все узлы done → Outcome Check → артефакты в Корпус Знаний
Прямого «агент звонит агенту» нет — это анти-паттерн (циклы, гонки). Вся координация через оркестратор и DAG. Нужен результат Reviewer? Это ребро в DAG, а не прямой вызов. At-least-once + идемпотентность по task_id+node_id.
Карта языков

Язык под нагрузку: Python · Go · Rust

LLM/ML-логика, быстро меняется, I/O-bound → Python Control-plane, демоны, hot-path, конкурентность, инфра-SDK → Go Доказанный профайлингом сверх-hot-path → Rust (после H2)
Карта языков · Python

Python — где доминирует LLM-экосистема

СервисПочему Python
agent-workerLLM-экосистема, structured output, парсеры tool-calls, скорость итерации reasoning
embedding-pipelinesentence-transformers, чанкинг, нормализация — Python-нативно
finetune-orchestratorLLaMA-Factory / axolotl / PEFT — только Python
eval-runnerEval-фреймворки, property-based генерация, анализ
review / security-agentLLM-логика + AST-анализаторы
discovery / sdd-builderLLM-heavy, быстрая эволюция промптов и шаблонов
crm-connectorИнтеграции, SDK CRM-систем, не latency-критично
Python только там, где (а) доминирует LLM/ML-экосистема, или (б) логика быстро меняется и не hot-path. Эти сервисы I/O-bound — GIL не мешает.
Карта языков · Go

Go — демоны, hot-path, конкурентность, инфра

СервисПочему Go
orchestratorТысячи параллельных DAG, goroutines
agent-supervisorДолгоживущий демон, supervision десятков воркеров, низкий overhead
tool-brokerHot-path (каждый tool-call), латентность + строгие контракты
model-routerВысокий RPS, маршрутизация по моделям, latency-критично
fleet-controlКонкурентное управление сотнями нод
platform-coreGateway, billing, metrics, audit — предсказуемая латентность
corpus-api / reuse-engineHot-path семантического поиска (обёртка над Qdrant)
delivery-suiteDocker/K8s SDK — first-class в Go
Карта языков · Rust

Rust — точечно, не на старте

КандидатКогда переходить
kv-cache-mgr / proxy перед vLLMЕсли профайлинг покажет Go-прокси как bottleneck на пиках
egress-firewall / sandbox hot-pathЕсли нужен ультра-низкий overhead на перехват syscall
tokenizer-serviceВысокочастотная токенизация (HF tokenizers имеют Rust-ядро)
Rust не на старте. Вводим точечно после H2, когда профайлинг укажет конкретные hot-path. Преждевременный Rust убьёт скорость разработки.
Хранилища данных

Каждому типу данных — своё хранилище

ТипТехнологияЧто хранит
РеляционнаяPostgreSQL 17 + PatroniЗадачи, биллинг, DAG-состояние, tenant, audit, метаданные. Источник истины.
ВекторнаяQdrantЭмбеддинги Корпуса Знаний → семантический reuse
ГрафоваяApache AGE → Neo4j (H2+)Граф зависимостей, задача→артефакт→модель→outcome
KV / cacheRedis / ValkeyСессии, кэш инференса, rate-limit, warm-pool registry
ObjectMinIO / CephEvidence, артефакты, бэкапы, fine-tune датасеты, веса
Time-seriesPrometheus + VictoriaMetricsGPU/per-task/бизнес-метрики на лету
Event logKafkaЛог reasoning-петель → fine-tune и аудит
Ключевое решение

Векторные vs графовые: не «или-или»

Вектор (Qdrant) · с H1

Закрывает 80% reuse-кейсов сразу и дёшево:

  • «Найди похожую задачу по смыслу» → cosine по эмбеддингу SDD
  • «Найди похожий код по функциональности»
Граф · с H2+

Когда reuse выходит на структурный уровень:

  • «Какие артефакты породила модель и дали успешный outcome?»
  • «Меняем компонент X — что отвалится?» (dependency graph)
  • Транзитивные цепочки переиспользования и импакт-анализ
H1Не нужна. Qdrant + Postgres (рекурсивные CTE для простых связей) хватает
H2Apache AGE — граф прямо в нашем Postgres. Не плодим новый сторадж
H3Выделенный Neo4j — только если AGE упрётся в производительность
Inference Layer

vLLM локально на ноде + Go-роутер

agent-worker ──gRPC──► model-router (Go) ──► vllm-server (нужная нода/модель) │ ├─ выбор модели по роли + сложности ├─ load-balance между репликами ├─ fallback: fine-tuned → base при ошибке └─ continuous batching awareness
ВопросРешениеОбоснование
ДвижокvLLMPagedAttention, continuous batching
РасположениеЛокально на GPU-нодеЛокальный сокет vs сеть — минимум latency
Структурный выводgrammar-constrained (Outlines)Валидный JSON для tool-calls без re-prompt
KV-cacheПрефиксный + warm-pool по проектуCoder+Tester делят префикс — экономия
Fine-tunedЧерез Model Registry, A/B на 10%Контролируемый canary-rollout
Состояние

Stateless compute, stateful storage

СостояниеГдеПочему
Состояние DAG задачиPostgresТранзакционность, источник истины
Лог событий задачиKafka + проекция в PostgresEvent sourcing для L4 multi-day, реплей
Сессионный контекст агентаRedis + чекпоинт в MinIOБыстрый доступ + durable снапшот
Warm-pool / slot registryRedisАтомарный захват слота
Очередь готовых узловNATS JetStreamWork-queue с ack, at-least-once
Кэш инференсаRedis (хэш→результат, TTL)Снижение стоимости
Задачи L4 (multi-day) не держат живой процесс сутками. Состояние — лог событий + structured memory. Воркер при возобновлении реконструирует контекст из чекпоинта → устойчивость к рестартам нод и spot-eviction.
Безопасность

Изоляция на уровне реализации

  • gVisor — перехват syscall, воркер не трогает ядро ноды
  • Egress-firewall — исходящий только в allowlist (broker, vllm); интернет — через R-уровень + HTTP-tool с allowlist доменов
  • Tenant-namespace — задачи заказчиков в разных K8s-namespace, нет shared-памяти
  • Secrets — HashiCorp Vault, воркер получает short-lived токены под конкретную задачу
  • Policy Hook enforcement — в tool-broker, мандатно, до любого действия (R0–R5)
Black Box (on-prem): та же архитектура в air-gapped режиме. NATS/Kafka/Postgres/Qdrant/MinIO/Vault/Keycloak — всё self-hosted в комплекте, ноль внешних подключений. Работает из коробки именно потому, что мы изначально не зависим ни от одного SaaS.
Observability + Деплой

Сквозной trace_id + node-pools

Observability-стек

МетрикиPrometheus + Grafana + VictoriaMetrics
ЛогиLoki (+ PII-маскирование)
ТрейсыTempo + OpenTelemetry
БизнесMetrics-engine → Grafana
GPUDCGM exporter → Prometheus

Node-pools (k3s bare-metal)

control-planeorchestrator, platform, NATS, PG, Redis
gpu-inferencevllm + supervisor + warm-pool
gpu-finetuneтренировочные джобы (ночь)
dataQdrant, MinIO, Kafka, VM
edgegateway, Mockarty, browser-pool
Каждая задача имеет сквозной trace_id: gateway → orchestrator → dispatcher → supervisor → worker → tool-broker → vllm. Полная трассируемость пути и стоимости. GitOps (Argo CD) + Helm на каждый набор + canary для router/worker.
Шпаргалка

Сводные инженерные решения

АгентыЭфемерные процессы-воркеры (Python) в gVisor; supervisor (Go) на каждой ноде; warm-pool
ХостингK8s для демонов; кастомный gVisor-spawner для воркеров; vLLM локально на ноде
MCPДа — внешняя граница (IDE, tools заказчика). Нет — внутри (свой gRPC tool-broker)
ТранспортA2A нет → DAG. Control-plane NATS + gRPC, data-plane Kafka
Распределениеplanner → DAG → dispatcher → fleet-scheduler (bin-pack + affinity + warm-cache)
Pythonworker, embedding, finetune, eval, review/security, discovery/SDD
Golangorchestrator, supervisor, tool-broker, router, fleet, platform, corpus, delivery
RustТочечно после H2: kv-cache proxy, tokenizer, sandbox hot-path
Графовые БДH1 — нет. H2 — Apache AGE (в Postgres). H3 — Neo4j при необходимости
Векторные БДQdrant с H1 — семантический reuse (80% кейсов)
◆ Техническая архитектура · v1.0 · май 2026

Решения приняты.
Профайлинг уточнит детали.

Каждый выбор — под нагрузку, а не под моду. Граница процесса = граница доверия. Stateless compute, stateful storage.

⚙️ 9 доменов 🤖 Эфемерные агенты 🔌 MCP на границе 🚌 NATS + Kafka 🐍 Python для LLM 🦫 Go для демонов 🦀 Rust точечно 🧭 Vector → Graph 🛡️ gVisor sandbox 🔭 Сквозной trace_id

Дополняет «Архитектуру стартапа v2.1». ESC — оглавление

навигация · ESC оглавление · F полный экран

Оглавление