Agenci AI i ich tożsamość — dlaczego persona jest ważniejsza od promptu i ile kosztuje w tokenach
Nadanie agentowi wyraźnej tożsamości — zakresu, narzędzi, stylu, definicji ukończenia — to najtańszy sposób na poprawę jakości i najdroższa pozycja na rachunku za tokeny, jeśli zrobi się to bez zrozumienia mechaniki. Oto inżynieria i matematyka.
- AI Agents
- Claude API
- Prompt Caching
- Tokens
- LLM
Wstęp
W 2026 roku "napisz dobry prompt" przestało być architekturą. Zespoły, z którymi pracuję, nie budują już jednego wielkiego promptu obsługującego wszystko. Budują agentów: wyspecjalizowane jednostki z własnym zakresem odpowiedzialności, własnym zestawem narzędzi i własną tożsamością.
Brzmi jak kosmetyka? Nie jest. Tożsamość agenta to jednocześnie najtańszy sposób na poprawę jakości odpowiedzi i najdroższa pozycja na rachunku za tokeny — jeśli zbudujesz ją bez zrozumienia tego, co dzieje się przy każdym pojedynczym zapytaniu.
Ten artykuł dotyczy trzech rzeczy: z czego naprawdę składa się tożsamość agenta, dlaczego zmienia zachowanie modelu i jak dokładnie przekłada się na tokeny oraz pieniądze.
Czym jest "tożsamość" agenta
Tożsamość to nie imię i miłe przywitanie. W praktyce to pięć warstw, a każda z nich jest nośna:
| Warstwa | Na jakie pytanie odpowiada | Gdzie żyje |
|---|---|---|
| Rola i zakres | Do czego ten agent służy — i do czego wprost NIE służy? | System prompt |
| Granica narzędzi | Jakie akcje może w ogóle wykonać? | Definicje narzędzi |
| Styl i format | Jak raportuje? Proza, JSON, diff? | System prompt + structured outputs |
| Definicja ukończenia | Kiedy zadanie jest skończone? | System prompt |
| Pamięć | Co wie z poprzednich sesji? | Narzędzie memory / zewnętrzny store |
Najciekawsze jest to, że te warstwy nie są dokumentacją dla ludzi. Są przestrzenią poszukiwań, w której operuje model. Wąska, jawna tożsamość eliminuje całe klasy błędnych decyzji, zanim model je podejmie.
using Anthropic;
using Anthropic.Models.Messages;
// Tożsamość to stabilny artefakt — traktuj ją jak kod, nie jak literał
// stringa rozsiany po codebase. Wersjonuj, przeglądaj w review, testuj.
const string ReleaseAuditorIdentity = """
Jesteś audytorem release'ów aplikacji mobilnej w .NET MAUI.
ZAKRES: przeglądasz diff release candidate i raportujesz ryzyko.
Nie piszesz funkcjonalności, nie refaktoryzujesz, nie dotykasz
konfiguracji CI.
METODA: dla każdego zmienionego pliku klasyfikuj ryzyko jako
niskie / średnie / wysokie i uzasadnij je konkretnym scenariuszem
awarii, nie ogólną obawą.
OUTPUT: tabela znalezisk posortowana po istotności, następnie jedna
rekomendacja go / no-go. Bez wstępu, bez streszczania własnych kroków.
DONE: każdy zmieniony plik z diffa pojawia się w tabeli dokładnie raz.
""";
AnthropicClient client = new();
var response = await client.Messages.Create(new MessageCreateParams
{
Model = "claude-opus-5",
MaxTokens = 16000,
Thinking = new ThinkingConfigAdaptive(),
OutputConfig = new OutputConfig { Effort = Effort.High },
System = new List<TextBlockParam>
{
new() { Text = ReleaseAuditorIdentity },
},
Messages = [new() { Role = Role.User, Content = releaseDiff }],
});Dlaczego tożsamość jest ważniejsza od sformułowania promptu
Zawęża przestrzeń decyzji
Agent bez zadeklarowanego zakresu traktuje każde zapytanie jako zaproszenie do bycia ogólnie pomocnym. Dokładnie tak powstaje code reviewer, który zaczyna refaktoryzować, albo ekstraktor danych, który dokłada uprzejme komentarze, wokół których potem trzeba parsować. "ZAKRES / poza zakresem" robi więcej roboty niż trzy akapity grzecznych instrukcji.
Przeżywa długie pętle
Pojedyncze wywołanie prawie nie zauważa słabej tożsamości. Agent wykonujący dwadzieścia wywołań narzędzi — zauważa. Każda iteracja to okazja do dryfu: do przyjęcia ramy ostatniego wyniku narzędzia zamiast ramy zadania. Silna tożsamość jest potwierdzana przy każdym pojedynczym zapytaniu, bo system prompt jest przy każdym pojedynczym zapytaniu wysyłany od nowa. Właśnie ta właściwość sprawia, że dryf jest opanowywalny — i właśnie ona ma swoją cenę.
Czyni agenta testowalnym
Tożsamość z jawną definicją ukończenia to kontrakt, dla którego można napisać asercje. "Każdy zmieniony plik pojawia się dokładnie raz" jest sprawdzalne. "Bądź dokładny" — nie.
To w niej żyje granica bezpieczeństwa
Claude nie zna Twojej polityki zatwierdzania. Zna ją Twój harness. Tożsamość plus świadomie wąska powierzchnia narzędzi to sposób, w jaki wyrażasz tę granicę: akcje trudno odwracalne dostają dedykowane, kontrolowalne narzędzia, a nie ogólny shell.
Cena tożsamości: tokeny
To ta mechanika, która zaskakuje osoby przechodzące z pojedynczych wywołań na agentów:
System prompt i definicje narzędzi są wysyłane ponownie przy każdym zapytaniu w pętli.
Przebieg agenta to nie jedno wywołanie API. To N wywołań, gdzie N to liczba round-tripów narzędziowych, a każde z nich niesie pełną tożsamość, pełny zestaw schematów narzędzi i całą dotychczasową konwersację.
Weźmy realistyczny setup:
| Komponent | Tokeny |
|---|---|
| Tożsamość (system prompt) | 1 500 |
| Definicje narzędzi (6 narzędzi) | 800 |
| Stały prefiks na zapytanie | 2 300 |
Agent wykonujący 20 wywołań narzędzi płaci więc za ten prefiks 20 razy: 46 000 tokenów wejściowych, zanim doliczymy choć jedną linię właściwej treści zadania. Przy cenach wejścia Claude Opus 5 (5 $ / 1 mln tokenów) to około 0,23 $ na przebieg tylko za to, żeby agent wciąż przedstawiał się sam sobie — a przy 10 000 przebiegów miesięcznie: 2 300 $.
To ta liczba, po której ludzie zaczynają skracać system prompty. Nie rób tego. Zacache'uj je.
Prompt caching — jak tożsamość staje się prawie darmowa
Prompt caching zamienia ten stały prefiks z kosztu na każde zapytanie w koszt bliski zeru. Wszystkim rządzi jedna niezmiennik:
Cache to dopasowanie prefiksu. Zmiana choćby jednego bajtu gdziekolwiek w prefiksie unieważnia wszystko, co jest za nim.
Kolejność renderowania to tools → system → messages. Breakpoint cache na ostatnim bloku system obejmuje więc narzędzia i tożsamość razem — dokładnie te 2 300 tokenów powyżej.
var response = await client.Messages.Create(new MessageCreateParams
{
Model = "claude-opus-5",
MaxTokens = 16000,
System = new List<TextBlockParam>
{
new()
{
Text = ReleaseAuditorIdentity, // bajt w bajt identyczny w każdym zapytaniu
CacheControl = new CacheControlEphemeral(), // domyślnie TTL 5 minut
},
},
Messages = messages,
});
// Zawsze weryfikuj — cache zawodzi po cichu, nigdy głośno
Console.WriteLine($"zapisane: {response.Usage.CacheCreationInputTokens}");
Console.WriteLine($"odczytane: {response.Usage.CacheReadInputTokens}");
Console.WriteLine($"pełna cena: {response.Usage.InputTokens}");Ekonomia: odczyt z cache kosztuje około 0,1× bazowej ceny wejścia, zapis do cache 1,25× przy domyślnym TTL 5 minut (albo 2× przy TTL 1 godziny). Zastosowane do tego samego przebiegu z 20 iteracjami:
| Scenariusz | Efektywne tokeny wejściowe | Koszt (Opus 5) |
|---|---|---|
| Bez cache (20 × 2 300) | 46 000 | 0,230 $ |
| Z cache (1 zapis + 19 odczytów) | ~7 250 | 0,036 $ |
84% mniej na tożsamościowej części rachunku, bez zmiany samego promptu. Break-even przychodzi trywialnie szybko: przy TTL 5 minut już dwa zapytania spłacają narzut zapisu.
Jeden szczegół warto znać: minimalny cache'owalny prefiks zależy od modelu i nie jest monotoniczny między generacjami — 512 tokenów w Claude Opus 5, 1 024 w Sonnet 5, 4 096 w Haiku 4.5. Tożsamość o długości 3 000 tokenów zacache'uje się na Opus 5, a na Haiku 4.5 po cichu nie. Bez błędu, po prostu cache_creation_input_tokens: 0.
Cisi zabójcy cache
Tu wycieka realna gotówka. Każdy z tych wzorców wygląda niewinnie na code review:
| Wzorzec | Dlaczego rachunek się podwaja |
|---|---|
DateTime.Now wstrzyknięte w system prompt | Prefiks zmienia się przy każdym zapytaniu — nic się nigdy nie cache'uje |
| ID użytkownika lub sesji w tożsamości | Osobny wpis cache na użytkownika; zero współdzielenia |
Warunkowe sekcje tożsamości (if (isPremium) system += ...) | Każda kombinacja flag to inny prefiks |
| Lista narzędzi budowana per użytkownik lub per zapytanie | Narzędzia renderują się na pozycji 0 — cały cache umiera |
| Niedeterministyczna serializacja JSON schematów narzędzi | Inna kolejność bajtów → inny prefiks |
| Zmiana modelu w trakcie konwersacji | Cache jest przypisany do modelu |
Rozwiązanie jest architektoniczne, a nie kwestią rozmieszczenia markerów: zamroź tożsamość i wypchnij wszystko zmienne na koniec promptu.
Kiedy instrukcja operatora naprawdę musi dotrzeć w środku konwersacji — przełączenie trybu, świeżo wstrzyknięty stan — nie edytuj system promptu na poziomie żądania. Na Claude Opus 5, Opus 4.8 i Fable 5 możesz zamiast tego dopisać wiadomość { "role": "system" } do tablicy messages. Siedzi ona za zacache'owaną historią, więc prefiks przeżywa — a w odróżnieniu od tekstu przemyconego w turze użytkownika jest niepodrabialnym kanałem operatora.
Jeden agent-monolit czy zespół specjalistów?
Kiedy zaakceptujesz, że tożsamość jest cache'owana, rachunek się zmienia. Wąski agent nie jest już droższy od szerokiego — a jest wymiernie lepszy:
| Wymiar | Jeden agent-generalista | Zespół specjalistów |
|---|---|---|
| Rozmiar promptu na zapytanie | Duży (wszystkie reguły do wszystkich zadań) | Mały (tylko istotne reguły) |
| Skuteczność cache | Niska — prompt przesuwa się per typ zadania | Wysoka — każda tożsamość jest zamrożona |
| Zanieczyszczenie kontekstu | Wszystko ląduje w jednym oknie | Czytanie zostaje w subagencie |
| Wybór modelu | Jeden model do wszystkiego | Tani do czytania, mocny do oceny |
| Diagnoza awarii | "Prompt się pogorszył" | Izolowana do jednego agenta |
Wiersz o zanieczyszczeniu kontekstu jest w praktyce najważniejszy. Podzadanie, które czyta dwadzieścia plików, nie musi zostawiać zawartości dwudziestu plików w oknie głównego agenta na zawsze. Zdeleguj je, a główna pętla dostanie wniosek zamiast surowca.
Wybór modelu wzmacnia ten efekt:
| Model | ID modelu | Wejście $/1 mln | Wyjście $/1 mln |
|---|---|---|---|
| Claude Fable 5 | claude-fable-5 | 10,00 $ | 50,00 $ |
| Claude Opus 5 | claude-opus-5 | 5,00 $ | 25,00 $ |
| Claude Sonnet 5 | claude-sonnet-5 | 3,00 $ | 15,00 $ |
| Claude Haiku 4.5 | claude-haiku-4-5 | 1,00 $ | 5,00 $ |
Podzadania z dużą ilością czytania i małą dawką oceny kosztują na Haiku 4.5 jedną piątą Opus 5 za token wejściowy. Ale uwaga na ograniczenie z poprzedniej sekcji: nie przełączaj modeli wewnątrz jednej konwersacji, żeby złapać tę oszczędność — cache jest przypisany do modelu i zapłacisz więcej, niż zaoszczędzisz. Zamiast tego uruchom subagenta na tańszym modelu, a główną pętlę trzymaj na jednym modelu.
Dwie kolejne dźwignie, obie dostępne na aktualnych modelach:
Effort (
output_config.effort, odlowdomax) steruje głębokością myślenia i ogólną rozlewnością. Niższy effort oznacza mniej, ale bardziej skonsolidowanych wywołań narzędzi i mniej wstępu — często najlepsza pojedyncza dźwignia kosztowa dla subagentów i rutynowej pracy.Context editing i compaction nie pozwalają długim przebiegom puchnąć: editing usuwa nieaktualne wyniki narzędzi, compaction streszcza wcześniejszą historię po stronie serwera, gdy zbliżasz się do okna kontekstu.
Praktyczny budżet tokenów
Dla powyższego agenta-audytora release'u, 20 wywołań narzędzi na średniej wielkości diffie:
| Pozycja | Tokeny | Uwagi |
|---|---|---|
| Tożsamość + narzędzia (cache) | ~7 250 efektywnie | 1 zapis + 19 odczytów |
| Wyniki narzędzi (diff, odczyty plików) | ~60 000 | Prawdziwy sprawca — przycinaj |
| Rosnąca historia konwersacji | ~35 000 efektywnie | Cache'owana przyrostowo per tura |
| Wyjście (znaleziska, uzasadnienia) | ~8 000 | Rozliczane 5× drożej niż wejście |
Wniosek z tej tabeli jest taki, jakiego nikt się nie spodziewa: po zacache'owaniu tożsamość jest najtańszą rzeczą w całym przebiegu. Drogie są niefiltrowane wyniki narzędzi i tokeny wyjściowe. Co oznacza, że odruch skracania system promptu w celu oszczędności jest dokładnie odwrotny do właściwego — dłuższa, ostrzejsza tożsamość, która powstrzyma agenta od przeczytania trzech niepotrzebnych plików, zwraca się wielokrotnie.
Podsumowanie
Sześć zasad, które stosuję teraz do każdego budowanego agenta:
Pisz tożsamość jako artefakt, nie literał stringa. Zakres, granica narzędzi, format wyjścia, definicja ukończenia. Wersjonuj, przeglądaj, testuj.
Przyjmij, że jest wysyłana ponownie przy każdym zapytaniu — bo jest. To dzięki temu działa i dlatego kosztuje.
Cache'uj prefiks i weryfikuj cache. Jeśli
cache_read_input_tokenswynosi zero w kolejnych zapytaniach, coś go unieważnia. Znajdź to.Zamroź prefiks, zmienne na koniec. Żadnych znaczników czasu, ID użytkowników, sekcji warunkowych ani zestawów narzędzi per zapytanie.
Kilka wąskich agentów bije jednego szerokiego. Lepsze cache, izolowany kontekst, izolowane awarie, tańszy dobór modelu per podzadanie.
Optymalizuj wyniki narzędzi, zanim zaczniesz optymalizować prompt. Tam naprawdę są tokeny.
Nadanie agentowi tożsamości to nie odgrywanie roli i nie dekoracja. To kontrakt interfejsu między Twoim systemem a komponentem niedeterministycznym — a kiedy jest zacache'owany, to również najtańsza niezawodność, jaką możesz kupić.
Uwaga: wszystkie liczby tokenów i koszty powyżej to szacunki rzędu wielkości z moich własnych przebiegów. Przed budżetowaniem zmierz własne przy pomocy endpointu do liczenia tokenów.
