Naar inhoud springen
25/30Hoofdstuk 25 van 30

Multi-agent orchestration: vijf patronen, en wanneer één wint

Dezelfde factuur op vier manieren opgelost en geprijsd: de orchestrator kostte 1,66× de single agent en kwam tot hetzelfde oordeel.

Op deze pagina

Hoofdstuk 24 eindigde met een vraag die het had verdiend: als een sub-agent fout zit, wat krijgt de parent dan precies te zien?

Dit hoofdstuk beantwoordt die vraag met een rekening. Eén taak — een klant betwist een factuur en wil een antwoord — op vier manieren opgelost, allemaal met de Hoofdstuk 23 harness tegen dezelfde gescripte provider, allemaal met dezelfde encoder voor dezelfde tokens, allemaal geprijsd tegen de tarieven die Hoofdstuk 16 op 6 september 2026 las.

opstellingmodelaanroepeninput-tokensoutputkostenwall clockoordeel
prompt chaining4900165$0.0037801.648 msfout
één agent, vier tools52.697179$0.0075422.224 msgoed
parallelle secties92.910324$0.0097082.165 msgoed
orchestrator-workers123.628438$0.0125125.090 msgoed, en kan het niet bewijzen

Lees de eerste en de laatste rij samen: daartussen zit elk argument dat deze sector momenteel voert. De goedkoopste opstelling was ook de snelste en produceerde een zelfverzekerd, fout, verzendbaar antwoord. De duurste had het goed, kostte 3,3 keer zoveel geld en 3,1 keer zoveel tijd, en eindigde met het citeren van de conclusie van een worker die hij op geen enkele manier kan controleren.

De rij die niemand in deze tabellen zet, is de tweede: één agent met de vier tools kwam tot hetzelfde oordeel als de orchestrator voor 60% van het geld en 44% van de wall clock. Dat is geen voorkeur voor eenvoud. Het is een meting, en de rest van dit hoofdstuk gaat over wanneer die ophoudt waar te zijn.

Details tonen

Wat dit hoofdstuk nodig heeft uit de eerdere hoofdstukken.

  • Hoofdstuk 18 voor het toolcontract: een schema dat het model ziet, een endpoint dat het nooit ziet. Een volledige agent past achter die interface, en dat is multi-agent in zijn geheel.
  • Hoofdstuk 22 voor de twee gepubliceerde definities van „agent” die het oneens zijn, en voor de rekensom dat een chain van prompts N aanroepen is.
  • Hoofdstuk 23 voor de loop, de vijf uitwegen, de run-state en de trace. Elke opstelling hieronder is dat bestand, anders aangeroepen.
  • Hoofdstuk 24 voor wat een window kost en wat eruit valt. Een sub-agent is de vierde van zijn vier strategieën, en de enige die een tweede agent is in plaats van een policy.

Geen tensors. Alles hier is TypeScript, behalve twee metingen tegen een echt lokaal model.

Een Portugees bedrijf schrijft over factuur FT-2026-0918. De e-mail zegt dat de btw verkeerd lijkt, en voegt de factuur toe: netto EUR 248,00, btw berekend tegen 21%, EUR 52,08, totaal EUR 300,08.

De feiten die nodig zijn om te antwoorden staan op drie plekken, en slechts één daarvan staat in de e-mail:

waarwat er staat
de bijgevoegde factuurverkoper in Spanje, btw toegepast tegen 21%, EUR 52,08
de orderregistratiede koper is geregistreerd in Portugal, met een geldig btw-identificatienummer, business-to-business
de belastingtabelSpaans binnenlands tarief 21%; intra-EU business-to-business met geldig identificatienummer, verleggingsregeling, 0%

Zet de drie bij elkaar en de factuur is fout: de verleggingsregeling geldt, de btw had nul moeten zijn, er is een creditnota voor EUR 52,08 verschuldigd. Kijk alleen naar de factuur en hij klopt rekenkundig perfect — 248,00 plus 52,08 is 300,08 — en dat zul je dan ook zeggen.

De e-mail vermeldt wel „wij zijn een Portugees bedrijf”. Dat is een bewering, geen registratie, en geen enkel facturatiesysteem geeft een creditnota uit op basis van een bewering. De val is geen truc: het is de normale vorm van zakelijk werk, waarin de beslissing een feit nodig heeft dat niemand eraan dacht op te halen.

Alles hierboven draait tegen een gescripte provider in de stijl van die uit Hoofdstuk 23, met precies één regel:

Een antwoord mag alleen een feit gebruiken dat in zijn prompt staat.

Het „model” vraagt elke tool die het heeft één keer op, in catalogusvolgorde, en past daarna een vaste regel toe op de tekst die het kan zien. Niets is per opstelling gescript, dus de verschillen in de begintabel zijn geen claims over modelintelligentie: ze zijn gemeten information routing. Een echt model voegt daar zijn eigen fouten bovenop toe; het haalt deze niet weg.

De vijf patronen, in ongeveer veertig regels

Link naar de sectie: De vijf patronen, in ongeveer veertig regels

De vijf namen hieronder zijn die van Anthropic, uit Building effective agents, waar deze woordenschat is geland.1 Geen van de vijf ideeën is nieuw, en zeggen welk huis wat heeft benoemd — en welk idee ouder is — is de helft van de waarde van ze kennen.

patterns.tsTS
/* 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 };
}

Dat is de hele toolkit: vijf functies, geen framework, en de parallelle is één regel — wat precies het punt is van uitschrijven in plaats van tekenen. Nu elk op zijn beurt, met zijn afkomst, zijn prijs en het geval waarin het fout zit.

Chaining, en de beslissing die het voor je neemt

Link naar de sectie: Chaining, en de beslissing die het voor je neemt

Prompt chaining „ontleedt een taak in een reeks stappen, waarbij elke LLM-aanroep de output van de vorige verwerkt”.1 Het idee is ouder dan taalmodellen: het is een pipeline, met de trade van de pipeline — helderheid in ruil voor een control flow die vastligt voordat de data arriveert.

Vier stappen voor onze taak: haal de factuurvelden eruit, controleer de berekening, beslis wat verschuldigd is, schrijf het antwoord. Hier faalt het op twee verschillende manieren, wat meer leert dan één keer falen.

TEXT
--- 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."

De relay chain kostte $0.001940 en verloor de factuurvelden tussen stap twee en drie, omdat stap drie een zin over rekenkunde kreeg en niets anders. Hij produceerde een wachtbericht: nutteloos, en zichtbaar nutteloos.

De accumulerende chain — de rij in de begintabel — kostte $0.003780, 95% meer voor vier identieke aanroepen, omdat elke stap nu alles meedraagt wat eraan voorafging. Hij produceerde de gevaarlijke output. Vloeiend, met verwijzing naar zijn berekening, correct op elk getal dat hij noemt, en hij vertelt een klant dat er niets verschuldigd is terwijl EUR 52,08 verschuldigd is.

Het verschil tussen de twee is één ternary. Een chain die minder meedraagt produceert antwoorden die duidelijk incompleet zijn; een chain die alles meedraagt produceert antwoorden die zelfverzekerd fout zijn — en alleen de tweede soort wordt verzonden.

Geen van beide is de echte fout. De echte fout is dat de pipeline vóór het lezen al besliste dat deze taak vier stappen over de inhoud van een e-mail is. Nergens in die structuur is er een plek om te zeggen: „het registratieland staat niet in deze e-mail; ga het halen”. Chaining is juist wanneer de ontleding vooraf bekend en stabiel is. Hier was het een gok, en de gok ging de deur uit.

Routing, de oudste, en het plan B dat niemand opschrijft

Link naar de sectie: Routing, de oudste, en het plan B dat niemand opschrijft

Routing „classificeert een input en stuurt die naar een gespecialiseerde vervolgtaak”.1 De naam is nieuw; het mechanisme is de dispatcher, ouder dan bijna alles in dit boek. Wat nieuw is, is dat de classifier een model kan zijn — en daardoor faalt hij op manieren waarop een switch dat nooit deed.

route.tsTS
const answer = await route(email,
  (q) => classifyWithSmallModel(q),          // cheap model, one call
  { billing: billingAgent, tax: taxAgent, dunning: dunningAgent },
  taxAgent,                                  // deterministic, chosen in advance
);

Twee dingen over dat laatste argument. Het is geen error handling; het is het patroon. Een model-based router heeft een faalmodus die een dispatcher niet heeft: hij kan een label teruggeven dat niet bestaat, time-outen, of — de dure — een plausibel verkeerd label teruggeven zonder signaal dat het verkeerd is. Alle drie moeten ergens landen, en dat ergens kan niet nog een modelaanroep zijn, want je zit al in de branch waar modelaanroepen faalden.

Het tweede is dat de eigen prompt van de router niet gratis is. Om een model te kiezen heeft een router een catalogus van modellen nodig om uit te kiezen, en elk item daarin is input waarvoor de router betaalt voordat hij de vraag van de gebruiker heeft gelezen. Tegen het inputtarief waarmee deze cursus rekent, kost een catalogus van ongeveer 3.800 tokens al evenveel als de volledige agent-run met vijf aanroepen uit de openingstabel. In de praktijk draait de routingaanroep op een goedkoop model, en dat is precies waarom routing zichzelf terugverdient; maar het loont om de rekensom in die richting te maken in plaats van het aan te nemen. Routing is verkeerd precies wanneer de gerouteerde taak goedkoper is dan de routingbeslissing.

Parallelisatie: secties, en stemmen, wat self-consistency is

Link naar de sectie: Parallelisatie: secties, en stemmen, wat self-consistency is

Anthropic splitst deze in tweeën: sectioning — „een taak opdelen in onafhankelijke subtaken die parallel worden uitgevoerd” — en voting — „dezelfde taak meerdere keren uitvoeren om diverse outputs te krijgen”.1 Ze delen een diagram en bijna niets anders.

Sectioning is de goedkope winst, en het is de regel uit patterns.ts: drie specialisten — facturatie, belasting, policy — elk met zijn eigen window en tools, over dezelfde e-mail, met één synthese-aanroep aan het einde. Identiek werk, op twee manieren geordend:

modelaanroepeninputoutputkostenwall clock
de drie workers, na elkaar92.910324$0.0097083.894 ms
dezelfde drie, Promise.all92.910324$0.0097082.165 ms

Token voor token hetzelfde, 1,8 keer sneller. Daarom verdient het patroon zijn eigen naam: het is de enige van de vijf die iets verbetert zonder iets te kosten. De adder is dat de secties echt onafhankelijk moeten zijn — geef sectie B een feit dat sectie A produceert en Promise.all draait ze allebei tegen een state die nog niet bestaat. De for loop verborg die bug; de one-liner legt hem bloot.

Voting is een ander dier met hetzelfde plaatje aan. Dezelfde vraag k keer uitvoeren en de meerderheid nemen is self-consistency, in maart 2022 gepubliceerd door Wang et al. als decoding-strategie, bijna drie jaar voordat iemand het een orchestration pattern noemde. Het abstract is precies over het mechanisme — „samplet eerst een diverse set reasoning paths in plaats van alleen de greedy te nemen, en selecteert daarna het meest consistente antwoord door de gesamplede reasoning paths weg te marginaliseren” — en over de winst: +17,9 punten op GSM8K.2

Daaruit volgen twee dingen die het plaatje verbergt. Ten eerste vereist voting de sampling uit Hoofdstuk 17: bij temperature nul zijn alle k samples dezelfde sample, en is de meerderheid één antwoord waarvoor k keer is betaald. Ten tweede werkt het alleen waar een meerderheid betekenisvol is — bij het factuurantwoord hierboven is er niets te tellen, want vijf concepten zijn vijf verschillende zinnen. Voting is voor taken met een kort, vergelijkbaar antwoord, wat precies Wangs benchmarks zijn en bijna niets wat een customer-facing agent doet.

Hier gemeten op 20 driestaps woordproblemen waarvan de antwoorden worden berekend in plaats van beoordeeld, met het lokale model uit Hoofdstuk 23 dat stap voor stap redeneert:

modelaanroepeninputoutputkosten voor de 20correct95%-interval
één greedy chain201.3302.649$0.0344489/2026–66%
meerderheid van 5, temperature 0.81006.65013.245$0.1722409/2026–66%

Vijf keer de aanroepen, vijf keer de tokens, exact vijf keer de rekening, en niet één extra correct antwoord. Voting is een weddenschap, geen verbetering, en deze run verloor hem.

Twee kanttekeningen, voordat iemand dat citeert als weerlegging van Wang. Twintig trials kunnen 45% niet onderscheiden van 60% — het interval is de breedte van de claim, wat de discipline uit Hoofdstuk 4 op mijn eigen resultaat toegepast is. En de gepubliceerde winsten komen van modellen die orden van grootte groter zijn, waar de diverse reasoning paths waar voting over marginaliseert ook echt divers zijn. Wat overdraagt is niet het getal: het is dat de multiplier exact is en vooraf bekend, terwijl de winst dat niet is.

Orchestrator-workers, en wat een samenvatting niet is

Link naar de sectie: Orchestrator-workers, en wat een samenvatting niet is

In de orchestrator-workers workflow „breekt een centrale LLM taken dynamisch op, delegeert ze aan worker LLMs en synthetiseert hun resultaten”, en het verschil met sectioning is dat „subtaken niet vooraf gedefinieerd zijn, maar door de orchestrator worden bepaald”.1 De afkomst hier komt helemaal niet uit taalmodellen: dit is master-worker, en de versie waarin workers bevindingen in een gedeelde ruimte schrijven die een controller leest, is de blackboard-architectuur, uit spraakverstaansonderzoek in de jaren 70. Wat in 2026 nieuw is, is dat de controller een model is en de ontleding dus per input kan worden beslist — de flexibiliteit en de kosten in één zin.

Het kostte 12 modelaanroepen tegenover 5 voor de single agent, en het kwam tot hetzelfde oordeel. Daarna deed het iets dat het bekijken waard is:

TEXT
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-4471

Beide hebben gelijk. Slechts één weet waarom. De tax worker had de factuur, de order en de belastingtabel in zijn eigen window, kwam tot de conclusie, en merkte ook op — niemand vroeg erom — dat het inkoopordernummer op de factuur niet overeenkomt met dat van de order. Daarna gaf hij een samenvatting terug. De orchestrator kan beide uitspraken herhalen en geen van beide controleren, omdat het bewijs in een window bleef dat hij nooit zag. Dat is de slotvraag van Hoofdstuk 24, beantwoord: de parent krijgt te zien wat het child ervoor koos op te schrijven.

De fix is een flag, en die heeft een prijs:

wat de worker teruggeeftorchestrator input-tokenskostenwat de parent kan doen
zijn conclusie3.628$0.012512herhalen
zijn conclusie en zijn bewijs4.065$0.013554opnieuw afleiden, en het oneens zijn

Twaalf procent meer input-tokens, 8,3% meer geld, en de frase source=worker_unverified verdwijnt uit het antwoord. Dat is de trade in elk multi-agent system en hij wordt bijna nooit uitgesproken: het schone window van het child is waardevol, het vermogen van de parent om het te auditen is het betalen waard, en je kunt niet allebei gratis hebben.

Wanneer is orchestrator-workers dus verkeerd? Hier, op deze taak. Het kocht een correct antwoord dat één agent met dezelfde vier tools ook bereikte, voor 1,66 keer de kosten en 2,3 keer de wall clock, en het maakte dat antwoord moeilijker te verdedigen. Anthropic's eigen richtlijn zegt hetzelfde voordat de patronen beginnen: vind „de eenvoudigst mogelijke oplossing, en verhoog complexiteit alleen wanneer nodig”, omdat „agentic systems vaak latency en kosten inruilen voor betere taakprestaties”.1 De tabellen hierboven zijn die zin met cijfers eronder.

Evaluator-optimiser, en de rechter die het examen schreef

Link naar de sectie: Evaluator-optimiser, en de rechter die het examen schreef

Eén aanroep genereert, een andere evalueert, en de loop herhaalt tot de evaluatie slaagt.1 De gepubliceerde voorouders zijn Self-Refine — hetzelfde model als „generator, refiner, and feedback provider”, met ongeveer 20 punten absolute verbetering gemiddeld over zeven taken3 — en Reflexion, dat de kritiek in een episodische buffer over pogingen heen bewaart en 91% pass@1 op HumanEval rapporteert waar de baseline 80% haalde.4

Het kostenmodel is de eenvoudigste van de vijf: twee aanroepen per ronde, en het aantal rondes is niet van jou. Drie verfijningsrondes op een taak die één aanroep kostte, is zes aanroepen, dus de bodem van het patroon is 6× en het plafond is welke cap jij instelt — waardoor de budget-exit uit Hoofdstuk 23 verplicht wordt in plaats van netjes.

Het plafond is subtieler, en meetbaar. Op dezelfde 20 problemen beantwoordde het lokale model er 9 correct. Daarna kreeg het elk van die antwoorden te zien en werd gevraagd of het klopte — zonder te vertellen dat het antwoord van hemzelf was, wat de vleierij-confound weghaalt en de capability overlaat:

het eigen antwoord van het modelhet zei „ja”het zei „nee”
de 9 die goed waren90
de 11 die fout waren38

Dat is een betere rechter dan de sectietitel suggereert, en dat zeggen is het punt van meten in plaats van beweren: hij blokkeerde niets corrects en ving 8 van de 11 fouten. Als filter is hij zijn aanroepen waard.

Als stopregel, wat een evaluator-optimiser loop er daadwerkelijk voor gebruikt, zijn die drie goedkeuringen het hele verhaal: ze beëindigen de loop met een fout antwoord in handen, en geen aantal extra rondes bereikt ze ooit. Een refinement loop kan niet correcter worden dan zijn rechter. Meer rondes kopen pogingen op de fouten die de rechter kan zien, tegen volle prijs, en helemaal niets tegen de fouten die hij niet kan zien.

Dus de regel: een evaluator verdient zijn aanroepen alleen wanneer hij iets heeft dat de generator niet heeft. Een compiler, een test suite, een schema validator, een ander model, een mens. Self-Refine's eigen resultaten zijn gemeten tegen menselijke voorkeur en taakmetrics, nooit tegen de mening van het model over zichzelf. Als het enige voordeel van je evaluator een andere prompt is, betaal je dubbel voor overeenstemming. Hoofdstuk 29 bouwt de versie met een echt voordeel: een golden set met de antwoorden vooraf opgeschreven.

De vijf hierboven zijn vormen voor jouw code. Daaronder zit een tweede familie die er vaak naast wordt gezet en dat niet zou moeten worden: ReAct, Reflexion, plan-and-execute en tree of thoughts zijn reasoning loops, en hun kosten zitten in requests.

Hoofdstuk 12 ging over reasoning binnen het model, waarvoor je betaalt in output-tokens op één aanroep. Dit is de andere soort. Het verschil doet ertoe als de rekening komt: een langere chain of thought maakt één aanroep duurder, en een reasoning loop maakt van één taak veel aanroepen, die elk alles ervoor opnieuw meesturen — het kwadratische dat Hoofdstuk 23 in zijn runaway-tabel mat.

loopaanroepen, per taakwat de extra aanroepen kopen
ReActéén per stap, tot hij stopthet model reageert op wat de tools teruggeven5
plan-and-executeéén om te plannen, daarna één per staphet plan ligt vast voordat de eerste stap draait6
Reflexionpogingen × (act + reflect)de kritiek overleeft tot in de volgende poging4
tree of thoughtsbranching factor × diepte, plus één evaluatie per nodesearch, met backtracking7

De tree-of-thoughts-paper publiceert zijn eigen kostentabel, wat zeldzamer is dan het zou moeten zijn. Op Game of 24 met GPT-4: input/output prompting best-of-100 loste 33% op voor $0.13 per case, chain of thought best-of-100 loste 49% op voor $0.47, en tree of thoughts loste 74% op voor $0.74, waarbij de auteurs opmerken dat het „5–100 keer meer gegenereerde tokens dan CoT zou kunnen vereisen”.7

Bijna zes keer de prijs van de goedkope methode voor iets meer dan het dubbele succespercentage. Of dat een koopje is, hangt af van wat een mislukte case je kost — de vraag die je moet stellen voordat je een van deze vier adopteert.

Deze cursus implementeert ze niet opnieuw. Alle vier hebben referentie-implementaties van hun eigen auteurs, in Python, en hun waarde is dat ze de bron zijn in plaats van een vertaling: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm en AGI-Edgerunners/Plan-and-Solve-Prompting. Lees de prompts in die repositories; de prompts zijn de papers.

Twee topologieën, en één daarvan komt niet terug

Link naar de sectie: Twee topologieën, en één daarvan komt niet terug

Nu multi-agent zelf, waar de meeste verwarring zit. Er zijn twee manieren waarop één agent een andere kan betrekken, het zijn geen varianten, en het verschil is wie daarna de leiding heeft.

Agent als tool. De parent roept hem aan, krijgt een antwoord en gaat door. Het is de tool-interface uit Hoofdstuk 18 met een volledige agent erachter, en de parent verliest nooit de controle. Dit is wat de orchestrator hierboven doet.

Handoff. De parent draagt het gesprek over en krijgt het niet terug. OpenAI's guide is de helderste gepubliceerde formulering: handoffs zijn „een eenrichtingsoverdracht waarmee een agent aan een andere agent kan delegeren... Als een agent een handoff function aanroept, starten we onmiddellijk de uitvoering op die nieuwe agent waaraan is overgedragen, terwijl we ook de nieuwste conversation state overdragen.”8

Een vocabulairewaarschuwing, want dit laat mensen voortdurend struikelen: „handoff” is het woord van één SDK, geen standaard. Het is terminologie uit de OpenAI Agents SDK en die guide, die de twee opstellingen ook „manager” en „decentralized” noemt en opmerkt dat in het manager pattern „edges tool calls voorstellen, terwijl edges in het decentralized pattern handoffs voorstellen”.8 Er is een open standaard in deze ruimte — A2A, op versie 1.0.0, onder copyright van de Linux Foundation, met een versiegeschiedenis en een gedocumenteerde lijst met breaking changes, waarvan het verklaarde principe opaque execution is: agents „collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations”.9 Dat is geen handoff, en de vergelijking hoort thuis in Hoofdstuk 26. Wat hier telt is dat een van de twee woorden de API van een library is en het andere een specificatie met governance.

Het onderscheid is een datastructuur, geen diagram:

graph.tsTS
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;
}

Twintig regels, twee bugs die je anders in productie zou vinden. reachable vindt de agent waar niemand bij kan — geconfigureerd, betaald, nooit aangeroepen. conflicts weigert de edge die beide soorten tegelijk is, wat pietluttig klinkt tot je het hardop leest: de parent behoudt de controle én geeft die weg. Draai het op een vijf-agent system met één orphan en één dubbele edge:

TEXT
reachable: lead@0 billing@1 tax@1 dunning@1
orphans:   ghost
conflicts: lead->tax

Nu de meting waar deze sectie voor bestaat, en de enige in het hoofdstuk tegen een echt model in plaats van een gescript model.

Een klant noemt in zijn eerste bericht een constraint — onze account is geregistreerd in Portugal, niet Spanje; alles wat met belasting te maken heeft moet Portugal gebruiken — chat over iets anders, en stelt daarna een vraag die billing moet beantwoorden. De case wordt overgedragen. Vierentwintig trials, telkens een ander land en bedrijf, vier transfer-payloads, en de ontvangende agent krijgt daarna één vraag: in welk land is deze klantaccount geregistreerd?

wat werd overgedragengemiddelde payloadde constraint zat erinde specialist herinnerde het zich95%-interval
het hele gesprek173 tokens24/2420/24 — 83%64–93%
een samenvatting die de zendende agent schreef62 tokens1/240/24 — 0%0–14%
alleen het laatste gebruikersbericht61 tokens0/240/24 — 0%0–14%
een typed record69 tokens24/2424/24 — 100%86–100%

De derde rij is een controle en gedraagt zich zo: het feit staat er niet in, dus kan het niet worden herinnerd. De andere drie zijn de bevinding.

Het volledige transcript is 173 tokens en werkt 83% van de tijd, waarbij de vier mislukkingen het onderwerp van Hoofdstuk 24 zijn in plaats van dat van dit hoofdstuk. Het typed record is 69 tokens — zeven meer dan de samenvatting — en werkt elke keer, omdat de constraint in een benoemd veld zit in plaats van in een zin.

En de samenvatting is de rij om naar te blijven kijken. Hij faalde 24 van de 24 keer, en de reden is niet dat de lezer het miste. De constraint verscheen überhaupt in slechts 1 van de 24 samenvattingen. De ontvangende agent was niet slordig; hij kreeg een tekst waarin het antwoord niet stond. Een samenvatting is een compaction die jij niet hebt geschreven, geproduceerd door een model waarvan je het window niet kunt zien, geoptimaliseerd om als samenvatting te lezen — en „de klant zegt dat onze records het verkeerde land hebben” is precies het soort bijzin dat een summariser als procedurele ruis laat vallen.

Een eerlijke beperking op dat getal: de summariser is een half-billion-parameter model en een groter model zou meer bewaren. Wat niet verbetert met grootte is de vorm van het risico — de zendende agent beslist, per handoff, per formulering, onobserveerbaar, welke feiten overleven. Het typed record hangt helemaal niet van dat oordeel af, en daarom wint het door constructie in plaats van door intelligentie. Wat een transfer moet overleven, moet een veld zijn, geen zin.

Dezelfde redenering geldt de andere kant op, voor de agent-as-tool-topologie, en de eerdere tabel heeft hem al geprijsd: wat terugkomt van een worker is ook een samenvatting, en 8,3% meer betalen om het bewijs erbij te ontvangen is dezelfde fix gezien vanaf de kant van de parent.

Drie slotfeiten, allemaal uit tabellen hierboven.

Een multi-agent system vermenigvuldigt aanroepen, en aanroepen zijn kwadratisch in context. De orchestrator deed 12 modelaanroepen waar één agent er 5 deed, en elk draagt zijn eigen groeiende transcript mee — 3.628 input-tokens tegenover 2.697, een kloof die groter wordt met de lengte van de taak.

Elke grens is een lossy channel. Twee agents betekent één samenvatting. Vier agents in een chain betekent drie, samengesteld, elk geschreven door een model dat voor iets anders optimaliseert dan jouw beslissing.

De single agent vond iets waar niemand om vroeg. De mismatch in het inkoopordernummer kwam boven omdat één window de factuur en de order tegelijk bevatte. Werk opsplitsen over specialisten splitst ook het vermogen om te merken dat twee feiten elkaar tegenspreken.

Niets daarvan pleit tegen de gepubliceerde multi-agent frameworks, die het waard zijn om als primaire bronnen te lezen in plaats van via tutorials.10 Het pleit ervoor de tweede agent zijn plek te laten verdienen.

Dus een test in plaats van een voorkeur. Voeg een tweede agent toe wanneer minstens één hiervan waar is: de subtaak heeft een clean window nodig dat de parent niet mag erven (Hoofdstuk 24); de subtaken zijn echt onafhankelijk en de wall clock doet ertoe, wat de 1,8× hierboven is; de subtaak heeft andere rechten of een ander model nodig, wat Hoofdstuk 30 in een security-argument omzet; of de subtaak is eigendom van iemand anders, waar een echt protocol belangrijk begint te worden. Als het antwoord is „zodat elke agent een duidelijkere prompt heeft”, geef de ene agent dan een duidelijkere prompt. Dat is gratis.

Je kunt nu de vijf patronen benoemen, ze op één taak tegen elkaar prijzen, een orchestrator onderscheiden van een sectioner en een tool call van een handoff, en een single agent verdedigen met een tabel in plaats van een voorkeur.

Elke opstelling hier deelde één gemak dat contact met iets echts niet zal overleven: alle tools waren van ons. Factuur, order, belastingtabel, de workers achter de orchestrator — dezelfde repository, dezelfde deploy, dezelfde types, dezelfde mensen.

Zet er nu één aan de andere kant van een bedrijfsgrens. De belastingtabel is van een boekhoudleverancier, de orderregistratie van een warehousesysteem, en geen van beide heeft jouw Tool interface gelezen. Je hebt een manier nodig waarop een model dat jij niet schreef een capability die iemand anders runt kan ontdekken, beschrijven en aanroepen — met authenticatie (wat de helft van Hoofdstuk 27 is), versioning, en de garantie dat een server de rest van je gesprek niet kan lezen. Dat is een protocolprobleem, het heeft een specificatie met een normatief schema, en bijna alles wat erover is geïndexeerd beschrijft een revisie die niet meer bestaat.

Hoofdstuk 26 leest die specificatie in plaats van haar samen te vatten, en begint door JSON-RPC met de hand in een terminal te typen.


Elke cost en elk token count hierboven kwam van de gescripte provider die in de tweede sectie is beschreven, op Node 22 over een loopback-interface, geteld met de o200k_base encoding en geprijsd tegen de tarieven die Hoofdstuk 16 op 6 september 2026 las — $2.00 per miljoen input-tokens en $12.00 per miljoen output. Wall-clock-cijfers komen uit dezelfde runs met de latency van de provider ingesteld op 400 ms per aanroep en tools op 50 ms, zodat ze de opstelling meten in plaats van een provider. De twee real-model-metingen — de handoff-tabel en de voting-and-judging-tabel — gebruikten Qwen/Qwen2.5-0.5B-Instruct in float32 op de CPU achter een endpoint met dezelfde vorm, greedy behalve waar een temperature wordt genoemd, met intervallen berekend volgens Wilsons methode uit Hoofdstuk 4. Geen enkele request in dit hoofdstuk ging naar een betaald endpoint, en geen enkel getal erin is geschat.

  1. Anthropic, Building effective agents, 19 december 2024, anthropic.com/engineering/building-effective-agents, gelezen op 7 september 2026. Bron van de vijf workflow-namen die hierboven worden gebruikt en van elke frase die daaruit wordt geciteerd — prompt chaining, routing, parallelisation met de varianten sectioning en voting, orchestrator-workers, evaluator-optimiser — en ook van de aanbeveling om „de eenvoudigst mogelijke oplossing te vinden, en complexiteit alleen te verhogen wanneer nodig” en de observatie dat „agentic systems often trade latency and cost for better task performance”. Hoofdstukken 22 en 23 citeren de definitie van een agent. 2 3 4 5 6 7

  2. Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. en Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (maart 2022). De oorsprong van het voting pattern, daar beschreven als decoding-strategie in plaats van architectuur: sample diverse reasoning paths en „select the most consistent answer by marginalizing out the sampled reasoning paths”, met gerapporteerde winsten van +17,9 op GSM8K, +11,0 op SVAMP, +12,2 op AQuA, +6,4 op StrategyQA en +3,9 op ARC-challenge.

  3. Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). De evaluator-optimiser loop met één model in alle drie rollen — „generator, refiner, and feedback provider” — die „by ~20% absolute on average in task performance” verbetert over zeven taken, gemeten met menselijke voorkeur en automatische metrics in plaats van met het eigen oordeel van het model.

  4. Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. en Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). Voegt een episodic memory van zelfkritieken over pogingen heen toe — „reinforce language agents not by updating weights, but through linguistic feedback” — en rapporteert 91% pass@1 op HumanEval tegenover 80% voor de GPT-4 baseline. Let op de voorwaarde waarvan de resultaten afhangen: een echt signaal uit de omgeving, zoals een falende test, in plaats van de mening van het model over zichzelf. 2

  5. Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. en Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). Interleaved reasoning traces en actions; Hoofdstuk 23 bouwde deze loop. Hier geciteerd om zijn kostenvorm in plaats van zijn resultaten: één modelaanroep per stap, waarbij telkens het hele transcript opnieuw wordt meegestuurd.

  6. Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. en 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” — de plan-then-execute-vorm, en de bron van de trade waar dit hoofdstuk om draait: het plan ligt vast voordat de eerste observatie arriveert, wat prompt chaining is met de ontleding geschreven door een model in plaats van door jou.

  7. Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. en Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023). Search over intermediate „thoughts” met zelfevaluatie en backtracking; 74% op Game of 24 tegenover 4% voor chain-of-thought prompting. De hierboven geciteerde kostencijfers zijn die van de paper zelf, uit Appendix B.3, Table 7: per case, input/output prompting best-of-100 op $0.13 voor 33%, chain of thought best-of-100 op $0.47 voor 49%, en tree of thoughts op $0.74 voor 74%, met de auteursopmerking dat ToT „could require 5-100 times more generated tokens than CoT”. 2

  8. OpenAI, A practical guide to building agents (PDF), gelezen op 7 september 2026. De splitsing manager-versus-decentralised, de hierboven geciteerde graph-framing („in the manager pattern, edges represent tool calls whereas in the decentralized pattern, edges represent handoffs”), en de definitie van een handoff als „a one way transfer... we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state”. Let op wat die laatste bijzin vastlegt: in deze SDK reist de conversation state mee, wat een designbeslissing van die library is en geen eigenschap van handoffs in het algemeen. 2

  9. Agent2Agent (A2A) Protocol Specification, nieuwste uitgebrachte versie 1.0.0, a2a-protocol.org/latest/specification/, gelezen op 7 september 2026; copyright The Linux Foundation, Apache-2.0. Hierboven geciteerd: een „open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems”, en het opaque execution-principe — agents „collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations”. De pagina bevat een releasegeschiedenis (0.1.0, 0.2.6, 0.3.0, 1.0.0), een appendix met breaking changes, en een appendix over de relatie met MCP. Hoofdstuk 26 maakt die vergelijking.

  10. De multi-agent frameworks die dit hoofdstuk niet onderwijst, voor de lezer die primaire bronnen wil in plaats van een tutorial: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), waar agents „customizable, conversable” zijn en conversation zelf het programmeermodel is; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), dat standard operating procedures in role prompts codeert en expliciet is dat „solutions to more complex tasks are complicated through logic inconsistencies due to cascading hallucinations caused by naively chaining LLMs” — de zelfverzekerd-foute chain die bovenaan dit hoofdstuk is gemeten, benoemd in een abstract; en Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), vijfentwintig agents met memory, reflection en planning, wat het grootste gepubliceerde antwoord is op „wat gebeurt er als je agents blijft toevoegen”.

Klaar om LIA te laten kiezen?

Bouw met elk AI-model op één plek — begin vandaag nog gratis.