Jak děláme software s AI agenty (a kde nás to zradilo)
Jak reálně používáme AI agenty při vývoji — orchestrátor + workeři, reference discovery, spec-driven workflow. A war story o tom, jak populární .NET abstrakce tiše vypnula prompt caching a my jsme platili zbytečně.
Rok zpátky jsem byl skeptický. Ne vůči AI jako takové — vůči způsobu, jakým se o ní mluvilo. „AI nahradí vývojáře." „Stačí prompt." „Copilot to napíše za vás." Pak jsem začal AI agenty reálně používat ve vlastních projektech, sledovat co funguje a co ne, a obraz se zkomplikoval.
Tenhle článek není o tom, jak je AI skvělá. Je o tom, jak ji konkrétně zapojujeme do vývoje, a o jednom incidentu, který nás stál víc peněz než bylo nutné — a naučil nás testovat abstrakce jinak.
Architektura, kterou používáme: orchestrátor + workeři
Naše AI workflow má dvě vrstvy.
Silný model (orchestrátor) drží celkový kontext. Plánuje. Dělá reference discovery — projde kód a najde VŠECHNA dotčená místa před každou změnou. Reviewuje výstup ostatních agentů. Rozhoduje, co je edge case a co je halucinace. Tahle práce stojí tokeny, ale vyplatí se — silný model tady dělá přesně to, v čem je dobrý.
Slabší, levnější modely (workeři) dostávají izolované, dobře definované kroky. Přidej import do 15 souborů. Vygeneruj test scaffold podle tohoto vzoru. Scrapni výsledky buildu. Přepiš DTO podle nové struktury. Tyhle kroky jsou dobře specifikovatelné, nevyžadují cross-file reasoning a jdou spustit paralelně. Workeři jsou levní a rychlí — a pokud jeden udělá chybu, orchestrátor ji ve review zachytí.
Jde o stejný princip jako u lidských týmů: senior drží architekturu a rozhodnutí, ostatní exekuují dobře definované kusy. Rozdíl je v rychlosti — paralelní workeři zpracují za minutu práci, která by jednomu člověku trvala hodinu.
Ale funguje to jen tehdy, když je práce opravdu dobře specifikovaná. Vágní zadání dá vágní výsledek. To platí pro juniora a platí to i pro AI.
Reference discovery: ponaučení z reálného incidentu
Jedna z prvních lekcí, které nás AI agenti naučili, nebyla o AI. Byla o disciplíně.
Při napojování SignalR handleru do frontendu jsme nechali agenta provést změnu. Změna vypadala správně. Testy prošly. Až za tři dny se ukázalo, že wiring funguje ve třech ze osmi míst — zbytek si agent tiše přeskočil, protože to nebylo ve stejném souboru.
Od té doby platí pravidlo: před každou změnou najdeme VŠECHNA místa, která se jí týkají. Teprve pak měníme. Agenti umí vyhledat reference rychle a důkladně — ale musíme jim to explicitně zadat. Bez toho optimalizují pro to, co vidí, ne pro to, co existuje.
Reference discovery je nuda. Je to práce, která se netočí v demo videu. Ale je to rozdíl mezi změnou, která funguje, a změnou, která vypadá že funguje.
Spec před kódem, ne po
Druhý posun byl v pořadí práce. Dřív jsme psali specifikaci jako dokumentaci po faktu — pokud vůbec. AI agenti to zhoršili: s AI jde vygenerovat kód rychle, ale rychle vygenerovaný kód bez specifikace je rychle vygenerovaný problém.
Teď platí pravidlo: spec je dohoda před začátkem, ne popis po skončení. Spec říká, co musí platit, proč, a jaká rozhodnutí za tím stojí. Kód je jenom implementace dohodnutého chování.
Výhoda: když agent navrhne řešení, které sedí na spec, je to dobrý návrh. Když ne, víme proč ne. Bez spec se každá AI halucinace musí vysvětlovat celým kontextem — a to zdražuje každé kolo review.
War story: jak nás Microsoft.Extensions.AI tiše okralo o peníze
Tohle je centrální příběh článku, protože ilustruje kategorii chyb, na kterou si AI abstrakce nestřeží.
Pracujeme s více poskytovateli LLM zároveň — Claude, OpenAI, Gemini, Grok — pod jednou abstrakcí. Microsoft.Extensions.AI je rozumná volba pro unifikované rozhraní: jeden interface pro více providerů, výměna konfigurace, žádný vendor lock-in na úrovni kódu.
Jenže jsme si všimli, že náklady na tokeny neklesají tak, jak by měly. Měli jsme nastavené prompt caching pro system message — což u Claude Sonnet a Opus ušetří až 90 % ceny u opakovaných volání. Model pracuje s dlouhými systémovými prompty, takže caching je u nás materiální rozdíl.
Jenomže caching nefungoval. Ne zjevně — žádná chybová hláška, žádný warning. Tokeny se prostě počítaly plnou cenou.
Chvíli jsme hledali konfiguraci. Pak jsme napsali integrační test, který porovnal očekávané cache hity s reálnými — a test selhal. Žádné cache hity. U žádného volání.
Příčina: Microsoft.Extensions.AI v té verzi tiše droppovala cache_control parametr, který Anthropic API vyžaduje pro označení tokenů k cachování. Abstrakce ho ignorovala — buď ho nepodporovala, nebo ho nepropagovala do raw requestu. Z pohledu kódu vypadalo vše správně. Z pohledu provider API jsme posílali requesty bez instrukce cachovat.
Řešení bylo přímočaré: u tohoto klienta jsme obešli abstrakci a šli na raw endpoint poskytovatele s fine-grained kontrolou. Prompt caching má model-specifické minimální prahy — přibližně 1024 tokenů pro Sonnet a Opus, 2048 pro Haiku. Musíte označit správné bloky, ve správném pořadí, se správnou minimální délkou. Abstrakce tenhle detail skrývala — a skryla ho špatně.
Lekce: Abstrakce ti může tiše ukrást chování. Nestačí otestovat happy path — musíš testovat hranici. U kritické integrace (cena, bezpečnost, stav) chceš vědět, co reálně přechází přes drát, ne co říká high-level API.
Dnes máme integrační test, který u každého providera ověří, že cache hity odpovídají očekávání. Nestačí, že volání neselže. Musí proběhnout tak, jak jsme chtěli.
Co AI reálně zrychluje — a co ne
Po roce práce s AI agenty mám dost dat na střízlivé srovnání.
AI zrychlí:
- Dobře specifikovanou, opakující se práci. Boilerplate, mappers, testy podle vzoru, rename napříč soubory.
- Exploration kódu. Najít kde je co definováno, jaké jsou všechny reference, jaký pattern se používá jinde v projektu.
- První draft. README, spec, PR popis, migration script. Výstup potřebuje review, ale výchozí bod je rychlejší.
AI nezrychlí:
- Architekturu. Která abstrakce je správná, jak rozdělit zodpovědnosti, kde bude bottleneck při škálování — tohle vyžaduje úsudek, který AI nemá.
- Integraci. Kde přesně se dvě systémy dotýkají, co se stane při chybovém stavu, co je reálné chování třetí strany versus co říká dokumentace — AI halucinuje, ne měří.
- Diagnostiku. Proč produkt neobsahuje cache hity? Proč je latence výrazně vyšší než v dev? AI odhaduje. Senior inženýr trasuje.
Nejnebezpečnější kombinace je junior vývojář a AI bez senior review. Výstup vypadá správně. Má typy, má testy, projde PR. A obsahuje bug, který se ukáže až v produkci, protože model nevěděl, co neví — a junior to nezachytil, protože to nezachytí AI.
Senior review je ten multiplikátor. Ne kontrola kvůli nedůvěře — je to vrstva úsudku, kterou AI nedodá.
Kde jsme dnes
V projektech běžíme s více poskytovateli LLM pod jednou abstrakcí a s vlastními MCP servery, které vystavují naše systémy AI agentům — katalogy, workflow, business data. Každé LLM volání má budget gate a auditní log. Náklady jsou předvídatelné a měřitelné, ne výsledek promptu bez přemýšlení.
Ale nejcennější věc, kterou jsme se naučili, není technická. Je to disciplína: reference discovery před každou změnou, spec před kódem, integrační test pro každou kritickou abstrakci. S AI nebo bez ní.
FAQ
Jaký model používáte jako orchestrátor?
Aktuálně Claude Opus nebo Sonnet pro orchestraci (velký kontext, dobrá reference discovery), levnější modely pro izolované kroky. Konkrétní volba se mění s každou novou verzí — testujeme a přehodnocujeme.
Jak testujete, že prompt caching reálně funguje?
Integrační test, který udělá dvě identická volání za sebou, porovná cache_read_input_tokens v response metadatech s input_tokens a ověří, že druhé volání mělo cache hit. Pokud ne, test selže — a víme to dřív, než nás to stojí peníze.
Kdy AI agenty nedoporučujete?
Při práci, kde je klíčový úsudek v kontextu, který agent nemá. Bezpečnostní architektura, databázová migrace s produkcí na drátě, ladění reálného výkonu — tady je AI nejvýš pomocník pro exploration, ne rozhodovatel. A vždy, když výstup jde přímo do produkce bez senior review.