Оркестрация multi-agent: пять паттернов и когда выигрывает один
Один спор по счету решён четырьмя способами: оркестратор стоил в 1,66 раза дороже одного agent и дал тот же вердикт.
На этой странице
Глава 24 закончилась заслуженным вопросом: когда sub-agent ошибается, на что именно может посмотреть родитель?
Эта глава отвечает на него счетом. Одна задача — клиент оспаривает инвойс и хочет получить ответ — решена четырьмя способами: все они запускают harness из главы 23 против одного и того же scripted provider, все считают одни и те же tokens одним и тем же encoder, все оценены по тарифам, которые глава 16 зафиксировала 6 сентября 2026 года.
| схема | вызовы модели | input tokens | output | стоимость | wall clock | вердикт |
|---|---|---|---|---|---|---|
| prompt chaining | 4 | 900 | 165 | $0.003780 | 1,648 ms | неверно |
| один agent, четыре инструмента | 5 | 2,697 | 179 | $0.007542 | 2,224 ms | верно |
| параллельные секции | 9 | 2,910 | 324 | $0.009708 | 2,165 ms | верно |
| orchestrator-workers | 12 | 3,628 | 438 | $0.012512 | 5,090 ms | верно, но доказать не может |
Сравните первую и последнюю строки: между ними — весь спор, который сейчас ведёт индустрия. Самая дешёвая схема оказалась и самой быстрой, и дала уверенный, неверный ответ, который вполне можно было отправить. Самая дорогая ответила правильно, стоила в 3,3 раза больше и заняла в 3,1 раза больше времени, а закончила тем, что процитировала вывод worker, который сама проверить не может.
Строка, которую никто не добавляет в такие таблицы, — вторая: один agent с четырьмя инструментами пришёл к тому же вердикту, что и оркестратор, за 60 % денег и 44 % wall clock. Это не предпочтение простоты. Это измерение, и дальше глава о том, когда оно перестаёт быть верным.
Показать детали
Что этой главе нужно из предыдущих.
- Глава 18 — контракт инструмента: схема, которую видит модель, и endpoint, который она не видит. За таким интерфейсом целиком помещается agent — в этом и состоит весь multi-agent.
- Глава 22 — два опубликованных определения «agent», которые друг с другом не согласны, и арифметика того, что цепочка prompts — это N вызовов.
- Глава 23 — loop, пять способов выйти, состояние run и trace. Каждая схема ниже — этот же файл, вызванный иначе.
- Глава 24 — сколько стоит окно и что из него выпадает. Sub-agent — четвёртая из её четырёх стратегий и единственная, где появляется второй agent, а не policy.
Никаких tensors. Всё здесь — TypeScript, кроме двух измерений на реальной локальной модели.
Задача и ловушка внутри неё
Ссылка на раздел: Задача и ловушка внутри неёПортугальская компания пишет насчёт инвойса FT-2026-0918. В письме сказано, что VAT выглядит неверно, и приложен инвойс: net EUR 248.00, VAT начислен по ставке 21 %, EUR 52.08, total EUR 300.08.
Факты, нужные для ответа, находятся в трёх местах, и только одно из них — в письме:
| где | что там сказано |
|---|---|
| приложенный инвойс | продавец в Испании, VAT применён по ставке 21 %, EUR 52.08 |
| запись заказа | покупатель зарегистрирован в Португалии, с действительным VAT identifier, business-to-business |
| налоговая таблица | внутренняя ставка Испании 21 %; intra-EU business-to-business с действительным identifier, reverse charge, 0 % |
Сложите эти три факта, и инвойс неверен: должен применяться reverse charge, VAT должен быть нулевым, клиенту положена кредит-нота на EUR 52.08. Посмотрите только на инвойс — и он арифметически идеален: 248.00 плюс 52.08 равно 300.08, — так вы и скажете.
В письме действительно сказано: «мы португальская компания». Это утверждение, а не запись в системе, и ни одна billing system не выпускает кредит-ноту на основании утверждения. Ловушка не в трюке: это обычная форма бизнес-работы, где для решения нужен факт, который никто не догадался получить.
Всё выше запускается против scripted provider в стиле главы 23, с ровно одним правилом:
Ответ может использовать только факт, который есть в его prompt.
«Модель» запрашивает каждый доступный ей инструмент один раз, в порядке каталога, а затем применяет фиксированное правило к тексту, который видит. Ничего не scripted отдельно для конкретной схемы, поэтому различия в начальной таблице — не утверждения об интеллекте модели: это измеренный routing информации. Реальная модель добавляет поверх свои собственные сбои; она не устраняет эти.
Пять паттернов примерно в сорока строках
Ссылка на раздел: Пять паттернов примерно в сорока строкахПять названий ниже — антропиковские, из Building effective agents, где этот словарь и закрепился.1 Ни одна из пяти идей не нова, а сказать, какая школа как что назвала — и какая идея старше, — половина пользы от их знания.
/* 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 };
}Это весь toolkit: пять функций, никакого framework, а параллельная — одна строка; именно поэтому её стоит выписать, а не рисовать. Теперь по очереди: происхождение, цена и случай, где она ошибается.
Chaining и решение, которое он принимает за вас
Ссылка на раздел: Chaining и решение, которое он принимает за васPrompt chaining «разбивает задачу на последовательность шагов, где каждый вызов LLM обрабатывает output предыдущего».1 Идея старше языковых моделей: это pipeline, с обычной сделкой pipeline — ясность в обмен на control flow, зафиксированный до прихода данных.
Для нашей задачи четыре шага: извлечь поля инвойса, проверить арифметику, решить, что причитается, написать ответ. Здесь он ломается двумя разными способами, и это учит большему, чем один сбой.
--- 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 стоила $0.001940 и потеряла поля инвойса между вторым и третьим шагами, потому что третьему шагу передали предложение об арифметике и ничего больше. Она выдала holding message: бесполезный и явно бесполезный.
Accumulating chain — строка в начальной таблице — стоила $0.003780, то есть на 95 % больше за четыре идентичных вызова, потому что теперь каждый шаг несёт всё, что было до него. Она выдала опасный output. Беглый, с ссылкой на арифметику, правильный по каждому числу, которое упоминает, и сообщающий клиенту, что ничего не причитается, хотя причитается EUR 52.08.
Разница между ними — один ternary. Цепочка, которая несёт меньше, даёт ответы, очевидно неполные; цепочка, которая несёт всё, даёт ответы уверенно неверные — и отправляют только второй тип.
Но ни то ни другое не является настоящим сбоем. Настоящий сбой в том, что pipeline ещё до чтения решил: эта задача — четыре шага над содержимым письма. В этой структуре нет места, где можно сказать: «страны регистрации нет в этом письме; сходи и получи её». Chaining подходит, когда decomposition заранее известна и стабильна. Здесь это была догадка, и догадку отправили.
Routing, самый старый паттерн, и план Б, который никто не пишет
Ссылка на раздел: Routing, самый старый паттерн, и план Б, который никто не пишетRouting «классифицирует input и направляет его в специализированную follow-up задачу».1 Название новое; механизм — dispatcher, старше почти всего остального в этой книге. Новое в том, что classifier может быть моделью — и именно поэтому он ломается способами, которые switch никогда не знал.
const answer = await route(email,
(q) => classifyWithSmallModel(q), // cheap model, one call
{ billing: billingAgent, tax: taxAgent, dunning: dunningAgent },
taxAgent, // deterministic, chosen in advance
);Две вещи о последнем аргументе. Это не error handling; это и есть паттерн. У router на базе модели есть failure mode, которого нет у dispatcher: он может вернуть label, которого не существует, уйти в timeout или — дорогой вариант — вернуть правдоподобный неверный label без сигнала, что он неверен. Все три должны куда-то приземлиться, и этим «куда-то» не может быть ещё один вызов модели, потому что вы уже в ветке, где вызовы модели отказали.
Вторая вещь: собственный prompt router не бесплатен. Чтобы выбрать модель, router нужен каталог моделей на выбор, и каждая запись в нём — это input, за который он платит до того, как router прочитал вопрос пользователя. По input rate, используемому в этом курсе, каталог примерно из 3,800 tokens уже стоит столько же, сколько весь пяти-вызовной agent run из начальной таблицы. На практике routing call запускается на дешёвой модели — именно поэтому routing окупается; но арифметику стоит делать именно в эту сторону, а не предполагать. Routing ошибочен ровно тогда, когда routed task дешевле решения о routing.
Parallelisation: секции и voting, то есть self-consistency
Ссылка на раздел: Parallelisation: секции и voting, то есть self-consistencyAnthropic делит этот паттерн надвое: sectioning — «разбиение задачи на независимые subtasks, запускаемые параллельно», — и voting — «запуск одной и той же задачи несколько раз для получения разнообразных outputs».1 У них общая диаграмма и почти ничего больше.
Sectioning — дешёвый выигрыш, та самая строка из patterns.ts: три специалиста — billing, tax, policy — у каждого своё окно и инструменты, все поверх одного письма, плюс один synthesis call в конце. Одна и та же работа в двух порядках:
| вызовы модели | input | output | стоимость | wall clock | |
|---|---|---|---|---|---|
| три workers, один за другим | 9 | 2,910 | 324 | $0.009708 | 3,894 ms |
те же трое, Promise.all | 9 | 2,910 | 324 | $0.009708 | 2,165 ms |
Token в token то же самое, быстрее в 1,8 раза. Поэтому паттерн заслуживает собственного имени: он единственный из пяти улучшает что-то, ничего не добавляя к цене. Подвох в том, что секции должны быть действительно независимы: дайте секции B факт, который производит секция A, и Promise.all запустит обе против состояния, которого ещё нет. Loop for спрятал этот баг; one-liner его показывает.
Voting — другое животное в той же картинке. Запуск одного вопроса k раз и выбор большинства — это self-consistency, опубликованная Wang et al. в марте 2022 года как decoding strategy, почти за три года до того, как кто-то назвал это orchestration pattern. Аннотация точна насчёт механизма — «сначала выбирает разнообразный набор reasoning paths вместо того, чтобы брать только greedy one, а затем выбирает наиболее consistent answer, marginalizing out the sampled reasoning paths» — и насчёт выигрыша: +17.9 пункта на GSM8K.2
Отсюда следуют две вещи, которые скрывает картинка. Во-первых, voting требует sampling из главы 17: при temperature zero все k samples — один и тот же sample, а majority — один ответ, оплаченный k раз. Во-вторых, он работает только там, где большинство осмысленно: в ответе по инвойсу выше нечего считать, потому что пять drafts — это пять разных предложений. Voting — для задач с коротким, сопоставимым ответом, то есть ровно для бенчмарков Wang и почти ни для чего, что делает customer-facing agent.
Здесь это измерено на 20 трёхшаговых word problems, ответы на которые вычисляются, а не оцениваются, с локальной моделью главы 23, рассуждающей step by step:
| вызовы модели | input | output | стоимость за 20 | верно | 95 % интервал | |
|---|---|---|---|---|---|---|
| одна greedy chain | 20 | 1,330 | 2,649 | $0.034448 | 9/20 | 26–66 % |
| majority of 5, temperature 0.8 | 100 | 6,650 | 13,245 | $0.172240 | 9/20 | 26–66 % |
В пять раз больше вызовов, в пять раз больше tokens, ровно в пять раз больше счёт — и ни одного дополнительного правильного ответа. Voting — ставка, а не улучшение, и этот run её проиграл.
Две оговорки, прежде чем кто-нибудь процитирует это как опровержение Wang. Двадцать trials не отличают 45 % от 60 %: интервал шириной с само утверждение, и это дисциплина главы 4, применённая к моему собственному результату. А опубликованные выигрыши пришли от моделей на порядки крупнее, где diverse reasoning paths, по которым voting marginalises, действительно разнообразны. Переносится не число, а то, что множитель точен и известен заранее, а выигрыш — нет.
Orchestrator-workers и чем summary не является
Ссылка на раздел: Orchestrator-workers и чем summary не являетсяВ workflow orchestrator-workers «центральная LLM динамически разбивает задачи, делегирует их worker LLM и синтезирует их результаты», а отличие от sectioning в том, что «subtasks не предопределены, а определяются orchestrator».1 Происхождение здесь вообще не из языковых моделей: это master-worker, а версия, где workers записывают findings в общее пространство, которое читает controller, — blackboard architecture из исследований распознавания речи 1970-х. Новое в 2026 году то, что controller — модель, а значит decomposition можно решать для каждого input отдельно: гибкость и цена в одном предложении.
Это стоило 12 model calls против 5 у single agent и пришло к тому же вердикту. Потом произошло нечто, на что стоит посмотреть внимательно:
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Оба ответа верны. Только один знает почему. Tax worker видел в своём окне инвойс, заказ и tax table, пришёл к выводу и ещё заметил — хотя никто не просил, — что номер purchase order в инвойсе не совпадает с номером в заказе. Затем он вернул summary. Оркестратор может повторить оба утверждения и не может проверить ни одно, потому что evidence осталось в окне, которого он не видел. Вот ответ на финальный вопрос главы 24: родитель видит то, что child решил записать.
Исправление — один flag, и у него есть цена:
| что возвращает worker | orchestrator input tokens | стоимость | что может сделать родитель |
|---|---|---|---|
| свой вывод | 3,628 | $0.012512 | повторить его |
| свой вывод и evidence | 4,065 | $0.013554 | вывести заново и не согласиться |
На 12 % больше input tokens, на 8,3 % больше денег — и фраза source=worker_unverified исчезает из ответа. Это сделка в любой multi-agent system, и её почти никогда не проговаривают: чистое окно child полезно, способность родителя audit тоже стоит денег, и бесплатно получить оба нельзя.
Так когда orchestrator-workers неверен? Здесь, на этой задаче. Он купил правильный ответ, к которому один agent с теми же четырьмя инструментами тоже пришёл, за 1,66 раза стоимости и 2,3 раза wall clock, и сделал этот ответ труднее защищать. Собственная рекомендация Anthropic говорит то же самое ещё до паттернов: искать «самое простое возможное решение и повышать сложность только при необходимости», потому что «agentic systems often trade latency and cost for better task performance».1 Таблицы выше — это та же фраза, но с числами под ней.
Evaluator-optimiser и судья, который сам написал экзамен
Ссылка на раздел: Evaluator-optimiser и судья, который сам написал экзаменОдин вызов генерирует, другой оценивает, и loop повторяется, пока evaluation не пройдена.1 Опубликованные предки — Self-Refine, где одна и та же модель выступает как «generator, refiner, and feedback provider» и сообщает примерно о 20 пунктах absolute improvement в среднем по семи задачам3, — и Reflexion, где критика хранится в episodic buffer между попытками и сообщается 91 % pass@1 на HumanEval при baseline 80 %.4
Cost model здесь самый простой из пяти: два вызова на round, и число rounds не ваше. Три rounds refinement для задачи, которая занимала один вызов, — это шесть вызовов, так что floor паттерна равен 6×, а ceiling — любой cap, который вы поставите; поэтому budget exit из главы 23 обязателен, а не просто аккуратен.
Ceiling тоньше, и его можно измерить. На тех же 20 задачах локальная модель ответила правильно на 9. Затем ей показали каждый из этих ответов и спросили, верен ли он, — не сообщая, что ответ её собственный; это убирает flattery confound и оставляет capability:
| собственный ответ модели | она сказала «yes» | она сказала «no» |
|---|---|---|
| 9 верных | 9 | 0 |
| 11 неверных | 3 | 8 |
Это лучший судья, чем намекает заголовок раздела, и именно поэтому нужно измерять, а не утверждать: он не заблокировал ничего верного и поймал 8 из 11 ошибок. Как фильтр он стоит своих вызовов.
Как stopping rule, то есть в той роли, для которой evaluator-optimiser loop фактически его использует, эти три одобрения — вся история: они завершают loop с неверным ответом на руках, и никакое количество дополнительных rounds до них уже не доберётся. Refinement loop не может стать правильнее своего судьи. Покупая больше rounds, вы покупаете попытки исправить ошибки, которые судья видит, по полной цене, и ровно ничего против тех, которых он не видит.
Отсюда правило: evaluator заслуживает свои вызовы только тогда, когда у него есть то, чего нет у generator. Компилятор, test suite, schema validator, другая модель, человек. Собственные результаты Self-Refine измеряются по human preference и task metrics, а не по мнению модели о самой себе. Если единственное преимущество evaluator — другой prompt, вы платите вдвое за согласие. Глава 29 строит версию с реальным преимуществом: golden set с заранее записанными ответами.
Loops — не паттерны
Ссылка на раздел: Loops — не паттерныПять пунктов выше — формы для вашего кода. Под ними есть второе семейство, которое часто перечисляют рядом с ними, хотя не должны: ReAct, Reflexion, plan-and-execute и tree of thoughts — это reasoning loops, и их стоимость выражается в requests.
Глава 12 была о reasoning внутри модели, за который вы платите output tokens в одном вызове. Здесь другой тип. Разница важна, когда приходит счёт: более длинная chain of thought делает один вызов дороже, а reasoning loop превращает одну задачу во много вызовов, каждый из которых заново отправляет всё, что было до него, — ту самую квадратичность, которую глава 23 измерила в runaway table.
| loop | вызовы на задачу | что покупают дополнительные вызовы |
|---|---|---|
| ReAct | один на step, пока не остановится | модель реагирует на то, что вернули инструменты5 |
| plan-and-execute | один для плана, затем один на step | план фиксируется до запуска первого step6 |
| Reflexion | attempts × (act + reflect) | критика переживает переход в следующую попытку4 |
| tree of thoughts | branching factor × depth плюс одна evaluation на node | поиск с backtracking7 |
Статья tree-of-thoughts публикует собственную cost table — это встречается реже, чем должно. На Game of 24 с GPT-4: input/output prompting best-of-100 решал 33 % по $0.13 за case, chain of thought best-of-100 — 49 % по $0.47, а tree of thoughts — 74 % по $0.74; авторы отмечают, что это «could require 5-100 times more generated tokens than CoT».7
Почти в шесть раз дороже дешёвого метода за чуть больше чем двойной success rate. Выгодная ли это сделка, зависит от того, сколько стоит failed case, — вопрос, который нужно задать до внедрения любого из этих четырёх.
Этот курс не реализует их заново. У всех четырёх есть reference implementations от собственных авторов, на Python, и их ценность в том, что это источник, а не перевод: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm и AGI-Edgerunners/Plan-and-Solve-Prompting. Читайте prompts в этих repositories; prompts и есть статьи.
Две топологии, и одна из них не возвращается
Ссылка на раздел: Две топологии, и одна из них не возвращаетсяТеперь собственно multi-agent, где живёт большая часть путаницы. Есть два способа, которыми один agent может задействовать другого; это не варианты одного и того же, и различие в том, кто после этого главный.
Agent как инструмент. Родитель вызывает его, получает ответ и продолжает. Это интерфейс инструмента из главы 18, только за ним целый agent, и родитель не теряет контроль. Именно это делает оркестратор выше.
Передача. Родитель передаёт разговор и не получает его обратно. У guide OpenAI самое ясное опубликованное описание: handoffs — это «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
Предупреждение о словаре, потому что это постоянно сбивает людей: «handoff» — слово одного SDK, а не стандарт. Это терминология OpenAI Agents SDK и этого guide, где две схемы также названы «manager» и «decentralized» и сказано, что в manager pattern «edges represent tool calls whereas in the decentralized pattern, edges represent handoffs».8 В этой области есть открытый стандарт — A2A, версия 1.0.0, под copyright Linux Foundation, с версионированной release history и документированным списком breaking changes; его заявленный принцип — opaque execution: agents «collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations».9 Это не handoff, и сравнение относится к главе 26. Здесь важно, что одно из двух слов — API библиотеки, а другое — спецификация с governance.
Различие — это структура данных, а не диаграмма:
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;
}Двадцать строк, два бага, которые иначе нашли бы в production. reachable находит agent, до которого никто не может добраться: сконфигурирован, оплачен, никогда не вызывается. conflicts отклоняет edge, который является обоими типами сразу; звучит педантично, пока не произнесёте вслух: родитель одновременно сохраняет контроль и отдаёт его. Запустите это на системе из пяти agents с одним orphan и одним double edge:
reachable: lead@0 billing@1 tax@1 dunning@1
orphans: ghost
conflicts: lead->taxЧто на самом деле пересекает границу
Ссылка на раздел: Что на самом деле пересекает границуТеперь измерение, ради которого существует этот раздел, и единственное в главе, сделанное на реальной модели, а не scripted.
Клиент формулирует constraint в первом сообщении — наш account зарегистрирован в Португалии, а не в Испании; всё, что касается налогов, должно использовать Португалию — потом говорит о другом, затем задаёт вопрос, на который должен ответить billing. Case передаётся. Двадцать четыре trials, каждый раз другая страна и компания, четыре transfer payloads, а receiving agent затем получает один вопрос: в какой стране зарегистрирован account этого клиента?
| что было передано | средний payload | constraint был внутри | specialist вспомнил его | 95 % интервал |
|---|---|---|---|---|
| весь разговор | 173 tokens | 24/24 | 20/24 — 83 % | 64–93 % |
| summary, написанная sending agent | 62 tokens | 1/24 | 0/24 — 0 % | 0–14 % |
| только последнее сообщение пользователя | 61 tokens | 0/24 | 0/24 — 0 % | 0–14 % |
| typed record | 69 tokens | 24/24 | 24/24 — 100 % | 86–100 % |
Третья строка — контроль, и ведёт себя как контроль: факта там нет, значит его нельзя вспомнить. Остальные три — результат.
Полная transcript — 173 tokens и работает в 83 % случаев; её четыре сбоя — тема главы 24, а не этой. Typed record — 69 tokens, всего на семь больше summary, — и работает каждый раз, потому что constraint лежит в named field, а не в предложении.
А строка summary — та, на которую нужно смотреть. Она провалилась 24 раза из 24, и причина не в том, что читатель её пропустил. Constraint вообще появился только в 1 из 24 summaries. Receiving agent не был невнимателен; ему передали текст, в котором не было ответа. Summary — это compaction, которую писали не вы, произведённая моделью, окна которой вы не видите, оптимизированная так, чтобы читаться как summary; а «клиент говорит, что в наших записях неправильная страна» — ровно такой clause, который summariser выкидывает как procedural noise.
Честное ограничение этого числа: summariser — модель на полмиллиарда параметров, и более крупная сохранила бы больше. Что не улучшается с размером, так это форма риска: sending agent решает при каждом handoff, при каждой phrasing, ненаблюдаемо, какие факты выживут. Typed record вообще не зависит от этого judgement, поэтому выигрывает by construction, а не интеллектом. Всё, что должно пережить transfer, должно быть полем, а не предложением.
Та же логика работает и в другую сторону, для topology «agent как инструмент», и ранняя таблица уже дала ей цену: то, что возвращается от worker, — тоже summary, и заплатить на 8,3 % больше, чтобы получить evidence вместе с ним, — то же исправление, только со стороны родителя.
Когда выигрывает один agent
Ссылка на раздел: Когда выигрывает один agentТри заключительных факта, все из таблиц выше.
Multi-agent system умножает вызовы, а вызовы квадратичны по context. Оркестратор сделал 12 model calls там, где один agent сделал 5, и каждый несёт собственную растущую transcript — 3,628 input tokens против 2,697, разрыв растёт вместе с длиной задачи.
Каждая граница — lossy channel. Два agents означают одну summary. Четыре agents в цепочке — три summaries, наложенные друг на друга, каждая написана моделью, оптимизирующей что-то отличное от вашего решения.
Один agent нашёл то, о чём никто не спрашивал. Несовпадение purchase order surfaced, потому что одно окно одновременно держало инвойс и заказ. Разделение работы между specialists также разделяет способность заметить, что два факта противоречат друг другу.
Ничто из этого не является аргументом против опубликованных multi-agent frameworks, которые стоит читать как первоисточники, а не через tutorials.10 Это аргумент за то, чтобы второй agent заслужил своё место.
Итак, не предпочтение, а тест. Добавляйте второго agent, когда верно хотя бы одно: sub-task нужно чистое окно, которое родитель не должен наследовать (глава 24); sub-tasks действительно независимы и важен wall clock — это 1.8× выше; sub-task требует других permissions или другой модели, что глава 30 превращает в аргумент безопасности; или sub-task принадлежит кому-то ещё, и тогда начинает иметь значение настоящий protocol. Если ответ: «чтобы у каждого agent был более ясный prompt», дайте одному agent более ясный prompt. Это бесплатно.
Куда дальше
Ссылка на раздел: Куда дальшеТеперь вы можете назвать пять паттернов, оценить их друг относительно друга на одной задаче, отличить orchestrator от sectioner и tool call от handoff, а также защитить single agent таблицей, а не предпочтением.
У всех схем здесь было одно удобство, которое не переживёт столкновения с чем-то реальным: все инструменты принадлежали нам. Инвойс, заказ, tax table, workers за orchestrator — один repository, один deploy, одни types, одни люди.
Теперь поместите один из них по другую сторону границы компании. Tax table принадлежит accounting vendor, order record — warehouse system, и ни одна из них не читала ваш интерфейс Tool. Вам нужен способ, чтобы модель, которую вы не писали, могла обнаружить, описать и вызвать capability, которой управляет кто-то другой, — с authentication (это половина главы 27), versioning и гарантией, что server не может прочитать остальную часть вашего разговора. Это protocol problem, у неё есть specification с normative schema, и почти всё проиндексированное о ней описывает revision, которого больше не существует.
Глава 26 читает эту specification вместо того, чтобы пересказывать её, и начинает с ручного ввода JSON-RPC в terminal.
Источники и метод
Ссылка на раздел: Источники и методВсе cost и token counts выше получены от scripted provider, описанного во втором разделе, на Node 22 через loopback interface, с подсчётом encoding o200k_base и оценкой по тарифам, которые глава 16 прочитала 6 сентября 2026 года: $2.00 за миллион input tokens и $12.00 за миллион output. Wall-clock figures — из тех же runs с latency provider 400 ms на call и tools 50 ms, поэтому они измеряют схему, а не provider. Два real-model measurements — таблица handoff и таблица voting-and-judging — использовали Qwen/Qwen2.5-0.5B-Instruct в float32 на CPU за endpoint той же формы, greedy, кроме мест, где указана temperature, с интервалами, вычисленными методом Wilson из главы 4. Ни один request в этой главе не ушёл на paid endpoint, и ни одно число в ней не было estimated.
Сноски
Ссылка на раздел: Сноски-
Anthropic, Building effective agents, 19 декабря 2024 года,
anthropic.com/engineering/building-effective-agents, прочитано 7 сентября 2026 года. Источник пяти названий workflows, использованных выше, и каждой процитированной оттуда фразы — prompt chaining, routing, parallelisation с вариантами sectioning и voting, orchestrator-workers, evaluator-optimiser, — а также рекомендации искать «the simplest solution possible, and only increasing complexity when needed» и наблюдения, что «agentic systems often trade latency and cost for better task performance». Главы 22 и 23 цитируют его определение 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 (март 2022). Происхождение паттерна voting, там описанного как decoding strategy, а не architecture: sample diverse reasoning paths, затем «select the most consistent answer by marginalizing out the sampled reasoning paths», с reported gains +17.9 на GSM8K, +11.0 на SVAMP, +12.2 на AQuA, +6.4 на StrategyQA и +3.9 на ARC-challenge. ↩
-
Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). Evaluator-optimiser loop с одной моделью во всех трёх ролях — «generator, refiner, and feedback provider» — улучшающий «by ~20% absolute on average in task performance» по семи задачам, измеренный human preference и automatic metrics, а не собственным вердиктом модели. ↩
-
Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. and Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). Добавляет episodic memory self-critiques между attempts — «reinforce language agents not by updating weights, but through linguistic feedback» — и сообщает 91 % pass@1 на HumanEval против 80 % у baseline GPT-4. Обратите внимание на требование, от которого зависят результаты: реальный сигнал из environment, например failing test, а не мнение модели о самой себе. ↩ ↩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). Interleaved reasoning traces и actions; глава 23 построила этот loop. Здесь цитируется за форму стоимости, а не за результаты: один model call на step, с повторной отправкой всей transcript каждый раз. ↩
-
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» — форма plan-then-execute и источник trade, важного для этой главы: план фиксируется до первого наблюдения, то есть это prompt chaining с decomposition, написанной моделью, а не вами. ↩
-
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 over intermediate «thoughts» with self-evaluation and backtracking; 74 % на Game of 24 против 4 % у chain-of-thought prompting. Cost figures, процитированные выше, — собственные данные статьи из Appendix B.3, Table 7: per case, input/output prompting best-of-100 по $0.13 за 33 %, chain of thought best-of-100 по $0.47 за 49 % и tree of thoughts по $0.74 за 74 %, с замечанием авторов, что ToT «could require 5-100 times more generated tokens than CoT». ↩ ↩2
-
OpenAI, A practical guide to building agents (PDF), прочитано 7 сентября 2026 года. Разделение manager-versus-decentralised, graph framing, процитированный выше («in the manager pattern, edges represent tool calls whereas in the decentralized pattern, edges represent handoffs»), и определение handoff как «a one way transfer... we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state». Обратите внимание, что фиксирует последняя clause: в этом SDK conversation state действительно travels, и это design decision этой library, а не свойство handoffs вообще. ↩ ↩2
-
Agent2Agent (A2A) Protocol Specification, последняя released version 1.0.0,
a2a-protocol.org/latest/specification/, прочитано 7 сентября 2026 года; copyright Linux Foundation, Apache-2.0. Выше процитировано: «open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems» и принцип opaque execution — agents «collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations». На странице есть release history (0.1.0, 0.2.6, 0.3.0, 1.0.0), appendix breaking changes и appendix о связи с MCP. Глава 26 делает это сравнение. ↩ -
Multi-agent frameworks, которые эта глава не учит, для читателя, которому нужны первоисточники, а не tutorial: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), где agents «customizable, conversable», а conversation itself is the programming model; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), где standard operating procedures encoded into role prompts и прямо сказано, что «solutions to more complex tasks are complicated through logic inconsistencies due to cascading hallucinations caused by naively chaining LLMs» — confidently-wrong chain, измеренная в начале этой главы, названа в abstract; и Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), двадцать пять agents с memory, reflection и planning, самый большой опубликованный ответ на вопрос «что будет, если продолжать добавлять agents». ↩