هماهنگسازی multi-agent: پنج الگو و زمان برندهشدن یکی از آنها
یک فاکتور به چهار روش حل شد: orchestrator به 1.66 برابر هزینه single agent رسید و همان رأی را داد.
در این صفحه
فصل 24 با پرسشی تمام شد که خودش آن را به دست آورده بود: وقتی یک sub-agent اشتباه میکند، parent دقیقاً اجازه دارد به چه چیزی نگاه کند؟
این فصل با یک صورتحساب به آن پاسخ میدهد. یک کار — مشتری به یک فاکتور اعتراض دارد و پاسخ میخواهد — به چهار روش حل شده است؛ همه با harness فصل 23 روی همان provider اسکریپتشده، همه با شمارش همان tokenها با همان encoder، و همه با قیمتهایی که فصل 16 در 6 سپتامبر 2026 خوانده بود.
| چیدمان | model callها | input tokenها | output | هزینه | زمان واقعی | رأی |
|---|---|---|---|---|---|---|
| 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٪ زمان واقعی orchestrator، به همان رأی رسید. این ترجیح دادن سادگی نیست. یک اندازهگیری است، و بقیه این فصل درباره زمانی است که دیگر درست نیست.
نمایش جزئیات
این فصل از فصلهای قبلی به چه چیزهایی نیاز دارد.
- فصل 18 برای قرارداد ابزار: schemaای که مدل میبیند، endpointی که هرگز نمیبیند. یک agent کامل پشت همین interface جا میشود، و این کل multi-agent است.
- فصل 22 برای دو تعریف منتشرشده از «agent» که با هم اختلاف دارند، و برای حساب و کتابی که نشان میدهد زنجیرهای از promptها یعنی N call.
- فصل 23 برای loop، پنج راه خروج، وضعیت run و trace. هر چیدمان پایین همان فایل است، فقط جور دیگری فراخوانی شده.
- فصل 24 برای اینکه یک window چه هزینهای دارد و چه چیزی از آن بیرون میافتد. sub-agent چهارمین استراتژی از چهار استراتژی آن است، و تنها موردی است که بهجای policy، agent دوم است.
هیچ tensorی در کار نیست. همهچیز اینجا TypeScript است، جز دو اندازهگیری که با یک مدل محلی واقعی انجام شدهاند.
کار، و دامی که داخل آن است
لینک به بخش: کار، و دامی که داخل آن استیک شرکت پرتغالی درباره فاکتور FT-2026-0918 ایمیل میزند. ایمیل میگوید VAT اشتباه به نظر میرسد، و فاکتور را پیوست میکند: مبلغ خالص EUR 248.00، VAT با نرخ 21٪، مبلغ EUR 52.08، جمع EUR 300.08.
حقایق لازم برای پاسخ دادن در سه جا زندگی میکنند، و فقط یکی از آنها در ایمیل است:
| کجا | چه میگوید |
|---|---|
| فاکتور پیوستشده | فروشنده در اسپانیا است، VAT با نرخ 21٪ اعمال شده، EUR 52.08 |
| رکورد سفارش | خریدار در پرتغال ثبت شده، شناسه VAT معتبر دارد، business-to-business است |
| جدول مالیات | نرخ داخلی اسپانیا 21٪؛ intra-EU business-to-business با شناسه معتبر، reverse charge، 0٪ |
این سه را کنار هم بگذارید و فاکتور اشتباه است: reverse charge اعمال میشود، VAT باید صفر میبود، و credit note به مبلغ EUR 52.08 بدهکار است. فقط به فاکتور نگاه کنید و از نظر حسابی بینقص است — 248.00 بهعلاوه 52.08 میشود 300.08 — و همین را خواهید گفت.
ایمیل میگوید «ما یک شرکت پرتغالی هستیم». این یک ادعاست، نه یک رکورد، و هیچ سیستم billing بر اساس یک ادعا credit note صادر نمیکند. دام یک حقه نیست: شکل معمول کار تجاری است، جایی که تصمیم به حقیقتی نیاز دارد که هیچکس فکر نکرده آن را fetch کند.
همهچیز بالا با یک provider اسکریپتشده به سبک فصل 23 اجرا میشود، با دقیقاً یک قانون:
پاسخ فقط میتواند از factی استفاده کند که در prompt خودش وجود دارد.
«مدل» برای هر ابزاری که دارد، یک بار، به ترتیب catalog درخواست میدهد، سپس یک قانون ثابت را روی متنی که میتواند ببیند اعمال میکند. هیچچیز برای هر چیدمان جداگانه اسکریپت نشده، پس تفاوتهای جدول آغازین ادعاهایی درباره هوش مدل نیستند: information routing هستند، اندازهگیریشده. مدل واقعی شکستهای خودش را هم اضافه میکند؛ این شکستها را حذف نمیکند.
پنج الگو، در حدود چهل خط
لینک به بخش: پنج الگو، در حدود چهل خطپنج نام زیر از Anthropic و مقاله 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 };
}این کل جعبهابزار است: پنج function، بدون framework، و مورد موازی یک خط است — که دقیقاً دلیل نوشتنش بهجای رسم کردنش همین است. حالا هر کدام بهترتیب، با تبار، قیمت و موردی که در آن اشتباه میکند.
Chaining، و تصمیمی که بهجای شما میگیرد
لینک به بخش: Chaining، و تصمیمی که بهجای شما میگیردPrompt chaining «یک کار را به دنبالهای از گامها تجزیه میکند، که در آن هر LLM call خروجی قبلی را پردازش میکند».1 این ایده قدیمیتر از مدلهای زبانی است: pipeline است، با معامله pipeline — وضوح در برابر control flowی که پیش از رسیدن داده ثابت شده است.
چهار گام برای کار ما: استخراج fieldهای فاکتور، بررسی حساب، تصمیم درباره مبلغ بدهکار، نوشتن پاسخ. اینجا از دو راه متفاوت شکست میخورد، که از یک بار شکست خوردن آموزندهتر است.
--- 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 داشت و fieldهای فاکتور را بین گام دو و سه از دست داد، چون به گام سه فقط جملهای درباره حساب داده شده بود و هیچ چیز دیگر. نتیجهاش یک پیام نگهدارنده بود: بیفایده، و آشکارا بیفایده.
accumulating chain — همان سطر جدول آغازین — هزینه $0.003780 داشت؛ یعنی 95٪ بیشتر برای چهار call یکسان، چون حالا هر گام همهچیز پیش از خودش را حمل میکند. خروجی خطرناک را تولید کرد. روان، با استناد به حساب خودش، درست درباره هر عددی که ذکر میکند، و در حال گفتن به مشتری که هیچ مبلغی بدهکار نیست در حالی که EUR 52.08 بدهکار است.
تفاوت بین این دو یک ternary است. زنجیرهای که کمتر حمل میکند پاسخهایی تولید میکند که آشکارا ناقصاند؛ زنجیرهای که همهچیز را حمل میکند پاسخهایی تولید میکند که با اطمینان اشتباهاند — و فقط نوع دوم ارسال میشود.
هیچکدام شکست واقعی نیست. شکست واقعی این است که pipeline پیش از خواندن هر چیزی تصمیم گرفت این کار چهار گام روی محتوای یک ایمیل است. در این ساختار هیچ جایی نیست که بگوید «کشور ثبتنام در این ایمیل نیست؛ برو و آن را بگیر». Chaining وقتی درست است که تجزیه از پیش معلوم و پایدار باشد. اینجا حدس بود، و حدس ship شد.
Routing، قدیمیترین مورد، و plan Bای که هیچکس نمینویسد
لینک به بخش: Routing، قدیمیترین مورد، و plan Bای که هیچکس نمینویسدRouting «یک input را طبقهبندی میکند و آن را به یک followup task تخصصی هدایت میکند».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
);دو نکته درباره آخرین argument. این error handling نیست؛ خود الگوست. router مبتنی بر مدل failure modeای دارد که dispatcher ندارد: میتواند labelی برگرداند که وجود ندارد، timeout شود، یا — مورد گران — labelی محتمل اما اشتباه برگرداند بیآنکه سیگنالی بدهد که اشتباه است. هر سه باید جایی فرود بیایند، و آن جا نمیتواند یک model call دیگر باشد، چون شما همین حالا در شاخهای هستید که model callها شکست خوردهاند.
نکته دوم این است که prompt خود router رایگان نیست. برای انتخاب مدل، router به catalogی از مدلها نیاز دارد، و هر entry در آن inputی است که router پیش از آنکه پرسش کاربر را خوانده باشد هزینهاش را میپردازد. با نرخ inputی که این دوره با آن قیمتگذاری میکند، یک catalog حدوداً 3,800 tokenی همین حالا به اندازه کل اجرای agent با پنج call در جدول آغاز فصل هزینه دارد. در عمل routing call روی یک مدل ارزان اجرا میشود، و تمام دلیل اینکه routing هزینه خودش را درمیآورد همین است؛ اما ارزش دارد این حساب را در همین جهت انجام دهید بهجای اینکه فرضش کنید. routing دقیقاً وقتی اشتباه است که task روتشده ارزانتر از خود تصمیم routing باشد.
Parallelisation: بخشها، و رأیگیری، که self-consistency است
لینک به بخش: Parallelisation: بخشها، و رأیگیری، که self-consistency استAnthropic این یکی را به دو قسمت تقسیم میکند: sectioning — «شکستن یک کار به subtaskهای مستقل که موازی اجرا میشوند» — و voting — «چند بار اجرای همان کار برای گرفتن outputهای متنوع».1 این دو یک diagram مشترک دارند و تقریباً هیچ چیز دیگری را مشترک ندارند.
Sectioning برد ارزان است، و همان خط از patterns.ts است: سه specialist — billing، tax، policy — هرکدام با window و ابزارهای خودشان، روی همان ایمیل، و یک synthesis call در پایان. همان کار، با دو ترتیب:
| model callها | input | output | هزینه | زمان واقعی | |
|---|---|---|---|---|---|
| سه worker، یکی پس از دیگری | 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 factی بدهید که بخش A تولید میکند، Promise.all هر دو را روی stateای اجرا میکند که هنوز وجود ندارد. loopِ for آن bug را پنهان کرد؛ one-liner آن را آشکار میکند.
Voting حیوان دیگری است که همان تصویر را پوشیده. اجرای همان سؤال k بار و گرفتن اکثریت، self-consistency است؛ Wang و همکاران در مارس 2022 آن را بهعنوان decoding strategy منتشر کردند، تقریباً سه سال پیش از آنکه کسی آن را الگوی orchestration بنامد. abstract آن درباره سازوکار دقیق است — «ابتدا مجموعه متنوعی از reasoning pathها را sample میکند بهجای اینکه فقط greedy one را بگیرد، سپس با marginalize کردن reasoning pathهای sampleشده، سازگارترین پاسخ را انتخاب میکند» — و درباره سود هم دقیق است: +17.9 امتیاز روی GSM8K.2
از این دو چیز نتیجه میشود که تصویر پنهان میکند. اول، voting نیازمند sampling فصل 17 است: در temperature صفر، هر k sample همان sample است، و majority یک پاسخ است که k بار برایش پول داده شده. دوم، فقط جایی کار میکند که majority معنا داشته باشد — در پاسخ فاکتور بالا چیزی برای شمردن وجود ندارد، چون پنج draft پنج جمله متفاوتاند. Voting برای کارهایی است با پاسخی کوتاه و قابل مقایسه، که دقیقاً benchmarkهای Wang است و تقریباً هیچچیزی نیست که یک customer-facing agent انجام میدهد.
اینجا روی 20 مسئله کلامی سهمرحلهای که پاسخهایشان محاسبه میشود نه قضاوت، با مدل محلی فصل 23 که step by step reasoning میکند، اندازهگیری شده:
| model callها | input | output | هزینه برای 20 مورد | درست | بازه 95٪ | |
|---|---|---|---|---|---|---|
| یک greedy chain | 20 | 1,330 | 2,649 | $0.034448 | 9/20 | 26–66٪ |
| اکثریت 5، temperature 0.8 | 100 | 6,650 | 13,245 | $0.172240 | 9/20 | 26–66٪ |
پنج برابر call، پنج برابر token، دقیقاً پنج برابر صورتحساب، و حتی یک پاسخ درست اضافه هم نه. Voting یک شرطبندی است، نه یک بهبود، و این run آن را باخت.
دو caveat، پیش از آنکه کسی این را ردیهای بر Wang نقل کند. بیست trial نمیتواند 45٪ را از 60٪ جدا کند — interval همعرض ادعاست، که همان انضباط فصل 4 است وقتی علیه نتیجه خودم اعمال میشود. و سودهای منتشرشده از مدلهایی میآیند که چند مرتبه بزرگی بزرگترند، جایی که reasoning pathهای متنوعی که voting روی آنها marginalise میکند واقعاً متنوعاند. چیزی که منتقل میشود عدد نیست: این است که ضریب دقیق و از پیش معلوم است، اما سود نه.
Orchestrator-workers، و اینکه summary چه چیزی نیست
لینک به بخش: Orchestrator-workers، و اینکه summary چه چیزی نیستدر workflowِ orchestrator-workers «یک LLM مرکزی بهصورت پویا taskها را میشکند، آنها را به worker LLMها delegate میکند، و نتیجههایشان را synthesize میکند»، و تفاوتش با sectioning این است که «subtaskها از پیش تعریف نشدهاند، بلکه توسط orchestrator تعیین میشوند».1 تبار این یکی اصلاً از مدلهای زبانی نیست: master-worker است، و نسخهای که workerها یافتهها را در فضای مشترکی مینویسند و controller آن را میخواند، blackboard architecture است، از پژوهش speech understanding در دهه 1970. چیز جدید در 2026 این است که controller مدل است و بنابراین decomposition میتواند برای هر input تصمیمگیری شود — flexibility و cost، در یک جمله.
در برابر 5 call تک agent، 12 model call هزینه داشت، و به همان رأی رسید. سپس کاری کرد که ارزش دارد دقیق نگاهش کنیم:
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 فاکتور، سفارش و جدول مالیات را در window خودش داشت، به نتیجه رسید، و همچنین متوجه شد — بیآنکه کسی پرسیده باشد — که شماره purchase order روی فاکتور با سفارش نمیخواند. سپس یک summary برگرداند. orchestrator میتواند هر دو statement را تکرار کند و هیچکدام را بررسی نکند، چون evidence در windowی ماند که هرگز ندید. این پاسخ پرسش پایانی فصل 24 است: parent اجازه دارد به هر چیزی نگاه کند که child تصمیم گرفته بنویسد.
راهحل یک flag است، و قیمت دارد:
| چیزی که worker برمیگرداند | input tokenهای orchestrator | هزینه | parent چه میتواند بکند |
|---|---|---|---|
| نتیجهگیری خودش | 3,628 | $0.012512 | آن را تکرار کند |
| نتیجهگیری و evidence خودش | 4,065 | $0.013554 | دوباره derive کند، و مخالفت کند |
دوازده درصد input token بیشتر، 8.3٪ پول بیشتر، و عبارت source=worker_unverified از پاسخ ناپدید میشود. این معامله در هر سیستم multi-agent است و تقریباً هرگز صریح گفته نمیشود: window تمیز child ارزش داشتن دارد، توانایی parent برای audit کردنش ارزش پرداخت دارد، و هیچکدام را رایگان با هم ندارید.
پس orchestrator-workers چه زمانی اشتباه است؟ همینجا، روی همین کار. پاسخ درستی خرید که یک agent با همان چهار ابزار هم به آن رسیده بود، با 1.66 برابر هزینه و 2.3 برابر زمان واقعی، و دفاع از آن پاسخ را سختتر کرد. راهنمایی خود Anthropic پیش از شروع الگوها همین را میگوید: «سادهترین راهحل ممکن» را پیدا کنید و «فقط وقتی لازم شد پیچیدگی را افزایش دهید»، چون «agentic systems اغلب latency و cost را با عملکرد بهتر task معاوضه میکنند».1 جدولهای بالا همان جملهاند، با عدد زیرشان.
Evaluator-optimiser، و داوری که خودش امتحان را نوشته بود
لینک به بخش: Evaluator-optimiser، و داوری که خودش امتحان را نوشته بودیک call تولید میکند، دیگری ارزیابی میکند، و loop تکرار میشود تا ارزیابی قبول شود.1 نیاکان منتشرشده Self-Refine هستند — همان مدل در نقش «generator، refiner و feedback provider»، با گزارش حدود 20 امتیاز بهبود مطلق بهطور میانگین روی هفت task3 — و Reflexion، که critique را در episodic buffer بین تلاشها ذخیره میکند و روی HumanEval، جایی که baseline به 80٪ رسیده بود، 91٪ pass@1 گزارش میدهد.4
cost model سادهترینِ پنج مورد است: دو call در هر round، و تعداد round دست شما نیست. سه round اصلاح روی کاری که یک call میگرفت یعنی شش call، پس کف این الگو 6× است و سقفش هر capی است که میگذارید — که budget exit فصل 23 را اجباری میکند، نه صرفاً مرتب.
سقف ظریفتر است، و قابل اندازهگیری. روی همان 20 مسئله، مدل محلی به 9 تا درست پاسخ داد. سپس هرکدام از آن پاسخها را به خودش نشان دادند و پرسیدند آیا درست است — بدون اینکه به او گفته شود پاسخ خودش است؛ این confound چاپلوسی را حذف میکند و capability را باقی میگذارد:
| پاسخ خود مدل | گفت «بله» | گفت «نه» |
|---|---|---|
| آن 9 تایی که درست بودند | 9 | 0 |
| آن 11 تایی که اشتباه بودند | 3 | 8 |
این داور بهتر از چیزی است که عنوان بخش القا میکند، و گفتن همین نکته دلیل اندازهگیری است نه ادعا کردن: هیچ درست را block نکرد و 8 تا از 11 اشتباه را گرفت. بهعنوان filter، ارزش callهایش را دارد.
اما بهعنوان stopping rule، که loopِ evaluator-optimiser واقعاً برای آن از داور استفاده میکند، همان سه approval کل داستاناند: آنها loop را با پاسخ اشتباه در دست تمام میکنند، و هیچ تعداد round اضافهای هرگز به آنها نمیرسد. refinement loop نمیتواند از داورش درستتر شود. خریدن roundهای بیشتر یعنی خریدن تلاش برای خطاهایی که داور میتواند ببیند، با قیمت کامل، و هیچ چیز در برابر خطاهایی که نمیتواند.
پس قاعده این است: evaluator فقط وقتی callهایش را به دست میآورد که چیزی داشته باشد که generator ندارد. یک compiler، یک test suite، یک schema validator، یک مدل متفاوت، یک انسان. نتایج خود Self-Refine با human preference و task metricها اندازهگیری شدهاند، نه با نظر مدل درباره خودش. اگر تنها مزیت evaluator شما prompt متفاوت است، دارید دو برابر برای توافق پول میدهید. فصل 29 نسخهای را میسازد که مزیت واقعی دارد: golden set با پاسخهایی که از پیش نوشته شدهاند.
Loopها الگوها نیستند
لینک به بخش: Loopها الگوها نیستندپنج مورد بالا شکلهایی برای کد شما هستند. زیر آنها خانواده دومی نشسته که اغلب کنارشان فهرست میشود و نباید بشود: ReAct، Reflexion، plan-and-execute و tree of thoughts reasoning loop هستند، و هزینهشان در requestهاست.
فصل 12 درباره reasoning داخل مدل بود، که هزینهاش را در output tokenهای یک call میپردازید. این نوع دیگر است. تفاوت وقتی قبض میرسد مهم میشود: chain of thought طولانیتر یک call را گرانتر میکند، و reasoning loop یک task را به چندین call تبدیل میکند، که هرکدام همهچیز قبل از خود را دوباره میفرستد — همان quadraticی که فصل 23 در جدول runaway خودش اندازه گرفت.
| loop | call بهازای هر task | callهای اضافه چه میخرند |
|---|---|---|
| ReAct | یکی در هر گام، تا وقتی متوقف شود | مدل به چیزی که ابزارها برگرداندند واکنش نشان میدهد5 |
| plan-and-execute | یکی برای plan، سپس یکی در هر گام | plan پیش از اجرای گام اول ثابت است6 |
| Reflexion | تلاشها × (act + reflect) | critique تا تلاش بعدی باقی میماند4 |
| tree of thoughts | branching factor × depth، بهعلاوه یک evaluation برای هر node | search، با backtracking7 |
مقاله tree-of-thoughts جدول cost خودش را منتشر میکند، چیزی که باید رایجتر از این باشد. روی 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، و نویسندگان اشاره کردند که «میتواند 5 تا 100 برابر token تولیدشده بیشتری نسبت به CoT لازم داشته باشد».7
تقریباً شش برابر قیمت روش ارزان برای کمی بیش از دو برابر نرخ موفقیت. اینکه این معامله خوب است یا نه بستگی دارد یک case شکستخورده برای شما چه هزینهای دارد — پرسشی که پیش از پذیرفتن هرکدام از این چهار باید بپرسید.
این دوره آنها را دوباره پیادهسازی نمیکند. هر چهار مورد reference implementationهایی از نویسندگان خودشان دارند، در Python، و ارزششان در source بودن است نه ترجمه: ysymyth/ReAct، noahshinn/reflexion، princeton-nlp/tree-of-thought-llm و AGI-Edgerunners/Plan-and-Solve-Prompting. promptهای آن repositoryها را بخوانید؛ promptها همان مقالهها هستند.
دو topology، و یکی از آنها برنمیگردد
لینک به بخش: دو topology، و یکی از آنها برنمیگرددحالا multi-agent واقعی، جایی که بیشتر سردرگمیها زندگی میکنند. دو راه برای این وجود دارد که یک agent، agent دیگری را درگیر کند؛ اینها variant هم نیستند، و تفاوت در این است که بعد از آن چه کسی کنترل را دارد.
Agent بهعنوان ابزار. parent آن را call میکند، پاسخ میگیرد، و ادامه میدهد. این همان interface ابزار فصل 18 است با یک agent کامل پشت آن، و parent هرگز کنترل را از دست نمیدهد. orchestrator بالا همین کار را میکند.
Handoff. parent گفتگو را منتقل میکند و آن را پس نمیگیرد. راهنمای OpenAI روشنترین بیان منتشرشده است: handoffها «انتقال یکطرفهای هستند که به یک agent اجازه میدهند به agent دیگری delegate کند... اگر یک agent یک handoff function را call کند، ما بلافاصله execution را روی agent جدیدی که به آن handoff شده شروع میکنیم و همزمان آخرین conversation state را هم منتقل میکنیم».8
یک هشدار واژگانی، چون دائم مردم را زمین میزند: «handoff» واژه یک SDK است، نه standard. این اصطلاح از OpenAI Agents SDK و همان راهنما میآید، که دو چیدمان را هم «manager» و «decentralized» مینامد و میگوید در manager pattern «edgeها tool callها را نشان میدهند در حالی که در decentralized pattern، edgeها handoffها را نشان میدهند».8 در این فضا یک standard باز هم وجود دارد — A2A، در نسخه 1.0.0، زیر copyright بنیاد Linux، با تاریخچه release نسخهدار و فهرست مستند breaking changeها، که اصل اعلامشدهاش opaque execution است: agentها «بر اساس capabilityهای اعلامشده و اطلاعات مبادلهشده همکاری میکنند، بدون نیاز به اشتراکگذاری thoughtهای داخلی، planها یا پیادهسازیهای ابزارشان».9 این handoff نیست، و مقایسهاش جای فصل 26 است. آنچه اینجا مهم است این است که یکی از این دو واژه API یک library است و دیگری specificationی با governance.
این تمایز data structure است، نه diagram:
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;
}بیست خط، دو bug که وگرنه در production پیدایشان میکردید. reachable agentی را پیدا میکند که هیچکس نمیتواند به آن برسد — configure شده، برایش پول داده شده، هرگز call نشده. conflicts edgeای را رد میکند که همزمان از هر دو نوع است، چیزی که pedantic به نظر میرسد تا وقتی آن را بلند بخوانید: parent هم کنترل را نگه میدارد و هم آن را واگذار میکند. آن را روی یک سیستم پنج-agent با یک orphan و یک double edge اجرا کنید:
reachable: lead@0 billing@1 tax@1 dunning@1
orphans: ghost
conflicts: lead->taxواقعاً چه چیزی از مرز عبور میکند
لینک به بخش: واقعاً چه چیزی از مرز عبور میکندحالا اندازهگیریای که این بخش برای آن وجود دارد، و تنها مورد این فصل که بهجای مدل اسکریپتشده با مدل واقعی انجام شده است.
مشتری در پیام اولش یک constraint بیان میکند — account ما در پرتغال ثبت شده، نه اسپانیا؛ هر چیزی که به مالیات مربوط است باید از پرتغال استفاده کند — بعد درباره چیز دیگری chat میکند، سپس سؤالی میپرسد که billing باید جواب دهد. case منتقل میشود. بیستوچهار trial، هر بار کشور و شرکت متفاوت، چهار transfer payload، و سپس از agent گیرنده یک سؤال پرسیده میشود: account این مشتری در کدام کشور ثبت شده است؟
| چیزی که منتقل شد | payload میانگین | constraint داخلش بود | specialist آن را به یاد آورد | بازه 95٪ |
|---|---|---|---|---|
| کل گفتگو | 173 token | 24/24 | 20/24 — 83٪ | 64–93٪ |
| summary که agent فرستنده نوشته بود | 62 token | 1/24 | 0/24 — 0٪ | 0–14٪ |
| فقط آخرین پیام کاربر | 61 token | 0/24 | 0/24 — 0٪ | 0–14٪ |
| یک رکورد typed | 69 token | 24/24 | 24/24 — 100٪ | 86–100٪ |
سطر سوم control است و مثل control رفتار میکند: fact آنجا نیست، پس نمیتواند recalled شود. سه سطر دیگر یافتهاند.
transcript کامل 173 token است و 83٪ مواقع کار میکند، و چهار شکستش موضوع فصل 24 است نه این فصل. رکورد typed 69 token است — هفت تا بیشتر از summary — و هر بار کار میکند، چون constraint بهجای یک جمله، در field نامدار نشسته است.
و summary سطری است که باید به آن خیره شد. 24 بار از 24 بار شکست خورد، و دلیلش این نیست که خواننده آن را ندید. constraint اصلاً فقط در 1 مورد از 24 summary ظاهر شد. agent گیرنده بیدقت نبود؛ متنی به او داده شده بود که پاسخ را در خودش نداشت. summary فشردهسازیای است که شما ننوشتهاید، تولیدشده توسط مدلی که window آن را نمیبینید، optimized برای اینکه مثل summary خوانده شود — و «مشتری میگوید رکوردهای ما کشور اشتباه دارند» دقیقاً همان نوع clauseای است که summariser بهعنوان noise رویهای حذف میکند.
یک محدودیت صادقانه برای آن عدد: summariser یک مدل نیممیلیارد-parameter است و مدل بزرگتر بیشتر نگه میدارد. چیزی که با اندازه بهتر نمیشود شکل ریسک است — agent فرستنده، در هر handoff، با هر phrasing، بهصورت غیرقابل مشاهده تصمیم میگیرد کدام factها زنده بمانند. رکورد typed اصلاً به آن judgement وابسته نیست، و به همین دلیل با construction میبرد نه با intelligence. هر چیزی که باید از transfer زنده بماند باید field باشد، نه جمله.
همین استدلال در جهت دیگر هم برای topologyِ agent-as-tool صادق است، و جدول قبلی همین حالا قیمتش را داده بود: چیزی که از worker برمیگردد هم summary است، و پرداخت 8.3٪ بیشتر برای دریافت evidence همراه آن همان راهحل است، از سمت parent.
وقتی یک agent برنده میشود
لینک به بخش: وقتی یک agent برنده میشودسه fact پایانی، همه از جدولهای بالا.
سیستم multi-agent تعداد callها را ضرب میکند، و callها در context بهصورت quadratic رشد میکنند. orchestrator جایی 12 model call انجام داد که یک agent 5 تا انجام داد، و هرکدام transcript در حال رشد خودش را حمل میکند — 3,628 input token در برابر 2,697، شکافی که با طول task بیشتر میشود.
هر مرز یک کانال lossy است. دو agent یعنی یک summary. چهار agent در chain یعنی سه تا، ترکیبشده، هرکدام نوشته مدلی که برای چیزی غیر از تصمیم شما optimize میکند.
single agent چیزی را پیدا کرد که هیچکس نپرسیده بود. عدم تطابق purchase-order بالا آمد چون یک window هم فاکتور و هم سفارش را همزمان داشت. تقسیم کار بین specialistها همچنین توانایی دیدن اینکه دو fact با هم نمیخوانند را تقسیم میکند.
هیچکدام از اینها استدلالی علیه frameworkهای multi-agent منتشرشده نیست، که ارزش خواندن بهعنوان primary source را دارند نه از طریق tutorialها.10 استدلالش این است که agent دوم باید جای خودش را به دست بیاورد.
پس یک آزمون، نه یک ترجیح. agent دوم را وقتی اضافه کنید که دستکم یکی از اینها درست باشد: sub-task به window تمیزی نیاز دارد که parent نباید inherit کند (فصل 24)؛ sub-taskها واقعاً مستقل هستند و زمان واقعی مهم است، که همان 1.8× بالاست؛ sub-task به permissionهای متفاوت یا مدل متفاوت نیاز دارد، که فصل 30 آن را به استدلال security تبدیل میکند؛ یا sub-task مال شخص دیگری است، جایی که یک protocol واقعی اهمیت پیدا میکند. اگر پاسخ این است «تا هر agent prompt روشنتری داشته باشد»، به همان یک agent prompt روشنتری بدهید. رایگان است.
بعد به کجا میرویم
لینک به بخش: بعد به کجا میرویمحالا میتوانید پنج الگو را نام ببرید، آنها را روی یک task نسبت به هم price کنید، orchestrator را از sectioner و tool call را از handoff تشخیص دهید، و از single agent با جدول دفاع کنید نه با ترجیح.
همه چیدمانهای اینجا یک راحتی مشترک داشتند که در تماس با چیز واقعی دوام نمیآورد: همه ابزارها مال ما بودند. فاکتور، سفارش، جدول مالیات، workerهای پشت orchestrator — همان repository، همان deploy، همان typeها، همان آدمها.
حالا یکی از آنها را آنطرف مرز یک شرکت بگذارید. جدول مالیات مال یک vendor حسابداری است، رکورد سفارش مال یک سیستم انبار، و هیچکدام interfaceِ Tool شما را نخواندهاند. شما به راهی نیاز دارید تا مدلی که ننوشتهاید بتواند capabilityی را که شخص دیگری operate میکند discover، describe و call کند — با authentication (که نیمه فصل 27 است)، versioning، و تضمین اینکه یک server نمیتواند بقیه conversation شما را بخواند. این یک مسئله protocol است، specificationی با schema هنجاری دارد، و تقریباً هر چیزی که دربارهاش index شده revisionی را توصیف میکند که دیگر وجود ندارد.
فصل 26 بهجای summary کردن specification، آن را میخواند، و با تایپ دستی JSON-RPC در terminal شروع میکند.
منابع و روش
لینک به بخش: منابع و روشهر cost و token count بالا از provider اسکریپتشده توصیفشده در بخش دوم آمده، روی Node 22 از طریق loopback interface، با شمارش توسط encodingِ o200k_base و قیمتگذاری با نرخهایی که فصل 16 در 6 سپتامبر 2026 خوانده بود — $2.00 برای هر یک میلیون input token و $12.00 برای هر یک میلیون output. رقمهای wall-clock از همان runها هستند، با latency provider روی 400 ms برای هر call و ابزارها روی 50 ms، پس چیدمان را اندازه میگیرند نه هیچ providerی را. دو اندازهگیری با مدل واقعی — جدول handoff و جدول voting-and-judging — از Qwen/Qwen2.5-0.5B-Instruct در float32 روی CPU پشت endpointی با همان شکل استفاده کردند، greedy مگر جایی که temperature گفته شده، با intervalهایی که با روش Wilson از فصل 4 محاسبه شدهاند. هیچ requestی در این فصل به endpoint پولی نرفت، و هیچ عددی در آن تخمینی نبود.
ارجاعات
لینک به بخش: ارجاعات-
Anthropic، Building effective agents، 19 دسامبر 2024،
anthropic.com/engineering/building-effective-agents، خواندهشده در 7 سپتامبر 2026. منبع پنج نام workflowی که بالا استفاده شد و هر عبارتی که از آنها نقل شد — prompt chaining، routing، parallelisation با variantهای sectioning و voting، orchestrator-workers، evaluator-optimiser — و نیز توصیه برای یافتن «سادهترین راهحل ممکن، و افزایش complexity فقط وقتی لازم است» و مشاهده اینکه «agentic systems اغلب latency و cost را با عملکرد بهتر task معاوضه میکنند». فصلهای 22 و 23 تعریف آن از agent را نقل میکنند. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 -
Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. و Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (مارس 2022). origin الگوی voting، که آنجا بهجای architecture بهعنوان decoding strategy توصیف شده است: reasoning pathهای متنوع را sample کنید، سپس «با marginalizing out کردن reasoning pathهای sampleشده، سازگارترین پاسخ را انتخاب کنید»، با سودهای گزارششده +17.9 روی GSM8K، +11.0 روی SVAMP، +12.2 روی AQuA، +6.4 روی StrategyQA و +3.9 روی ARC-challenge. ↩
-
Madaan, A. و همکاران. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). loopِ evaluator-optimiser با یک مدل در هر سه نقش — «generator، refiner و feedback provider» — که «بهطور میانگین حدود ~20% مطلق در task performance» روی هفت task بهبود میدهد، اندازهگیریشده با human preference و metricهای خودکار، نه با verdict خود مدل. ↩
-
Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. و Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). episodic memory از self-critiqueها را بین تلاشها اضافه میکند — «agentهای زبانی را نه با update کردن weightها، بلکه از طریق feedback زبانی reinforce میکند» — و 91٪ pass@1 روی HumanEval در برابر 80٪ برای baselineِ GPT-4 گزارش میدهد. به requirementی توجه کنید که نتایجش به آن وابستهاند: سیگنال واقعی از environment، مثل test failing، نه نظر مدل درباره خودش. ↩ ↩2
-
Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. و Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). reasoning traceها و actionهای درهمتنیده؛ فصل 23 این loop را ساخت. اینجا برای شکل cost آن cite شده نه نتایجش: یک model call در هر step، با transcript کامل که هر بار دوباره ارسال میشود. ↩
-
Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. و Lim, E.-P. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. arXiv:2305.04091 (2023). «ابتدا، devising a plan برای تقسیم کل task به subtaskهای کوچکتر، و سپس انجام subtaskها طبق plan» — شکل plan-then-execute، و منبع tradeای که این فصل به آن اهمیت میدهد: plan پیش از رسیدن نخستین observation ثابت است، که همان prompt chaining است با decomposition نوشتهشده توسط مدل بهجای شما. ↩
-
Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. و Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023). search روی «thought»های میانی با self-evaluation و backtracking؛ 74٪ روی Game of 24 در برابر 4٪ برای chain-of-thought prompting. رقمهای cost نقلشده در بالا از خود مقالهاند، از Appendix B.3، Table 7: بهازای هر 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 «میتواند 5 تا 100 برابر token تولیدشده بیشتری نسبت به CoT لازم داشته باشد». ↩ ↩2
-
OpenAI، A practical guide to building agents (PDF)، خواندهشده در 7 سپتامبر 2026. تفکیک manager در برابر decentralised، framing گرافی نقلشده در بالا («در manager pattern، edgeها tool callها را نشان میدهند در حالی که در decentralized pattern، edgeها handoffها را نشان میدهند»)، و تعریف handoff بهعنوان «انتقال یکطرفه... ما بلافاصله execution را روی agent جدیدی که به آن handoff شده شروع میکنیم و همزمان آخرین conversation state را منتقل میکنیم». توجه کنید آن بند آخر چه چیزی را تعیین میکند: در این SDK، conversation state واقعاً سفر میکند، که تصمیم design آن library است و property کلی handoffها نیست. ↩ ↩2
-
Agent2Agent (A2A) Protocol Specification، آخرین نسخه منتشرشده 1.0.0،
a2a-protocol.org/latest/specification/، خواندهشده در 7 سپتامبر 2026؛ copyright بنیاد Linux، Apache-2.0. نقلشده در بالا: یک «standard باز طراحیشده برای تسهیل communication و interoperability بین سیستمهای AI agent مستقل و بالقوه opaque»، و اصل opaque execution — agentها «بر اساس capabilityهای اعلامشده و اطلاعات مبادلهشده همکاری میکنند، بدون نیاز به اشتراکگذاری thoughtهای داخلی، planها یا پیادهسازیهای ابزارشان». صفحه تاریخچه release دارد (0.1.0، 0.2.6، 0.3.0، 1.0.0)، appendixی از breaking changeها، و appendixی درباره رابطهاش با MCP. فصل 26 آن مقایسه را انجام میدهد. ↩ -
frameworkهای multi-agentی که این فصل آموزش نمیدهد، برای خوانندهای که primary source میخواهد نه tutorial: Wu, Q. و همکاران، AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation، arXiv:2308.08155 (2023)، جایی که agentها «customizable, conversable» هستند و خود conversation مدل programming است؛ Hong, S. و همکاران، MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework، arXiv:2308.00352 (2023)، که standard operating procedureها را در role promptها encode میکند و صریح میگوید «راهحلهای taskهای پیچیدهتر بهدلیل logic inconsistency ناشی از cascading hallucinationها در اثر chaining سادهلوحانه LLMها پیچیده میشوند» — همان chain با اطمینان اشتباه که ابتدای این فصل اندازهگیری شد، در abstract نامگذاریشده؛ و Park, J. S. و همکاران، Generative Agents: Interactive Simulacra of Human Behavior، arXiv:2304.03442 (2023)، بیستوپنج agent با memory، reflection و planning، که بزرگترین پاسخ منتشرشده به «اگر به افزودن agent ادامه دهید چه میشود» است. ↩