Mergado Chat – WS konzole

„Swagger" pro WebSocket: přihlaš se, posílej zprávy, koukej na syrové události. REST API má vlastní Swagger na odpojeno

Připojení

Login vrátí secret token zamčený na tvoji IP.
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.

Klient → server
→ 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" }
Server → klient
← 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.

Lokální nástroje (ne MCP)

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" }]
}

Konverzace

Síťová komunikace