Переведено с китайского оригинала. При расхождении приоритет у оригинала.
Confer — архитектура системы
Этот документ описывает целевую архитектуру, а не то, что реализовано. Сейчас gateway — это один процесс, одна инсталляция: таблица WebSocket-соединений, nonce-защита от повторов A2A и счётчики ограничения частоты живут в памяти процесса (
ws/handler.ts,lib/nonce-cache.ts,middleware/rate-limit.ts).Поэтому у gateway не может быть второй реплики. Добавление реплик молча ломает защиту от повторов A2A: повторённый запрос попадает на другую реплику, где таблица nonce пуста, и проходит. Плюс уведомления по WS не доходят до пользователей, подключённых к другой реплике, а порог ограничения частоты умножается на число реплик.
NATS и Redis, упомянутые ниже, — это план на случай горизонтального масштабирования; сегодня они не развёрнуты и ни к чему не подключены (удалены из
docker-compose*.ymlиenv.ts2026-08-07; до этого они были контейнерами, крутившимися вхолостую, и переменной окружения, которую никто не читал). Чтобы действительно масштабироваться горизонтально, сначала нужно перенести эти три состояния из памяти в общее хранилище — в первую очередь nonce, они критичны для безопасности.
Общая схема
┌────────────────────────────────────────────────────────────┐
│ Clients (Tauri 2.0) │
│ iOS · Android · Windows · macOS · Linux │
└──────────────────────────┬─────────────────────────────────┘
│ WSS / HTTPS / SSE
▼
┌────────────────────────────────────────────────────────────┐
│ Edge API Gateway (Bun + Hono) │
│ Auth · Rate limit · Routing · WS fan-out │
└─────┬─────────────┬─────────────────┬────────────────┬─────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────┐ ┌─────────────┐ ┌────────────┐ ┌──────────────┐
│ Agent │ │Conversation │ │ Identity & │ │ MCP / Tools │
│Runtime │ │ Hub │ │A2A Gateway │ │ Connector │
└───┬────┘ └──────┬──────┘ └─────┬──────┘ └──────┬───────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ Data layer: PostgreSQL · Redis · NATS · Vector (Qdrant)·S3 │
└──────────────────────────────────────────────────────────────┘
│ │
▼ ▼
LLM providers Other instances' Agents
(Claude / GPT / (federation via A2A
DeepSeek / Qwen) over HTTPS)
Принципы проектирования
- Край без состояния, ядро с состоянием (цель, не реализовано): gateway без состояния и с горизонтальным масштабированием — это форма, к которой мы идём; сейчас у gateway есть состояние в процессе, и он работает только в одном экземпляре — см. вводную заметку.
- Готовность к федерации с первого дня: идентичность DID:web + AgentFacts, и даже одиночная инсталляция говорит по федеративному протоколу, так что переход к федерации позже не потребует миграции.
- Свой ключ к LLM: платформа не берёт на себя расходы на LLM; каждый использует собственный ключ API.
- Протокол прежде всего: ключевые взаимодействия идут по открытым протоколам (A2A, MCP, DID:web, NANDA AgentFacts), без привязки к нашему собственному.
- Bun + TypeScript на всём стеке: бэкенд на Bun + Hono, клиент на Tauri + React, общие типы.
Границы сервисов
1. Edge API Gateway
См. docs/05-api.md.
- Задача: терминация TLS, двойная аутентификация (пользователь и A2A), ограничение частоты по четырём измерениям, маршрутизация HTTP/WS/SSE, рассылка на несколько устройств.
- Технологии: Bun + Hono.
- Ключевые зависимости: JWKS (проверка пользовательского токена), кеш DID-документов, NATS (рассылка).
- Чего не делает: бизнес-логику, хранение бизнес-данных, вызовы LLM.
2. Agent Runtime
Каждому пользователю соответствует постоянно живущий экземпляр Агента.
- Задача:
- Хранить состояние Агента пользователя (выбор модели, инструменты, политика, память).
- Цикл вызовов LLM (с абстракцией над несколькими поставщиками).
- MCP-клиент, подключённый к установленным пользователем серверам инструментов.
- Исходящие A2A-вызовы (пойти поговорить с чужим Агентом).
- Движок политик (решать, что можно сообщить другой стороне).
- Жизненный цикл: просыпается по требованию. Когда приходит сообщение или A2A-запрос, загружает состояние из PostgreSQL, отрабатывает один ход и записывает обратно.
- Ключевые зависимости: поставщики LLM, MCP-серверы, служба идентичности.
3. Conversation Hub
- Задача: хранение сообщений, подписка, доставка.
- Поддерживаемые виды разговоров:
- Пользователь ↔ собственный Агент.
- Пользователь ↔ чужой Агент (через собственного Агента).
- Пользователь ↔ пользователь (обычный мессенджер).
- Групповые чаты (люди и Агенты вперемешку).
- Ключевые зависимости: NATS Streams (персистентность + рассылка), PostgreSQL (история сообщений), Redis (присутствие, счётчики непрочитанного).
4. Identity & A2A Gateway
- Задача:
- Управлять DID:web-документами пользователей.
- Публиковать и кешировать AgentFacts.
- Обрабатывать входящие A2A-запросы (проверять HTTP-подпись и capability-токен).
- Пересылать исходящие A2A-запросы.
- Ограничение частоты и защита от спама для федеративных пиров.
- Ключевые зависимости: PostgreSQL (кеш DID и пиров), Redis (счётчики ограничения).
Подробное устройство протокола — в docs/03-protocol.md.
5. MCP / Tools Connector
- Задача:
- Управление соединениями с установленными пользователем MCP-серверами инструментов.
- Через него Agent Runtime вызывает инструменты.
- Приведение результатов вызовов инструментов к единому виду.
- Ключевые зависимости:
@modelcontextprotocol/sdk.
Слой данных
| Компонент | Для чего | Состояние |
|---|---|---|
| PostgreSQL | Пользователи, Агенты, разговоры, сообщения, разрешения, связи с пирами (основное хранилище) | ✅ используется |
| Qdrant | RAG долговременной памяти Агента, индекс баз знаний пользователя | ✅ используется |
| S3-совместимое (MinIO) | Хранение файлов баз знаний | ✅ используется |
| Redis | Сессии, присутствие, счётчики ограничения, кеш горячих данных | ⬜ не развёрнут, понадобится только при горизонтальном масштабировании |
| NATS Streams | Рассылка сообщений (user.{uid}.events) + очередь задач Agent Runtime | ⬜ не развёрнут, понадобится только при горизонтальном масштабировании |
Архитектура клиента
- Основа: Tauri 2.0 (ядро на Rust + отрисовка в WebView).
- Фронтенд: React 19 + TypeScript + Tailwind CSS.
- Состояние: Zustand или Jotai (лёгкие).
- Маршрутизация: TanStack Router.
- Сеть: нативный fetch + нативный WebSocket + EventSource (SSE).
- Локальное хранилище: SQLite и key-value-хранилище от Tauri (кеш разговоров, черновики офлайн).
Покрытие платформ
| Платформа | Через |
|---|---|
| iOS | Поддержка iOS в Tauri 2.0 |
| Android | Поддержка Android в Tauri 2.0 |
| Windows | Tauri 2.0 |
| macOS | Tauri 2.0 |
| Linux | Tauri 2.0 |
Одна кодовая база, никаких нативных запасных вариантов.
Плагин Claude Code
См. docs/06-claude-code-plugin.md.
- Отдельный процесс MCP-сервера, написанный на Node.js или Bun.
- Пользователь ставит его командой
claude mcp add confer <command>. - Привязывается к аккаунту Confer через OAuth или токен.
Архитектура развёртывания
Одна инсталляция (личная / небольшая команда)
Реальный docker-compose.prod.yml (agent-runtime и identity — библиотеки внутри gateway, а не отдельные сервисы):
- gateway (сервис Bun, одна реплика — см. вводную заметку)
- client (фронтенд, раздаваемый nginx)
- migrate (разовая задача)
- postgres
- qdrant
- minio
Развёртывание: docker compose -f docker-compose.prod.yml up -d — и всё работает.
Корпоративная инсталляция
- Тот же Docker Compose, поднятый как отдельное развёртывание.
- Со своим доменом (
acme.com). - С публикацией
https://acme.com/.well-known/did.jsonиhttps://acme.com/.well-known/agent.json. - Внутренние пользователи входят через SSO.
Облако (собственное облако Confer)
Предварительное условие: сейчас gateway работает в одну реплику (состояние в процессе). Прежде чем ставить несколько, нужно перенести таблицу WS-соединений, A2A-nonce и счётчики ограничения в общее хранилище, иначе защита от повторов молча перестанет работать.
- Многоарендный Kubernetes.
- У каждого пользователя или компании свой namespace или схема.
- Общий слой абстракции над поставщиками LLM (но ключ по-прежнему свой у каждого).
- Развёртывание по регионам мира, вход через ближайший.
Федерация (между инсталляциями)
Любая инсталляция Confer — собственная или облачная — может общаться с другими по протоколу A2A.
[acme.com] [vendor-x.com] [confer.cloud]
Agent A <─── A2A ───> Agent B <─── A2A ───> Agent C
Идентичность и обнаружение:
- Каждая инсталляция публикует DID-документ по
/.well-known/did.json. - Каждый Агент публикует AgentFacts по
/.well-known/agent.json. - Поиск между инсталляциями: рассылка по известным инсталляциям + публичный реестр.
Наблюдаемость
- Трассировка: OpenTelemetry;
trace_idвнедряется в gateway и проходит через все сервисы. - Логи: структурированный JSON, сбор через Vector / Loki.
- Метрики: Prometheus. Ключевые:
gateway_active_ws_connections{user_id}agent_runtime_llm_tokens_total{provider,role}a2a_inbound_requests_total{peer_domain,status}mcp_tool_calls_total{tool,result}
Границы безопасности
- Пользователь ↔ gateway: JWT с проверкой через JWKS.
- A2A-пир ↔ gateway: HTTP Message Signatures (RFC 9421) + открытый ключ DID:web.
- Внутренние RPC между сервисами: mTLS или общий секрет (внутри сети Docker).
- Вызовы поставщиков LLM: ключ API хранится зашифрованным (AES-256, ключ в Vault / KMS).
- Файлы пользователей: серверное шифрование S3.
Ключевые технические решения
| Решение | Выбор | Альтернативы | Причина |
|---|---|---|---|
| Язык бэкенда | Bun + TypeScript | Go | SDK для MCP и A2A сделаны в первую очередь под TS; типы общие на всём стеке |
| Веб-фреймворк | Hono | Elysia, Fastify | Лёгкий, быстрый, стабильная экосистема |
| Клиент | Tauri 2.0 | Flutter, Electron | Одна кодовая база на пять платформ, безопасность Rust, небольшой размер |
| Основное хранилище | PostgreSQL 18 | MySQL | Хорошая поддержка JSON, богатая расширяемость, pgvector при желании |
| Шина сообщений | NATS | Kafka, Redis Pub/Sub | Лёгкая, с персистентностью и точной подпиской |
| Векторная база | Qdrant | Pinecone, pgvector | Зрелая для собственного хостинга, написана на Rust, стабильная производительность |
| Идентичность | DID:web | DID:key, только OAuth | Совместима с существующей веб-инфраструктурой, рекомендована NANDA |
| Протокол | A2A + MCP + AgentFacts | Собственный протокол | Ставим на экосистему открытых протоколов |