به عامل هوش مصنوعی، ابزار محدود بدهید، نه کلید اصلی

دادن کلید API اصلی حساب پیام‌رسان به یک عامل هوش مصنوعی یعنی دادن اختیار ارسال به هر کسی، در هر چت، بدون بازبینی. راهکار یونیوم برای عامل‌ها یک سرور MCP با ابزارهای مشخص (send_message، get_chat_history، get_me) است که عامل فقط همان‌ها را می‌بیند، scope هر کلید محدود است و قبل از هر ارسال واقعی، یک انسان پاسخ را تأیید می‌کند.

۳ ابزار MCP PAT محدود به scope ۱ بازبینی انسانی ۱ لاگ tool call
کلید scopedPAT فقط با ابزارهای مجاز
ابزار MCPsend_message, get_chat_history, get_me
لاگ کاملهر tool call با ورودی و خروجی ثبت می‌شود
بازبینی انسانیهیچ ارسالی بدون تأیید قبلی انجام نمی‌شود

چرا دادن API key مستقیم به عامل خطرناک است

فرض کنید به Claude یا Cursor می‌گویید «پاسخ مشتری‌های ناراضی را بخوان و جواب بده». اگر همان کلید API اصلی حساب را به عامل بدهید، عامل می‌تواند به هر چت پیام بفرستد، روی هر حساب دسترسی بنویسد و در صورت توهم (hallucination) یک شناسه اشتباه را هدف بگیرد. هیچ رد روشنی از اینکه چه دستوری اجرا شده باقی نمی‌ماند، چون درخواست‌ها مستقیم از کلاینت عامل می‌آیند. این الگو برای یک demo خوب است، برای داده واقعی مشتری فاجعه.

مکانیزم یونیوم: عامل هرگز کلید اصلی شما را نمی‌بیند. فقط یک PAT با scope محدود می‌گیرد و فقط ابزارهایی که در آن scope هست فراخوانی می‌کند. پشت صحنه یونیوم همان درخواست را با حسابی که شما اجازه داده‌اید اجرا می‌کند و همه‌چیز را در لاگ ثبت می‌کند.

  • عامل یک شناسه چت را توهم می‌زند → ابزار قبل از ارسال، موجود بودن chat_id را اعتبارسنجی می‌کند.
  • عامل می‌خواهد به حسابی که مجاز نیست پیام بدهد → scope کلید جلوی فراخوانی را می‌گیرد.
  • بعد از یک هفته نمی‌دانید عامل چه کرده → لاگ tool callها ورودی، خروجی و نتیجه API را نگه می‌دارد.
  • کلید لو رفت → فقط همان PAT را revoke می‌کنید؛ حساب اصلی سر جایش می‌ماند.

از پرامپت عامل تا پیام ارسال‌شده، در چهار گام

این دقیقاً مسیری است که یک درخواست عامل طی می‌کند: از لحظه‌ای که عامل تصمیم می‌گیرد ابزاری را صدا بزند تا پیام واقعی روی پیام‌رسان می‌نشیند.

عامل ابزار را با پارامتر صدا می‌زند

عامل تصمیم می‌گیرد send_message را فراخوانی کند. کلاینت MCP درخواست را با بدنه JSON (شامل chat_id و text) به نشانی https://mcp.uniom.ir/mcp می‌فرستد. فقط ابزارهای داخل scopeِ PAT قابل دیدن و فراخوانی هستند.

اعتبارسنجی و بررسی مجوز

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

بازبینی انسانی (Human-in-the-loop)

برای عملیات نوشتن، پاسخ پیشنهادی عامل به‌صورت پیش‌نویس به یک انسان نشان داده می‌شود. تا تأیید نگردد، send واقعی اجرا نمی‌شود. برای عملیات خواندن این گام اختیاری است، اما برای ارسال پیام به مشتری واقعی باید روشن باشد.

اجرای روی حساب و ثبت لاگ

پس از تأیید، یونیوم درخواست را با حساب مجاز به پیام‌رسان (ایتا، بله، تلگرام و …) می‌فرستد. نتیجه API، شناسه پیام (مثلاً message_id: 283114)، شناسه درخواست و وضعیت (sent / failed) هم به عامل برمی‌گردد و هم در لاگ بازبینی ثبت می‌شود.

هر عامل فقط همان ابزارهایی را می‌بیند که واقعاً نیاز دارد

طراحی MCP یونیوم بر اساس کمترین دسترسی (least privilege) است. یک عامل خلاصه‌ساز فقط get_chat_history و get_me می‌گیرد؛ یک عامل پاسخگو send_message هم می‌گیرد اما پشت بازبینی انسانی. هیچ عاملی به ابزار مدیریت حساب یا revoke کلید نمی‌رسد مگر اینکه صریحاً scope گرفته باشد.

ابزارهای فقط‌خواندنی

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

send_message با بازبینی

عامل متن پیشنهادی را آماده می‌کند؛ ارسال واقعی پشت تأیید انسانی یا یک قاعده از پیش تعریف‌شده اجرا می‌شود. متن و مقصد پیش از رسیدن به پیام‌رسان اعتبارسنجی می‌شوند.

scope در سطح ابزار و حساب

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

لاگ کامل اقدامات عامل

هر tool call با ورودی JSON، خروجی API، status code و زمان ثبت می‌شود. برای بازبینی امنیتی و پاسخ به «عامل آخرین بار چه کرد؟» کافی است.

اعتبارسنجی dry-run

قبل از ارسال واقعی، chat_id و موجود بودن چت بررسی می‌شود. اگر عامل شناسه‌ای را توهم زده باشد، فراخوانی در همین‌جا رد می‌شود و به پیام‌رسان نمی‌رسد.

قطع دسترسی آنی

revoke یک PAT فوری است. بدون اینکه جلسه‌های دیگر حساب یا کلیدهای دیگری که برای کارهای دیگر ساخته‌اید تحت تأثیر قرار گیرند.

چه کار نکنیم: پنج اشتباهی که عامل را خطرناک می‌کند

بیشتر حوادث عامل‌ها از همین پنج الگو ناشی می‌شوند. هیچ‌کدام نقص مدل نیست — نقص طراحی دسترسی است.

۱. دادن کلید اصلی به عامل

به جای PAT scoped، کلید کامل API به کلاینت داده می‌شود. اولین بار که عامل توهم می‌زند یا کلاینت لو می‌رود، کل حساب در معرض است. همیشه PAT جدا بسازید.

۲. بازبینی انسانی را خاموش گذاشتن

برای دمو سریع‌تر است، اما اولین ارسال خودکار به مشتری اشتباه همان چیزی است که اعتماد را از بین می‌برد. برای هر عملیات نوشتن روی داده واقعی، تأیید انسان را روشن کنید.

۳. اعتماد به chat_id عامل

عامل‌ها شناسه‌ها را توهم می‌زنند. بدون اعتبارسنجی dry-run، ممکن است پیام به چت اشتباه یا ناموجود برود. همیشه chat_id را قبل از ارسال بررسی کنید.

۴. لاگ‌نگاری نکردن tool callها

اگر لاگ ندارید، نمی‌توانید بپرسید «عامل چه کرد؟». در یک حادثه، نداشتن ردِ اقدامات عامل یعنی ناتوانی در پاسخ به مشتری یا auditور.

۵. scope خیلی باز

یک PAT با همه scopeها برای همه حساب‌ها، در عمل مثل کلید اصلی است. scope را تا حد یک ابزار و یک حساب محدود کنید؛ اگر لازم شد، چند PAT بسازید.

یک فراخوانی واقعی send_message از داخل عامل

این شکل دقیق چیزی است که کلاینت MCP به یونیوم می‌فرستد. عامل این بدنه را می‌سازد؛ یونیوم scope و پارامترها را بررسی می‌کند، در صورت نیاز منتظر تأیید انسان می‌ماند و سپس روی حساب مقصد اجرا می‌کند.

درخواست از سمت عامل

کلاینت MCP با Authorization: Bearer pat_… این بدنه را می‌فرستد:

tool: send_message
{
  "chat_id": 44752012,
  "text": "سفارش شما تا ۱۸:۰۰ ارسال می‌شود"
}

پاسخ موفق

پس از تأیید انسان و اجرا روی حساب، عامل این را می‌بیند و می‌فهمد ارسال واقعی شده:

{
  "ok": true,
  "result": { "message_id": 283114,
    "status": "sent" }
}

رد شدن به‌خاطر توهم

اگر chat_id وجود نداشته باشد یا خارج لیست مجاز باشد، ارسال اصلاً به پیام‌رسان نمی‌رسد:

{
  "ok": false,
  "error": "chat_id not allowed
    in this scope"
}

آدرس اتصال MCP که به کلاینت عامل می‌دهید ثابت است: https://mcp.uniom.ir/mcp. تنظیم کامل Cursor، Claude Code و Codex در راهنمای شروع سریع آمده.

انتخاب پلتفرم بر اساس قابلیت و محدودیت

این قابلیت‌ها روی همه credentialها معنی یکسان ندارد. مثلاً get_chat_history روی حساب کاربری ایتا یا روبیکا به یاد داشتن تاریخچه وابسته است، در حالی که روی بات رسمی بله خیر. انتخاب پلتفرم را با این تفاوت‌ها انجام دهید.

  • بات رسمی (BotFather / بازو): scope تمیز، کنترل دقیق و لاگ قابل اتکا. گزینه مناسب عامل‌های پاسخگو که با کاربر ناشناس صحبت می‌کنند.
  • حساب کاربری (Account API): برای خواندن تاریخچه چت‌های شخصی یا کانال‌ها روی ایتا، روبیکا و سروش‌پلاس؛ ولی باید بدانید get_chat_history به وضعیت سشن وابسته است و گاهی INVALID_AUTH می‌گیرد.
  • بله: هم بات رسمی دارد هم حساب کاربری — برای عامل‌های پرداختی و خدمات‌محور انتخاب منطقی است چون درگاه پرداخت بومی دارد.

چک‌لیست ساخت یک عامل امن روی یونیوم

به ترتیب از بالا به پایین پیش بروید. هر قدم یک تصمیم دسترسی است، نه یک تنظیم نشان‌دار.

۱. حساب مجاز را مشخص کنید

یک حساب جدا برای عامل وصل کنید — نه حساب شخصی خودتان. این حساب همان چیزی است که پیام‌ها از آن می‌رود.

۲. PAT با حداقل scope بسازید

فقط ابزارهای لازم را در scope بگذارید (مثلاً فقط get_me و get_chat_history برای عامل خواننده). برای ارسال، send_message را جدا اضافه کنید.

۳. MCP را به کلاینت وصل کنید

نشانی https://mcp.uniom.ir/mcp و PAT را در Cursor / Claude Code / Codex ثبت کنید. دستورالعمل کامل در راهنمای شروع سریع است.

۴. ابتدا فقط خواندن تست کنید

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

۵. بازبینی انسانی را اجباری کنید

برای هر عملیات نوشتن روی داده واقعی مشتری، تأیید انسان را روشن بگذارید. این بزرگ‌ترین ضامن امنیت در برابر توهم عامل است.

۶. لاگ را فعال نگه دارید

مطمئن شوید tool callها با ورودی و خروجی ثبت می‌شوند. هفته‌ای یک‌بار چند فراخوانی آخر را بازبینی کنید تا الگوی رفتار عامل را بشناسید.

وقتی عامل اشتباه می‌کند، یونیوم کجا نگه‌اش می‌دارد

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

توهم شناسه چت

عامل یک chat_id را از متن پرامپت استخراج یا ساخته است. اعتبارسنجی dry-run درست قبل از ارسال، آن را رد می‌کند و خطای «chat_id not allowed in this scope» برمی‌گرداند — بدون ارسال واقعی.

سطح دسترسی بیش از حد

عامل سعی می‌کند به حسابی که مجاز نیست دسترسی پیدا کند. scope توکن این فراخوانی را قبل از رسیدن به پلتفرم رد می‌کند. این یعنی حتی یک عامل سرکش هم به محدوده خودش محدود است.

قطعی پلتفرم یا INVALID_AUTH

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

عامل‌هایی که با MCP به پیام‌رسان وصل می‌شوند

یونیوم با MCP server به عامل‌های هوشمند اجازه می‌دهد پیام بفرستند و رویدادها را بخوانند؛ هر اقدام با کلید محدود (PAT) و در لاگ ثبت می‌شود.

Claude Desktop

با PAT محدود، عامل پیام‌رسان‌های ایرانی را همان‌طور می‌بیند که ابزارهای دیگر را؛ ارسال انبوه با scope کنترل می‌شود.

Cursor

ایده‌ها را در محیط توسعه مستقیم از IDE به پیام آزمایشی تبدیل کنید؛ sendMessage درون‌خطی روی کانال تست.

n8n

نود MCP یا درخواست HTTP در n8n به به‌هوک یونیوم وصل می‌شود و گردش‌کارهای پیام‌رسان را بدون کد می‌سازد.

LangChain و چارچوب‌ها

کلاینت‌های MCP استاندارد با نقطه‌ی اتصال یونیوم کار می‌کنند؛ قالب متد همان Telegram Bot API است.

هر عامل را با PAT جدا و scope فقط‌ارسال شروع کنید؛ سپس به‌تدریج ابزارهای دریافت را باز کنید. لاگ هر فراخوانی را برای حسابرسی نگه دارید.

اولین عامل امن خود را در یک بعدازظهر بسازید

یک حساب آزمایشی، یک PAT فقط‌خواندنی و نشانی MCP. همین برای اینکه ببینید عامل چه می‌بیند و چطور بازبینی می‌شود — بدون ریسک روی داده واقعی مشتری.

شروع سریع MCP