درس ۱۰ از ۱۱

Module 10

عنوان اصلی: Agents and Workflows هدف یادگیری ماژول: تسلط بر الگوهای اصلی orchestration که در مقاله‌ی Anthropic «Building Effective Agents» معرفی شده‌اند: parallelization، chaining، routing، agents vs workflows، evaluator-optimizer و orchestrator-workers. تشخیص اینکه چه زمانی کدام الگو مناسب است. مفاهیم کلیدی: parallelization, chaining, routing, agent, workflow, evaluator-optimizer, orchestrator-workers, ReAct, environmental feedback, termination condition.

این ماژول مهم‌ترین ماژول سیستم‌سازی در کل دوره است. اگر فقط یک منبع را برای ساخت سیستم‌های AI تولیدی بخوانید، باید مقاله‌ی Building Effective Agents باشد. اینجا کل آن را مرحله‌به‌مرحله مرور می‌کنیم.

۱۰.۱ Parallelization — موازی‌سازی

هدف: اجرای subtask های مستقل به‌صورت همزمان — sectioning (subtask های مختلف) یا voting (یک subtask، چند بار).

از مقاله‌ی Anthropic: parallelization مناسب است «وقتی subtask های تقسیم‌شده می‌توانند برای سرعت موازی شوند، یا وقتی چندین چشم‌انداز نیاز است.» دو طعم دارد:

Sectioning — یک task را به قطعات مستقل می‌شکنیم. مثلاً: یک مدل summary می‌سازد، یکی sentiment تشخیص می‌دهد، یکی entity ها را extract می‌کند. سپس merge می‌کنیم. fan-out → fan-in.

Voting — یک task را N بار اجرا می‌کنیم و خروجی‌ها را aggregate می‌کنیم. majority vote برای classification، self-consistency برای ریاضی، median برای عدد.

import asyncio
from anthropic import AsyncAnthropic
ac = AsyncAnthropic()

async def call(prompt):
    r = await ac.messages.create(model="claude-haiku-4-5", max_tokens=128,
                                 messages=[{"role": "user", "content": prompt}])
    return r.content[0].text

async def vote(text, n=5):
    answers = await asyncio.gather(*[
        call(f"Is this product review positive, negative, or neutral?\n{text}\nAnswer with one word.")
        for _ in range(n)
    ])
    from collections import Counter
    return Counter(a.strip().lower() for a in answers).most_common(1)[0][0]

یک قاعده‌ی مهم. parallelization فقط وقتی موجه است که call ها واقعاً مستقل باشند. اگر یکی به خروجی دیگری احتیاج دارد، آن chaining است (۱۰.۲)، نه parallelization.

اشتباهات رایج.

  • استفاده از parallelization به‌عنوان حالت پیش‌فرض → فقط اگر latency گلوگاه است یا lift کیفیت واقعی دارد.
  • voting روی task هایی که جواب درست واحد ندارند → آشوب میانگین می‌شود.

منابع: Building effective agents.

۱۰.۲ Chaining — زنجیره‌سازی prompt

هدف: تجزیه‌ی task به مراحل sequential، که خروجی هر مرحله ورودی بعدی است.

از مقاله: chaining «ایده‌آل برای موقعیت‌هایی است که task به‌راحتی و تمیزی به subtask های ثابت تجزیه می‌شود.» مثال‌ها: outline → draft → polish؛ classify → route → respond؛ extract → summarize → translate.

هر مرحله یک LLM call جداگانه با prompt مخصوص خودش است. می‌توانید بین مراحل یک gate بگذارید — یک مدل ارزان‌تر که schema یا کیفیت را چک کند و در صورت تخطی، fail-fast کند.

یک نکته‌ی هزینه. مراحل اول (outline، classify) معمولاً ساده‌اند — Haiku بدهید. مرحله‌ی نهایی که هنر می‌خواهد، Opus.

def write_persian_marketing_email(topic):
    # Step 1: outline (English, fast model)
    outline = call("claude-haiku-4-5",
        f"Outline a 3-paragraph marketing email about {topic}. Bullet list of paragraphs.")
    # Step 2: draft (Persian, capable model)
    draft = call("claude-opus-4-8",
        f"Write the email in Persian. Outline:\n{outline}\nFormal tone, ≤120 words.")
    # Step 3: polish (Persian)
    polished = call("claude-haiku-4-5",
        f"Improve flow and fix any English-only phrasing. Keep ≤120 words:\n{draft}")
    return polished

اشتباهات رایج.

  • chaining وقتی یک prompt کفایت می‌کرد → latency اضافی بدون lift.
  • validate نکردن خروجی میانی → خطاها compound می‌شوند.
  • استفاده از یک مدل برای همه‌ی مراحل → اتلاف هزینه.

منابع: Building effective agents.

۱۰.۳ Routing — مسیریابی

هدف: استفاده از یک classifier-LLM برای dispatch ورودی‌ها به handler های تخصصی.

routing نسخه‌ی agentic از یک switch-case است. یک مدل کوچک سریع، intent یا difficulty را classify می‌کند، بعد به prompt / model / tool-set تخصصی dispatch می‌کند. از مقاله: «خوب کار می‌کند برای task های پیچیده که دسته‌های متمایز دارند که جداگانه بهتر handle می‌شوند.»

مثال کلاسیک: customer-service bot که بر اساس intent (refund / shipping / product) و complexity (Haiku برای FAQ، Opus برای دعواهای پیچیده) مسیر می‌دهد.

def route(user_msg):
    cls = call("claude-haiku-4-5",
        f"Classify the intent of this message into one of: refund, shipping, product, other.\n{user_msg}\nReply with one word.").strip().lower()
    return {
        "refund":   handle_refund,
        "shipping": handle_shipping,
        "product":  handle_product,
    }.get(cls, handle_general)(user_msg)

اشتباهات رایج.

  • اجازه دادن به Claude که به دسته‌ای route کند که شما handler ندارید → همیشه default داشته باشید.
  • routing روی feature های زیاد (intent + sentiment + length + …) → معمولاً intent + difficulty کافی است.
  • استفاده از Opus برای همه‌ی مراحل → benefit هزینه از بین می‌رود.

منابع: Building effective agents.

۱۰.۴ Agents و tools — تفاوت با workflow

هدف: تمایز بین agent های خودگردان (مدل حلقه را می‌چرخاند) و workflow ها (کد حلقه را می‌چرخاند).

تفکیک canonical Anthropic:

  • Workflows = «سیستم‌هایی که LLM ها و tool ها از طریق مسیرهای کد از پیش‌تعریف‌شده orchestrate می‌شوند.»
  • Agents = «سیستم‌هایی که LLM ها به‌صورت پویا فرایندها و استفاده از tool های خود را هدایت می‌کنند.»

Workflow ها قابل پیش‌بینی، debug‌پذیر و ارزان هستند. Agent ها open-ended، تطبیق‌پذیر و گران هستند.

توصیه‌ی محوری مقاله (که باید قاب کنید): «با prompt های ساده شروع کنید، با evaluation جامع بهینه کنید، و سیستم‌های agentic چندمرحله‌ای را فقط وقتی اضافه کنید که راه‌حل‌های ساده‌تر کم می‌آورند.»

ساختار یک agent سالم.

  • یک هدف روشن.
  • tool surface کوچک و خوب-مستندشده.
  • environmental feedback (errors, observations).
  • شرط ختم صریح.
  • سقف‌های سخت: max iterations، max tokens، max wall-clock.
def agent(objective, tools, executor, max_iter=20, max_tokens=200_000):
    messages = [{"role": "user", "content": objective}]
    used = 0
    for _ in range(max_iter):
        r = client.messages.create(
            model="claude-opus-4-8", max_tokens=4096, tools=tools, messages=messages,
        )
        used += r.usage.input_tokens + r.usage.output_tokens
        if used > max_tokens:
            raise RuntimeError("Token budget exceeded.")
        messages.append({"role": "assistant", "content": r.content})
        if r.stop_reason != "tool_use":
            return r
        results = [{"type": "tool_result", "tool_use_id": b.id,
                    "content": executor(b.name, b.input)}
                   for b in r.content if b.type == "tool_use"]
        messages.append({"role": "user", "content": results})
    raise RuntimeError("Max iterations reached.")

Computer Use (ماژول ۹) خودگردان‌ترین agent ای است که Anthropic عرضه می‌کند.

اشتباهات رایج.

  • بدون سقف → cost runaway، یک حادثه‌ی شبانه می‌تواند بیلیون token مصرف کند.
  • tool های زیاد بدون توضیح → Claude رندوم انتخاب می‌کند.
  • بدون environmental feedback → یادگیری حلقوی نداریم.

منابع: Building effective agents.

۱۰.۵ Environment inspection — مشاهده‌ی محیط

هدف: دادن tool های perceptual به agent (filesystem، browser، API state) تا قبل از act کردن، observe کند.

بزرگ‌ترین اهرم کیفیت برای agent ها، perception است. agent باید قبل از اقدام، محیط را ببیند. یک coding agent باید قبل از commit، git status بزند. یک computer-use agent باید قبل از کلیک، screenshot بگیرد. یک refactor agent باید قبل از edit، grep کند.

الگوی canonical: ReAct (Reasoning + Acting). مدل یک thought می‌نویسد، یک observation می‌گیرد، نتیجه را می‌خواند، روی thought جدید act می‌کند.

از مقاله‌ی «Effective harnesses for long-running agents»: برای agent های browser-style، در ابتدای هر session یک end-to-end verification انجام دهید — تا regression ها را زود بگیرید، نه بعد از implementation.

SYSTEM = """\
After each action, take a screenshot and explicitly verify the result.
Pattern:
1. Think: what should I do next?
2. Act: take one action.
3. Observe: take a screenshot.
4. Verify: 'I expected X; the screenshot shows Y. Match? yes/no.'
5. If no, retry. If yes, continue.
Never assume an action succeeded without verifying."""

اشتباهات رایج.

  • act سپس report → مدل ادعا می‌کند موفق شده، اما نشده.
  • observation های زیاد → latency.
  • بدون verification → silent failure.

منابع: Building effective agents · Effective harnesses for long-running agents.

۱۰.۶ Workflows vs Agents — ماتریس انتخاب

هدف: انتخاب abstraction درست — workflow وقتی مراحل قابل پیش‌بینی هستند، agent وقتی نیستند.

ماتریس تصمیم از مقاله:

الگو چه زمان هزینه قابلیت debug
Augmented LLM (single call) task های one-shot، بدون tool $ بالا
Prompt chaining pipeline ثابت $$ بالا
Routing دسته‌های متمایز $ بالا
Parallelization subtask های مستقل $$ بالا
Orchestrator-workers subtask ها از پیش معلوم نیستند $$$ متوسط
Evaluator-optimizer refinement تکراری با criteria واضح $$$ متوسط
Autonomous agent open-ended، تعداد مرحله نامعلوم $$$$ پایین

شعار مقاله. اگر workflow کافی است، agent نسازید. اکثر پروژه‌های «agent» در production، در واقع orchestrator-worker workflow هایی هستند که لباس agentic پوشیده‌اند.

Evaluator-optimizer. الگویی که می‌نویسد، بعد نقد می‌کند، بعد دوباره می‌نویسد، تا معیار pass شود.

def evaluator_optimizer(task, max_rounds=3):
    draft = call("claude-opus-4-8", f"Task: {task}\nDraft a response.")
    for _ in range(max_rounds):
        critique = call("claude-opus-4-8",
            f"Task: {task}\nDraft: {draft}\nCritique strictly: list every weakness or 'PASS'.")
        if "PASS" in critique:
            return draft
        draft = call("claude-opus-4-8",
            f"Task: {task}\nPrevious draft: {draft}\nCritique: {critique}\nRewrite addressing every point.")
    return draft

Orchestrator-workers. الگویی که در آن یک LLM «orchestrator» تصمیم می‌گیرد چه subtask هایی نیاز است، آنها را به worker LLM ها می‌سپارد، و خروجی را اجتماع می‌کند. مناسب وقتی شما نمی‌دانید چند step لازم است، اما می‌دانید که هر step خوش‌تعریف خواهد بود.

اشتباهات رایج.

  • ساخت agent چون «جالب به نظر می‌رسد» → workflow معمولاً بهتر است.
  • اندازه‌نگرفتن این که آیا بخش agentic است که کیفیت را بالا برده → اغلب نیست.
  • log نکردن هر step حلقه → debug ناممکن.

منابع: Building effective agents.

۱۰.۷ Quiz سریع Module 10

سوالات نمونه:

  • کدام الگو برای «خلاصه کن، ترجمه کن، چک کن»؟ → chaining.
  • برای «سه نسخه بساز و بهترین را انتخاب کن»؟ → parallelization-voting + evaluator-optimizer.
  • برای «Q&A عمومی روی یک SaaS با ۵ tenant»؟ → routing بر اساس tenant + intent.
  • چه زمانی agent توجیه دارد؟ → task open-ended با مراحل نامعلوم، و workflow های ساده‌تر در eval شکست خوردند.