Sari la conținut
25/30Capitolul 25 din 30

Orchestrare multi-agent: cinci tipare și când câștigă unul

Aceeași factură rezolvată în patru feluri și costurile într-un tabel: orchestratorul a costat 1,66× cât un singur agent.

Pe această pagină

Capitolul 24 s-a încheiat cu o întrebare pe care și-o câștigase: când un sub-agent greșește, la ce anume ajunge părintele să se uite?

Acest capitol răspunde cu o notă de plată. O singură sarcină — un client contestă o factură și vrea un răspuns — rezolvată în patru feluri, toate rulând harness-ul din Capitolul 23 împotriva aceluiași provider scriptat, toate numărând aceiași token cu același encoder, toate evaluate la tarifele citite de Capitolul 16 pe 6 septembrie 2026.

aranjamentapeluri de modelinput tokensoutputcosttimp totalverdict
prompt chaining4900165$0.0037801,648 msgreșit
un agent, patru instrumente52,697179$0.0075422,224 mscorect
secțiuni paralele92,910324$0.0097082,165 mscorect
orchestrator-workers123,628438$0.0125125,090 mscorect, și nu poate dovedi

Citește primul și ultimul rând împreună: între ele se află fiecare dispută pe care industria o poartă în prezent. Cel mai ieftin aranjament a fost și cel mai rapid și a produs un răspuns sigur pe el, greșit, gata de trimis. Cel mai scump a nimerit răspunsul, a luat de 3,3 ori mai mulți bani și de 3,1 ori mai mult timp, apoi a încheiat citând concluzia unui worker pe care nu are cum s-o verifice.

Rândul pe care nimeni nu-l pune în aceste tabele este al doilea: un agent cu cele patru instrumente a ajuns la același verdict ca orchestratorul pentru 60 % din bani și 44 % din timpul total. Asta nu este o preferință pentru simplitate. Este o măsurătoare, iar restul capitolului explică momentul în care încetează să mai fie adevărată.

Afișează detaliile

De ce are nevoie acest capitol din cele anterioare.

  • Capitolul 18 pentru contractul de instrument: o schemă pe care modelul o vede, un endpoint pe care nu-l vede niciodată. Un agent întreg încape în spatele acelei interfețe, ceea ce este tot multi-agent.
  • Capitolul 22 pentru cele două definiții publicate ale lui „agent” care nu se pun de acord și pentru aritmetica potrivit căreia un lanț de prompts înseamnă N apeluri.
  • Capitolul 23 pentru buclă, cele cinci ieșiri, starea rulării și trace-ul. Fiecare aranjament de mai jos este acel fișier, apelat altfel.
  • Capitolul 24 pentru cât costă o fereastră și ce cade din ea. Un sub-agent este a patra dintre cele patru strategii ale sale și singura care este un al doilea agent, nu o politică.

Fără tensors. Totul aici este TypeScript, cu excepția a două măsurători făcute pe un model local real.

O companie portugheză scrie despre factura FT-2026-0918. Emailul spune că TVA-ul pare greșit și atașează factura: net EUR 248.00, TVA aplicat la 21 %, EUR 52.08, total EUR 300.08.

Faptele necesare pentru răspuns se află în trei locuri, iar doar unul dintre ele este în email:

undece spune
factura atașatăvânzător în Spania, TVA aplicat la 21 %, EUR 52.08
înregistrarea comenziicumpărătorul este înregistrat în Portugalia, cu un identificator TVA valid, business-to-business
tabelul fiscalcotă internă spaniolă 21 %; intra-UE business-to-business cu identificator valid, taxare inversă, 0 %

Puse împreună, cele trei arată că factura este greșită: se aplică taxarea inversă, TVA-ul ar fi trebuit să fie zero, se datorează o notă de credit de EUR 52.08. Dacă te uiți doar la factură, ea este perfectă aritmetic — 248.00 plus 52.08 fac 300.08 — și asta vei spune.

Emailul chiar afirmă „suntem o companie portugheză”. Aceasta este o afirmație, nu o înregistrare, iar niciun sistem de facturare nu emite o notă de credit pe baza unei afirmații. Capcana nu este un truc: este forma obișnuită a muncii de business, în care decizia are nevoie de un fapt pe care nimeni nu s-a gândit să-l aducă.

Tot ce urmează rulează împotriva unui provider scriptat în stilul celui din Capitolul 23, cu exact o regulă:

Un răspuns poate folosi doar un fapt care se află în prompt-ul său.

„Modelul” cere fiecare instrument pe care îl are, o singură dată, în ordinea catalogului, apoi aplică o regulă fixă textului pe care îl poate vedea. Nimic nu este scriptat per aranjament, deci diferențele din tabelul de început nu sunt afirmații despre inteligența modelului: sunt routing de informație, măsurat. Un model real adaugă propriile eșecuri deasupra; nu le elimină pe acestea.

Cele cinci nume de mai jos sunt ale Anthropic, din Building effective agents, locul unde acest vocabular s-a stabilizat.1 Niciuna dintre cele cinci idei nu este nouă, iar a spune care casă a numit ce — și care idee este mai veche — reprezintă jumătate din valoarea cunoașterii lor.

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 };
}

Acesta este tot setul de instrumente: cinci funcții, niciun framework, iar cea paralelă este o singură linie — acesta este și motivul pentru care merită scrisă, nu desenată. Acum fiecare pe rând, cu originea, prețul și cazul în care greșește.

Prompt chaining „descompune o sarcină într-o secvență de pași, în care fiecare apel LLM procesează output-ul celui anterior”.1 Ideea precedă modelele lingvistice: este un pipeline, cu compromisul pipeline-ului — claritate în schimbul unui flux de control fixat înainte să sosească datele.

Patru pași pentru sarcina noastră: extrage câmpurile facturii, verifică aritmetica, decide ce este datorat, scrie răspunsul. Aici eșuează în două feluri diferite, ceea ce ne învață mai mult decât un singur eșec.

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

Lanțul de relay a costat $0.001940 și a pierdut câmpurile facturii între pașii doi și trei, pentru că pasul trei a primit o propoziție despre aritmetică și nimic altceva. A produs un mesaj de așteptare: inutil și vizibil inutil.

Lanțul cumulativ — rândul din tabelul de început — a costat $0.003780, cu 95 % mai mult pentru patru apeluri identice, pentru că fiecare pas cară acum tot ce a fost înaintea lui. A produs output-ul periculos. Fluent, citându-și aritmetica, corect pe fiecare număr pe care îl menționează și spunându-i clientului că nu se datorează nimic, când se datorează EUR 52.08.

Diferența dintre cele două este un ternar. Un lanț care cară mai puțin produce răspunsuri evident incomplete; un lanț care cară tot produce răspunsuri sigur-pe-ele și greșite — iar doar al doilea tip ajunge trimis.

Nici acesta nu este eșecul real. Eșecul real este că pipeline-ul a decis, înainte de a citi ceva, că această sarcină are patru pași peste conținutul unui email. Nicăieri în acea structură nu există un loc în care să spună „țara de înregistrare nu este în acest email; du-te și ia-o”. Chaining este corect când descompunerea este cunoscută dinainte și stabilă. Aici a fost o presupunere, iar presupunerea a fost livrată.

Routing, cel mai vechi, și planul B pe care nimeni nu-l scrie

Link către secțiunea: Routing, cel mai vechi, și planul B pe care nimeni nu-l scrie

Routing „clasifică un input și îl direcționează către o sarcină follow-up specializată”.1 Numele este nou; mecanismul este dispatcher-ul, mai vechi decât aproape orice altceva din această carte. Ce este nou este că acest clasificator poate fi un model — ceea ce îl face să eșueze în feluri în care un switch nu a făcut-o niciodată.

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
);

Două lucruri despre acel ultim argument. Nu este error handling; este tiparul. Un router bazat pe model are un mod de eșec pe care un dispatcher nu-l are: poate returna o etichetă care nu există, poate expira sau — varianta scumpă — poate returna o etichetă plauzibilă, greșită, fără semnal că este greșită. Toate trei trebuie să ajungă undeva, iar acel undeva nu poate fi un alt apel de model, pentru că ești deja în ramura în care apelurile de model au eșuat.

Al doilea lucru este că prompt-ul routerului nu este gratuit. Ca să aleagă un model, un router are nevoie de un catalog de modele din care să aleagă, iar fiecare intrare din el este input pe care routerul îl plătește înainte să fi citit întrebarea utilizatorului. La tariful de input cu care calculează prețurile acest curs, un catalog de aproximativ 3.800 tokens costă deja cât întreaga rulare de agent cu cinci apeluri din tabelul de deschidere. În practică, apelul de routing rulează pe un model ieftin, și acesta este tot motivul pentru care routing-ul se amortizează; dar merită făcută aritmetica în acea direcție, nu presupusă. Routing-ul este greșit exact atunci când sarcina rutată este mai ieftină decât decizia de routing.

Paralelizare: secțiuni și voting, adică self-consistency

Link către secțiunea: Paralelizare: secțiuni și voting, adică self-consistency

Anthropic împarte acest tipar în două: sectioning — „împărțirea unei sarcini în sub-sarcini independente rulate în paralel” — și voting — „rularea aceleiași sarcini de mai multe ori pentru a obține output-uri diverse”.1 Împart o diagramă și aproape nimic altceva.

Sectioning este câștigul ieftin și este linia din patterns.ts: trei specialiști — facturare, taxe, politică — fiecare cu propria fereastră și propriile instrumente, peste același email, cu un apel de sinteză la final. Muncă identică, ordonată în două feluri:

apeluri de modelinputoutputcosttimp total
cei trei workers, unul după altul92,910324$0.0097083,894 ms
aceiași trei, Promise.all92,910324$0.0097082,165 ms

Același token cu token, de 1,8 ori mai rapid. De aceea tiparul își merită propriul nume: este singurul dintre cele cinci care îmbunătățește ceva fără să coste nimic. Capcana este că secțiunile trebuie să fie cu adevărat independente — dă secțiunii B un fapt pe care îl produce secțiunea A și Promise.all le rulează pe amândouă împotriva unei stări care încă nu există. Bucla for ascundea bugul; one-liner-ul îl expune.

Voting este un alt animal purtând aceeași imagine. A rula aceeași întrebare de k ori și a lua majoritatea este self-consistency, publicată de Wang et al. în martie 2022 ca strategie de decoding, cu aproape trei ani înainte ca cineva s-o numească tipar de orchestrare. Abstractul este precis despre mecanism — „mai întâi eșantionează un set divers de căi de raționament în loc să ia doar calea greedy, apoi selectează răspunsul cel mai consistent prin marginalizarea căilor de raționament eșantionate” — și despre câștig: +17,9 puncte pe GSM8K.2

De aici urmează două lucruri pe care imaginea le ascunde. Primul, voting necesită sampling-ul din Capitolul 17: la temperatură zero toate cele k samples sunt același sample, iar majoritatea este un singur răspuns plătit de k ori. Al doilea, funcționează doar acolo unde o majoritate are sens — la răspunsul la factura de mai sus nu ai ce număra, pentru că cinci drafturi sunt cinci propoziții diferite. Voting este pentru sarcini cu un răspuns scurt, comparabil, exact benchmarkurile lui Wang și aproape nimic din ce face un agent orientat către client.

Măsurat aici pe 20 de probleme textuale în trei pași, ale căror răspunsuri sunt calculate, nu judecate, cu modelul local din Capitolul 23 raționând pas cu pas:

apeluri de modelinputoutputcost pentru cele 20corecteinterval 95 %
un lanț greedy201,3302,649$0.0344489/2026–66 %
majoritate din 5, temperatură 0.81006,65013,245$0.1722409/2026–66 %

De cinci ori apelurile, de cinci ori tokens, exact de cinci ori nota de plată și niciun răspuns corect în plus. Voting este un pariu, nu o îmbunătățire, iar această rulare l-a pierdut.

Două precizări, înainte ca cineva să citeze asta ca infirmare a lui Wang. Douăzeci de încercări nu pot distinge 45 % de 60 % — intervalul are lățimea afirmației, adică disciplina din Capitolul 4 întoarsă asupra propriului meu rezultat. Iar câștigurile publicate vin de la modele cu ordine de mărime mai mari, unde căile diverse de raționament peste care voting marginalizează sunt chiar diverse. Ce se transferă nu este numărul: este faptul că multiplicatorul este exact și cunoscut dinainte, pe când câștigul nu este nici una, nici alta.

În workflow-ul orchestrator-workers, „un LLM central descompune dinamic sarcini, le deleagă unor worker LLMs și le sintetizează rezultatele”, iar diferența față de sectioning este că „sub-sarcinile nu sunt predefinite, ci determinate de orchestrator”.1 Originea de aici nu vine deloc din modelele lingvistice: acesta este master-worker, iar versiunea în care workers scriu constatări într-un spațiu comun citit de un controller este arhitectura blackboard, din cercetarea de recunoaștere a vorbirii din anii 1970. Ce este nou în 2026 este că controllerul este un model și, prin urmare, descompunerea poate fi decisă per input — flexibilitatea și costul, într-o singură propoziție.

A costat 12 apeluri de model față de cele 5 ale agent singular și a ajuns la același verdict. Apoi a făcut ceva la care merită să ne uităm atent:

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

Ambele sunt corecte. Doar unul știe de ce. Workerul fiscal avea factura, comanda și tabelul fiscal în propria fereastră, a ajuns la concluzie și a mai observat — deși nimeni nu ceruse — că numărul comenzii de achiziție de pe factură nu se potrivește cu cel din comandă. Apoi a returnat un rezumat. Orchestratorul poate repeta ambele afirmații și nu poate verifica niciuna, pentru că dovezile au rămas într-o fereastră pe care el nu a văzut-o niciodată. Aceasta este întrebarea de final din Capitolul 24, cu răspuns: părintele ajunge să vadă orice a ales copilul să scrie.

Soluția este un flag și are un preț:

ce returnează workerulorchestrator input tokenscostce poate face părintele
concluzia sa3,628$0.012512s-o repete
concluzia și dovezile sale4,065$0.013554s-o derive din nou și să nu fie de acord

Cu 12 % mai mulți input tokens, cu 8,3 % mai mulți bani, iar expresia source=worker_unverified dispare din răspuns. Acesta este compromisul din fiecare sistem multi-agent și aproape niciodată nu este spus: fereastra curată a copilului merită avută, capacitatea părintelui de a o audita merită plătită și nu le poți avea pe amândouă gratuit.

Deci când greșește orchestrator-workers? Aici, pe această sarcină. A cumpărat un răspuns corect la care a ajuns și un agent cu aceleași patru instrumente, pentru 1,66 ori costul și 2,3 ori timpul total, și a făcut acel răspuns mai greu de apărat. Ghidarea Anthropic spune același lucru înainte ca tiparele să înceapă: găsește „cea mai simplă soluție posibilă și crește complexitatea doar când este nevoie”, pentru că „sistemele agentic schimbă adesea latența și costul pe o performanță mai bună a sarcinii”.1 Tabelele de mai sus sunt acea propoziție cu numere dedesubt.

Evaluator-optimiser și judecătorul care a scris examenul

Link către secțiunea: Evaluator-optimiser și judecătorul care a scris examenul

Un apel generează, altul evaluează, iar bucla se repetă până când evaluarea trece.1 Strămoșii publicați sunt Self-Refine — același model ca „generator, refiner și feedback provider”, raportând aproximativ 20 de puncte de îmbunătățire absolută în medie peste șapte sarcini3 — și Reflexion, care stochează critica într-un buffer episodic între încercări și raportează 91 % pass@1 pe HumanEval, unde baseline-ul a ajuns la 80 %.4

Modelul de cost este cel mai simplu dintre cele cinci: două apeluri pe rundă, iar numărul de runde nu îți aparține. Trei runde de refinement pe o sarcină care a luat un apel înseamnă șase apeluri, deci pragul de jos al tiparului este 6×, iar plafonul este orice limită setezi — ceea ce face ieșirea de buget din Capitolul 23 obligatorie, nu doar ordonată.

Plafonul este mai subtil și măsurabil. Pe aceleași 20 de probleme, modelul local a răspuns corect la 9. Apoi i s-a arătat fiecare dintre acele răspunsuri și a fost întrebat dacă este corect — fără să i se spună că răspunsul era al lui, ceea ce elimină confuzia lingușirii și lasă doar capacitatea:

răspunsul propriu al modeluluia spus „da”a spus „nu”
cele 9 corecte90
cele 11 greșite38

Este un judecător mai bun decât sugerează titlul secțiunii, iar a spune asta este rostul măsurării, nu al afirmației: nu a blocat nimic corect și a prins 8 din 11 greșeli. Ca filtru, își merită apelurile.

Ca regulă de oprire, adică exact pentru ce o folosește de fapt o buclă evaluator-optimiser, cele trei aprobări sunt toată povestea: ele încheie bucla cu un răspuns greșit în mână, iar niciun număr de runde suplimentare nu ajunge vreodată la ele. O buclă de refinement nu poate deveni mai corectă decât judecătorul ei. Cumpărând mai multe runde cumperi încercări asupra erorilor pe care judecătorul le poate vedea, la preț întreg, și absolut nimic împotriva celor pe care nu le poate vedea.

De aici regula: un evaluator își câștigă apelurile doar când are ceva ce generatorul nu are. Un compiler, o suită de teste, un validator de schemă, un alt model, un om. Rezultatele Self-Refine sunt măsurate față de preferința umană și metrici de sarcină, niciodată față de opinia modelului despre sine. Dacă singurul avantaj al evaluatorului tău este un prompt diferit, plătești dublu pentru acord. Capitolul 29 construiește versiunea cu un avantaj real: un golden set cu răspunsurile scrise dinainte.

Cele cinci de mai sus sunt forme pentru codul tău. Sub ele se află o a doua familie care este adesea listată alături de ele și nu ar trebui să fie: ReAct, Reflexion, plan-and-execute și tree of thoughts sunt bucle de raționament, iar costul lor este în requests.

Capitolul 12 a fost despre raționamentul din interiorul modelului, pe care îl plătești în output tokens într-un singur apel. Acesta este celălalt tip. Diferența contează când sosește nota de plată: un chain of thought mai lung face un apel mai scump, iar o buclă de raționament transformă o sarcină în multe apeluri, fiecare retrimițând tot ce a fost înainte — pătraticul măsurat de Capitolul 23 în tabelul runaway.

buclăapeluri, per sarcinăce cumpără apelurile suplimentare
ReActunul per pas, până se opreștemodelul reacționează la ce au returnat instrumentele5
plan-and-executeunul pentru plan, apoi unul per pasplanul este fixat înainte ca primul pas să ruleze6
Reflexionîncercări × (act + reflect)critica supraviețuiește în încercarea următoare4
tree of thoughtsbranching factor × depth, plus o evaluare per nodcăutare, cu backtracking7

Lucrarea tree-of-thoughts își publică propriul tabel de costuri, lucru mai rar decât ar trebui să fie. Pe Game of 24 cu GPT-4: input/output prompting best-of-100 a rezolvat 33 % la $0.13 per caz, chain of thought best-of-100 a rezolvat 49 % la $0.47, iar tree of thoughts a rezolvat 74 % la $0.74, autorii notând că „ar putea necesita de 5-100 ori mai mulți generated tokens decât CoT”.7

Aproape de șase ori prețul metodei ieftine pentru puțin peste dublul ratei de succes. Dacă este sau nu o afacere bună depinde de cât te costă un caz eșuat — întrebarea de pus înainte de a adopta oricare dintre acestea patru.

Acest curs nu le reimplementează. Toate patru au implementări de referință ale propriilor autori, în Python, iar valoarea lor este că sunt sursa, nu o traducere: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm și AGI-Edgerunners/Plan-and-Solve-Prompting. Citește prompts din acele repositories; prompts sunt lucrările.

Două topologii, iar una dintre ele nu se întoarce

Link către secțiunea: Două topologii, iar una dintre ele nu se întoarce

Acum multi-agent propriu-zis, unde trăiește cea mai mare parte a confuziei. Există două moduri prin care un agent îl implică pe altul, nu sunt variante, iar diferența este cine rămâne la conducere după aceea.

Agent ca instrument. Părintele îl apelează, primește un răspuns și continuă. Este interfața de instrument din Capitolul 18 cu un agent întreg în spate, iar părintele nu pierde niciodată controlul. Asta face orchestratorul de mai sus.

Handoff. Părintele transferă conversația și nu o primește înapoi. Ghidul OpenAI este cea mai clară formulare publicată: handoffs sunt „un transfer unidirecțional care permite unui agent să delege unui alt agent... Dacă un agent apelează o funcție de handoff, pornim imediat execuția pe acel nou agent către care s-a făcut handoff, transferând în același timp cea mai recentă stare a conversației”.8

Un avertisment de vocabular, pentru că oamenii se împiedică constant aici: „handoff” este cuvântul unui SDK, nu un standard. Este terminologie din OpenAI Agents SDK și din acel ghid, care numește cele două aranjamente și „manager” și „decentralized” și notează că în tiparul manager „muchiiile reprezintă tool calls, pe când în tiparul decentralized, muchiile reprezintă handoffs”.8 Există un standard deschis în acest spațiu — A2A, la versiunea 1.0.0, sub copyrightul Linux Foundation, cu istoric de versiuni și o listă documentată de breaking changes, al cărui principiu declarat este execuția opacă: agents „colaborează pe baza capabilităților declarate și a informațiilor schimbate, fără a trebui să-și împărtășească gândurile interne, planurile sau implementările de instrumente”.9 Acesta nu este un handoff, iar comparația își are locul în Capitolul 26. Ce contează aici este că unul dintre cele două cuvinte este API-ul unei biblioteci, iar celălalt este o specificație cu guvernanță.

Distincția este o structură de date, nu o 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;
}

Douăzeci de linii, două buguri pe care altfel le-ai găsi în producție. reachable găsește agent la care nu poate ajunge nimeni — configurat, plătit, niciodată apelat. conflicts refuză muchia care este ambele tipuri deodată, ceea ce sună pedant până când o citești cu voce tare: părintele și păstrează controlul, și îl cedează. Ruleaz-o pe un sistem cu cinci agents, cu un orfan și o muchie dublă:

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

Acum măsurătoarea pentru care există această secțiune și singura din capitol făcută pe un model real, nu pe unul scriptat.

Un client declară o constrângere în primul mesaj — contul nostru este înregistrat în Portugalia, nu în Spania; tot ce ține de taxe trebuie să folosească Portugalia — vorbește despre altceva, apoi pune o întrebare la care facturarea trebuie să răspundă. Cazul este transferat. Douăzeci și patru de încercări, câte o țară și o companie diferite de fiecare dată, patru payload-uri de transfer, iar agent specialist primește apoi o singură întrebare: în ce țară este înregistrat contul acestui client?

ce a fost transferatpayload mediuconstrângerea era în elspecialistul și-a amintit-ointerval 95 %
întreaga conversație173 tokens24/2420/24 — 83 %64–93 %
un rezumat scris de agent expeditor62 tokens1/240/24 — 0 %0–14 %
doar ultimul mesaj al utilizatorului61 tokens0/240/24 — 0 %0–14 %
o înregistrare tipizată69 tokens24/2424/24 — 100 %86–100 %

Al treilea rând este un control și se comportă ca atare: faptul nu este acolo, deci nu poate fi reamintit. Celelalte trei sunt rezultatul.

Transcrierea completă are 173 tokens și funcționează în 83 % din cazuri, cele patru eșecuri fiind subiectul Capitolului 24, nu al acestuia. Înregistrarea tipizată are 69 tokens — cu șapte mai mult decât rezumatul — și funcționează de fiecare dată, pentru că această constrângere stă într-un câmp numit, nu într-o propoziție.

Iar rezumatul este rândul la care trebuie să te uiți. A eșuat de 24 de ori din 24, iar motivul nu este că cititorul l-a ratat. Constrângerea a apărut în doar 1 dintre cele 24 de rezumate. Agent primitor nu a fost neglijent; i s-a dat un text care nu conținea răspunsul. Un rezumat este o compactare pe care nu ai scris-o, produsă de un model a cărui fereastră nu o poți vedea, optimizată să se citească precum un rezumat — iar „clientul spune că înregistrările noastre au țara greșită” este exact tipul de clauză pe care un sumarizator o aruncă drept zgomot procedural.

O limită onestă a acelui număr: sumarizatorul este un model de jumătate de miliard de parametri, iar unul mai mare ar păstra mai mult. Ce nu se îmbunătățește cu dimensiunea este forma riscului — agent expeditor decide, per handoff, per formulare, neobservabil, care fapte supraviețuiesc. Înregistrarea tipizată nu depinde deloc de acea judecată, motiv pentru care câștigă prin construcție, nu prin inteligență. Tot ce trebuie să supraviețuiască unui transfer ar trebui să fie un câmp, nu o propoziție.

Același raționament se aplică în sens invers, la topologia agent-ca-instrument, iar tabelul anterior i-a pus deja prețul: ce se întoarce de la un worker este tot un rezumat, iar plata a 8,3 % în plus ca să primești și dovezile odată cu el este aceeași soluție văzută din partea părintelui.

Trei fapte de încheiere, toate din tabelele de mai sus.

Un sistem multi-agent multiplică apelurile, iar apelurile sunt pătratice în context. Orchestratorul a făcut 12 apeluri de model acolo unde un agent a făcut 5, iar fiecare își cară propriul transcript în creștere — 3,628 input tokens față de 2,697, o diferență care se lărgește odată cu lungimea sarcinii.

Fiecare graniță este un canal cu pierderi. Doi agents înseamnă un rezumat. Patru agents într-un lanț înseamnă trei, compuse, fiecare scris de un model optimizând pentru altceva decât decizia ta.

Agent singular a găsit ceva ce nu ceruse nimeni. Nepotrivirea comenzii de achiziție a ieșit la suprafață pentru că o singură fereastră ținea factura și comanda în același timp. Împărțirea muncii între specialiști împarte și capacitatea de a observa că două fapte se contrazic.

Nimic din asta nu argumentează împotriva frameworkurilor multi-agent publicate, care merită citite ca surse primare, nu prin tutoriale.10 Argumentează pentru a face al doilea agent să-și câștige locul.

Așadar, un test, nu o preferință. Adaugă un al doilea agent când cel puțin una dintre acestea este adevărată: sub-sarcina are nevoie de o fereastră curată pe care părintele nu trebuie s-o moștenească (Capitolul 24); sub-sarcinile sunt cu adevărat independente și timpul total contează, adică 1,8× de mai sus; sub-sarcina are nevoie de permisiuni diferite sau de un model diferit, ceea ce Capitolul 30 transformă într-un argument de securitate; sau sub-sarcina este deținută de altcineva, acolo unde un protocol real începe să conteze. Dacă răspunsul este „ca fiecare agent să aibă un prompt mai clar”, dă-i agent singular un prompt mai clar. Este gratuit.

Acum poți numi cele cinci tipare, le poți compara costurile pe o singură sarcină, poți deosebi un orchestrator de un sectioner și un tool call de un handoff, și poți apăra un singur agent cu un tabel, nu cu o preferință.

Fiecare aranjament de aici a împărțit o comoditate care nu va supraviețui contactului cu ceva real: toate instrumentele ne aparțineau. Factură, comandă, tabel fiscal, workers din spatele orchestratorului — același repository, același deploy, aceleași tipuri, aceiași oameni.

Acum pune unul dintre ele de cealaltă parte a graniței unei companii. Tabelul fiscal aparține unui furnizor de contabilitate, înregistrarea comenzii unui sistem de depozit, iar niciunul nu ți-a citit interfața Tool. Ai nevoie de o cale prin care un model pe care nu l-ai scris să descopere, să descrie și să apeleze o capabilitate operată de altcineva — cu autentificare (care este jumătatea Capitolului 27), versioning și garanția că un server nu poate citi restul conversației tale. Aceasta este o problemă de protocol, are o specificație cu o schemă normativă, iar aproape tot ce este indexat despre ea descrie o revizie care nu mai există.

Capitolul 26 citește acea specificație în loc s-o rezume și începe prin a tasta JSON-RPC într-un terminal, manual.


Fiecare cost și fiecare număr de token de mai sus a venit de la providerul scriptat descris în a doua secțiune, pe Node 22 peste o interfață loopback, numărând cu encoding-ul o200k_base și evaluat la tarifele citite de Capitolul 16 pe 6 septembrie 2026 — $2.00 per milion de input tokens și $12.00 per milion de output. Timpii wall-clock provin din aceleași rulări, cu latența providerului setată la 400 ms per apel și instrumentele la 50 ms, deci măsoară aranjamentul, nu un provider anume. Cele două măsurători cu model real — tabelul de handoff și tabelul de voting-and-judging — au folosit Qwen/Qwen2.5-0.5B-Instruct în float32 pe CPU, în spatele unui endpoint de aceeași formă, greedy cu excepția cazurilor în care este declarată o temperatură, cu intervale calculate prin metoda Wilson din Capitolul 4. Nicio cerere din acest capitol nu a mers către un endpoint plătit și niciun număr din el nu a fost estimat.

  1. Anthropic, Building effective agents, 19 decembrie 2024, anthropic.com/engineering/building-effective-agents, citit pe 7 septembrie 2026. Sursa celor cinci nume de workflow folosite mai sus și a fiecărei expresii citate din ele — prompt chaining, routing, parallelisation cu variantele sectioning și voting, orchestrator-workers, evaluator-optimiser — precum și a recomandării de a găsi „cea mai simplă soluție posibilă și de a crește complexitatea doar când este nevoie” și a observației că „sistemele agentic schimbă adesea latența și costul pe o performanță mai bună a sarcinii”. Capitolele 22 și 23 îi citează definiția pentru agent. 2 3 4 5 6 7

  2. Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. și Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (martie 2022). Originea tiparului voting, descris acolo ca strategie de decoding, nu ca arhitectură: sample căi diverse de raționament, apoi „selectează răspunsul cel mai consistent prin marginalizarea căilor de raționament eșantionate”, cu câștiguri raportate de +17,9 pe GSM8K, +11,0 pe SVAMP, +12,2 pe AQuA, +6,4 pe StrategyQA și +3,9 pe ARC-challenge.

  3. Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). Bucla evaluator-optimiser cu un singur model în toate cele trei roluri — „generator, refiner și feedback provider” — îmbunătățind „cu ~20% absolut în medie performanța pe sarcină” peste șapte sarcini, măsurat prin preferință umană și metrici automate, nu prin verdictul propriu al modelului.

  4. Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. și Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). Adaugă o memorie episodică a autocriticilor între încercări — „consolidează language agents nu prin actualizarea weights, ci prin feedback lingvistic” — raportând 91 % pass@1 pe HumanEval față de 80 % pentru baseline-ul GPT-4. Observă cerința de care depind rezultatele sale: un semnal real din mediu, precum un test eșuat, nu opinia modelului despre sine. 2

  5. Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. și Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). Traces de raționament și acțiuni intercalate; Capitolul 23 a construit această buclă. Citat aici pentru forma costului, nu pentru rezultate: un apel de model per pas, cu întregul transcript retrimis de fiecare dată.

  6. Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. și Lim, E.-P. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. arXiv:2305.04091 (2023). „Mai întâi, conceperea unui plan pentru a împărți întreaga sarcină în sub-sarcini mai mici, apoi executarea sub-sarcinilor conform planului” — forma plan-then-execute și sursa compromisului care interesează acest capitol: planul este fixat înainte ca prima observație să sosească, ceea ce este prompt chaining cu descompunerea scrisă de un model, nu de tine.

  7. Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. și Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023). Căutare peste „thoughts” intermediare, cu autoevaluare și backtracking; 74 % pe Game of 24 față de 4 % pentru chain-of-thought prompting. Cifrele de cost citate mai sus sunt ale lucrării, din Appendix B.3, Table 7: per caz, input/output prompting best-of-100 la $0.13 pentru 33 %, chain of thought best-of-100 la $0.47 pentru 49 % și tree of thoughts la $0.74 pentru 74 %, cu nota autorilor că ToT „ar putea necesita de 5-100 ori mai mulți generated tokens decât CoT”. 2

  8. OpenAI, A practical guide to building agents (PDF), citit pe 7 septembrie 2026. Împărțirea manager-versus-decentralised, încadrarea ca graf citată mai sus („în tiparul manager, muchiile reprezintă tool calls, pe când în tiparul decentralized, muchiile reprezintă handoffs”) și definiția unui handoff ca „un transfer unidirecțional... pornim imediat execuția pe acel nou agent către care s-a făcut handoff, transferând în același timp cea mai recentă stare a conversației”. Observă ce stabilește ultima clauză: în acest SDK, starea conversației călătorește, ceea ce este o decizie de design a acelei biblioteci, nu o proprietate a handoffs în general. 2

  9. Agent2Agent (A2A) Protocol Specification, cea mai recentă versiune publicată 1.0.0, a2a-protocol.org/latest/specification/, citită pe 7 septembrie 2026; copyright Linux Foundation, Apache-2.0. Citat mai sus: un „standard deschis conceput pentru a facilita comunicarea și interoperabilitatea între sisteme AI agent independente, potențial opace” și principiul opaque execution — agents „colaborează pe baza capabilităților declarate și a informațiilor schimbate, fără a trebui să-și împărtășească gândurile interne, planurile sau implementările de instrumente”. Pagina are un istoric de versiuni (0.1.0, 0.2.6, 0.3.0, 1.0.0), un appendix de breaking changes și un appendix despre relația sa cu MCP. Capitolul 26 face acea comparație.

  10. Frameworkurile multi-agent pe care acest capitol nu le predă, pentru cititorul care vrea surse primare, nu un tutorial: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), unde agents sunt „customizable, conversable” și conversația însăși este modelul de programare; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), care encodează proceduri operaționale standard în role prompts și spune explicit că „soluțiile la sarcini mai complexe sunt complicate prin inconsistențe logice cauzate de hallucinations în cascadă produse de înlănțuirea naivă a LLMs” — lanțul sigur-pe-el-și-greșit măsurat la începutul acestui capitol, numit într-un abstract; și Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), douăzeci și cinci de agents cu memorie, reflecție și planificare, cel mai mare răspuns publicat la „ce se întâmplă dacă tot adaugi agents”.

Gata să lași LIA să aleagă?

Construiește cu toate modelele AI într-un singur loc — începe gratuit azi.