Tuhle situaci je dobré poznat na první pohled, proto začneme právě jí. Dopsali jste hru, skóre se po restartu vynuluje a ptáte se agenta:

Proč se po restartu ztrácí skóre?

Odpověď přijde klidná a uhlazená:

Skóre se v projektu už ukládá, jen zápis není nikde zapnutý.
Stačí změnit jedno nastavení a výsledek přežije restart.

Jdete si to ověřit. Ani nastavení, ani ukládání skóre v projektu neexistuje a nikdy neexistovalo - ani řádek, ani náznak. Odpověď zněla jako rozbor vašeho kódu, ale byl to jen předpoklad o tom, jak bývají takové projekty obvykle uspořádané.

A přitom tomu nepředcházela žádná pauza ani výhrada. Intonace je přesně stejná jako u všech předchozích odpovědí, které se ukázaly jako správné. Nástroj přitom funguje a model není horší než včera.

Důvod je v tom, jak odpověď vůbec vzniká. Model nevytahuje hotový fakt z nějakého úložiště - vybírá pravděpodobné pokračování vašeho textu, kousek po kousku. Jenže pravděpodobné a správné jsou dvě různé věci, zvlášť když jde o váš projekt, který model nikdy neviděl. Vymyšleným, ale věrohodným podrobnostem se obvykle říká halucinace.

Stůl rozdělený napůl: vlevo ve tmě rozložené vykládací karty a hrací kostky, vpravo v paprsku světla otevřená kniha se záložkami a lupou

Dál - kde číhají pasti, proč má chyba vždycky klidný tón a které tři kontroly pokryjí většinu takových případů.

Co model vidí ve vašem požadavku

Tahle past je ze všech nejjednodušší: zdá se, že se model dívá na váš projekt. Ve skutečnosti vidí jen to, co dostal, a dostává tohle:

  • Vestavěné znalosti. Zákonitosti, které se během tréninku usadily v parametrech modelu. Nejsou to kartičky s fakty a odkazy, ale čísla, a proto model může i známý fakt zopakovat nepřesně. A mají časovou hranici: o knihovně, která vyšla později, model ví přesně tolik, kolik mu z ní ukázali.
  • Aktuální konverzace. Váš požadavek, historie konverzace, soubory, které agent přečetl, výstup příkazů, které spustil.
  • Paměť aplikace. To, co je uložené v samostatných souborech a vkládá se do konverzace na začátku další relace. V Claude Code je to CLAUDE.md, který píšete vy, a auto memory, kam si agent zapisuje poznámky sám.
  • Vnější zdroje. Dokumentace, vyhledávání, databáze, soubory projektu - všechno, co v trénovacích datech být nemuselo nebo se od té doby změnilo.

Poslední tři přicházejí stejnou cestou: aby ovlivnily odpověď, musí se dostat do aktuální konverzace. Sám od sebe se model do projektu nepodívá.

Z toho plyne důsledek, který stojí za to si jednou provždy srovnat v hlavě. Soubor, který nikdo neotevřel, pro model neexistuje. Dokud se jeho text nedostane do konverzace, je poctivější číst otázku "kde se u nás řeší autorizace" jako "jak se takový soubor v podobných projektech obvykle jmenuje". Odpověď dostanete v obou případech a bude vypadat úplně stejně.

Hned vedle číhá menší, zato nepříjemná past. Přečtený soubor zůstává v konverzaci takový, jaký byl ve chvíli čtení. Opravili jste řádek u sebe v editoru, ale v historii konverzace leží stará verze. Claude Code sice označí, že se soubor změnil, ale jestli si ho agent přečte znovu, už rozhoduje model. Upravovali jste ručně uprostřed konverzace? Spolehlivější je přímo ho požádat, ať si soubor přečte znovu.

Na co se dívat v Claude Code

Claude Code nejdřív čte projekt a spouští příkazy, a teprve potom odpovídá. V odpovědi je obvykle vidět, které soubory otevřel a co spustil. Pokud se odpověď o vašem kódu objevila dřív, než agent vůbec něco přečetl, díváte se na předpoklad o typickém projektu, ne na rozbor toho vašeho.

Proč formulace mění výsledek

Ze všeho, co se dostane do konverzace, je váš požadavek to jediné, co píšete sami. Proto v něm rozhodují i maličkosti: přehodíte pár slov, přidáte upřesnění - a odpověď se stočí jinam. Není to rozmar nástroje.

Tady se snadno zamotáte, tak to řeknu zvlášť. I stejný požadavek zadaný dvakrát dává různé odpovědi: do odpovědi nemusí jít ta nejpravděpodobnější varianta pokračování, generování má nastavení, která určují, jak ochotně se vezme i varianta méně pravděpodobná. Nabízí se otázka: když odpověď stejně kolísá, co s tím mají moje slova. Rozdíl je v tom, co přesně kolísá. Rozptyl mezi stejnými požadavky je šum kolem jedné a téže volby: formulace se budou lišit, směr zůstane stejný. Kdežto slova v požadavku posouvají samotný směr, a to spolehlivě.

Nejhůř funguje vágní prosba. Nechává modelu volbu, a model volí to, co je nejpravděpodobnější obecně - průměr ze všeho, co kdy viděl. Vezměte si obyčejné "zkrať text". O kolik - o pár procent, o třetinu, na polovinu? Co se dá vyhodit a na co se sahat nesmí? Na žádnou z těch otázek prosba neodpovídá, takže odpovídat bude model, a formálně bude mít pravdu. Zato "zkrať popis o 30 %" nebo "zkrať popis na 300 znaků" mu nenechávají volbu tam, kde je ta volba vaše.

Dobře je to vidět na dvojici požadavků na totéž. "Oprav řazení" nechává otevřené všechno: jaký seznam, podle kterého pole, co se vůbec považuje za chybu. Zato druhá formulace nenechává otevřeného skoro nic:

V seznamu objednávek jdou data od nejstarších k nejnovějším, potřebuji to obráceně.
Nejdřív ukaž soubor a řádek, kde je nastavené pořadí řazení, a teprve potom navrhni opravu.

Je delší přesně o tolik, kolik si první formulace žádala hádání. A navíc za vás udělá polovinu kontroly: agent přinese místo v kódu dřív, než se na něj zeptáte.

Závěr je jednoduchý: čím méně volnosti v požadavku, tím méně hádání v odpovědi. Nejde o kouzelná zaklínadla, ale o obyčejnou věc - rámec buď určíte vy, nebo ho zvolí někdo za vás.

Sebevědomý tón neznamená fakt

A tady je hlavní past. Model nemá jednu intonaci pro "tohle vím jistě" a jinou pro "tohle jsem si právě domyslel": obě věty vznikají stejným způsobem a zní stejně klidně. Souvislost tu není úplně nulová, ale k užitku není: sebejistota modelu je vždycky nadsazená, takže podle tónu ověřené od domyšleného nerozeznáte.

V běžném textu vás podivné tvrzení praští do očí a sami zpomalíte. V kódu tahle ochrana nefunguje: názvy vypadají správně, konstrukce jsou povědomé a skutečnou metodu knihovny od metody poskládané podle analogie na první pohled nerozeznáte, pokud tu knihovnu neznáte nazpaměť. Proto se přešlap většinou ukáže až při spuštění, ne při čtení.

Navíc název bývá málokdy vymyšlený úplně od nuly. V jednom rozboru generovaného kódu, kde se hledaly odkazy na neexistující knihovny, byla víc než třetina takových názvů slepená ze dvou skutečných. Odtud ten pocit věrohodnosti: části názvu jste už někde viděli, jen ne v téhle kombinaci.

Čtyři případy, které poznáte hned napoprvé, když víte, co hledat:

Jak to vypadáCo se staloJak to odhalit
u příkazu je uveden přepínač, který neexistujemodel poskládal řádek podle obvyklého vzoru, proto přepínač vypadá jako skutečnýnápověda příkazu nebo jeho dokumentace
je uveden soubor, funkce nebo konfigurační pole, které v projektu nejsounázev vypadá typicky pro takový projekt, ale projekt nikdo nečetlhledání v projektu, žádost ukázat řádek
sebevědomě popsáno, jak je váš projekt postavenýv konverzaci nebyl ani jeden soubor projektu, proto je popsán typický projektzeptat se, které soubory před odpovědí otevřel
hlášeno "hotovo", ale příkaz se nespustilhlášení vzniklo z textu úkolu, ne z výsledku spuštěníspustit sami a podívat se na výstup

Všechny čtyři mají jedno společné: odpověď zní jako výsledek práce, i když za ní žádná práce nebyla.

Posledním případem je dobré se zabývat zvlášť, protože vypadá jako podvod, a podvod to není. Agent se zastaví, když práce vypadá hotově. Pokud nemá co spustit, je "vypadá hotově" jediný signál, který má, a kontrolní smyčkou se stáváte vy.

Cena je tu měřitelná. V jednom rozboru logů agentů tvořila falešná "hotovo" skoro polovinu všech neúspěchů. A tam, kde se stav ověřoval nezávisle na hlášení samotného agenta, takové případy téměř zmizely. V tom je smysl druhé kontroly z další sekce: místo hlášení nabízí to, co si můžete prohlédnout na vlastní oči.

Zbývá otázka, proč model raději domýšlí, než aby přiznal, že neví. Jde o to, jak ho učili a jak ho hodnotili. Představte si test s možnostmi, kde za prázdný list je jistá nula a za náhodně zaškrtnutou odpověď šance na bod. Mlčet se v takovém systému nevyplatí nikdy a odpovídat i při sebemenší nejistotě dává smysl. Člověk se pak přeučí na skutečných úkolech, kde špatná odpověď stojí víc než poctivé "nevím". Model takové přeučení nemá.

Požádat model, aby poctivě upozornil, když si není jistý, pomáhá - jenže i to je text poskládaný stejným mechanismem. Jako doplňkový signál poslouží, jako náhrada kontroly ne.

Nástroje zmenšují slepé skvrny

Tady se vyplatí oddělit dvě slova, která se v řeči obvykle házejí do jednoho pytle. Model umí přesně jednu věc: dostat konverzaci a vrátit pokračování. Agent je program kolem modelu, který má nástroje: čtení souboru, spuštění příkazu, úpravu projektu.

A teď detail, na kterém závisí, kde přesně chyba vzniká. Nástroje nevybírá program. Model ve své odpovědi požádá o otevření určitého souboru nebo spuštění určitého příkazu, a program tuto žádost zkontroluje, provede a vrátí výsledek zpět do konverzace. Rozhoduje model, akci provádí program. Takže se může splést i samotné rozhodnutí: jiný soubor, jiný příkaz, jiný test.

Rozdíl je i tak obrovský. Dokud soubor není otevřený, odpověď o něm vzniká podle vzpomínek na podobné projekty. Jakmile je soubor přečtený a test proběhl, objeví se v konverzaci fakt: tady je obsah, tady je výstup. To už není vzpomínka, ale ověření, a kvalita odpovědí je potom znatelně jiná.

Odtud trik, který stojí jeden řádek na začátku konverzace:

Nejdřív najdi a ukaž, kde to v projektu je, a teprve potom vysvětluj.

Slepé skvrny se tím zužují, ale nemizí. Agent může otevřít vedlejší soubor místo toho správného, vyložit si výstup příkazu po svém nebo se zastavit u prvního věrohodného vysvětlení a ke skutečné příčině se nedostat. Tohle všechno jsem viděl, a ne jednou. Proto vnější signál - výstup testu, text dokumentace, obsah souboru - váží víc než i ta nejsebejistější úvaha bez opory.

Tři kontroly, které stojí minutu

Dobrá zpráva je, že takové přešlapy se dají odhalit skoro bez námahy. Všechno se scvrkne na jedno rozcestí.

Rozcestí při kontrole odpovědi: pokud odpověď neodkazuje na soubor, příkaz nebo test, bere se jako hypotéza a žádá se ukázání místa; pokud odkaz obsahuje, výsledek si ověříte samiOdpověď agentaOdkazuje na soubor,příkaz nebo test?Bereme jako hypotézužádáme ukázat místoOvěřujeme samiotevřeme, spustímeneano
Rozcestí je stejné u každého úkolu: nejdřív v odpovědi hledáme oporu, pak se rozhodneme, jestli ověřovat, nebo se doptat

Dívat se tu nemusíte na to, jak přesvědčivě je odpověď napsaná, ale na to, jestli je v ní něčeho se chytit: konkrétní soubor, konkrétní řádek, příkaz s jeho výstupem. Chybí opora - pak máte před sebou zatím hypotézu, ne výsledek. Takhle začíná spousta odpovědí, otázka je jen, co s tím uděláte dál.

Následují tři kontroly. Každá zabere méně než minutu a všechny tři najednou jsou potřeba jen zřídka.

  1. Požádat o ukázání místa. Ne "vysvětli podrobněji", ale "ukaž soubor, řádek a samotný úryvek". Pokud to místo neexistuje, vyjde to najevo hned.
  2. Otevřít nebo spustit výsledek sami. Stránku v prohlížeči, příkaz v terminálu, test v projektu. Hlášení o práci a práce samotná nejsou totéž.
  3. Ověřit tvrzení o nástroji přímo v nástroji. Příkaz má vestavěnou nápovědu, knihovna dokumentaci. Uvedený přepínač nebo konfigurační klíč tam buď je, nebo není, a zjistíte to za půl minuty. U metody knihovny je třeba víc opatrnosti: do dokumentace se nedostane všechno, takže když tam metoda chybí, je to důvod se doptat, ne definitivní verdikt.
Formulace, která šetří čas

Místo dohadování s odpovědí si o oporu řekněte napřímo:

Ukaž soubor a řádek, kde je to popsané.
Pokud takové místo v projektu není, řekni rovnou, že jde o předpoklad.

Dva řádky, které se vyplatí mít po ruce. První pošle agenta do projektu, místo aby odpovídal podle vzpomínek na podobné projekty. Druhý mu dává únikovou cestu: říct, že takové místo není, ho vyjde levněji než dotáhnout odpověď do věrohodné podoby.

U hlášení "hotovo" funguje stejná žádost, jen ohledně spuštění: "ukaž příkaz, který jsi spustil, a celý jeho výstup".

Záruka to není: věta "jde o předpoklad" vzniká stejným mechanismem jako všechno ostatní. Šanci na přešlap snižuje, kontrolu nenahrazuje.

A rovnou jedna poznámka, ať vám nezůstane špatná pachuť. Ověřovat neznamená nedůvěřovat nástroji. Vlastní diff si před commitem taky pročítáte, přestože jste ho psali sami. Tady je to totéž, jen důvod je o něco vážnější.

Co to znamená pro práci s Claude Code

Co z toho všeho plyne přímo u klávesnice:

  • odpověď s odkazem na soubor, řádek nebo výstup příkazu ověříte během pár sekund. Odpověď bez nich nemáte čím ověřit: zbývá ji jen přečíst a souhlasit;
  • nechte agenta přečíst, co je potřeba, ještě než položíte otázku. Jeden krok navíc odstraní celou třídu přešlapů;
  • podle sebejistoty soudit nelze: je nadsazená bez ohledu na to, jestli za slovy stojí ověření, nebo odhad;
  • "zní správně" a "funguje správně" jsou dvě různé věci a rozliší je jen spuštění;
  • čím dražší je chyba, tím dřív by se v konverzaci mělo objevit něco vnějšího: test, dokumentace, skutečný soubor. U drobné úpravy stačí pohled na diff;
  • když se agent spletl, řekněte mu to jako fakt, ne jako hodnocení. "Taková funkce v projektu není, tady je, co ve složce opravdu leží" posune práci dál, "zase sis všechno vymyslel" ji neposune nikam. A mějte na paměti: na sebejistou námitku se agent spíš přizpůsobí, než aby se přel, i když pravdu měl on. Souhlas agenta není potvrzením, že máte pravdu vy.

Mechanismus, který se občas sebejistě mýlí, přitom zůstává nesmírně užitečný. Znát jeho hranice potřebujete právě proto, abyste neztráceli čas údivem a rovnou přešli ke kontrole.