مثالی از پیاده‌سازی Agent Orchestration

این مطلب، یک مثال عملی از توسعه سیستم‌های چند ایجنتی به ‌همراه Orchestrator است. من تصمیم گرفتم با توجه به دشواری دسترسی به سرویس‌های ابری در ایران؛ این مثال رو با ابزارها و مدل‌هایی طراحی کنم که از نظر دسترسی، و هزینه برای طیف وسیع‌تری از مخاطبین مناسب باشه.

هدف اینه که با یک مثال واقعی ولی کوچیک، ببینیم چه زمانی یه ایجنت کافیه، و چه زمانی تقسیم مسئولیت بین چند ایجنت منطقی می‌شه و Orchestrator دقیقاً چه نقشی توی این معماری داره. در کنارش هم می‌بینیم که همه تصمیم‌ها لزوماً به یه مدل زبانی بزرگ نیاز ندارن و گاهی چند خط کد معمولی یا یه مدل کوچیک که مخصوص تصمیم‌گیریه، می‌تونه انتخاب بهتری باشه.

یک تمایز مهم رو هم باید از ابتدا روشن کنم: Self-hosted بودن Gateway الزاماً به معنی آفلاین بودن سیستم نیست. اگر شما GPU خوبی ندارید، نگران نباشید چون مثال رو با API دیپ‌سیک هم طراحی کردم تا از نظر هزینه به مراتب مقرون‌به‌صرفه‌تر باشه، و از نظر سخت‌گیری‌های انسداد حساب کاربری؛ قابلیت اتکا بیشتری نسبت به مدل‌های غربی داشته باشه، و همچنین کیفیت مدل هم قابل رقابت باشه.

حتی اگر تهیه حساب دیپ‌سیک هم مقدور نبود، نگران نباشید، با مدل کوچک‌تر ولی محلی (قابل اجرا روی کامپیوتر خودتون) می‌تونید یادگیری رو دنبال کنید.

برای مثال مقاله، یه سیستم کوچیک بازبین کد رو انتخاب می‌کنم که از نظر درک نیاز و موضوع، ساده و سرراست باشه. این سناریو برای توضیح Routing، تخصص ایجنت‌ها، دسترسی به ابزار، کنترل پاسخ و نقش Orchestrator، مناسبه و نیاز به پایگاه داده یا زیرساخت پیچیده نداره.

لایهابزار پیشنهادیدلیل انتخاب
Agent OrchestrationLangGraphمتن‌باز، کنترل جریان، وضعیت و مسیریابی
LLM GatewayLiteLLMجایگزین Self-hosted برای نقش API Gateway در OpenRouter
LLM ProviderDeepSeekAPI سازگار با OpenAI
مدل محلیOllamaاجرای مدل بدون وابستگی به API ابری
RuntimePython + Dockerساده و قابل اجرا روی سرور معمولی

الان دیگه ساختن یه AI Agent کار ساده‌ایه. کافیه تا پرامپت مورد نظر مون رو همراه چند ابزار (Tool) در اختیار یه مدل زبانی بدیم؛ و اون‌وقت می‌تونیم انتظار داشته باشیم که کار مشخصی رو برامون انجام بده.

اما وقتی مسئله پیچیده‌تر بشه چی؟ فرض کنین می‌خوایم ابزاری بسازیم که سورس یک پروژه نرم‌افزاری رو بررسی کنه و مشکلات احتمالی اون رو از نظر کیفیت کد، وابستگی‌ها و مستندات پیدا کنه. ساده‌ترین راه اینه که همه فایل‌ها رو به یه LLM بدیم و بگیم: «لطفاً این پروژه رو بررسی کن!»

شاید برای یه کد یا پروژه کوچیک همین هم کار کنه؛ ولی اگه پروژه بزرگ‌تر باشه چی؟ اگر بخوایم هر بخش ابزارهای تخصصی خودش رو داشته باشه؟ یا بخوایم فرآیند بررسی و نتیجه هر مرحله قابلیت ردیابی و آزمایش داشته باشه، چی؟

کاربرد معماری Multi-Agent و مفهوم Agent Orchestration اینجا مهم می‌شه. این مطلب درباره یه سیستم کوچیک ولی واقعیه تا طراحی و بخش‌های مهم پیاده‌سازی چنین سیستمی رو مرور کنیم.

۱. از یک Agent به چند Agent

قبل از شروع بحث، بیاین ماهیت ایجنت رو از فراخوانی ساده‌ی یه LLM تفکیک کنیم. وقتی از مدل می‌خوایم یه متن رو خلاصه کنه، لزوماً Agent نساختیم. اما وقتی مدل می‌تونه بر اساس یه هدف تصمیم بگیره چه ابزارهایی رو فراخوانی کنه، نتایج رو بررسی کنه و برای رسیدن به هدف، مراحلی رو پیش بره، وارد قلمرو ایجنتیک شدیم.

البته باید بین Agent و Workflow تفاوت قائل بشیم. توی یه Workflow معمولی، مسیر اجرای کارها عمدتاً از قبل مشخصه. اما توی یه ایجنت، مدل می‌تونه با توجه به شرایط تصمیم بگیره چه ابزاری رو فراخوانی کنه، چه اطلاعات بیشتری لازم داره و قدم بعدی چی باشه. بنابراین هر Node توی یه نمودار یا هر فراخوانی LLM الزاماً ایجنت نیست!

حالا فرض کنیم ابزار بررسی پروژه ما، سه تا مسئولیت متفاوت داره:

  • Code Reviewer Agent: مسئول بررسی ساختار کد، مدیریت خطا و مشکلات نگهداشت‌پذیری.
  • Dependency Agent: بررسی فایل‌های وابستگی، محدودیت نسخه‌ها و ریسک‌های قابل شناسایی.
  • Documentation Agent: بررسی README و تطبیق مستندات با ساختار واقعی پروژه.

هر ایجنت ابزارهای مخصوص خودش رو داره. مثلاً Code Reviewer می‌تونه فایل‌های سورس رو بخونه، اما Dependency Agent بیشتر با فایل‌هایی مثل pyproject.toml و requirements.txt سروکار داره و مثلاً می‌دونه چجوری چک کنه که ورژن مورد استفاده از فلان کتابخونه آیا آسیب‌پذیری امنیتی شناخته‌شده‌ای داره یا نه؛ یا اینکه مجوز استفاده‌اش رایگانه یا نه.

این تقسیم مسئولیت کمک می‌کنه تا هر ایجنت با اطلاعات مرتبط و ابزارهای محدودتری کار کنه. اما سؤال بعدی ما می‌تونه این باشه که چه کسی مشخص می‌کنه کدوم ایجنت باید اجرا بشه؟ اگر چند تا ایجنت هم‌زمان کار کنن، چه کسی نتایج رو جمع می‌کنه؟

کاربرد Orchestrator همینه. در حقیقت Orchestrator مسئول هماهنگی اجرای کارهاست. می‌تونه درخواست رو تحلیل کنه، به ایجنت مناسب ارجاع بده، وابستگی‌ها رو مدیریت کنه، نتایج رو جمع‌آوری کنه و نهایتاً پاسخ بده. نکته مهم اینه که Orchestrator الزاماً خودش یک AI Agent نیست. گاهی یه Workflow با قوانین مشخص، قابل پیش‌بینی‌تر و حتی مناسب‌تره.

۲. نقش و مسئولیت Agent Orchestrator

Orchestrator مسئول هماهنگی اجرای کارهاست. برای مثالی که توی این مقاله بهش می‌پردازیم، وظایفش می‌تونه این‌ها باشه:

  1. تشخیص بده درخواست کاربر به کدوم ایجنت‌ها نیاز داره.
  2. کارها رو به ایجنت‌های مناسب واگذار کنه.
  3. اجرای موازی یا ترتیبی اون‌ها رو مدیریت کنه.
  4. خروجی‌ها و خطاها رو جمع‌آوری کنه.
  5. نتایج رو برای تولید گزارش نهایی آماده کنه.

اما یه نکته‌ی مهم هم داریم: Orchestrator الزاماً خودش یک AI Agent نیست!

گاهی تصمیم‌گیری با چند شرط ساده توی کد کاملاً کافیه. مثلاً اگر کاربر فقط بررسی مستندات رو بخواد، نیازی به اجرای دو تا ایجنت دیگه نداریم. در مقابل، برای مسئله‌های پیچیده‌تر می‌تونیم از یک LLM برای برنامه‌ریزی و انتخاب ایجنت‌ها استفاده کنیم. پس Multi-Agent بودن الزاماً به معنی این نیست که چند مدل زبانی دائماً مشغول گفتگو با هم باشن!

۳. معماری مثال مورد بررسی؛ سیستم بازبینی کد

برای این پروژه از سه تا ابزار اصلی استفاده می‌کنیم:

LangGraph: مسئول اجرای Workflow، مسیریابی بین Agentها و مدیریت State.

LiteLLM: یه LLM Gateway که روی زیرساخت خودمون اجرا می‌شه و یک API یکپارچه برای اتصال به مدل‌های مختلف ارائه می‌ده.

Ollama: برای اجرای مدل‌های زبانی روی سیستم یا سرور محلی.

در صورت داشتن دسترسی، می‌تونیم به جای مدل محلی، از DeepSeek API هم استفاده کنیم. مسیر کلی درخواست به این صورته:

User ➡️ Orchestrator ➡️ Specialized Agents ➡️ Validation ➡️ Report

و ایجنت‌ها برای فراخوانی مدل از مسیر زیر استفاده می‌کنن:

Agent ➡️ LiteLLM Gateway ➡️ Ollama / DeepSeek

دقت کنین اینجا دو نوع Routing متفاوت داریم:

Agent Routing: تصمیم می‌گیره کدوم Agent مسئول انجام یک کاره.

Model Routing: تصمیم می‌گیره فراخوانی مدل زبانی به کدوم مدل یا ارائه‌دهنده ارسال بشه.

آیا برای هر تصمیمی به یک LLM نیاز داریم؟

تا اینجا فرض کردیم Orchestrator با منطق مشخصی تصمیم می‌گیره کدوم Agent اجرا بشه. اما اگه بخوایم این تصمیم‌گیری هوشمندتر بشه چی؟ مثلاً کاربر یه درخواست مبهم بده و سیستم تشخیص بده که باید Code Reviewer اجرا بشه، Documentation Agent یا هر دو.

یه راه اینه که از یک LLM معمولی بخوایم تصمیم بگیره. اما آیا واقعاً برای انتخاب از بین سه یا چهار گزینه، به مدلی نیاز داریم که برای تولید متن و استدلال‌های طولانی طراحی شده؟

اینجاست که خانواده‌ای از مدل‌ها که ذیل عنوان System-1 یا Decision Models می‌شناسیم جالب می‌شن. این مدل‌ها به‌جای تولید متن آزاد، برای تصمیم‌گیری‌های مشخص و ساختاریافته طراحی شدن؛ مثلاً انتخاب بین چند گزینه، امتیازدهی یا تخمین احتمال یک وضعیت.

یکی از نمونه‌های شناخته‌شده این رویکرد، Jev است که TypeSafe AI توسعه داده. در کنار اون، مدل‌ها و پیاده‌سازی‌های باز مثل Laya و Kev هم ارائه شدن که امکان آزمایش رویکرد مشابه روی زیرساخت شخصی رو فراهم می‌کنن.

برای مثال ما، یه Decision Model می‌تونه درخواست کاربر رو بررسی کنه و مشخص کنه کدوم ایجنت‌ها احتمالاً مرتبط هستن. بعد Orchestrator با توجه به خروجی مدل و قوانین برنامه، Workflow مناسب رو اجرا کنه.

البته چند نکته مهم داریم:

اول اینکه System-1 جایگزین Orchestrator نیست؛ صرفاً می‌تونه توی بعضی تصمیم‌ها به اون کمک کنه.

دوم اینکه خروجی ساختاریافته، و داشتن Confidence به معنی تصمیم درست نیست. اگه تصمیم اشتباه گرفته بشه، ممکنه کل Workflow به مسیر نامناسبی بره. بنابراین بهتره چنین مدل‌هایی رو روی داده واقعی ارزیابی کنیم و برای موارد نامطمئن، مسیر جایگزین داشته باشیم.

و سوم اینکه اصلاً شاید برای مسئله ما همین چند شرط ساده Python هم کافی باشه!

بنابراین توی نسخه اصلی پروژه از Routing قطعی استفاده می‌کنیم و امکان استفاده از یک Decision Model محلی رو به‌عنوان مسیر توسعه بعدی در نظر می‌گیریم.

هدف این نیست که برای هر تصمیم کوچکی یک مدل جدید اضافه کنیم؛ هدف اینه که مدل مناسب رو برای تصمیم مناسب انتخاب کنیم.

اولی توی مثال ما با LangGraph مدیریت می‌شه و دومی با LiteLLM. بنابراین اگر فردا تصمیم بگیریم مدل محلی رو عوض کنیم یا درخواست‌ها رو به DeepSeek بفرستیم، لازم نیست معماری ایجنت‌ها رو تغییر بدیم. و سازگاری API هم به معنی یکسان بودن قابلیت، کیفیت یا رفتار همه مدل‌ها نیست؛ خصوصاً برای Tool Calling باید سازگاری مدل انتخابی رو بررسی کنیم.

۴. پیاده‌سازی

LangGraph چیه و چه کاری انجام می‌ده؟

LangGraph یه فریم‌ورک متن‌باز برای ساخت Workflowها و سیستم‌های Agentic با ساختار گرافه. به زبون ساده، به‌جای اینکه کل فرآیند رو توی یه تابع بزرگ یا مجموعه‌ای از فراخوانی‌های پراکنده LLM پیاده‌سازی کنیم، مراحل اجرا و ارتباط بین اون‌ها رو به شکل یک گراف تعریف می‌کنیم.

سه مفهوم مهم توی این ساختار داریم:

  • Node: یک مرحله از اجراست. می‌تونه یک تابع معمولی، فراخوانی یک LLM یا یه Agent با چند ابزار باشه.
  • Edge: مشخص می‌کنه بعد از اجرای هر مرحله، جریان به کجا بره. این مسیر می‌تونه ثابت یا وابسته به نتیجه مرحله قبلی باشه.
  • State: اطلاعاتیه که در طول اجرای گراف نگهداری و به‌روزرسانی می‌شه.

مثلاً توی پروژه ما، Orchestrator می‌تونه با استفاده از قابلیت Send چند Worker رو با ورودی‌های متفاوت اجرا کنه. نتایج اون‌ها رو توی State جمع کنه و بعد به مرحله اعتبارسنجی و تولید گزارش بفرسته.

مزیت این روش فقط ترسیم یک نمودار فانتزی نیست! مدیریت اجرای موازی، کنترل تغییرات State، امکان تعریف مسیرهای شرطی و توسعه Workflowهای دارای حافظه و قابلیت ادامه اجرا از ویژگی‌های مهم LangGraph هستن.

البته استفاده از LangGraph به معنی این نیست که سیستم ما خودبه‌خود در برابر خطا مقاوم می‌شه؛ مدیریت Timeout، محدودیت تکرار، خطای Workerها و اعتبارسنجی خروجی همچنان مسئولیت ماست.


from typing import Annotated, TypedDict
import operator

class Finding(TypedDict):
    agent: str
    severity: str
    file: str
    title: str

class ReviewState(TypedDict):
    repo_path: str
    selected_agents: list[str]
    findings: Annotated[list[Finding], operator.add]
    final_report: str

این State در واقع قرارداد داده بین مراحل Workflow ماست. هر Node می‌تونه بخشی از اون رو بخونه و تغییرات مربوط به خودش رو برگردونه. مثلاً وقتی دو تا ایجنت به‌صورت موازی نتیجه بررسی خودشون رو تولید می‌کنن، هر دو ممکنه بخوان فیلد findings رو به‌روزرسانی کنن. اما قرار نیست نتیجه یکی، نتیجه دیگری رو پاک کنه!

به همین دلیل از Annotated و operator.add استفاده کردیم تا LangGraph بدونه خروجی‌های جدید باید به لیست یافته‌ها اضافه بشن.

البته این فقط روش تجمیع داده‌هاست؛ ترتیب یافته‌های موازی الزاماً ثابت نیست و باید در مرحله تولید گزارش، خروجی‌ها رو مرتب و موارد تکراری رو حذف کنیم.

توی این کد، repo_path مسیر پروژه است و selected_agents مشخص می‌کنه کدوم ایجنت‌ها باید اجرا بشن. هر ایجنت هم نتیجه بررسی خودش رو در قالب findings برمی‌گردونه.

حالا فرض کنیم می‌خوایم فقط ایجنت‌های مورد نیاز اجرا بشن:

from langgraph.types import Send

def dispatch(state: ReviewState):
    return [
        Send(
            agent,
            {"repo_path": state["repo_path"]}
        )
        for agent in state["selected_agents"]
    ]

توی این مثال فرض کردیم اسم ایجنت‌ها قبلاً اعتبارسنجی شده و Node متناظر هرکدوم توی گراف ثبت شده. همین‌طور هر Worker باید ورودی دریافتی از Send رو پشتیبانی کنه و خروجی سازگار با State برگردونه.

نکته مهم اینکه Send برای توزیع کار به Workerهای مختلف استفاده می‌شه، نه برای فراخوانی مستقیم یک مدل زبانی. در واقع LangGraph اجرای کارها رو مدیریت می‌کنه و هر Worker در داخل خودش می‌تونه از LLM و Toolهای مورد نیازش استفاده کنه.

۵. وظایف ایجنت‌ها

توی این مثال، Code Reviewer یک ابزار read_file داره که با اون فایل مورد نظرش رو می‌خونه. اما قرار نیست کل پروژه رو بدون هیچ محدودیتی بریزیم توی Context مدل! ایجنت می‌تونه با ابزار list_files ساختار پروژه رو ببینه و بعد فقط فایل‌های مرتبط و مهم رو درخواست کنه. توی این نسخه آموزشی، ابزارها فقط اجازه خوندن فایل‌ها رو دارن و به مسیر پروژه محدود هستن. هیچ ایجنتی اجازه اجرای دلخواه دستورات سیستم‌عامل یا تغییر فایل‌ها رو نداره. خروجی هر ایجنت هم بهتره یک ساختار مشخص داشته باشه، نه صرفاً یک متن آزاد.

این محدودیت‌ها رو نباید صرفاً با System Prompt اعمال کنیم. اگر به مدل بگیم «لطفاً فایل‌های خارج از پروژه رو نخون»، این یک کنترل امنیتی قابل اعتماد نیست!

خود ابزار read_file باید مسیر درخواستی رو بررسی کنه، دسترسی به فایل‌های خارج از ریشه پروژه رو رد کنه و محدودیت‌هایی مثل حداکثر حجم فایل و تعداد فراخوانی‌ها رو اعمال کنه.

از طرف دیگه، محتوای سورس پروژه هم داده‌ای غیرقابل اعتماد محسوب می‌شه. ممکنه داخل یک کامنت یا README دستوراتی نوشته شده باشه که تلاش کنن رفتار ایجنت رو تغییر بدن. این محتوا نباید به‌عنوان دستور معتبر برای سیستم اجرا بشه.

مثلاً:

{
  "agent": "code_reviewer",
  "severity": "medium",
  "file": "app.py",
  "line": 24,
  "title": "Missing error handling",
  "description": "File read errors are not handled.",
  "recommendation": "Handle expected I/O exceptions."
}

این خروجی به ما اجازه می‌ده نتایج ایجنت‌های مختلف رو بدون تکیه روی تفسیر دوباره متن آزاد، دسته‌بندی، اعتبارسنجی و گزارش کنیم. برای مثال، مرحله Validation می‌تونه بررسی کنه که نام فایل واقعاً وجود داره، شماره خط معتبره و یافته‌های تکراری حذف شدن. معتبر بودن ساختار یک یافته، به معنی درست بودن تحلیل مدل نیست. مدل ممکنه همچنان یه مشکل غیرواقعی گزارش کنه.

۶. چرا LiteLLM؟

هماهنگی بین ایجنت‌ها رو دیدیم. اما یه مسئله دیگه هم داریم: هر ایجنت برای انجام وظیفه خودش باید بتونه یه مدل زبانی رو فراخوانی کنه. فرض کنیم امروز از Ollama و مدل‌هایی که به وسیله‌ی اون روی سرور یا ماشین خودمون اجرا می کنیم استفاده می‌کنیم، فردا می‌خوایم یکی از Agentها رو به DeepSeek متصل کنیم و بعداً هم هر مدل دیگه‌ای رو آزمایش کنیم. آیا باید برای هر ارائه‌دهنده، منطق اتصال جداگانه‌ای بنویسیم و ایجنت‌ها رو به APIهای مختلف وابسته کنیم؟ محل استفاده LiteLLM اینجاست.

LiteLLM یه پروژه متن‌بازه که علاوه بر SDK پایتون، یه Proxy Server هم ارائه می‌ده. ما توی این مثال از همین Proxy به‌عنوان LLM Gateway استفاده می‌کنیم. به زبون ساده، LiteLLM یه نقطه ورود مشترک برای فراخوانی مدل‌های مختلف ایجاد می‌کنه. برنامه ما با یه API نسبتاً یکپارچه ارتباط برقرار می‌کنه و Gateway درخواست رو به مدل یا ارائه‌دهنده مناسب می‌فرسته. مثلاً توی تنظیمات Gateway تعریف می‌کنیم:

  • reviewer-local به مدل محلی در Ollama متصل بشه.
  • reviewer-deepseek به API دیپ‌سیک متصل بشه.

در نتیجه Code Reviewer می‌تونه از یه مدل قوی‌تر استفاده کنه و Documentation Agent از یه مدل کوچیک‌تر و کم‌هزینه‌تر، بدون اینکه منطق Orchestration تغییر کنه. LiteLLM همچنین امکاناتی مثل Load Balancing، مدیریت Retry و Fallback، ثبت مصرف و کنترل دسترسی رو در اختیار می‌گذاره؛ البته بعضی قابلیت‌های مدیریتی و بودجه‌بندی به تنظیمات و زیرساخت اضافی مثل دیتابیس نیاز دارن.

تفاوت مهم اینجاست:

LangGraph تصمیم می‌گیره چه کاری، توسط کدوم ایجنت و توی کدوم مرحله‌ انجام بشه.

LiteLLM مسئول فراهم کردن مسیر دسترسی به مدل‌ها و مدیریت ارتباط با اون‌هاست.

پس LiteLLM جایگزین LangGraph نیست، همون‌طور که LangGraph هم جایگزین یه Model Gateway نیست.

حتی می‌تونیم LiteLLM رو کاملاً روی سرور شرکت اجرا کنیم. اما اگه درخواست‌ها رو از روی LiteLLM به یه سرویس خارجی مثل DeepSeek بفرستیم، همچنان به اینترنت و دسترسی به سرویس نیاز داریم. برای اجرای کاملاً محلی، می‌تونیم پشت Gateway از Ollama و مدل دانلودشده استفاده کنیم.

و یک نکته امنیتی: اگر قرار باشه سورس یه پروژه واقعی رو برای بررسی به ایجنت‌ها بدیم، باید از اول مشخص کنیم داده‌ها روی زیرساخت خودمون باقی می‌مونن یا به یک ارائه‌دهنده خارجی ارسال می‌شن. Gateway به‌تنهایی تضمین نمی‌کنه که اطلاعات از سازمان خارج نشن.

۷. اجرای پروژه

سورس کامل مثال رو روی GitHub گذاشتم که شامل یه پروژه Python کوچیک با چند ایراد عمدی است. بعد از اجرای Ollama و Gateway، کافیه چیزی شبیه این دستور رو اجرا کنیم:


# اجرای آزمایشی بدون مدل و اینترنت
python -m repo_reviewer review ./sample_project --mode mock

# اجرای واقعی با مدل محلی
python -m repo_reviewer review ./sample_project --mode local

# اجرای فقط Agent بررسی مستندات
python -m repo_reviewer review ./sample_project \
  --agents documentation --mode local

توی حالت Mock می‌تونیم بدون اجرای هیچ مدل زبانی، جریان Orchestration و نحوه جمع‌آوری نتایج رو بررسی کنیم. این حالت برای فهم معماری و تست خود Workflow مناسبه، اما طبیعتاً کیفیت تحلیل یک مدل واقعی رو نشون نمی‌ده.

برای بررسی واقعی پروژه، از حالت Local استفاده می‌کنیم که درخواست‌ها رو از طریق LiteLLM به مدل اجراشده در Ollama می‌فرسته.

بعد از پایان کار، سیستم یه گزارش در قالب Markdown تولید می‌کنه که مشکلات، فایل‌های مربوطه، سطح اهمیت و پیشنهاد اصلاح رو نشون می‌ده. مثلاً ممکنه گزارش بده که یک تابع مدیریت خطای مناسبی نداره، یه Dependency بدون محدودیت نسخه تعریف شده، یا راهنمای نصب پروژه ناقصه. این گزارش فقط خروجی یک LLM نیست، بلکه حاصل اجرای چند Worker تخصصی و ترکیب یافته‌هاشون در قالب یک Workflow مشخصه.

۸. آیا Multi-Agent همیشه انتخاب بهتریه؟

نه! و اتفاقاً به نظرم این مهم‌ترین بخش داستانه. وقتی می‌تونیم مسئله‌ای رو با یه تابع، چند قانون مشخص یا حتی یه ایجنت ساده حل کنیم، لزوماً نیازی به ساختن یک تیم از ایجنت‌ها نداریم. هر ایجنت جدید می‌تونه هزینه، زمان پاسخ، پیچیدگی و احتمال خطا رو بیشتر کنه. ضمن اینکه چند ایجنت لزوماً به معنی چند تحلیل مستقل و قابل اعتماد نیست. ممکنه همه اون‌ها اشتباه مشابهی انجام بدن. بنابراین بهتره قبل از انتخاب Multi-Agent از خودمون بپرسیم:

  • آیا واقعاً چند حوزه تخصصی و مستقل داریم؟
  • آیا هر حوزه به ابزارها و Context متفاوتی نیاز داره؟
  • آیا امکان آزمایش و مشاهده عملکرد هر Agent وجود داره؟
  • اگر یکی از Agentها شکست بخوره، تکلیف بقیه کارها چیه؟
  • آیا پیچیدگی اضافه‌شده واقعاً ارزشش رو داره؟

اگر پاسخ‌ها قانع‌کننده نبود، احتمالاً همون یه ایجنت کافیه! معماری Multi-Agent صرفاً کنار هم گذاشتن چند LLM نیست که به نوبت با هم گپ بزنن!

مسئله اصلی، طراحی مرز مسئولیت‌ها، مدیریت جریان اجرا، کنترل دسترسی به ابزارها و هماهنگی نتایجه.

توی این مثال دیدیم که می‌شه Orchestration رو با کد معمولی مدیریت کرد، تصمیم‌های تخصصی رو به ایجنت‌ها سپرد و لایه اتصال به مدل‌های زبانی رو هم مستقل نگه داشت. این ساختار می‌تونه از یه پروژه کوچیک آموزشی تا سیستم‌های پیچیده‌تر توسعه پیدا کنه، اما بهتره از ابتدا پیچیدگی غیرضروری بهش اضافه نکنیم.

شاید هنر اصلی طراحی Multi-Agent این نباشه که بدونیم چجوری ایجنت‌های بیشتری بسازیم؛ بلکه این باشه که بدونیم کجا واقعاً به ایجنت دیگه‌ای نیاز نداریم!

از طرف دیگه، طراحی خوب الزاماً به معنی استفاده از قدرتمندترین مدل برای تمام مراحل نیست. شاید یک بخش از سیستم به LLM قدرتمند و Tool Calling نیاز داشته باشه، مرحله دیگری با یک Decision Model کوچک انجام بشه و بخش بزرگی از هماهنگی کارها هم با کد معمولی پیاده‌سازی بشه.

به نظرم یکی از مهم‌ترین مهارت‌ها در طراحی سیستم‌های Agentic همین انتخاب آگاهانه بین مدل، ابزار و منطق قطعی برنامه‌ست.

🔗 سورس کامل پروژه و راهنمای اجرای محل

دیدگاهتان را بنویسید