Agenti

Smyčka plánuj-jednej-pozoruj a kde se láme.

Co se naučíš: Pochopíš smyčku agenta, spočítáš si její kvadratickou cenu a budeš vědět, kdy agenta nepsat.

10 min čtení + cvičeníNavazuje na:🛠️ Nástroje (tool use)

Agent je LLM, které dostalo nástroje a smí je volat v cyklu, dokud úkol nedokončí. Místo jedné odpovědi tedy vzniká série kroků: rozmysli se → něco udělej → podívej se na výsledek → pokračuj. Umí to působivé věci, ale je to zároveň nejkřehčí konstrukce v celém oboru a nejdražší, když se to zvrtne.


Jak agent běží

Rozdíl proti obyčejnému volání: historie kroků roste a model se rozhoduje na jejím základě. S každým krokem je kontext delší, dražší a nepřehlednější.


Kdy agenta chtít a kdy ne

SituaceŘešení
Znáš postup dopředuNepiš agenta. Napiš normální kód, který volá model na jednotlivé kroky.
Kroků je pár a jsou pevnéZřetězení volání (pipeline), ne agent
Úkol vyžaduje průzkum, počet kroků není známAgent dává smysl
Chyba je drahá (peníze, mazání)Agent jen s potvrzením člověkem

⚠️ Nejčastější chyba: postavit agenta na úlohu, která je ve skutečnosti tři kroky za sebou. Pevný postup v kódu je levnější, rychlejší, testovatelný a nespadne kvůli tomu, že se model „rozhodl jinak“. Agent je poslední možnost, ne první.


Proč to selhává

  1. Nabalování chyb. Špatný krok se stane součástí kontextu a model na něm staví dál. U dvacetikrokové úlohy stačí jedna chyba na začátku.
  2. Zacyklení. Model volá pořád stejný nástroj, protože nedostává, co čeká.
  3. Kontext přeteče. Historie kroků s výstupy nástrojů roste rychle.
  4. Cena vybuchne. Každý krok je celé volání s celou historií. Dvacet kroků = dvacet volání, z nichž každé veze všechno předchozí.
  5. Špatný nástroj ve špatnou chvíli. Čím víc nástrojů, tím větší šance na omyl; nad zhruba deset se model ztrácí.

Proč cena roste kvadraticky

Tohle je nejčastější nepříjemné překvapení, a stojí za to si ho spočítat, ne odhadnout. Řekněme systémový prompt 500 tokenů, zadání 100, model si v každém kroku rozmyslí 150 tokenů a nástroj vrátí 300.

KrokKolik tokenů jde na vstup
1600
21 050
52 400
104 650
209 150

Kontext v každém kroku povyroste o 150 + 300 = 450 tokenů. Jenže platíš ho pokaždé znovu celý, takže se sčítá řada, ne konstanta. Za dvacet kroků zaplatíš 97 500 vstupních tokenů, zatímco jedno obyčejné volání by stálo 600. To je 162násobek.

A hlavně: deset kroků stojí 26 250 tokenů, dvacet kroků 97 500. Zdvojnásobení počtu kroků tedy neznamená dvojnásobnou cenu, ale skoro čtyřnásobnou. Proto je strop na počet kroků to úplně první, co do agenta zabuduješ, a proto se vyplatí historii zkracovat, ne ji nechat růst.

Prompt caching pomůže, ale míň, než by člověk čekal: stálý je jen systémový prompt, tedy 10 000 z těch 97 500 tokenů. Zbytek je pokaždé jiný, protože historie se v každém kroku mění. Viz cena a latence.


Jak agenta udržet na uzdě

  • Strop na počet kroků. Bez výjimky. Po vyčerpání vrať, co má, nebo předej člověku.
  • Rozpočet na tokeny/peníze pro jeden běh a tvrdé zastavení při překročení.
  • Oddělené čtení a zápis. Čtecí nástroje volně, zapisovací (platba, mazání, odeslání) s potvrzením.
  • Krátká a jasná zpětná vazba z nástrojů. Když nástroj selže, vrať srozumitelnou chybu, ne stacktrace na dvacet řádků, model podle ní opraví postup.
  • Zkracuj historii. Starší kroky shrň, nech jen podstatné výsledky.
  • Logování každého kroku. Bez záznamu (co model chtěl, co dostal, kolik to stálo) nemáš šanci ladit ani vyšetřit incident.

Jak vypadá ta smyčka s pojistkami

Agent není framework, je to while cyklus. Tady je celý, včetně věcí, které v tutoriálech obvykle chybí:

✂ Úryvek, ne celý program. Volané pomocné funkce jako bezpecne_spust nebo potvrzeno_clovekem si dopiš podle svého klienta. Jde o kostru a o to, kde v ní sedí pojistky.

MAX_KROKU = 12
ROZPOCET_TOKENU = 60_000

def agent(cil, nastroje, klient):
    historie = [{"role": "user", "content": cil}]
    utraceno = 0

    for krok in range(MAX_KROKU):
        odpoved = klient.zavolej(historie, nastroje=nastroje)
        utraceno += odpoved.tokeny_celkem
        log(krok, odpoved)                      # bez logu nevyšetříš vůbec nic

        if utraceno > ROZPOCET_TOKENU:
            return predej_cloveku("došel rozpočet", historie)
        if not odpoved.volani_nastroje:
            return odpoved.text                 # model tvrdí, že je hotovo

        for volani in odpoved.volani_nastroje:
            if volani.jmeno in NEVRATNE and not potvrzeno_clovekem(volani):
                vysledek = "Zamítnuto: tuhle akci musí schválit člověk."
            else:
                vysledek = bezpecne_spust(volani)   # chyby vracej jako text, ne výjimku

            historie.append(zprava_nastroje(volani, zkrat(vysledek, 800)))

        if krok == MAX_KROKU - 3:
            historie = shrn_starsi_kroky(historie)  # udělej místo, než dojde

    return predej_cloveku("došly kroky", historie)

Všimni si, že skoro všechno v tom kódu jsou pojistky, ne logika. To je na agentech to podstatné: samotná smyčka je triviální, práce je v tom, aby se nezbláznila.

Dvě věci, které se přehlížejí nejčastěji. zkrat(vysledek, 800): nástroj, který vrátí padesátikilobajtový JSON, ti sám o sobě zabije celý běh. A chyby vracej jako text do historie místo vyhození výjimky, protože model se z „soubor neexistuje, zkus jinou cestu“ dokáže vzpamatovat, zatímco spadlý proces ne.


Osvědčený vzor: plán a kontrola

Místo volného „dělej, co uznáš“ se osvědčuje:

  1. Nech model napsat plán (seznam kroků) a plán zkontroluj kódem nebo člověkem.
  2. Kroky prováděj řízeně ve svém kódu.
  3. Po každém kroku ověř výsledek a rozhodni, jestli pokračovat.

Získáš tím většinu užitku agenta a přitom máš kontrolu nad tím, co se doopravdy stane.


Jak agenta vůbec testovat

Obyčejné volání otestuješ tak, že porovnáš výstup. U agenta je výstup jen špička: stejného výsledku se dá dojít za tři kroky i za patnáct, jednou s voláním platební brány a jednou bez. Proto se u agentů měří trajektorie, ne jen odpověď:

MetrikaCo říká
Úspěšnost úkolupodíl běhů, které skončily správným výsledkem
Počet krokůmedián a p95, protože ocas tě zabije v ceně
Cena na úkoltokeny za celý běh, ne za jedno volání
Podíl zásahů člověkakolik běhů skončilo předáním
Nevratné akcekolikrát agent sáhl na něco, na co neměl

Nejdřív si postav dvacet reálných úkolů se známým výsledkem a spouštěj je při každé změně promptu nebo modelu. Bez toho neuvidíš regresi, dokud ji nenahlásí uživatel. Viz evaluace.


Cvičení

  1. Agent má strop 12 kroků. Systémový prompt 500 tokenů, zadání 100, úvaha 150, výstup nástroje 300. Spočítej celkový počet vstupních tokenů a porovnej ho s jedním běžným voláním.
  2. Tvůj agent se u třetiny běhů zacyklí na stejném nástroji. Vyjmenuj tři zásahy v pořadí, v jakém je zkusíš, a zdůvodni to pořadí.
Náčrt řešení: rozbal, až si cvičení zkusíš sám
  1. Zhruba 36 900 vstupních tokenů proti 600 u jednoho volání, tedy 62násobek. Kontext v kroku k je 600 + (k − 1) × 450, součet přes dvanáct kroků dá 12 × 600 + 450 × 66 = 36 900. Všimni si, jak se to chová: dvanáct kroků je 36 900, dvacet kroků 97 500. Skoro dvojnásobek kroků znamená dva a půl násobek ceny, protože se sčítá řada, ne konstanta.
  2. Nejdřív zpětná vazba z nástroje, pak popis nástroje, teprve pak model. Zacyklení skoro vždycky znamená, že model nedostává informaci, kterou potřebuje k dalšímu kroku: nástroj vrací prázdno, nesrozumitelnou chybu nebo příliš dlouhý výstup, ve kterém se odpověď utopí. Druhá nejčastější příčina je popis nástroje, ze kterého není jasné, kdy ho použít a kdy už ne. Výměna modelu je až poslední, protože je nejdražší a nejčastěji jen zamaskuje první dvě příčiny. K tomu vždy patří tvrdý strop na počet kroků, aby zacyklení nestálo peníze.

Shrnutí

  • Agent = model volá nástroje v cyklu, dokud není hotovo.
  • Kde znáš postup, napiš ho v kódu, agent je až poslední možnost.
  • Selhává na nabalování chyb, zacyklení, přetečení kontextu a ceně.
  • Limity kroků a rozpočtu, oddělení zápisu a logování jsou povinná výbava.
  • Cena roste kvadraticky s počtem kroků: dvojnásobek kroků je zhruba čtyřnásobek ceny.
  • Testuje se trajektorie, ne jen výsledek: kroky, cena, zásahy člověka, nevratné akce.
Máš úlohu: stáhnout fakturu, vytáhnout z ní částku a uložit do databáze. Agent, nebo obyčejný kód?

Obyčejný kód se třemi voláními modelu tam, kde je potřeba. Postup je známý a pevný, takže agent by jen přidal nepředvídatelnost, cenu a chybovost. Agent má smysl, až když počet a pořadí kroků dopředu neznáš.

Agent běží dvacet kroků a účet je desetkrát vyšší, než jsi čekal. Proč?

Každý krok je samostatné volání, které veze celou dosavadní historii včetně výstupů nástrojů. Náklady tak rostou zhruba kvadraticky. Řeší se to stropem na počet kroků, rozpočtem na běh a zkracováním historie.

Jak zabránit tomu, aby agent provedl nevratnou akci omylem?

Oddělit čtecí a zapisovací nástroje, u destruktivních akcí vyžadovat potvrzení člověkem, omezit rozsah nástroje na data, ke kterým má uživatel právo, a všechna volání logovat. Autorizace patří do kódu, nikdy do promptu.