13. července 2026

Malé úniky: co stojí latenci, když se na to zapomene

Když si tým stanoví cíl „odpověď do tří sekund", často si představuje, že jde o jeden velký problém - rychlejší model, lepší vyhledávání. Ve skutečnosti je to budget, rozepsaný na desítky malých výdajů, a často není jeden velký výdaj ten, co vás vyvede z limitu. Jsou to drobné úniky, žádný sám o sobě nevýznamný, ale dohromady rozhodující. Tady jsou čtyři, na které se často zapomíná.

Streamuj, nečekej

Největší vnímaná latence není doba, než odpověď skončí - je to doba, než se co první objeví. Uživatel, který vidí, jak se text začíná sypat, čeká trpělivě. Uživatel, který zírá na spinner, čeká netrpělivě už po vteřině. Z toho vyplývá pravidlo: streamujte tokeny, jakmile je máte. Nečekejte, až bude odpověď kompletní, než ji pošlete. Každý chunk, který pošlete dřív, posouvá vnímanou rychlost dolů, i když celkový čas je stejný.

A tohle se škáluje. Pokud odpověď přináší entity - klikatelné karty, detaily - nepošlete je až po textu. Pošlete je paralelně, ve vlastním framu, ještě než text skončí. Frontend pak má data k popoveru rovnou, když uživatel na odkaz klikne - žádný spinner, žádný druhý request. Paralelizovat framy je stejný trik jako paralelizovat tool cally: nezávislá práce má běžet souběžně, ne za sebou.

Žádný nový handshake

Tady je únik, který vypadá nevinně, ale časem nasčítá. Když váš agent volá embedding API na každý dotaz a každé volání otevírá fresh TLS spojení, platíte handshake - desítky milisekund - na každém requestu. Na jednom requestu to nikdo nepozná. Na tisících requestů denně je to konzistentní daň, která nic nepřináší.

Řešení je sdílený keep-alive pool - spojení se otevírá jednou a drží se, další volání ho reuseují. Žádný fresh handshake, žádná čekání na TCP a TLS. Je to jeden z těch triků, které nevyřeší váš hlavní bottleneck, ale uvolní budget, který pak chybí něčemu důležitějšímu.

Selhej potichu, nepřerušuj

Co se stane, když tool selže v agent loopu? Naivní verze vyhodí výjimku, loop se zhroutí, uživatel dostane chybu, konverzace se musí restartovat. To je drahé nejen proto, že uživatel odešel - je to drahé i v latenci, protože restart znamená celý turn znovu, od nuly.

Lepší invariant: každý tool selhává potichu - vrátí zprávu o chybě místo výjimky. Agent loop se nepřeruší. Model dostane „tento tool teď nefunguje, zkus to jinak" a pokračuje. Většina turnů, kde se něco rozbije, se tak dokončí s rozumnou odpovědí („nenašel jsem to, ale tady jsou alternativy") místo tvrdé chyby. A ty, které se nedokončí, stojí jeden turn, ne celý restart. Soft-fail není jen hezčí UX - je to latenční optimalizace, protože eliminuje práci, kterou byste museli dělat znovu.

Skonči, když můžeš

Poslední únik je ten nejzáludnější, protože vypadá jako správná práce. Agent rozpozná, že dotaz je nejednoznačný, a má se uživatele zeptat na upřesnění. Instinkt je: zeptej se, a pak počkej, co model řekne dál. Ale v tu chvíli není co říkat - odpověď je ta otázka. Přesto necháváte agenta dělat další model-call, aby „shrnil" situaci, kterou už shrnul.

Řešení je early termination: jakmile je formulářová otázka hotová, turn končí. Žádný další model-call. Je to jeden z těch momentů, kdy agent loop musí vědět, kdy se zastavit - a tým, který ho k tomu nepřinutí, platí celý extra model-call za odpověď, která už byla napsaná. Můžete tomu říkat return_direct: výsledek toolu je odpověď, model se už nevolá.

Co si vzít s sebou

Žádný z těchto úniků sám o sobě neudělá z pomalého bota rychlý. Ale dohromady tvoří rozdíl mezi týmem, který se vejde do limitu, a týmem, který se nevejde a neví proč - protože žádný jediný krok nevyčnívá. Streamujte, co máte, posílejte paralelní framy, držte keep-alive, selhávejte potichu, končete, když už je odpověď napsaná. Budget na latenci se nevyčerpá jedním velkým výdajem; prosvědčí ho spousta drobných, které nikdo nesledoval.


Váš bot se „vejde do tří sekund" většinou, ale občas ne, a nevíte proč? Většinou to nejsou velké věci - jsou to úniky, které se nasčítají. Pojďme si je najít.