Обзор
Версия
v1.0 — Stable
Статус
stable, 2026-06-06
Лицензия
MIT
Поддерживает
Fasad Salatov (Unyly)
Quark — это streaming-first протокол для соединения AI-агентов (LLM-клиентов) с инструментами (tool servers). Он заменяет Model Context Protocol (MCP) в production-сценариях где MCP даёт сбой: композиция, стриминг, подписки, backpressure, capability-based security и multi-agent — встроены в протокол, а не сделаны костылями поверх.
▸ v1.0 — stable (2026-06-06)
- ✓ Stability guarantee — никаких breaking changes через v1.x
- ✓ Federation — server-to-server routing через mesh discovery
- ✓ MessagePack binary frames — opt-in через subprotocol
- ✓ Расширенный filter — matches/in/notIn, parens, !, arithmetic, nested.field
- ✓ Schema registry — $ref к https://schemas.quark.dev/
- ✓ Python SDK — [email protected]
- ✓ Conformance test suite — 78 tests (Go 35 + TS 21 + Python 22)
- ✓ IETF draft alignment (quark-protocol-00)
▸ v0.2 — production-grade (2026-06-05)
- ✓ Криптографически подписанные capability-токены (QCT, HMAC-SHA256)
- ✓ Bearer-аутентификация в handshake
- ✓ Восстановление сессии после disconnect (RSM)
- ✓ Heartbeat (HBT/HBA) — detect dead connections
- ✓ Валидация input через JSON Schema (server-side)
- ✓ Cost-трекинг в RES/END
- ✓ Distributed tracing (W3C trace_id/span_id)
- ✓ Версионирование инструментов (name@version)
- ✓ Поле версии протокола бамп 1 → 2
▸ v0.1 (2026-04-15)
Первоначальный draft: streaming, композиция, подписки, backpressure, capabilities.
MCP от Anthropic шипнул в 2024 и стал де-факто стандартом для AI-tooling. Технически — это JSON-RPC поверх stdio/SSE, спроектированный для desktop-app мира. На production-нагрузках видны архитектурные трещины:
✗ Нет нативного стриминга
Long-running tool calls (LLM-стримы, file uploads, log tails) — через SSE-костыли.
✗ Stateless каждый call
Каждый tool invocation пересоздаёт контекст. Жжёт токены, увеличивает latency.
✗ Нет композиции
"Get repos → filter → summarize → post to Slack" — N round-trips с полным payload.
✗ Нет подписок
Реактивные workflow (notify on new PR) — внешние poll-loops.
✗ Нет backpressure
Поток запросов может DoS-нуть tool server. Нет graceful degradation.
✗ Нет multi-agent
Agent-to-agent (Claude → Gemini) требует кастомных мостов.
✗ Нет capability model
Tool может делать что угодно. Клиент не может ограничить.
Это не баги, а следствия выбора JSON-RPC как подложки. Чтобы починить — нужен новый протокол. Quark — это он.
✓ Streaming-native
Двунаправленные стримы — first-class. Каждый call может стримить.
✓ Композиция
Pipe syntax (tool₁ | filter | tool₂) — server-side execution.
✓ Stateful сессии
Открой канал, держи контекст — экономь токены и latency.
✓ Подписки
Подпишись на события. Сервер пушит. Никакого polling.
✓ Backpressure
Встроенный flow control. Серверы троттлят gracefully.
✓ Типизация
JSON Schema повсюду. Композиция — type-checked.
✓ Multi-agent
Agent IDs в протоколе. Прямые agent-to-agent вызовы.
✓ Capability-based
Вызовы требуют capability-токены. Агент не может что не разрешено.
✓ MCP-совместимость
Adapter оборачивает существующие MCP-сервера. Zero migration cost.
Quark использует WebSocket как основной транспорт. WebSocket даёт двунаправленный стриминг, работает в каждом браузере и на любом сервере, переживает mobile-network handovers.
ws://server:port/quark
wss://server:port/quark (TLS, recommended)Для server-to-server federation допустим plain TCP с тем же framing — меньше overhead. Опциональный QUIC резервируется для v0.3+.
Каждое сообщение в линии — это frame: 4-байтовый header + JSON payload.
┌─────────┬─────────┬─────────────────────────────┐
│ version │ kind │ payload (JSON) │
│ 1 byte │ 3 bytes │ variable length │
└─────────┴─────────┴─────────────────────────────┘version— версия протокола, сейчас0x01kind— 3-буквенный ASCII opcode (см. ниже)payload— UTF-8 JSON, может быть пустым
WebSocket text-frames используются. Binary-frames зарезервированы для будущей бинарной payload (MessagePack в v0.2).
Channels
channel — это persistent stateful соединение между клиентом (AI-агентом) и Quark-сервером. Открывается на connect, закрывается на disconnect.
Внутри канала сохраняется состояние:
- Capability grants (валидны до конца канала или revoke)
- Подписки (живут пока не отписался или канал закрыт)
- Открытые tool-стримы (живы пока не completed или cancelled)
Один канал может нести несколько одновременных вызовов / стримов / подписок, различаемых через seq.
Quark v0.2 ввёл криптографически подписанные capability-токены — Quark Capability Tokens (QCT). Похоже на JWT, но spec-defined для Quark.
▸ Формат токена
qct.v1.<base64url(payload)>.<base64url(signature)>
signature = HMAC-SHA256(secret, "v1." + base64url(payload))▸ Payload
{
"iss": "https://issuer.example.com",
"sub": "[email protected]",
"iat": 1690000000,
"nbf": 1690000000,
"exp": 1700000000,
"scope": ["github:read:*", "slack:notify:#dev"],
"client_id": "claude-desktop",
"max_cost_usd": 5.00
}iss— issuer URL (required)sub— subject (user/principal) (required)iat— issued at, Unix secondsnbf— not before, optionalexp— expires, Unix seconds (required)scope— array of capability strings (required)client_id— restricts which client (optional)max_cost_usd— ceiling on total cost (optional)
▸ Capability-строки
github:read:* # read anything on GitHub
github:write:repo:owner/name # write to specific repo
slack:notify:#general # notify a specific Slack channel
slack:notify:* # notify any Slack channel
*:read # read anything anywhereCapability "a:b:c" grant'ит exact match И descendants если grant'нут "a:b:c:*".
▸ Использование
{
"kind": "HEY",
"v": 2,
"auth": { "type": "bearer", "token": "qct.v1.eyJ..." },
"agent": { "id": "claude-desktop", "kind": "llm", "name": "Claude" }
}▸ Серверная верификация
- Парсим QCT (split по ".")
- Верифицируем HMAC-подпись
- Проверяем iat <= now, nbf <= now, exp > now
- Если client_id задан — проверяем что совпадает с agent.id
- Сохраняем scope как granted capabilities канала
При неудаче — ERR { code: "AUTH_INVALID" } + close.
▸ почему важно
Без подписанных токенов AI-агент мог выдумать любые capabilities и сервер их принимал. QCT означает что только legitимный issuer может выдать токен. Это foundation для enterprise/compliance use cases (audit trails, SOC2, GDPR).
▸ клиент → сервер
▸ сервер → клиент
Каждый канал стартует с обмена HEY.
{
"kind": "HEY",
"v": 1,
"agent": {
"id": "claude-desktop-3.7-mac",
"kind": "llm",
"name": "Claude Desktop"
},
"supports": ["streaming", "subscribe", "compose", "capabilities"]
}{
"kind": "HEY",
"v": 1,
"server": {
"id": "github-tools-v2",
"name": "GitHub Tools",
"version": "2.1.0"
},
"supports": ["streaming", "subscribe", "compose", "capabilities"],
"tools": 12,
"topics": 4
}Если версии не совпадают, сервер отвечает ERR и закрывает канал.
Обе стороны обмениваются heartbeat'ами для определения мёртвых соединений (firewall timeouts, mobile NAT drops).
// Client (every 30s)
{ "kind": "HBT", "ts": 1700000000 }
// Server
{ "kind": "HBA", "ts": 1700000000 }▸ client
Не получил HBA в 60s → reconnect
▸ server
Не получил HBT в 90s → close (state хранится TTL)
После disconnect (drop, mobile sleep) клиент переподключается и шлёт RSM:
{
"kind": "RSM",
"v": 2,
"session_id": "ses_a7b3c9d1",
"last_seq_received": 42
}Сервер:
- Если session жив — реплеит буферизованные frames с seq > 42, потом продолжает
- Если истёк — ERR { code: "SESSION_EXPIRED" }, клиент fallback на свежий HEY
Subscriptions и capability grants переживают resume. Открытые tool-streams отменяются (клиент должен re-INV если нужно).
Серверы ОБЯЗАНЫ буферизовать последние 64 outgoing frames на сессию.
▸ mobile-friendly
Айфон в кармане → 4G переключается → WebSocket падает → юзер открывает приложение → client автоматически делает RSM → последние 30s пропущенных push-событий приходят разом. Никаких потерь.
Инструменты регистрируются на сервере при старте. Клиенты discoverят через LST:
{
"kind": "LST",
"seq": 1,
"tools": [
{
"name": "github.list_repos",
"description": "List repos for a user/org",
"input": { "type": "object", "properties": { "owner": { "type": "string" } } },
"output": { "type": "array", "items": { "$ref": "#/types/Repo" } },
"effects": ["network", "read"],
"cost": { "estimate": 0.0001, "currency": "USD" },
"streaming": true,
"requires_capability": "github:read"
}
]
}Tool schemas используют JSON Schema Draft 2020-12 с двумя расширениями:
effects— массив изpure | read | write | network | money | irreversible | costcost— оценённая стоимость вызова (помогает AI бюджетировать)requires_capability— capability которая нужна для вызова
▸ One-shot
{
"kind": "INV",
"seq": 2,
"tool": "github.list_repos",
"input": { "owner": "anthropic" }
}{
"kind": "RES",
"seq": 2,
"output": [{ "name": "claude-code", "stars": 12000, "owner": "anthropic" }]
}▸ Streaming
Когда у инструмента в spec streaming: true, результаты приходят чанками STR, завершается END.
// → INV { "seq": 3, "tool": "logs.tail", "input": { "file": "app.log" } }
// ← STR { "seq": 3, "data": { "line": "GET /api 200" } }
// ← STR { "seq": 3, "data": { "line": "GET /api 200" } }
// ← STR { "seq": 3, "data": { "line": "GET /api 500" } }
// ← END { "seq": 3 }Это killer-фича Quark vs MCP.
Один INV может описать pipeline. Сервер выполняет всю цепочку, отправляя клиенту только финальный результат. Никаких round-trips между шагами.
{
"kind": "INV",
"seq": 4,
"pipeline": [
{ "tool": "github.list_repos", "input": { "owner": "anthropic" } },
{ "filter": "stars > 100" },
{ "map": ["name"] },
{ "tool": "slack.notify", "input_bind": { "items": "$prev", "channel": "#dev" } }
]
}Стадии:
tool— вызов tool, output течёт в следующую стадиюfilter— CEL/SQL-like выражениеmap— проекция полейreduce— агрегацияinput_bind— байнд предыдущей output в input следующего tool
▸ эффект
4 HTTP round-trips превращаются в один. ~10× снижение latency в production workloads.
{
"kind": "SUB",
"seq": 5,
"topic": "github.pr_opened",
"filter": { "repo": "anthropic/claude-code" }
}Сервер отвечает RES с subscription id, потом стримит EVT:
{ "kind": "EVT", "seq": 5, "data": { "pr": 123, "title": "Fix typo" } }Пока клиент не пошлёт UNS с тем же seq, или канал не закроется.
Когда сервер перегружен, он шлёт WIN с меньшим окном. Клиент НЕ ДОЛЖЕН слать больше чем window outstanding requests.
{ "kind": "WIN", "window": 3 }Дефолтное окно: 64. Сервер может сжать в любой момент. Клиент обязан respect.
Capabilities
Quark v0.1 ставит минимальную capability model. Capabilities — это строки которые tool декларирует, а юзер grant'ит.
Tool декларирует: requires_capability: "github:write:repo:foo/bar"
Клиент (после согласия юзера) в HEY:
"capabilities": [
"github:read:*",
"github:write:repo:foo/bar",
"slack:notify:#dev"
]Сервер валидирует capability против granted списка на каждом INV. Если missing — ERR с кодом MISSING_CAPABILITY. В v0.2 будут cryptographically signed grants для audit/compliance.
Errors
{
"kind": "ERR",
"seq": 4,
"code": "MISSING_CAPABILITY",
"message": "Tool github.write_issue requires github:write",
"stage": 1
}Стандартные коды ошибок:
Tracing
Каждый frame может содержать tracing metadata по стандарту W3C Trace Context:
{
"kind": "INV",
"seq": 5,
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"parent_span_id": "00f067aa0ba902b1",
"tool": "github.list_repos"
}trace_id— 32 hex chars, идентифицирует distributed tracespan_id— 16 hex chars, идентифицирует span внутри traceparent_span_id— связывает span с родителем
Сервер пропагирует trace_id ко всем child-операциям (pipeline stages, federation). OpenTelemetry collectors могут ingest'ить Quark traces через sidecar который читает frames и emit'ит spans.
▸ примеры использования
- • Debugging: какие именно вызовы делал AI агент в этой сессии
- • Latency analysis: где в pipeline узкие места
- • Compliance: full audit trail кто-что-когда
- • Cost attribution: какая фича сколько потратила
Quark поставляется с MCP-Quark adapter. Любой существующий MCP-сервер можно обернуть:
[AI agent] ──Quark──> [Quark adapter] ──MCP──> [legacy MCP server]Adapter:
- Конвертит Quark INV → MCP tools/call
- Конвертит MCP ответы → Quark RES
- Теряет streaming/composition/subscriptions (MCP не поддерживает)
- Логает warning когда advanced feature запрошен
Это значит zero migration cost. Клиенты начинают использовать Quark, существующие MCPs работают через adapter, авторы мигрируют на native Quark когда захотят новые фичи.
SDKs
Reference implementations в этом репо:
▸ Go server
srv := quark.NewServer()
srv.RegisterTool(quark.Tool{
Name: "echo.upper",
Description: "Echo text in uppercase",
Handler: func(ctx context.Context, in map[string]any) (any, error) {
return strings.ToUpper(in["text"].(string)), nil
},
})
http.Handle("/quark/ws", srv)▸ TypeScript client
import { Quark } from '@fasad_salatov/quark-client'
const ch = await Quark.connect('wss://server/quark/ws', {
agent: { id: 'my-bot', kind: 'llm', name: 'My Bot' },
})
const repos = await ch.invoke('github.list_repos', { owner: 'anthropic' })
for await (const log of ch.stream('logs.tail', { file: 'app.log' })) {
console.log(log.line)
}
const filtered = await ch.pipeline([
{ tool: 'github.list_repos', input: { owner: 'anthropic' } },
{ filter: 'stars > 100' },
{ map: ['name'] },
])Roadmap
- v0.1Apr 2026initial draft, reference impls, MCP adapter
- v0.2Jun 5, 2026QCT auth, session resume, heartbeat, validation, cost tracking, tracing
- v1.0Jun 6, 2026stable. Federation, MessagePack, extended filter, schema registry, Python SDK.▸ now
- v1.1Q3 2026QUIC transport, mesh routing improvements
- v1.2Q4 2026WebRTC P2P для browser-to-browser AI агентов
- v1.3Q1 2027WASM pipeline stages (sandboxed user code)
- v2.0Q3 2027Asymmetric QCT signing (RSA/ECDSA), full CEL adoption, capability delegation chains
▸ обсуждение
Спека — открытая, MIT. Контрибутить через issues или PR на GitHub. Вопросы и интеграции — email или Telegram.