Orkiestracja multi-agent: pięć wzorców i kiedy wygrywa jeden
Ta sama faktura rozwiązana na cztery sposoby: orchestrator kosztował 1,66× więcej niż pojedynczy agent i doszedł do tego samego wniosku.
Na tej stronie
Rozdział 24 zakończył się pytaniem, na które sam sobie zasłużył: gdy sub-agent się myli, na co dokładnie może spojrzeć parent?
Ten rozdział odpowiada rachunkiem. Jedno zadanie — klient kwestionuje fakturę i chce odpowiedzi — rozwiązane na cztery sposoby; wszystkie uruchamiają harness z Rozdziału 23 przeciwko temu samemu skryptowanemu providerowi, wszystkie liczą te same tokeny tym samym encoderem, wszystkie wycenione według stawek, które Rozdział 16 odczytał 6 września 2026 roku.
| układ | wywołania modelu | tokeny wejściowe | output | koszt | wall clock | werdykt |
|---|---|---|---|---|---|---|
| prompt chaining | 4 | 900 | 165 | $0.003780 | 1,648 ms | błędny |
| jeden agent, cztery narzędzia | 5 | 2,697 | 179 | $0.007542 | 2,224 ms | prawidłowy |
| sekcje równoległe | 9 | 2,910 | 324 | $0.009708 | 2,165 ms | prawidłowy |
| orchestrator-workers | 12 | 3,628 | 438 | $0.012512 | 5,090 ms | prawidłowy, ale nie umie tego dowieść |
Przeczytaj razem pierwszy i ostatni wiersz: między nimi mieści się każdy spór, jaki ta branża prowadzi obecnie. Najtańszy układ był też najszybszy i wygenerował pewną siebie, błędną, gotową do wysłania odpowiedź. Najdroższy miał rację, kosztował 3,3 raza więcej i zajął 3,1 raza więcej czasu, a skończył, cytując wniosek workera, którego nie ma jak sprawdzić.
Wiersz, którego nikt nie wkłada do takich tabel, to drugi: jeden agent z czterema narzędziami doszedł do tego samego werdyktu co orchestrator za 60% pieniędzy i 44% wall clock. To nie jest preferencja prostoty. To pomiar, a reszta tego rozdziału jest o tym, kiedy przestaje być prawdziwy.
Pokaż szczegóły
Czego ten rozdział potrzebuje z poprzednich.
- Rozdział 18 — kontraktu narzędzia: schema, którą widzi model, endpoint, którego nigdy nie widzi. Cały agent mieści się za tym interfejsem, i na tym polega całe multi-agent.
- Rozdział 22 — dwóch opublikowanych definicji „agent”, które się nie zgadzają, oraz arytmetyki mówiącej, że chain promptów to N wywołań.
- Rozdział 23 — pętli, pięciu wyjść, stanu uruchomienia i trace. Każdy układ poniżej to ten sam plik, wywołany inaczej.
- Rozdział 24 — tego, ile kosztuje context window i co z niego wypada. Sub-agent jest czwartą z jego czterech strategii i jedyną, która jest drugim agent, a nie policy.
Bez tensorów. Wszystko tutaj to TypeScript, poza dwoma pomiarami wykonanymi na prawdziwym lokalnym modelu.
Zadanie i pułapka w środku
Link do sekcji: Zadanie i pułapka w środkuPortugalska firma pisze w sprawie faktury FT-2026-0918. Email mówi, że VAT wygląda źle, i załącza fakturę: netto EUR 248.00, VAT naliczony według 21%, EUR 52.08, razem EUR 300.08.
Fakty potrzebne do odpowiedzi są w trzech miejscach, a tylko jedno z nich znajduje się w emailu:
| gdzie | co mówi |
|---|---|
| załączona faktura | sprzedawca w Hiszpanii, VAT zastosowany według 21%, EUR 52.08 |
| rekord zamówienia | kupujący jest zarejestrowany w Portugalii, ma ważny identyfikator VAT, business-to-business |
| tabela podatkowa | hiszpańska stawka krajowa 21%; wewnątrzunijne business-to-business z ważnym identyfikatorem, reverse charge, 0% |
Połącz te trzy rzeczy i faktura jest błędna: obowiązuje reverse charge, VAT powinien wynosić zero, należy się nota kredytowa na EUR 52.08. Spójrz tylko na fakturę, a arytmetycznie jest doskonała — 248.00 plus 52.08 daje 300.08 — i tak właśnie powiesz.
Email rzeczywiście stwierdza „jesteśmy portugalską firmą”. To deklaracja, nie rekord, a żaden system rozliczeniowy nie wystawia noty kredytowej na podstawie deklaracji. Pułapka nie jest sztuczką: to zwykły kształt pracy biznesowej, w której decyzja wymaga faktu, którego nikt nie pomyślał pobrać.
Wszystko powyżej działa przeciwko skryptowanemu providerowi w stylu tego z Rozdziału 23, z dokładnie jedną regułą:
Odpowiedź może użyć tylko faktu, który znajduje się w jej prompt.
„Model” prosi o każde narzędzie, które ma, raz, w kolejności katalogowej, a potem stosuje stałą regułę do tekstu, który widzi. Nic nie jest skryptowane per układ, więc różnice w tabeli otwierającej nie są twierdzeniami o inteligencji modelu: to mierzone routowanie informacji. Prawdziwy model dokłada do tego własne porażki; nie usuwa tych.
Pięć wzorców w około czterdziestu liniach
Link do sekcji: Pięć wzorców w około czterdziestu liniachPięć nazw poniżej pochodzi od Anthropic, z Building effective agents, gdzie to słownictwo się utrwaliło.1 Żaden z pięciu pomysłów nie jest nowy, a powiedzenie, który dom nazwał co — i który pomysł jest starszy — to połowa wartości ich znajomości.
/* 1. Prompt chaining: a fixed pipeline. The control flow is yours. */
export async function chain(steps: Step[], first: string) {
let carry = first, all = first;
for (const s of steps) {
const r = await step(s.role, s.system, s.accumulate ? all : carry);
carry = r.text;
all = `${all}\n${r.text}`;
}
return carry;
}
/* 2. Routing: one cheap call picks the branch. The fallback is not a model. */
export async function route<T>(input: string, classify: Classifier,
routes: Record<string, Branch<T>>, fallback: Branch<T>) {
let label: string | undefined;
try { label = await classify(input); } catch { label = undefined; }
return ((label && routes[label]) || fallback)(input);
}
/* 3. Parallelisation. The pattern IS this line. */
export const parallel = <T>(workers: Branch<T>[], input: string) =>
Promise.all(workers.map((w) => w(input)));
/* 4. Orchestrator-workers: an agent behind a tool. Chapter 18's interface, unchanged. */
export function agentTool(o: WorkerSpec): Tool {
return {
name: o.name, description: o.description, readOnly: true,
parameters: { type: "object", properties: { question: { type: "string" } } },
async run(args: { question: string }) {
const child = newRun(o.system, args.question); // its own window
await runTracked(child, o.tools, o.usage); // its own limits
const conclusion = child.output ?? "no result";
if (!o.carryFindings) return conclusion;
return `${conclusion}\nFINDINGS ${evidence(child)}`;
},
};
}
/* 5. Evaluator-optimiser: make, judge, remake. Rounds are calls. */
export async function refine(make: Make, judge: Judge, maxRounds: number) {
let draft = "", feedback: string | undefined;
for (let r = 1; r <= maxRounds; r++) {
draft = (await make(feedback)).text;
const j = await judge(draft);
if (j.ok) return { draft, rounds: r };
feedback = j.note;
}
return { draft, rounds: maxRounds };
}To cały zestaw narzędzi: pięć funkcji, bez frameworka, a równoległa to jedna linia — i właśnie dlatego warto ją rozpisać, zamiast rysować. Teraz po kolei: rodowód, cena i przypadek, w którym się myli.
Chaining i decyzja, którą podejmuje za ciebie
Link do sekcji: Chaining i decyzja, którą podejmuje za ciebiePrompt chaining „dekomponuje zadanie na sekwencję kroków, w której każde wywołanie LLM przetwarza output poprzedniego”.1 Pomysł poprzedza modele językowe: to pipeline, z typową transakcją pipeline — przejrzystość w zamian za control flow ustalony przed nadejściem danych.
Cztery kroki dla naszego zadania: wyciągnąć pola faktury, sprawdzić arytmetykę, zdecydować, co się należy, napisać odpowiedź. Tutaj zawodzi na dwa różne sposoby, co uczy więcej niż pojedyncza porażka.
--- relay: each step sees only the previous step's output
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 vat_amount=52.08 ...
check: ARITHMETIC ok 248.00+52.08=300.08
decide: VERDICT=unknown reason=no_invoice_in_context
draft: "we are looking into invoice FT-2026-0918 and will come back to you."
--- accumulating: each step sees the email and everything produced so far
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 ...
check: ARITHMETIC ok 248.00+52.08=300.08
decide: VERDICT=invoice_correct reason=net_248.00_plus_21pct_vat_52.08_equals_300.08
draft: "we have checked FT-2026-0918 and it is correct... Nothing is owed back."Relay chain kosztował $0.001940 i zgubił pola faktury między krokami drugim i trzecim, bo krok trzeci dostał zdanie o arytmetyce i nic więcej. Wygenerował wiadomość wstrzymującą: bezużyteczną i widocznie bezużyteczną.
Accumulating chain — wiersz z tabeli otwierającej — kosztował $0.003780, czyli o 95% więcej za cztery identyczne wywołania, bo każdy krok niesie teraz wszystko sprzed niego. Wygenerował output niebezpieczny. Płynny, cytujący własną arytmetykę, poprawny w każdej liczbie, którą wymienia, i mówiący klientowi, że nic się nie należy, gdy należy się EUR 52.08.
Różnica między nimi to jeden ternary. Chain, który niesie mniej, produkuje odpowiedzi oczywiście niekompletne; chain, który niesie wszystko, produkuje odpowiedzi pewne siebie i błędne — a wysyłany jest tylko drugi rodzaj.
Żadne z nich nie jest prawdziwą awarią. Prawdziwa awaria polega na tym, że pipeline zdecydował, zanim cokolwiek przeczytał, że to zadanie to cztery kroki na treści emaila. Nigdzie w tej strukturze nie ma miejsca, by powiedzieć „kraj rejestracji nie jest w tym emailu; idź i go pobierz”. Chaining jest właściwy, gdy dekompozycja jest znana z góry i stabilna. Tutaj była zgadywanką, a zgadywanka trafiła do produkcji.
Routing, najstarszy wzorzec, i plan B, którego nikt nie pisze
Link do sekcji: Routing, najstarszy wzorzec, i plan B, którego nikt nie piszeRouting „klasyfikuje input i kieruje go do wyspecjalizowanego zadania następczego”.1 Nazwa jest nowa; mechanizm to dispatcher, starszy niż prawie wszystko inne w tej książce. Nowe jest to, że klasyfikatorem może być model — i właśnie dlatego zawodzi w sposób, w jaki switch nigdy nie zawodził.
const answer = await route(email,
(q) => classifyWithSmallModel(q), // cheap model, one call
{ billing: billingAgent, tax: taxAgent, dunning: dunningAgent },
taxAgent, // deterministic, chosen in advance
);Dwie rzeczy o tym ostatnim argumencie. To nie jest obsługa błędów; to wzorzec. Router oparty na modelu ma tryb awarii, którego dispatcher nie ma: może zwrócić etykietę, która nie istnieje, przekroczyć czas albo — drogi wariant — zwrócić wiarygodnie brzmiącą złą etykietę bez sygnału, że jest zła. Wszystkie trzy muszą gdzieś wylądować, a tym gdzieś nie może być kolejne wywołanie modelu, bo jesteś już w gałęzi, w której wywołania modelu zawiodły.
Druga rzecz: własny prompt routera nie jest darmowy. Aby wybrać model, router potrzebuje katalogu modeli do wyboru, a każdy wpis w nim to wejście, za które router płaci, zanim przeczyta pytanie użytkownika. Przy stawce wejściowej używanej w tym kursie katalog liczący około 3,800 tokenów kosztuje już tyle, co całe pięciowywołaniowe uruchomienie agent z tabeli otwierającej. W praktyce wywołanie routingu działa na tanim modelu, i właśnie dlatego routing się zwraca; ale arytmetykę warto wykonać w tę stronę, zamiast zakładać. Routing jest błędny dokładnie wtedy, gdy zadanie routowane jest tańsze niż decyzja routingu.
Parallelisation: sekcje i głosowanie, czyli self-consistency
Link do sekcji: Parallelisation: sekcje i głosowanie, czyli self-consistencyAnthropic dzieli ten wzorzec na dwa: sectioning — „dzielenie zadania na niezależne podzadania uruchamiane równolegle” — oraz voting — „uruchamianie tego samego zadania wiele razy, aby uzyskać zróżnicowane outputy”.1 Dzielą diagram i prawie nic poza nim.
Sectioning to tani zysk, i to linia z patterns.ts: trzech specjalistów — billing, tax, policy — każdy z własnym context window i narzędziami, nad tym samym emailem, z jednym wywołaniem syntezy na końcu. Identyczna praca, uporządkowana na dwa sposoby:
| wywołania modelu | input | output | koszt | wall clock | |
|---|---|---|---|---|---|
| trzech workerów, jeden po drugim | 9 | 2,910 | 324 | $0.009708 | 3,894 ms |
ci sami trzej, Promise.all | 9 | 2,910 | 324 | $0.009708 | 2,165 ms |
Token w token to samo, 1,8 raza szybciej. Dlatego wzorzec zasługuje na własną nazwę: to jedyny z pięciu, który coś poprawia, nic nie kosztując. Haczyk polega na tym, że sekcje muszą być naprawdę niezależne — daj sekcji B fakt, który produkuje sekcja A, a Promise.all uruchomi obie przeciwko stanowi, który jeszcze nie istnieje. Pętla for ukryła ten bug; jednolinijkowiec go ujawnia.
Voting to inne zwierzę ubrane w ten sam obrazek. Uruchomienie tego samego pytania k razy i wzięcie większości to self-consistency, opublikowane przez Wanga i współautorów w marcu 2022 roku jako strategia decodingu, prawie trzy lata zanim ktokolwiek nazwał to wzorcem orkiestracji. Abstrakt precyzyjnie opisuje mechanizm — „najpierw próbkowanie zróżnicowanego zestawu ścieżek rozumowania zamiast brania tylko zachłannej, a potem wybór najbardziej spójnej odpowiedzi przez marginalizowanie spróbkowanych ścieżek rozumowania” — oraz zysk: +17,9 punktu na GSM8K.2
Z tego wynikają dwie rzeczy, które obrazek ukrywa. Po pierwsze, voting wymaga sampling z Rozdziału 17: przy temperaturze zero wszystkie k próbek to ta sama próbka, a większość to jedna odpowiedź opłacona k razy. Po drugie, działa tylko tam, gdzie większość ma sens — przy odpowiedzi na fakturę powyżej nie ma czego liczyć, bo pięć szkiców to pięć różnych zdań. Voting jest dla zadań z krótką, porównywalną odpowiedzią, dokładnie jak benchmarki Wanga i prawie nic, co robi customer-facing agent.
Zmierzone tutaj na 20 trzyetapowych zadaniach tekstowych, których odpowiedzi są obliczane, a nie oceniane, z lokalnym modelem z Rozdziału 23 rozumującym krok po kroku:
| wywołania modelu | input | output | koszt dla 20 | poprawne | przedział 95% | |
|---|---|---|---|---|---|---|
| jeden greedy chain | 20 | 1,330 | 2,649 | $0.034448 | 9/20 | 26–66% |
| większość z 5, temperatura 0.8 | 100 | 6,650 | 13,245 | $0.172240 | 9/20 | 26–66% |
Pięć razy więcej wywołań, pięć razy więcej tokenów, dokładnie pięć razy większy rachunek i ani jednej dodatkowej poprawnej odpowiedzi. Voting to zakład, nie ulepszenie, a to uruchomienie go przegrało.
Dwa zastrzeżenia, zanim ktoś zacytuje to jako obalenie Wanga. Dwadzieścia prób nie odróżni 45% od 60% — przedział ma szerokość twierdzenia, czyli dyscyplina z Rozdziału 4 zastosowana do mojego własnego wyniku. A opublikowane zyski pochodzą z modeli o rzędy wielkości większych, gdzie zróżnicowane ścieżki rozumowania, po których voting marginalizuje, faktycznie są zróżnicowane. Nie przenosi się liczba: przenosi się to, że mnożnik jest dokładny i znany z góry, a zysk nie.
Orchestrator-workers i czym podsumowanie nie jest
Link do sekcji: Orchestrator-workers i czym podsumowanie nie jestW workflow orchestrator-workers „centralny LLM dynamicznie rozbija zadania, deleguje je do worker LLMs i syntetyzuje ich wyniki”, a różnica względem sectioning polega na tym, że „podzadania nie są zdefiniowane wcześniej, lecz określane przez orchestrator”.1 Rodowód nie pochodzi tu wcale z modeli językowych: to master-worker, a wersja, w której workerzy zapisują ustalenia we wspólnej przestrzeni odczytywanej przez kontroler, to architektura blackboard z badań nad rozumieniem mowy w latach 70. XX wieku. Nowością w 2026 roku jest to, że kontrolerem jest model, a więc dekompozycja może być ustalana per input — elastyczność i koszt w jednym zdaniu.
Kosztowało to 12 wywołań modelu wobec 5 dla pojedynczego agent i doszło do tego samego werdyktu. Potem zrobiło coś, czemu warto przyjrzeć się z bliska:
orchestrator final: VERDICT=credit_note_due amount=52.08 source=worker_unverified
| PO_MISMATCH=yes source=worker_unverified
single agent: VERDICT=credit_note_due amount=52.08 reason=reverse_charge_should_have_applied
| PO_MISMATCH=yes invoice_says=PO-4417 order_says=PO-4471Oba są poprawne. Tylko jedno wie dlaczego. Tax worker miał fakturę, zamówienie i tabelę podatkową we własnym context window, doszedł do wniosku, a także zauważył — nikt go o to nie prosił — że numer zamówienia zakupu na fakturze nie zgadza się z numerem w zamówieniu. Potem zwrócił podsumowanie. Orchestrator może powtórzyć oba stwierdzenia i nie sprawdzić żadnego, bo dowody zostały w context window, którego nigdy nie zobaczył. To odpowiedź na pytanie zamykające Rozdział 24: parent może spojrzeć na to, co child postanowił zapisać.
Poprawka to flaga, i ma cenę:
| co zwraca worker | tokeny wejściowe orchestrator | koszt | co może zrobić parent |
|---|---|---|---|
| swój wniosek | 3,628 | $0.012512 | powtórzyć go |
| swój wniosek i dowody | 4,065 | $0.013554 | wyprowadzić go ponownie i się nie zgodzić |
Dwanaście procent więcej tokenów wejściowych, 8,3% więcej pieniędzy, i fraza source=worker_unverified znika z odpowiedzi. To transakcja w każdym systemie multi-agent i prawie nigdy nie jest wypowiadana: czyste context window child jest warte posiadania, możliwość audytu przez parent jest warta zapłaty, i nie możesz mieć obu za darmo.
Kiedy więc orchestrator-workers jest błędny? Tutaj, w tym zadaniu. Kupił poprawną odpowiedź, do której jeden agent z tymi samymi czterema narzędziami też doszedł, za 1,66 raza kosztu i 2,3 raza wall clock, i utrudnił obronę tej odpowiedzi. Własne zalecenie Anthropic mówi to samo, zanim wzorce się zaczynają: znaleźć „najprostsze możliwe rozwiązanie i zwiększać złożoność tylko wtedy, gdy jest potrzebna”, bo „systemy agentic często zamieniają latency i koszt na lepszą jakość zadania”.1 Tabele powyżej to to zdanie z liczbami pod spodem.
Evaluator-optimiser i sędzia, który napisał egzamin
Link do sekcji: Evaluator-optimiser i sędzia, który napisał egzaminJedno wywołanie generuje, drugie ocenia, a pętla powtarza się, aż ocena przejdzie.1 Opublikowani przodkowie to Self-Refine — ten sam model jako „generator, refiner i feedback provider”, raportujący około 20 punktów bezwzględnej poprawy średnio w siedmiu zadaniach3 — oraz Reflexion, który przechowuje krytykę w buforze epizodycznym między próbami i raportuje 91% pass@1 na HumanEval tam, gdzie baseline osiągał 80%.4
Model kosztowy jest najprostszy z pięciu: dwa wywołania na rundę, a liczba rund nie należy do ciebie. Trzy rundy refinementu na zadaniu, które zajęło jedno wywołanie, to sześć wywołań, więc podłoga wzorca wynosi 6×, a sufit jest taki, jaki limit ustawisz — co czyni wyjście budżetowe z Rozdziału 23 obowiązkowym, a nie eleganckim dodatkiem.
Sufit jest subtelniejszy i mierzalny. Na tych samych 20 problemach lokalny model odpowiedział poprawnie na 9. Potem pokazano mu każdą z tych odpowiedzi i zapytano, czy jest poprawna — bez informowania, że to jego własna odpowiedź, co usuwa confound pochlebstwa i zostawia problem capability:
| własna odpowiedź modelu | powiedział „tak” | powiedział „nie” |
|---|---|---|
| 9 poprawnych | 9 | 0 |
| 11 błędnych | 3 | 8 |
To lepszy sędzia, niż sugeruje tytuł sekcji, i właśnie po to się mierzy, zamiast twierdzić: nie zablokował nic poprawnego i złapał 8 z 11 błędów. Jako filtr jest wart swoich wywołań.
Jako reguła zatrzymania, czyli to, do czego pętla evaluator-optimiser naprawdę go używa, te trzy akceptacje są całą historią: kończą pętlę z błędną odpowiedzią w ręku, i żadna liczba dodatkowych rund nigdy do nich nie dociera. Pętla refinement nie może stać się poprawniejsza niż jej sędzia. Kupowanie kolejnych rund kupuje próby wobec błędów, które sędzia widzi, w pełnej cenie, i nic wobec tych, których nie widzi.
Stąd reguła: evaluator zarabia na swoje wywołania tylko wtedy, gdy ma coś, czego generator nie ma. Kompilator, zestaw testów, walidator schema, inny model, człowiek. Własne wyniki Self-Refine są mierzone wobec ludzkiej preferencji i metryk zadania, nigdy wobec opinii modelu o samym sobie. Jeśli jedyną przewagą evaluator jest inny prompt, płacisz podwójnie za zgodę. Rozdział 29 buduje wersję z prawdziwą przewagą: golden set z odpowiedziami zapisanymi z góry.
Pętle nie są wzorcami
Link do sekcji: Pętle nie są wzorcamiPięć powyżej to kształty dla twojego kodu. Pod nimi siedzi druga rodzina, która często bywa wymieniana obok nich, a nie powinna: ReAct, Reflexion, plan-and-execute i tree of thoughts to pętle rozumowania, a ich koszt jest w requestach.
Rozdział 12 był o rozumowaniu wewnątrz modelu, za które płacisz output tokenami w jednym wywołaniu. To jest drugi rodzaj. Różnica ma znaczenie, gdy przychodzi rachunek: dłuższy chain of thought podnosi koszt jednego wywołania, a pętla rozumowania zamienia jedno zadanie w wiele wywołań, z których każde ponownie wysyła wszystko sprzed niego — kwadratowość, którą Rozdział 23 zmierzył w tabeli runaway.
| pętla | wywołania na zadanie | co kupują dodatkowe wywołania |
|---|---|---|
| ReAct | jedno na krok, aż się zatrzyma | model reaguje na to, co zwróciły narzędzia5 |
| plan-and-execute | jedno na plan, potem jedno na krok | plan jest ustalony, zanim pierwszy krok ruszy6 |
| Reflexion | próby × (act + reflect) | krytyka przeżywa do następnej próby4 |
| tree of thoughts | branching factor × depth plus jedna ocena na node | search, z backtracking7 |
Paper tree-of-thoughts publikuje własną tabelę kosztów, co jest rzadsze, niż powinno. Na Game of 24 z GPT-4: input/output prompting best-of-100 rozwiązał 33% po $0.13 za przypadek, chain of thought best-of-100 rozwiązał 49% po $0.47, a tree of thoughts rozwiązał 74% po $0.74, przy czym autorzy zauważają, że „could require 5-100 times more generated tokens than CoT”.7
Prawie sześć razy cena taniej metody za nieco ponad dwukrotność skuteczności. To, czy to okazja, zależy od tego, ile kosztuje cię nieudany przypadek — pytanie, które trzeba zadać przed przyjęciem którejkolwiek z tych czterech metod.
Ten kurs ich nie reimplementuje. Wszystkie cztery mają referencyjne implementacje własnych autorów, w Pythonie, a ich wartość polega na tym, że są źródłem, nie tłumaczeniem: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm i AGI-Edgerunners/Plan-and-Solve-Prompting. Przeczytaj prompty w tych repozytoriach; prompty są paperami.
Dwie topologie, i jedna z nich nie wraca
Link do sekcji: Dwie topologie, i jedna z nich nie wracaTeraz właściwe multi-agent, gdzie mieszka większość zamieszania. Są dwa sposoby, by jeden agent zaangażował drugiego; nie są wariantami, a różnica brzmi: kto potem dowodzi.
Agent jako narzędzie. Parent go wywołuje, dostaje odpowiedź i kontynuuje. To interfejs narzędzia z Rozdziału 18 z całym agent za nim, a parent nigdy nie traci kontroli. To właśnie robi orchestrator powyżej.
Przekazanie. Parent przekazuje rozmowę i nie dostaje jej z powrotem. Guide OpenAI daje najjaśniejsze opublikowane stwierdzenie: handoffs to „a one way transfer that allow an agent to delegate to another agent... If an agent calls a handoff function, we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state”.8
Ostrzeżenie słownikowe, bo to nieustannie potyka ludzi: „handoff” to słowo jednego SDK, nie standard. To terminologia z OpenAI Agents SDK i tego guide, który nazywa też dwa układy „manager” i „decentralized” oraz zauważa, że w pattern manager „edges represent tool calls whereas in the decentralized pattern, edges represent handoffs”.8 W tej przestrzeni istnieje otwarty standard — A2A, w wersji 1.0.0, objęty copyright Linux Foundation, z wersjonowaną historią wydań i udokumentowaną listą breaking changes, którego deklarowaną zasadą jest opaque execution: agent „collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations”.9 To nie jest handoff, a porównanie należy do Rozdziału 26. Tutaj ważne jest to, że jedno z dwóch słów jest API biblioteki, a drugie specyfikacją z governance.
Rozróżnienie jest strukturą danych, nie diagramem:
export type EdgeKind = "tool" | "handoff";
export interface AgentEdge { from: string; to: string; kind: EdgeKind }
export interface AgentGraph { root: string; agents: Record<string, AgentSpec>; edges: AgentEdge[] }
/** One agent may not be both a tool of X and a handoff target of X. */
export function conflicts(g: AgentGraph): AgentEdge[] {
const seen = new Map<string, EdgeKind>();
const bad: AgentEdge[] = [];
for (const e of g.edges) {
const key = `${e.from}->${e.to}`;
const other = seen.get(key);
if (other && other !== e.kind) bad.push(e);
else seen.set(key, e.kind);
}
return bad;
}
/** Every agent reachable from the root, and at what depth. */
export function reachable(g: AgentGraph): Map<string, number> {
const depth = new Map([[g.root, 0]]);
const queue = [g.root];
while (queue.length) {
const id = queue.shift()!;
for (const e of g.edges.filter((x) => x.from === id)) {
if (depth.has(e.to)) continue;
depth.set(e.to, depth.get(id)! + 1);
queue.push(e.to);
}
}
return depth;
}Dwadzieścia linii, dwa bugi, które inaczej znalazłbyś na produkcji. reachable znajduje agent, do którego nikt nie może dotrzeć — skonfigurowany, opłacony, nigdy niewywołany. conflicts odrzuca krawędź, która jest oboma rodzajami naraz, co brzmi pedantycznie, dopóki nie przeczytasz tego na głos: parent jednocześnie zachowuje kontrolę i ją oddaje. Uruchom to na pięcio-agent systemie z jednym orphan i jedną podwójną krawędzią:
reachable: lead@0 billing@1 tax@1 dunning@1
orphans: ghost
conflicts: lead->taxCo naprawdę przekracza granicę
Link do sekcji: Co naprawdę przekracza granicęTeraz pomiar, dla którego istnieje ta sekcja, i jedyny w rozdziale wykonany na prawdziwym modelu, a nie skryptowanym.
Klient podaje ograniczenie w pierwszej wiadomości — nasze konto jest zarejestrowane w Portugalii, nie w Hiszpanii; wszystko podatkowe ma używać Portugalii — rozmawia o czymś innym, a potem zadaje pytanie, na które musi odpowiedzieć billing. Sprawa zostaje przekazana. Dwadzieścia cztery próby, inny kraj i firma za każdym razem, cztery payloady transferu, a receiving agent dostaje potem jedno pytanie: w jakim kraju zarejestrowane jest konto tego klienta?
| co przekazano | średni payload | ograniczenie było w nim | specjalista je przywołał | przedział 95% |
|---|---|---|---|---|
| cała rozmowa | 173 tokeny | 24/24 | 20/24 — 83% | 64–93% |
| podsumowanie napisane przez sending agent | 62 tokeny | 1/24 | 0/24 — 0% | 0–14% |
| tylko ostatnia wiadomość użytkownika | 61 tokenów | 0/24 | 0/24 — 0% | 0–14% |
| typowany rekord | 69 tokenów | 24/24 | 24/24 — 100% | 86–100% |
Trzeci wiersz jest kontrolą i zachowuje się jak kontrola: faktu tam nie ma, więc nie da się go przywołać. Pozostałe trzy to wynik.
Pełny transcript ma 173 tokeny i działa w 83% przypadków, a jego cztery porażki są tematem Rozdziału 24, nie tego. Typowany rekord ma 69 tokenów — siedem więcej niż podsumowanie — i działa za każdym razem, bo ograniczenie siedzi w nazwanym polu zamiast w zdaniu.
A wiersz z podsumowaniem trzeba oglądać długo. Zawiódł 24 razy na 24, a powód nie jest taki, że czytelnik go przeoczył. Ograniczenie pojawiło się w ogóle tylko w 1 z 24 podsumowań. Receiving agent nie był niestaranny; dostał tekst, który nie zawierał odpowiedzi. Podsumowanie to kompresja, której nie napisałeś, wyprodukowana przez model, którego context window nie widzisz, zoptymalizowana pod to, by brzmieć jak podsumowanie — a „klient mówi, że nasze rekordy mają zły kraj” jest dokładnie takim clause, który summarizer odrzuca jako proceduralny szum.
Uczciwe ograniczenie tej liczby: summarizer to model o pół miliarda parametrów, a większy zachowałby więcej. To, czego nie poprawia rozmiar, to kształt ryzyka — sending agent decyduje per handoff, per phrasing, nieobserwowalnie, które fakty przetrwają. Typowany rekord w ogóle nie zależy od tego osądu, dlatego wygrywa konstrukcją, a nie inteligencją. Wszystko, co musi przetrwać transfer, powinno być polem, nie zdaniem.
To samo rozumowanie działa w drugą stronę, dla topologii agent-as-tool, a wcześniejsza tabela już to wyceniła: to, co wraca od workera, też jest podsumowaniem, a dopłata 8,3%, by otrzymać z nim dowody, to ta sama poprawka widziana od strony parent.
Kiedy wygrywa jeden agent
Link do sekcji: Kiedy wygrywa jeden agentTrzy fakty na zamknięcie, wszystkie z tabel powyżej.
System multi-agent mnoży wywołania, a wywołania są kwadratowe w context. Orchestrator wykonał 12 wywołań modelu tam, gdzie jeden agent wykonał 5, a każde niesie własny rosnący transcript — 3,628 tokenów wejściowych wobec 2,697, luka powiększająca się z długością zadania.
Każda granica jest kanałem stratnym. Dwa agent to jedno podsumowanie. Cztery agent w chain to trzy, złożone, każde napisane przez model optymalizujący pod coś innego niż twoja decyzja.
Pojedynczy agent znalazł coś, o co nikt nie prosił. Niezgodność numeru zamówienia zakupu wypłynęła, bo jedno context window trzymało jednocześnie fakturę i zamówienie. Dzielenie pracy między specjalistów dzieli też zdolność zauważenia, że dwa fakty się nie zgadzają.
Nic z tego nie jest argumentem przeciwko opublikowanym frameworkom multi-agent, które warto czytać jako źródła pierwotne, a nie przez tutoriale.10 To argument za tym, by drugi agent zasłużył na swoje miejsce.
Zatem test, nie preferencja. Dodaj drugiego agent, gdy prawdziwe jest co najmniej jedno z tych zdań: podzadanie potrzebuje czystego context window, którego parent nie może odziedziczyć (Rozdział 24); podzadania są naprawdę niezależne i wall clock ma znaczenie, czyli 1,8× powyżej; podzadanie wymaga innych uprawnień albo innego modelu, co Rozdział 30 zamienia w argument bezpieczeństwa; albo podzadanie jest czyjąś własnością, gdzie prawdziwy protokół zaczyna mieć znaczenie. Jeśli odpowiedź brzmi „żeby każdy agent miał jaśniejszy prompt”, daj jednemu agent jaśniejszy prompt. To darmowe.
Dokąd to prowadzi dalej
Link do sekcji: Dokąd to prowadzi dalejUmiesz teraz nazwać pięć wzorców, wycenić je względem siebie na jednym zadaniu, odróżnić orchestrator od sectioner i tool call od handoff, oraz obronić pojedynczego agent tabelą, a nie preferencją.
Każdy układ tutaj dzielił jedną wygodę, która nie przetrwa kontaktu z niczym prawdziwym: wszystkie narzędzia należały do nas. Faktura, zamówienie, tabela podatkowa, workerzy za orchestrator — to samo repozytorium, ten sam deploy, te same typy, ci sami ludzie.
Teraz przenieś jedno z nich na drugą stronę granicy firmy. Tabela podatkowa należy do vendora księgowego, rekord zamówienia do systemu magazynowego, i żadne z nich nie czytało twojego interfejsu Tool. Potrzebujesz sposobu, by model, którego nie napisałeś, odkrył, opisał i wywołał capability obsługiwaną przez kogoś innego — z authentication (co jest połową Rozdziału 27), versioning i gwarancją, że server nie może przeczytać reszty twojej rozmowy. To problem protokołu, ma specyfikację z normatywną schema, a prawie wszystko zaindeksowane na jego temat opisuje rewizję, która już nie istnieje.
Rozdział 26 czyta tę specyfikację zamiast ją streszczać i zaczyna od ręcznego wpisania JSON-RPC do terminala.
Źródła i metoda
Link do sekcji: Źródła i metodaKażdy koszt i liczba tokenów powyżej pochodziły ze skryptowanego providera opisanego w drugiej sekcji, na Node 22 przez interfejs loopback, liczone z encoding o200k_base i wycenione według stawek, które Rozdział 16 odczytał 6 września 2026 — $2.00 za milion input tokenów i $12.00 za milion output. Dane wall-clock pochodzą z tych samych uruchomień z latency providera ustawioną na 400 ms na wywołanie i narzędzi na 50 ms, więc mierzą układ, a nie providera. Dwa pomiary na prawdziwym modelu — tabela handoff oraz tabela voting-and-judging — użyły Qwen/Qwen2.5-0.5B-Instruct w float32 na CPU za endpointem o tym samym kształcie, greedy poza miejscami, gdzie podano temperaturę, z przedziałami obliczonymi metodą Wilsona z Rozdziału 4. Żaden request w tym rozdziale nie trafił do płatnego endpointu i żadna liczba w nim nie była szacowana.
Przypisy
Link do sekcji: Przypisy-
Anthropic, Building effective agents, 19 grudnia 2024,
anthropic.com/engineering/building-effective-agents, odczytane 7 września 2026. Źródło pięciu nazw workflow używanych powyżej i każdej cytowanej z nich frazy — prompt chaining, routing, parallelisation z wariantami sectioning i voting, orchestrator-workers, evaluator-optimiser — a także rekomendacji, by znaleźć „the simplest solution possible, and only increasing complexity when needed” oraz obserwacji, że „agentic systems often trade latency and cost for better task performance”. Rozdziały 22 i 23 cytują jego definicję agent. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 -
Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. and Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (marzec 2022). Pochodzenie wzorca voting, opisanego tam jako strategia decodingu, a nie architektura: próbkuj zróżnicowane ścieżki rozumowania, a potem „select the most consistent answer by marginalizing out the sampled reasoning paths”, z raportowanymi zyskami +17.9 na GSM8K, +11.0 na SVAMP, +12.2 na AQuA, +6.4 na StrategyQA i +3.9 na ARC-challenge. ↩
-
Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). Pętla evaluator-optimiser z jednym modelem we wszystkich trzech rolach — „generator, refiner, and feedback provider” — poprawiająca „by ~20% absolute on average in task performance” w siedmiu zadaniach, mierzona ludzką preferencją i automatycznymi metrykami, a nie własnym werdyktem modelu. ↩
-
Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. and Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). Dodaje epizodyczną pamięć samokrytyk między próbami — „reinforce language agents not by updating weights, but through linguistic feedback” — raportując 91% pass@1 na HumanEval wobec 80% dla baseline GPT-4. Zauważ wymaganie, od którego zależą wyniki: prawdziwy sygnał ze środowiska, taki jak failing test, a nie opinia modelu o samym sobie. ↩ ↩2
-
Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. and Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). Przeplatane ślady rozumowania i akcje; Rozdział 23 zbudował tę pętlę. Cytowane tutaj ze względu na kształt kosztu, a nie wyniki: jedno wywołanie modelu na krok, z całym transcript wysyłanym ponownie za każdym razem. ↩
-
Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. and Lim, E.-P. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. arXiv:2305.04091 (2023). „First, devising a plan to divide the entire task into smaller subtasks, and then carrying out the subtasks according to the plan” — kształt plan-then-execute i źródło trade, który interesuje ten rozdział: plan jest ustalony przed nadejściem pierwszej obserwacji, czyli prompt chaining z dekompozycją napisaną przez model zamiast przez ciebie. ↩
-
Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. and Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023). Search po pośrednich „thoughts” z self-evaluation i backtracking; 74% na Game of 24 wobec 4% dla chain-of-thought prompting. Koszty cytowane powyżej pochodzą z samego paperu, z Appendix B.3, Table 7: per case, input/output prompting best-of-100 po $0.13 dla 33%, chain of thought best-of-100 po $0.47 dla 49% oraz tree of thoughts po $0.74 dla 74%, z uwagą autorów, że ToT „could require 5-100 times more generated tokens than CoT”. ↩ ↩2
-
OpenAI, A practical guide to building agents (PDF), odczytane 7 września 2026. Podział manager-versus-decentralised, framing grafu cytowany powyżej („in the manager pattern, edges represent tool calls whereas in the decentralized pattern, edges represent handoffs”) oraz definicja handoff jako „a one way transfer... we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state”. Zauważ, co rozstrzyga ostatnia klauzula: w tym SDK stan rozmowy podróżuje, co jest decyzją projektową tej biblioteki, a nie właściwością handoffs w ogóle. ↩ ↩2
-
Agent2Agent (A2A) Protocol Specification, najnowsza wydana wersja 1.0.0,
a2a-protocol.org/latest/specification/, odczytane 7 września 2026; copyright Linux Foundation, Apache-2.0. Cytowane powyżej: „open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems” oraz zasada opaque execution — agents „collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations”. Strona zawiera historię wydań (0.1.0, 0.2.6, 0.3.0, 1.0.0), appendix breaking changes oraz appendix o relacji do MCP. Rozdział 26 robi to porównanie. ↩ -
Frameworki multi-agent, których ten rozdział nie uczy, dla czytelnika chcącego źródeł pierwotnych zamiast tutoriala: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), gdzie agents są „customizable, conversable”, a sama rozmowa jest modelem programowania; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), który koduje standard operating procedures w role prompts i wprost mówi, że „solutions to more complex tasks are complicated through logic inconsistencies due to cascading hallucinations caused by naively chaining LLMs” — pewny siebie błędny chain zmierzony na początku tego rozdziału, nazwany w abstrakcie; oraz Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), dwadzieścia pięć agents z memory, reflection i planning, czyli największa opublikowana odpowiedź na „co się stanie, jeśli będziesz dodawać agents”. ↩