پرش به محتوای اصلی
پرش به محتوای مقاله

توزیع متمرکز Nylas: جایگزینی عامل‌های غول‌پیکر با کارگران متخصص

·۱۰ تیر ۱۴۰۵۱۴ دقیقه مطالعه۱ بازدید
راهنما
توجه خودکار نامه‌های ورودی به نماینده مناسب
توجه خودکار نامه‌های ورودی به نماینده مناسب
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

جایگزینی مسیریابی مبتنی بر LLM با مسیریابی قطعی در سطح پلتفرم (Platform Fan-out)؛ این کار باعث می‌شود هزینه استنتاج برای پیام‌های شناسایی‌شده صفر شود و مقیاس‌پذیری هر عامل مستقل گردد.

تصور کنید یک مدیر اداری تمام نامه‌های یک شرکت را می‌گیرد و برای هر کدام باید تصمیم بگیرد که چه کسی پاسخ دهد؛ این دقیقاً همان گلوگاهی است که عامل‌های هوش مصنوعی فعلی در مقیاس واقعی با آن دست‌وپنجه می‌کنند. اگر امروز از یک مدل واحد برای مدیریت تمام ایمیل‌های پشتیبانی استفاده می‌کنید، احتمالاً متوجه شده‌اید که هزینه‌ها و نرخ خطای طبقه‌بندی با افزایش حجم پیام‌ها، به‌شدت بالا می‌رود. یک عامل هوش مصنوعی یکپارچه (Monolithic) که هر ایمیل را طبقه‌بندی و شاخه‌بندی می‌کند، در واقع یک گلوگاه مقیاس‌پذیری است.

طبق گزارش فنی Nylas، مشکل اصلی در دموهای فعلی این است که هر پیام، فارغ از محتوا، از یک پرامپت سیستمی (System Prompt) — شبیه به دستورالعمل‌های سخت‌گیرانه‌ای که به یک کارمند تازه‌وارد می‌دهیم تا هر چیزی را مدیریت کند — و یک بستر متنی یکسان عبور می‌کند. برای بهینه‌سازی این تعاملات، استفاده از تکنیک‌های پیشرفته در طراحی دستورالعمل‌ها ضروری است؛ برای مثال، برخی از ترفندهای مهندسی پرامپت می‌توانند زمان پیش‌نویس ایمیل‌ها را از ساعت‌ها به ثانیه‌ها کاهش دهند و کارایی مدل را در مذاکرات دشوار بالا ببرند. در اکثر این پیاده‌سازی‌ها، برای هر صندوق ورودی تنها یک مدل استفاده می‌شود: هر پیامی که می‌رسد، همان پرامپت، همان کانتکست و همان هندلر (Handler) را دریافت می‌کند. این رویکرد برای یک پروژه کوچک یا دمو مناسب است، اما وقتی یک آدرس واحد مانند [email protected] وظایف متنوعی را مدیریت می‌کند، سیستم فرو می‌پاشد؛ جایی که یک سوال مربوط به صورت‌حساب، یک گزارش امنیتی و یک سرنخ فروش هم‌زمان در یک دقیقه می‌رسند.

راهکار رایج برای رفع این مشکل، استفاده از یک پرامپت سیستمی غول‌پیکر برای طبقه‌بندی است. اما این کار یک «مونولیت» ایجاد می‌کند که تست آن دشوار است، محدود کردن نرخ درخواست‌ها (Rate-limit) برای هر موضوع در آن سخت است و مقیاس‌بندی مستقل آن غیرممکن است. این وضعیت یک بدهی فنی ایجاد می‌کند که در آن هر پیام، صرفاً برای اینکه تصمیم بگیرد کدام فراخوان LLM بعدی را اجرا کند، باید یک فراخوان LLM را تحریک کند.

راهکار Nylas جایگزینی این فرآیند با معماری «توزیع بادبزنی» (Fan-out) است. در این مدل، فرآیند جداسازی پیام‌ها از لایه مدل زبانی خارج شده و به زیرساخت پلتفرم منتقل می‌شود تا «مالیات طبقه‌بندی» از روی هر پیام حذف شود. این رویکرد تضمین می‌کند که یک عامل صورت‌حساب فقط ایمیل‌های مالی را ببیند و یک عامل امنیتی فقط گزارش‌های سوءاستفاده (Abuse) را دریافت کند.

به نقل از مستندات فنی این شرکت، توسعه‌دهندگان با استفاده از حساب عامل نایلز (Nylas Agent Account)، ایمیل‌ها را پیش از رسیدن به عامل، به صف‌های تخصصی هدایت می‌کنند. این یعنی صندوق ورودی به یک مسیریاب هوشمند تبدیل می‌شود که برای مشتری نامرئی است اما در پشت صحنه، پیام‌های مربوط به پرداخت را فقط به عامل حسابداری و گزارش‌های تخلف را فقط به عامل امنیتی می‌رساند. این رویکرد به‌طور آگاهانه با «پاس‌کاری بین عامل‌ها» (Agent-to-Agent Handoff) متفاوت است؛ در پاس‌کاری، یک عامل برای تفویض اختیار به عامل دیگر ایمیل می‌زند. در مقابل، در مدل Fan-out، یک جریان ورودی واحد بر اساس قوانین به صف‌های موازی تقسیم می‌شود و هر صف توسط یک متخصص مصرف می‌شود.

بر اساس بررسی‌های فنی، این معماری سه ضلع حیاتی را از هم جدا می‌کند: تصمیم مسیریابی، منطق تخصصی و واحد مقیاس‌بندی. این جداسازی باعث می‌شود که نیازی به بازطراحی کل پشته (Stack) عامل نباشد، زمانی که تنها یک پرامپت خاص (مثلاً منطق صورت‌حساب) نیاز به اصلاح رگرسیون دارد. اگر حجم درخواست‌های فروش افزایش یابد، شما فقط کارگر (Worker) مربوط به فروش را مقیاس‌بندی می‌کنید. اگر پرامپت صورت‌حساب دچار خطا شود، فقط آن متخصص را مجدداً مستقر (Redeploy) می‌کنید. این ساختار تضمین می‌کند که اعتبار دامین واحد حفظ شود، در حالی که پردازش داخلی به‌شدت تکه تکه و تخصصی شده است.

برای ایجاد این خط لوله قطعی (Deterministic Pipeline)، سه گام عملیاتی تعریف شده است. پیش از شروع، شما به یک اپلیکیشن Nylas، یک کلید API و یک حساب عامل (Agent Account) روی یک دامین ثبت‌شده نیاز دارید. اگر حسابی تعریف نکرده‌اید، از درخواست POST /v3/connect/custom یا دستور CLI nylas agent account create <email> استفاده کنید.

بسیار حیاتی است که درک کنید «قوانین» (Rules) و «پوشه‌ها» (Folders) در سطوح متفاوتی عمل می‌کنند. پوشه‌ها در سطح Grant هستند و درون صندوق ورودیِ حساب عامل قرار دارند. اما قوانین در سطح Application هستند؛ آن‌ها در مسیر خود Grant ندارند و تا زمانی که یک فضای کاری (Workspace) به آن‌ها ارجاع ندهد، غیرفعال می‌مانند. به یاد داشته باشید: یک قانون تا زمانی که فضای کاری آن را فعال نکند، هیچ کاری انجام نمی‌دهد.

  • گام اول: ایجاد پوشه. توسعه‌دهندگان پوشه‌های مجزایی مثل «billing»، «security» یا «sales» را در صندوق ورودی حساب عامل می‌سازند. این یک فراخوان در سطح Grant به مسیر /v3/grants/<NYLAS_GRANT_ID>/folders است.

    • CLI: دستور nylas email folders create "billing" <NYLAS_GRANT_ID>
    • API: استفاده از POST به https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/folders با بدنه {"name": "billing"}.
      شناسه‌های به‌دست آمده (مانند <BILLING_FOLDER_ID>) به عنوان دستگیره‌های پایدار برای تمام منطق‌های پایین‌دستی عمل می‌کنند. هرگز نام پوشه‌ها را Hard-code نکنید؛ ID تنها دستگیره پایدار است. برای تأیید ایجاد، از nylas email folders list <NYLAS_GRANT_ID> یا درخواست GET معادل استفاده کنید.
  • گام دوم: تعریف قوانین. قوانین ورودی (Inbound Rules) پیام‌ها را هنگام دریافت تطبیق داده و یک اکشن اجرا می‌کنند. هدف در اینجا assign_to_folder است که پیام را مستقیماً در صف متخصص می‌اندازد.

    • فیلدهای تطبیق: شرایط تطبیق فقط از فیلدهای فرستنده استفاده می‌کنند: from.address (آدرس)، from.domain (دامین) و from.tld (پسوند دامین).
    • عملگرها: عملگرهای پشتیبانی شده شامل is (است)، is_not (نیست)، contains (شامل می‌شود) و in_list (در لیست است) می‌باشد.
    • مثال (Stripe): قانونی با شرط from.domain,is,stripe.com و اکشن assign_to_folder=<BILLING_FOLDER_ID> تضمین می‌کند که ایمیل‌های پردازشگر پرداخت به‌طور خودکار مسیریابی شوند.
    • پیاده‌سازی CLI: دستور nylas agent rule create --name "Stripe to billing" --trigger inbound --condition from.domain,is,stripe.com --action assign_to_folder=<BILLING_FOLDER_ID>
  • گام سوم: فعال‌سازی فضای کاری. قوانین تا زمانی که به یک فضای کاری متصل نشوند، غیرفعال می‌مانند. یک درخواست PATCH به /v3/workspaces/<WORKSPACE_ID> با یک آرایه کامل از rule_ids فعال‌ساز این فرآیند طبقه‌بندی است.

    • CLI: دستور nylas workspace update <WORKSPACE_ID> --rules-ids <BILLING_RULE_ID>,<SECURITY_RULE_ID>,<SALES_RULE_ID>
    • API: استفاده از PATCH به https://api.us.nylas.com/v3/workspaces/<WORKSPACE_ID>.
      از آنجایی که آرایه rule_ids یک جایگزینی کامل است و نه یک افزودن (Append)، حذف یک ID باعث قطع شدن بی‌صدای آن قانون می‌شود. پس از فعال‌سازی، هر حساب عامل در آن فضای کاری، قوانین را هنگام دریافت پیام ارزیابی می‌کند.

در مورد مکانیسم منطقی، قوانین بر اساس اولویت (Priority) ارزیابی می‌شوند و کمترین عدد ابتدا اجرا می‌شود. محدوده اولویت بین ۰ تا ۱۰۰۰ است و مقدار پیش‌فرض ۱۰ است. قوانین تخصصی (مثل is یا in_list با یک لیست محدود) باید قبل از قوانین کلی (مثل contains) قرار گیرند تا تطبیق دقیق برنده شود. اگرچه اولین اکشنِ بلوک‌کننده پایان‌دهنده است، اما assign_to_folder پایان‌دهنده نیست؛ اگر دو قانون پوشه تطبیق یابند، اولویت تعیین می‌کند که کدام پوشه پیروز شود.

به عنوان مثال، مسیریابی from.domain is stripe.com به پوشه billing، قطعی، قابل حساب‌رسی و رایگان است. این یک تصمیم تخمینی نیست؛ یا تطبیق می‌یابد یا نمی‌یابد. برای موارد پیچیده‌تر، یک قانون می‌تواند چندین شرط را با استفاده از عملگر تطبیق any (یا) ترکیب کند. یک قانون امنیتی می‌تواند هر آدرسی که شامل abuse@ باشد یا هر دامین ارسالی از hackerone.com را از طریق ساختار API زیر شناسایی کند:

{
  "name": "Security reports to security folder",
  "trigger": "inbound",
  "match": {
    "operator": "any",
    "conditions": [
      { "field": "from.address", "operator": "contains", "value": "abuse@" },
      { "field": "from.domain", "operator": "contains", "value": "hackerone.com" }
    ]
  },
  "actions": [
    { "type": "assign_to_folder", "value": "<SECURITY_FOLDER_ID>" }
  ]
}

اگر لیست تامین‌کنندگان (Vendors) زیاد تغییر کند — مثلاً لیستی در حال چرخش از دامین‌هایی که همگی باید به بخش صورت‌حساب بروند — استفاده از عملگر in_list به افراد غیرمهندس اجازه می‌دهد بدون دست زدن به تعریف قوانین، لیست را به‌روزرسانی کنند. این کار خط لوله مهندسی را پاکیزه نگه داشته و پیکربندی را به لایه داده (Data Plane) منتقل می‌کند.

اما برای محتواهای مبهم (Fuzzy Content) که قوانین سرور نمی‌توانند آن‌ها را بخوانند (زیرا قوانین سروری نمی‌توانند خط موضوع یا بدنه پیام را بخوانند و فیلدهای گیرنده و outbound.type فقط برای قوانین خروجی هستند)، Nylas مسیر ثانویه‌ای را برای مسیریابی مبتنی بر محتوا ارائه می‌دهد. یک قانون نمی‌تواند تشخیص دهد که آیا در موضوع ایمیل کلمه "INVOICE" آمده است یا اینکه مشتری عصبانی به نظر می‌رسد. این همان «مسیر محتوا» در گام چهارم است.

وقتی پیامی نیاز به خوانش در سطح انسانی دارد، اپلیکیشن از یک وب‌هوک message.created استفاده می‌کند. جریان کار به این صورت است:

۱. اپلیکیشن وب‌هوک را دریافت کرده و پیام کامل را از طریق GET /v3/grants/{grant_id}/messages/{message_id} واکشی می‌کند. این کار ضروری است زیرا اگر پیام بزرگ باشد، رویداد به صورت message.created.truncated ارسال می‌شود و بدنه را در خط را دریافت نمی‌کنید. برای دیدن قابل‌اعتمادِ موضوع، لیست پوشه‌ها یا بدنه، باید پیام را واکشی کنید.
۲. کارگر (Worker) پیام را با استفاده از Regex، بررسی کلمات کلیدی یا فراخوان LLM برای موارد واقعاً مبهم، طبقه‌بندی می‌کند. این رویکرد به جای اتکا به سیستم‌های RAG پیچیده، بر داده‌های مستقیم تکیه می‌کند؛ مشابه آنچه در استفاده از پایگاه‌های داده ساده مثل SQLite برای مقیاس‌بندی تولید محتوا می‌بینیم تا پیچیدگی‌های غیرضروری حذف شود.
۳. سپس کارگر پیام را با یک درخواست PUT برای بازنویسی آرایه پوشه‌ها به پوشه مناسب منتقل می‌کند: {"folders": ["<SECURITY_FOLDER_ID>"]}.

این فرآیند تضمین می‌کند که حتی ایمیل‌های طبقه‌بندی‌شده بر اساس محتوا نیز در یک صف بادوام و قابل‌راه‌اندازی مجدد قرار گیرند. این دو الگو به‌خوبی ترکیب می‌شوند: قوانین، ایمیل‌های بدون ابهام (مثل پردازشگرهای پرداخت یا پلتفرم‌های Bug-bounty) را پیش-مرتب‌بندی می‌کنند و طبقه‌بندی‌کننده (Classifier) موارد مبهم را جمع‌آوری می‌کند. هیچ کانال متادیتا-ی سفارشی برای تصمیمات مسیریابی وجود ندارد؛ تخصیص پوشه سیگنال اصلی است. به پوشه تکیه کنید، نه به یک کانال جانبی.

در نهایت، عامل‌های متخصص می‌توانند صف‌های خود را به دو روش تخلیه کنند:

گزینه الف — گشت‌زنی (Polling)
کارگران پیام‌ها را با فیلتر ID پوشه با استفاده از پارامتر کوئری in لیست می‌کنند (مثلاً: GET /v3/grants/<NYLAS_GRANT_ID>/messages?in=<SECURITY_FOLDER_ID>). در اینجا خودِ پوشه به عنوان صف عمل می‌کند که استدلال درباره آن را آسان کرده و در برابر ری‌استارت شدن کارگر مقاوم است.

  • پردازش: کارگران با فیلتر --unread (از طریق nylas email list <NYLAS_GRANT_ID> --folder <SECURITY_FOLDER_ID> --unread) پیام‌ها را می‌یابند و پس از پردازش، با یک درخواست PUT به اندپوینت پیام با بدنه {"unread": false}، آن‌ها را به عنوان «خوانده شده» علامت‌گذاری می‌کنند.
  • بهای تبدیل: این روش، تأخیر در زمان واقعی (Real-time latency) را فدای سادگی می‌کند. شما بر اساس بازه زمانی گشت‌زنی خود واکنش نشان می‌دهید، نه در لحظه رسیدن ایمیل. این روش نقطه شروع توصیه‌شده برای اکثر تیم‌هاست.

گزینه ب — وب‌هوک‌ها (Webhooks)
یک گیرنده در سطح اپلیکیشن، رویدادهای message.created را از طریق POST /v3/webhooks گوش می‌دهد. از آنجایی که قانون، پوشه را پیش از شلیک وب‌هوک تخصیص می‌دهد، گیرنده می‌تواند بر اساس تخصیص پوشه پیام، آن را به کارگران متخصص ارجاع دهد. این امر واکنش در لحظه را ممکن کرده و به یک گیرنده واحد مقیاس می‌یابد، هرچند باید توزیع داخلی را مدیریت کنید.

برای این مسیر، Nylas بر دو الزام حیاتی SRE تأکید می‌کند:

  • حذف تکراری‌ها (Deduplication): نایلز تحویل «حداقل یک‌بار» (تا سه بار) را تضمین می‌کند. کارگران باید پیام‌ها را بر اساس ID اعلان سطح بالا (Top-level notification ID) حذف تکراری کنند. همچنین باید در برابر data.object.id داخلی نیز محافظت کنند تا از واکنش دوبار به یک ایمیل جلوگیری شود.
  • امنیت: هدر X-Nylas-Signature (یک HMAC-SHA256 هگزا از بدنه خام) را با یک بررسی زمان-ثابت (Constant-time check) مانند crypto.timingSafeEqual تأیید کنید. ابتدا مطمئن شوید هر دو بافر طول یکسانی دارند، زیرا این تابع در صورت عدم تطبیق طول، خطا می‌دهد. برای تست‌های محلی از nylas webhook verify در CLI استفاده کنید.

تحلیل معماری

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

از منظر DevOps، این جداسازی به این معناست که عامل فروش می‌تواند در طول یک پیک حجمی به‌طور افقی مقیاس‌بندی شود بدون اینکه بر SLA عامل امنیتی تأثیر بگذارد. همچنین خرابی‌ها را ایزوله می‌کند؛ کرش کردن کارگر صورت‌حساب مانع از پردازش گزارش‌های حیاتی سوءاستفاده توسط کارگر امنیتی نمی‌شود. هر متخصص، پروسه مستقل خود است، به این معنی که می‌توانید عامل فروش را بدون دست زدن به بخش صورت‌حساب ری‌استارت کنید. این دقیقاً نقطه مقابل رویکرد «عامل غول‌پیکر» است که در آن هر پیام مالیات طبقه‌بندی می‌پردازد و هر به‌روزرسانی منطقی، کل سیستم را به ریسک می‌اندازد.

آخرین حفاظ، حساب‌رسی (Auditing) است. اگر پیامی در جای اشتباهی فرود آمد، GET /v3/grants/{grant_id}/rule-evaluations لیستی از تمام ارزیابی‌ها را از جدیدترین به قدیمی‌ترین نمایش می‌دهد و رکورد دقیقی از اینکه کدام قانون تطبیق یافته و کدام اکشن اعمال شده فراهم می‌کند. این کار نیاز به جست‌وجوی دشوار در لاگ‌ها برای پاسخ به سؤال «این پیام کجا رفت؟» را از بین می‌برد.

بهای این تحول، افزایش اندک در پیچیدگی تنظیمات اولیه است و انتقال از یک پرامپت واحد به مجموعه‌ای مدیریت‌شده از قوانین و پوشه‌ها. با این حال، نتیجه سیستمی است که تست آن آسان‌تر است، به‌طور مستقل مقیاس می‌یابد و شکنندگی مسیریابی‌های مبتنی بر LLM را برای داده‌های قطعی حذف می‌کند.

گام بعدی شما

  • اگر از عامل‌های جامع برای مدیریت ایمیل استفاده می‌کنید، لیست دامین‌های تکرارشونده خود را استخراج کنید تا آن‌ها را به قوانین قطعی (Deterministic Rules) تبدیل کرده و هزینه استنتاج را کاهش دهید.
  • ساختار پوشه‌بندی را در لایه زیرساخت پیاده‌سازی کنید تا بتوانید هر عامل متخصص را به‌طور مستقل در محیط Staging تست کنید.
  • برای پیام‌های حساس، سیستم تایید امضای وب‌هوک را با crypto.timingSafeEqual پیاده کنید تا از صحت منشا پیام‌ها مطمئن شوید.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell و بهینه‌سازی استنتاج در لبه مراجعه کنید.

چرا این موضوع مهم است؟

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

تأثیر برای ایران

به‌دلیل محدودیت‌های API و نیاز به حساب‌های ثبت‌شده در دامین‌های خارجی، پیاده‌سازی مستقیم این معماری برای توسعه‌دهندگان ایرانی دشوار است؛ اما منطق «توزیع بادبزنی» را می‌توان در زیرساخت‌های داخلی با ابزارهای متن‌باز جایگزین کرد.

·نگاه ما
تحریریه دات‌هوش

انتقال منطق طبقه‌بندی از لایه پرامپت به لایه داده، در واقع پذیرش این واقعیت است که مدل‌های زبانی برای کارهای ساده‌ی مسیریابی بیش از حد پیچیده و گران هستند. این رویکرد «تخصص‌گرایی زیرساختی» احتمالاً به استانداردی تبدیل خواهد شد که در آن LLM فقط برای تصمیمات سخت به کار می‌رود و بقیه مسیر توسط قوانین سخت (Hard Rules) مدیریت می‌شود تا قابلیت پیش‌بینی سیستم بالا برود.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.