Připojení
Typy zpráv (protokol)
Každý rámec ze serveru má type, rostoucí seq a ts (ISO UTC). Výjimka: unauthorized jde bez seq/ts a spojení se hned zavře kódem 4401. Jedno odeslání = jeden turn_id.
→ user_message
Dotaz. message_id je volitelné, vrátí se v turn_start.reply_to.
context je volitelný a platí jen pro odpověď na tuhle zprávu. Jsou v něm ID, se kterými uživatel na stránce pracuje: eshop_id, project_id, rule_id, query_id, element_id, variable_id, product_id, app_name. Každý nástroj, který dané ID bere, ho dostane, ať model vyplní cokoli. Typ se převede podle schématu nástroje. null a "" se ignorují. Neznámé pole nebo špatná hodnota vrátí error s kódem bad_context.
Výjimky: shop_id v duplicate_project a update_project je cílový eshop a nevynucuje se. Nevynucují se ani from_project_id, parent_id a pole pro hromadné akce (rule_ids…). Holé id se vynucuje jen tam, kde znamená eshop, projekt, pravidlo, dotaz, element, proměnnou nebo produkt. Pozor: s project_id míří i delete_project na tenhle projekt. Celá tabulka je v tutoriálu, krok 4.
{
"type": "user_message",
"content": "Kolik mám projektů?",
"message_id": "c1",
"context": { "eshop_id": "1276", "project_id": null }
}
→ stop
Přeruší běžící generování. Jinak přijde error s kódem not_generating.
{ "type": "stop" }
→ reset
Smaže historii. Během generování přijde error busy.
{ "type": "reset" }
→ connect_to_conversation
Pokračování dřívější konverzace. conversation_id je ze seznamu GET /conversations na REST API. Server obnoví kontext modelu a odpoví conversation_connected; přepis po WebSocketu nechodí, ten si vezmi z GET /conversations/{id}. Navázat jde i na konverzaci, ve které zrovna běží odpověď (refresh, druhá záložka): conversation_connected má generating: true a hned za ním přijde dosavadní průběh tahu (turn_start, rozepsaná bublina, čekající schválení) a pak živé delty. Když generuje konverzace, ve které právě jsi, přijde error busy; na cizí nebo neznámou konverzaci conversation_not_found.
{
"type": "connect_to_conversation",
"conversation_id": "9f2c1a7b40e5d3a8"
}
→ ping
Keep-alive. Odpověď je pong.
{ "type": "ping" }
← connected
Hned po handshake. mcp.error je string, když katalog nástrojů spadl (connected: false). conversation_id říká, do které konverzace se zapisuje; can_resume: false znamená, že se konverzace neukládají do databáze a connect_to_conversation nebude fungovat.
{
"type": "connected",
"seq": 1,
"ts": "2026-08-31T14:12:00+00:00",
"protocol_version": "1.0",
"session_id": "…",
"conversation_id": "9f2c1a7b40e5d3a8",
"can_resume": true,
"mergado_user_id": 12345,
"name": "Jan Novák",
"model": "gemma4:26b[262k]",
"expires_at": "2026-08-31T01:12:00+00:00",
"format": "markdown",
"mcp": {
"url": "https://mcp.mergado.com",
"connected": true,
"tools": ["list_apps", "chart_create"],
"error": null
}
}
← turn_start
Začátek výměny. reply_to = tvoje message_id (nebo null). Když přišel s dotazem context, vrátí se tu ověřený (prázdná pole vynechaná).
{
"type": "turn_start",
"seq": 2,
"ts": "…",
"turn_id": "turn_a1b2c3d4e5f6",
"reply_to": "c1"
}
← status
state: queued (+ workers, free_slots) · generating · calling_tools (+ tools[]) · retrying_tool (+ tools[]) · tools_preselected (+ tools[], duration_ms) · tools_unavailable (+ message).
{
"type": "status",
"seq": 3,
"ts": "…",
"turn_id": "turn_…",
"state": "calling_tools",
"tools": ["list_apps"]
}
← thinking_delta / thinking_end
Uvažování modelu (jen thinking varianty). Append text, na thinking_end blok zavři.
{ "type": "thinking_delta", "seq": 4, "ts": "…", "turn_id": "turn_…", "text": "Nejdřív zjistím…" }
{ "type": "thinking_end", "seq": 5, "ts": "…", "turn_id": "turn_…" }
← message_start
Založ prázdnou bublinu podle message_id. role je vždy assistant, format markdown.
{
"type": "message_start",
"seq": 6,
"ts": "…",
"turn_id": "turn_…",
"message_id": "msg_…",
"role": "assistant",
"format": "markdown"
}
← delta
Připoj text na konec bubliny message_id. Chunky jsou markdown, jak jdou z modelu.
{
"type": "delta",
"seq": 7,
"ts": "…",
"turn_id": "turn_…",
"message_id": "msg_…",
"text": "Máš **"
}
← message_end
Přepiš bublinu kanonickým content a vyrenderuj markdown. finish_reason: stop · tool_calls · stopped.
{
"type": "message_end",
"seq": 8,
"ts": "…",
"turn_id": "turn_…",
"message_id": "msg_…",
"content": "Máš **12** projektů.",
"finish_reason": "stop"
}
← tool_call
Model volá nástroj. arguments je objekt (prázdný {}, když JSON nešel naparsovat) a už obsahuje hodnoty vynucené z context. Co se vynutilo, je v forced. Pole přijde jen tehdy, když se nějaké ID opravdu přepsalo.
{
"type": "tool_call",
"seq": 9,
"ts": "…",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "list_shop_projects",
"arguments": { "id": "1276", "limit": 20 },
"forced": { "id": "1276" }
}
← tool_result
status: ok · error. preview je zkrácený výstup. U grafu je v artifacts jen odkaz {kind, title, message_id}, data jsou v graph_data.
{
"type": "tool_result",
"seq": 10,
"ts": "…",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "list_apps",
"status": "ok",
"duration_ms": 142,
"preview": "[{…}]",
"truncated": false,
"artifacts": []
}
← artifact · file
Soubor ke stažení. Nabídni odkaz url s name a size.
{
"type": "artifact",
"seq": 12,
"ts": "…",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "file_create_text",
"artifact": {
"kind": "file",
"title": "Export produktů",
"url": "/files/u20667-…/export.csv",
"mime": "text/csv",
"name": "export.csv",
"size": 4096
}
}
← graph_data
Vlastní blok s message_id — zařaď ho mezi textové bubliny. graph.type: pie · bar · line. Vykreslení (D3) je věc frontendu.
{
"type": "graph_data",
"seq": 13,
"ts": "…",
"turn_id": "turn_…",
"message_id": "msg_a5af39483f84",
"call_id": "call_1",
"name": "chart_create",
"title": "Podíl objednávek",
"graph": {
"type": "pie",
"title": "Podíl objednávek",
"x_label": "",
"y_label": "",
"unit": "ks",
"series": [{
"name": "Objednávky",
"points": [
{ "label": "Heureka", "value": 120 },
{ "label": "Zboží.cz", "value": 80 }
]
}]
}
}
← turn_end
Odemkni vstup. finish_reason: stop · stopped · error · max_iterations. usage je jen při normálním doběhnutí.
{
"type": "turn_end",
"seq": 14,
"ts": "…",
"turn_id": "turn_…",
"finish_reason": "stop",
"usage": {
"prompt_tokens": 41200,
"completion_tokens": 180,
"total_tokens": 41380
}
}
← error
Kódy: unauthorized · mergado_token_invalid · bad_payload · empty_message · busy · not_generating · unknown_type · llm_error (+ turn_id) · max_iterations (+ turn_id).
{
"type": "error",
"seq": 15,
"ts": "…",
"code": "busy",
"message": "Předchozí odpověď ještě běží"
}
← conversation_connected
Navázalo se na dřívější konverzaci. restored_messages je počet zpráv, které dostal do kontextu model – po ořezu historie jich může být míň, než kolik jich přepis má.
{
"type": "conversation_connected",
"seq": 2,
"ts": "…",
"conversation_id": "9f2c1a7b40e5d3a8",
"title": "Nastavení Heureka feedu",
"restored_messages": 6,
"turns": 2,
"messages": 5
}
← conversation_title
Název konverzace, který po první výměně vymyslel model. Přijde jednou za konverzaci a hodí se do seznamu vlevo; do GET /conversations se propíše taky.
{
"type": "conversation_title",
"seq": 51,
"ts": "…",
"conversation_id": "9f2c1a7b40e5d3a8",
"title": "Nastavení Heureka feedu"
}
← pong / history_cleared
Odpověď na ping / reset. Po history_cleared vymaž konverzaci.
{ "type": "pong", "seq": 16, "ts": "…" }
{ "type": "history_cleared", "seq": 17, "ts": "…" }
Typický turn: turn_start → status(generating) → message_start → delta × N → message_end → tool_call → artifact|graph_data → tool_result → nová bublina → turn_end.
Stejná dvojice tool_call / tool_result jako u MCP. Některé navíc pošlou artifact nebo graph_data ještě před tool_result.
← date_now
Aktuální datum a čas. Výchozí zóna Europe/Prague.
{
"type": "tool_call",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_now",
"arguments": { "timezone": "Europe/Prague" }
}
{
"type": "tool_result",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_now",
"status": "ok",
"duration_ms": 2,
"preview": "2026-08-31T18:40:00+02:00 (Europe/Prague)\nčesky: pondělí 31. srpna 2026, 18:40",
"truncated": false,
"artifacts": []
}
← date_shift
Posun data. Bez base počítá od teď. Kladné do budoucna, záporné do minulosti.
{
"type": "tool_call",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_shift",
"arguments": { "days": 4, "timezone": "Europe/Prague" }
}
{
"type": "tool_result",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_shift",
"status": "ok",
"duration_ms": 2,
"preview": "výchozí: 2026-08-31T18:40:00+02:00\nvýsledek:\n2026-09-04T18:40:00+02:00 …",
"truncated": false,
"artifacts": []
}
← date_diff
Rozdíl mezi dvěma daty – kalendářní i pracovní dny.
{
"type": "tool_call",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_diff",
"arguments": { "start": "2026-01-01", "end": "2026-12-24", "timezone": "Europe/Prague" }
}
{
"type": "tool_result",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_diff",
"status": "ok",
"duration_ms": 3,
"preview": "od 2026-01-01T00:00:00+01:00 do 2026-12-24T00:00:00+01:00\nkalendářních dnů: 357, pracovních dnů: 255",
"truncated": false,
"artifacts": []
}
← date_parse
Rozpozná volný zápis data. output_format: iso · cs · date_only.
{
"type": "tool_call",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_parse",
"arguments": { "text": "24. prosince 2026 18:30", "timezone": "Europe/Prague", "output_format": "iso" }
}
{
"type": "tool_result",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "date_parse",
"status": "ok",
"duration_ms": 2,
"preview": "2026-12-24T18:30:00+01:00 (Europe/Prague)\nčesky: čtvrtek 24. prosince 2026, 18:30",
"truncated": false,
"artifacts": []
}
← file_create_text
Soubor ke stažení. format: md · txt · csv. Před výsledkem přijde artifact s kind: "file".
{
"type": "tool_call",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "file_create_text",
"arguments": {
"filename": "export-projektu",
"format": "csv",
"content": "id,name\n1,Shop",
"title": "Export produktů"
}
}
{
"type": "artifact",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "file_create_text",
"artifact": {
"kind": "file",
"title": "Export produktů",
"url": "/files/u20667-…/export-projektu.csv",
"mime": "text/csv; charset=utf-8",
"name": "export-projektu.csv",
"size": 18
}
}
{
"type": "tool_result",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "file_create_text",
"status": "ok",
"duration_ms": 12,
"preview": "Soubor export-projektu.csv (18 B) je připravený ke stažení…",
"truncated": false,
"artifacts": [{
"kind": "file",
"title": "Export produktů",
"url": "/files/u20667-…/export-projektu.csv",
"mime": "text/csv; charset=utf-8",
"name": "export-projektu.csv",
"size": 18
}]
}
← chart_create
Data pro graf. type: pie · bar · line. Před výsledkem přijde graph_data s vlastním message_id. Koláč = 1 řada, bez záporných hodnot.
{
"type": "tool_call",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "chart_create",
"arguments": {
"type": "pie",
"title": "Podíl objednávek",
"unit": "ks",
"series": [{
"name": "Objednávky",
"points": [
{ "label": "Heureka", "value": 120 },
{ "label": "Zboží.cz", "value": 80 }
]
}]
}
}
{
"type": "graph_data",
"turn_id": "turn_…",
"message_id": "msg_a5af39483f84",
"call_id": "call_1",
"name": "chart_create",
"title": "Podíl objednávek",
"graph": {
"type": "pie",
"title": "Podíl objednávek",
"x_label": "",
"y_label": "",
"unit": "ks",
"series": [{
"name": "Objednávky",
"points": [
{ "label": "Heureka", "value": 120 },
{ "label": "Zboží.cz", "value": 80 }
]
}]
}
}
{
"type": "tool_result",
"turn_id": "turn_…",
"call_id": "call_1",
"name": "chart_create",
"status": "ok",
"duration_ms": 4,
"preview": "Graf „Podíl objednávek“ (pie, 1 řad, 2 bodů) se uživateli vykreslil.",
"truncated": false,
"artifacts": [{ "kind": "chart", "title": "Podíl objednávek", "message_id": "msg_a5af39483f84" }]
}