Mainstream messaging
وضعیت: آماده برای استفاده در محیط تولید از طریق WhatsApp Web (Baileys). Gateway مالک نشست(های) پیوندشده است؛ کانال WhatsApp جداگانهای برای Twilio وجود ندارد.
نصب
openclaw onboard و openclaw channels add --channel whatsapp نخستین باری که آن را انتخاب میکنید، نصب Plugin را پیشنهاد میدهند؛ اگر Plugin موجود نباشد، openclaw channels login --channel whatsapp همان جریان نصب را ارائه میکند. نسخههای توسعه از مسیر Plugin محلی استفاده میکنند؛ نصبهای پایدار/بتا ابتدا @openclaw/whatsapp را از ClawHub نصب میکنند و در صورت شکست به npm برمیگردند. زماناجرای WhatsApp خارج از بسته اصلی npm OpenClaw عرضه میشود، بنابراین وابستگیهای زماناجرای آن همراه Plugin خارجی باقی میمانند. نصب دستی:
openclaw plugins install clawhub:@openclaw/whatsappاز بسته ساده npm (@openclaw/whatsapp) فقط برای مسیر جایگزین رجیستری استفاده کنید؛ تنها برای نصب تکرارپذیر، یک نسخه دقیق را پین کنید.
سیاست پیشفرض پیام مستقیم برای فرستندگان ناشناس، جفتسازی است.
راهنماهای تشخیص و تعمیر میانکانالی.
الگوها و نمونههای کامل پیکربندی کانال.
راهاندازی سریع
پیکربندی سیاست دسترسی
{channels: {whatsapp: { dmPolicy: "pairing", allowFrom: ["+15551234567"], groupPolicy: "allowlist", groupAllowFrom: ["+15551234567"],},},}پیوند WhatsApp (QR)
openclaw channels login --channel whatsappورود فقط از طریق QR انجام میشود. در میزبانهای راهدور یا بدون رابط گرافیکی، پیش از آغاز ورود، روشی مطمئن برای رساندن QR زنده به تلفن فراهم کنید؛ QRهای نمایشدادهشده در ترمینال، نماگرفتها یا پیوستهای گفتوگو ممکن است هنگام انتقال منقضی شوند.
برای یک حساب مشخص:
openclaw channels login --channel whatsapp --account workبرای متصلکردن یک پوشه احراز هویت موجود/سفارشی پیش از ورود:
openclaw channels add --channel whatsapp --account work --auth-dir /path/to/wa-authopenclaw channels login --channel whatsapp --account workراهاندازی Gateway
openclaw gatewayتأیید نخستین درخواست دسترسی پیام مستقیم (حالت جفتسازی)
Settings → Channels → DM access requests را باز کنید، حساب WhatsApp را بیابید و فرستنده را تأیید کنید. اگر CLI را ترجیح میدهید:
openclaw pairing list whatsappopenclaw pairing approve whatsapp <CODE>درخواستهای دسترسی پیام مستقیم پس از 1 ساعت منقضی میشوند؛ تعداد درخواستهای در انتظار برای هر حساب حداکثر 3 است. این تأیید با QR ورود WhatsApp که برای پیوند خود حساب استفاده میشود، تفاوت دارد.
الگوهای استقرار
شماره اختصاصی (توصیهشده)
- هویت WhatsApp جداگانه برای OpenClaw
- فهرستهای مجاز پیام مستقیم و مرزهای مسیریابی شفافتر
- احتمال کمتر سردرگمی در گفتوگو با خود
{ channels: { whatsapp: { dmPolicy: "allowlist", allowFrom: ["+15551234567"], }, },}مسیر جایگزین شماره شخصی
فرایند راهاندازی از حالت شماره شخصی پشتیبانی میکند و یک خطمبنای مناسب برای گفتوگو با خود مینویسد: dmPolicy: "allowlist"، allowFrom شامل شماره خودتان، selfChatMode: true. محافظتهای زماناجرا برای گفتوگو با خود بر اساس شماره خودِ پیوندشده بهعلاوه allowFrom عمل میکنند.
مدل زماناجرا
- Gateway مالک سوکت WhatsApp و حلقه اتصال مجدد است.
- یک ناظر، دو سیگنال را مستقل از هم ردیابی میکند: فعالیت خام انتقال WhatsApp Web و فعالیت پیامهای برنامه. نشستی که ساکت اما متصل است، صرفاً بهدلیل نرسیدن پیام در زمان اخیر دوباره راهاندازی نمیشود؛ اتصال مجدد فقط زمانی اجباری میشود که فریمهای انتقال برای یک بازه داخلی ثابت (غیرقابلپیکربندی توسط کاربر) متوقف شوند یا پیامهای برنامه برای مدتی بیش از 4 برابر مهلت عادی پیام ساکت بمانند. بلافاصله پس از اتصال مجدد یک نشست که اخیراً فعال بوده است، آن بازه نخست بهجای بازه 4 برابری از مهلت عادی و کوتاهتر پیام استفاده میکند. OpenClaw میتواند به پیامهای آفلاینی که Baileys در ابتدای آن اتصال مجدد تحویل میدهد، بهطور خودکار پاسخ دهد؛ این رفتار به طولعمر حذف موارد تکراری شناسه پیام ورودی محدود است. راهاندازی اولیه محافظ کوتاه در برابر تاریخچه قدیمی را حفظ میکند.
- ارسالهای خروجی به شنونده فعال WhatsApp برای حساب مقصد نیاز دارند؛ در غیر این صورت، ارسال بیدرنگ شکست میخورد.
- ارسالهای گروهی، هنگامی که توکن با فراداده فعلی شرکتکننده مطابقت داشته باشد، فراداده بومی اشاره را برای توکنهای
@+<digits>و@<digits>(در متن و شرح رسانه) پیوست میکنند؛ این شامل گروههای مبتنی بر LID نیز میشود. - گفتوگوهای وضعیت و پخش همگانی (
@status، @broadcast) نادیده گرفته میشوند. - گفتوگوهای مستقیم از قواعد نشست پیام مستقیم استفاده میکنند (
session.dmScope؛ مقدار پیشفرضmainپیامهای مستقیم را در نشست اصلی عامل ادغام میکند). نشستهای گروهی برای هر JID جدا میشوند (agent:<agentId>:whatsapp:group:<jid>). - کانالها/خبرنامههای WhatsApp میتوانند از طریق JID بومی
@newsletterخود، مقصد صریح خروجی باشند و بهجای معنای پیام مستقیم از فراداده نشست کانال (agent:<agentId>:whatsapp:channel:<jid>) استفاده کنند. - انتقال WhatsApp Web از متغیرهای محیطی استاندارد پراکسی در میزبان Gateway (
HTTPS_PROXY، HTTP_PROXY، NO_PROXYو گونههای حروف کوچک) پیروی میکند. پیکربندی پراکسی در سطح میزبان را به تنظیمات هر کانال ترجیح دهید.
تماس با درخواستکننده فعلی با MeowCaller (آزمایشی)
Plugin میتواند whatsapp_call را در نوبتهای عامل که از WhatsApp آغاز شدهاند، ارائه کند. این قابلیت از MeowCaller برای برقراری تماس صوتی WhatsApp با درخواستکننده مجاز فعلی و پخش پیام TTS OpenClaw پس از پاسخدادن او استفاده میکند. ابزار هیچ پارامتری برای شماره مقصد ندارد، بنابراین یک پرامپت نمیتواند تماس را تغییر مسیر دهد. بهطور پیشفرض غیرفعال است.
فعالسازی تماسهای آزمایشی
actions.calls: true را به پیکربندی کانال WhatsApp اضافه کنید و Gateway را دوباره راهاندازی کنید:
{"channels": {"whatsapp": { "actions": { "calls": true }}}}وقتی وجود نداشته باشد یا false باشد، OpenClaw ابزار whatsapp_call را ارائه نمیکند.
نصب CLI بازبینیشده MeowCaller
آداپتور انتظار دارد فایل اجرایی meowcaller در PATH میزبان Gateway موجود باشد. تا زمانی که Pull request شماره 7 MeowCaller ادغام شود، شاخه بازبینیشده را بسازید:
git clone --branch feat/send-only-notify https://github.com/steipete/meowcaller.gitcd meowcallergit checkout 752050471fc2bf7a8cdfbf7dbd3cd4e865d85d3fmkdir -p "$HOME/.local/bin"go build -o "$HOME/.local/bin/meowcaller" ./cmd/meowcallerمطمئن شوید $HOME/.local/bin در PATH سرویس Gateway قرار دارد. این بازبینی دارای فرمانهای صریح pair و notify صرفاً ارسالی است؛ notify هیچ میکروفون، بلندگو، دستگاه ویدئویی یا ضبط تشخیصی را باز نمیکند. فرمان play از CLI نمونه بالادستی را جایگزین آن نکنید.
جفتسازی دستگاه پیوندشده MeowCaller
از عامل WhatsApp بخواهید راهاندازی تماس را بررسی کند (کنش وضعیت whatsapp_call، پوشه وضعیت مختص حساب و فرمان جفتسازی را گزارش میکند). برای حساب پیشفرض:
state_dir="$HOME/.openclaw/credentials/whatsapp-calls/default"mkdir -p "$state_dir"chmod 700 "$state_dir"meowcaller pair --store "$state_dir/wa-voip.db"این فرمان را بهصورت تعاملی اجرا کنید، QR را از WhatsApp > Linked devices اسکن کنید و منتظر MeowCaller linked device ready بمانید. wa-voip.db را خصوصی نگه دارید؛ این نشست MeowCaller است. حسابهای غیراصلی مسیر ذخیرهسازی خود را از کنش وضعیت دریافت میکنند؛ در Windows، فرمان PowerShell آن را اجرا کنید.
پیکربندی TTS و تماس از WhatsApp
یک ارائهدهنده TTS با قابلیت تلفنی پیکربندی کنید، Gateway را دوباره راهاندازی کنید، سپس درخواستی مانند Call me and say the build finished. ارسال کنید. ابزار، فرستنده را از زمینه ورودی مورداعتماد تعیین میکند، یک فایل WAV خصوصی موقت میسازد، MeowCaller را برای یک بازه تماس محدود اجرا میکند و پس از آن فایل صوتی را حذف میکند. OpenClaw محل ذخیرهسازی حساب را صریحاً ارسال میکند، پس از پاسخ/پخش/قطع تماس منتظر وضعیت خروج صفر میماند و پایان مهلت یا خروج غیرصفر را فراخوانی ناموفق ابزار تلقی میکند.
محدودیتها: فقط تماسهای صوتی خروجی یکبهیک، بدون شمارههای مقصد دلخواه، بدون احراز هویت مشترک با اتصال گفتوگو، بدون تماس با خود در حالت شماره شخصی/گفتوگو با خود، صدای تولیدشده با سقف 60 ثانیه، بدون رسید شنیدهشدن در سمت گوشی فراتر از تکمیل پاسخ/پخش/قطع تماس MeowCaller، و OpenClaw فرایند همراه را پس از یک بازه محدود 115 تا 175 ثانیهای متوقف میکند (که مراحل اتصال، پاسخ، پخش و خاموششدن MeowCaller را پوشش میدهد).
پرامپتهای تأیید
WhatsApp میتواند پرامپتهای تأیید اجرا و Plugin را بهشکل واکنشهای 👍/👎 نمایش دهد که پیکربندی سطحبالای هدایت تأیید آنها را کنترل میکند:
{ approvals: { exec: { enabled: true, mode: "session", }, plugin: { enabled: true, mode: "targets", targets: [{ channel: "whatsapp", to: "+15551234567" }], }, },}approvals.exec و approvals.plugin مستقل هستند؛ فعالسازی WhatsApp بهعنوان کانال فقط انتقال را پیوند میدهد و تا زمانی که خانواده تأیید متناظر فعال و به آنجا مسیریابی نشده باشد، چیزی ارسال نمیکند. حالت نشست، تأییدهای بومی ایموجی را فقط برای تأییدهایی تحویل میدهد که از WhatsApp منشأ میگیرند. حالت مقصد از پایپلاین هدایت مشترک برای مقصدهای صریح استفاده میکند و توزیع جداگانه پیام مستقیم برای تأییدکنندگان ایجاد نمیکند.
واکنشهای تأیید WhatsApp به تأییدکنندگان صریح در allowFrom (یا "*") نیاز دارند. defaultTo مقصدهای عادی و پیشفرض پیام را تنظیم میکند، نه فهرست تأییدکنندگان را. فرمانهای دستی /approve همچنان پیش از رسیدگی به تأیید، از مسیر عادی مجوزدهی فرستنده WhatsApp عبور میکنند.
واکنشهای پرسش
برای یک پرامپت ask_user با یک پرسش غیرمحرمانه تکانتخابی و یک تا چهار گزینه، WhatsApp 1️⃣ تا 4️⃣ را کنار برچسب گزینهها نشان میدهد. برای پاسخدادن، با شماره متناظر به پرامپت تحویلشده واکنش نشان دهید. OpenClaw از طریق Gateway شماره را به گزینه معیار نگاشت میکند؛ ضربههای قدیمی یا تکراری نادیده گرفته میشوند. پرامپتهای چندپرسشی، چندانتخابی و متنآزاد همچنان فقط با پاسخ متنی کار میکنند. قواعد عادی پذیرش پیام مستقیم/گروهی WhatsApp به فرستنده واکنشدهنده مجوز میدهند.
هوکهای Plugin و حریم خصوصی
پیامهای ورودی WhatsApp میتوانند شامل محتوای شخصی، شماره تلفن، شناسه گروه، نام فرستنده و فیلدهای همبستگی نشست باشند. WhatsApp محمولههای ورودی هوک message_received را برای Pluginها پخش نمیکند، مگر اینکه آن را فعال کنید:
{ channels: { whatsapp: { pluginHooks: { messageReceived: true, }, }, },}فعالسازی را در channels.whatsapp.accounts.<id>.pluginHooks.messageReceived به یک حساب محدود کنید. این گزینه را فقط برای Pluginهایی فعال کنید که برای دسترسی به محتوای ورودی و شناسههای WhatsApp به آنها اعتماد دارید.
کنترل دسترسی و فعالسازی
سیاست پیام مستقیم
channels.whatsapp.dmPolicy:
| مقدار | رفتار |
|---|---|
pairing (پیشفرض) |
فرستندگان ناشناس درخواست جفتسازی میدهند؛ مالک تأیید میکند |
allowlist |
فقط فرستندگان allowFrom پذیرفته میشوند |
open |
لازم است allowFrom شامل "*" باشد |
disabled |
مسدودکردن همه پیامهای مستقیم |
allowFrom شمارههای به سبک E.164 را میپذیرد (که بهصورت داخلی نرمالسازی میشوند). این فقط فهرست کنترل دسترسی فرستندگان پیام خصوصی است — ارسالهای خروجی صریح به JIDهای گروه یا JIDهای کانال @newsletter را محدود نمیکند.
بازنویسی چندحسابی: channels.whatsapp.accounts.<id>.dmPolicy (و .allowFrom) برای آن حساب بر پیشفرضهای سطح کانال اولویت دارند.
نکات زمان اجرا:
- جفتسازیها در مخزن مجاز کانال ماندگار میشوند و با
allowFromپیکربندیشده ادغام میشوند - اتوماسیون زمانبندیشده و مقصد جایگزین گیرنده Heartbeat از اهداف تحویل صریح یا
allowFromپیکربندیشده استفاده میکنند؛ تأییدهای جفتسازی پیام خصوصی بهطور ضمنی گیرنده cron/Heartbeat نیستند - اگر هیچ فهرست مجازی پیکربندی نشده باشد، شماره خودِ پیوندشده بهطور پیشفرض مجاز است
- OpenClaw هرگز پیامهای خصوصی خروجی
fromMeرا بهطور خودکار جفت نمیکند (پیامهایی که از دستگاه پیوندشده برای خودتان میفرستید)
سیاست گروه و فهرستهای مجاز
دسترسی گروه دو لایه دارد:
- فهرست مجاز عضویت گروه (
channels.whatsapp.groups): اگرgroupsحذف شده باشد، همه گروهها واجد شرایطاند؛ اگر وجود داشته باشد، بهعنوان فهرست مجاز گروه عمل میکند ("*"همه را میپذیرد). - سیاست فرستنده گروه (
channels.whatsapp.groupPolicy+groupAllowFrom):openفهرست مجاز فرستنده را دور میزند،allowlistبه تطبیق باgroupAllowFrom(یا*) نیاز دارد، وdisabledهمه ورودیهای گروه را مسدود میکند.
اگر groupAllowFrom تنظیم نشده باشد، بررسیهای فرستنده در صورت داشتن ورودی به allowFrom بازمیگردند. فهرستهای مجاز فرستنده پیش از فعالسازی با اشاره/پاسخ ارزیابی میشوند.
اگر هیچ بلوک channels.whatsapp وجود نداشته باشد، زمان اجرا به groupPolicy: "allowlist" بازمیگردد (همراه با ثبت هشدار)، حتی اگر channels.defaults.groupPolicy روی مقدار دیگری تنظیم شده باشد.
اشارهها و /activation
پاسخهای گروه بهطور پیشفرض به اشاره نیاز دارند. تشخیص اشاره شامل موارد زیر است:
- اشارههای صریح WhatsApp به هویت بات
- الگوهای عبارت منظم اشاره پیکربندیشده (
agents.entries.*.groupChat.mentionPatterns، با بازگشت بهmessages.groupChat.mentionPatterns) - رونوشت یادداشتهای صوتی ورودی برای پیامهای گروهی مجاز
- تشخیص ضمنی پاسخ به بات (فرستنده پاسخ با هویت بات تطبیق دارد)
امنیت: نقلقول/پاسخ فقط شرط اشاره را برآورده میکند — و مجوز فرستنده را اعطا نمیکند. با groupPolicy: "allowlist"، فرستندگان خارج از فهرست مجاز حتی هنگام پاسخ به پیام کاربری مجاز، مسدود میمانند.
فرمان فعالسازی در سطح نشست: /activation mention یا /activation always. این فرمان وضعیت نشست را بهروزرسانی میکند (نه پیکربندی سراسری) و به مالک محدود است.
اتصالهای ACP پیکربندیشده
WhatsApp از اتصالهای ماندگار ACP از طریق bindings[] سطحبالا پشتیبانی میکند:
{ bindings: [ { type: "acp", agentId: "codex", match: { channel: "whatsapp", accountId: "work", peer: { kind: "direct", id: "+15555550123" }, }, }, { type: "acp", agentId: "codex", match: { channel: "whatsapp", accountId: "work", peer: { kind: "group", id: "120363424282127706@g.us" }, }, }, ],}گفتوگوهای مستقیم با شمارههای E.164 و گروهها با JIDهای گروه WhatsApp تطبیق داده میشوند. فهرستهای مجاز گروه، سیاست فرستنده و محدودسازی اشاره/فعالسازی پیش از آن اجرا میشوند که OpenClaw از وجود نشست ACP متصل اطمینان حاصل کند. یک اتصال تطبیقیافته مالک مسیر است — گروههای پخش آن نوبت را به نشستهای عادی WhatsApp توزیع نمیکنند.
رفتار شماره شخصی و گفتوگو با خود
وقتی شماره خودِ پیوندشده در allowFrom نیز وجود داشته باشد، سازوکارهای ایمنی گفتوگو با خود فعال میشوند: رسیدهای خواندن برای نوبتهای گفتوگو با خود نادیده گرفته میشوند، رفتار راهاندازی خودکار اشاره با JID که باعث اعلان به خودتان میشود نادیده گرفته میشود، و وقتی responsePrefix کانال/حساب تنظیم نشده باشد، پاسخها بهطور پیشفرض به [{identity.name}] (یا [openclaw]) میروند.
نرمالسازی پیام و زمینه
پوش ورودی و زمینه پاسخ
پیامهای ورودی در پوش ورودی مشترک قرار میگیرند. یک پاسخ نقلقولشده، زمینه را با قالب زیر میافزاید:
[Replying to <sender> id:<stanzaId>]<quoted body or media placeholder>[/Replying]فراداده پاسخ (ReplyToId، ReplyToBody، ReplyToSender، JID/E.164 فرستنده) در صورت دسترسبودن مقداردهی میشود. اگر هدف نقلقولشده رسانهای قابلبارگیری باشد، OpenClaw آن را از طریق مخزن عادی رسانه ورودی ذخیره میکند و MediaPath/MediaType را در دسترس قرار میدهد تا عامل بتواند بهجای مشاهده صرف <media:image>، آن را مستقیماً بررسی کند.
جانگهدارهای رسانه و استخراج مکان/مخاطب
پیامهای صرفاً رسانهای به جانگهدارهای زیر نرمالسازی میشوند: <media:image>، <media:video>، <media:audio>، <media:document>، <media:sticker>.
یادداشتهای صوتی گروهی مجاز پیش از محدودسازی اشاره رونویسی میشوند، بهشرط آنکه بدنه فقط <media:audio> باشد؛ بنابراین بیان اشاره بات در یادداشت صوتی میتواند پاسخ را راهاندازی کند. اگر رونوشت همچنان اشارهای به بات نداشته باشد، بهجای جانگهدار خام در تاریخچه گروه در انتظار باقی میماند.
بدنههای مکان بهصورت متن مختصر مختصات نمایش داده میشوند. برچسبها/نظرهای مکان و جزئیات مخاطب/vCard بهصورت فراداده نامطمئن محصورشده نمایش داده میشوند، نه متن درونخطی پرامپت.
تزریق تاریخچه گروه در انتظار
پیامهای پردازشنشده گروه در بافر قرار میگیرند و زمانی که بات سرانجام راهاندازی شود، بهعنوان زمینه تزریق میشوند.
- محدودیت پیشفرض:
50 - پیکربندی:
channels.whatsapp.historyLimit، با بازگشت بهmessages.groupChat.historyLimit 0غیرفعال میکند
نشانگرهای تزریق: [Chat messages since your last reply - for context] و [Current message - respond to this].
رسیدهای خواندن
برای پیامهای ورودی پذیرفتهشده بهطور پیشفرض فعال است. غیرفعالسازی سراسری:
{ channels: { whatsapp: { sendReadReceipts: false } } }بازنویسی برای هر حساب: channels.whatsapp.accounts.<id>.sendReadReceipts. نوبتهای گفتوگو با خود، حتی هنگام فعالبودن سراسری، رسیدهای خواندن را نادیده میگیرند.
تحویل، قطعهبندی و رسانه
قطعهبندی متن
- محدودیت پیشفرض قطعه:
channels.whatsapp.textChunkLimit = 4000 channels.whatsapp.streaming.chunkMode = "length" | "newline"؛newlineمرزهای بند (خطوط خالی) را ترجیح میدهد، سپس به قطعهبندی ایمن از نظر طول بازمیگردد
رفتار رسانه خروجی
- از محمولههای تصویر، ویدئو، صدا (یادداشت صوتی PTT) و سند پشتیبانی میکند
- صدا بهصورت محموله
audioدر Baileys همراه باptt: trueارسال میشود و بهشکل یادداشت صوتی فشردنی برای صحبت پخش میشود؛audioAsVoiceدر محمولههای پاسخ حفظ میشود تا خروجی یادداشت صوتی TTS صرفنظر از قالب مبدأ ارائهدهنده در همین مسیر باقی بماند - صدای بومی Ogg/Opus بهصورت
audio/ogg; codecs=opusارسال میشود؛ هر قالب دیگر (از جمله خروجی MP3/WebM در TTS مربوط به Microsoft Edge) پیش از تحویل PTT باffmpegبه Ogg/Opus تککاناله 48 kHz تبدیل میشود /tts latestآخرین پاسخ دستیار را بهصورت یک یادداشت صوتی ارسال میکند و ارسالهای تکراری همان پاسخ را متوقف میکند؛/tts chat on|off|defaultتبدیل خودکار متن به گفتار را برای گفتوگوی جاری کنترل میکندgifPlayback: trueهنگام ارسال ویدئو، پخش GIF متحرک را فعال میکندforceDocument/asDocumentتصاویر، GIFها و ویدئوهای خروجی را از طریق محموله سند Baileys مسیریابی میکند تا از فشردهسازی رسانه WhatsApp جلوگیری شود و نام فایل و نوع MIME تفکیکشده حفظ شوند- زیرنویسها روی نخستین مورد رسانه در پاسخ چندرسانهای اعمال میشوند، بهجز یادداشتهای صوتی PTT: صدا ابتدا بدون زیرنویس ارسال میشود، سپس زیرنویس بهصورت یک پیام متنی جداگانه ارسال میشود (کلاینتهای WhatsApp زیرنویس یادداشت صوتی را بهطور یکسان نمایش نمیدهند)
- منبع رسانه میتواند HTTP(S)،
file://یا یک مسیر محلی باشد
محدودیت اندازه رسانه و رفتار بازگشت
- سقف ذخیره ورودی و سقف ارسال خروجی:
channels.whatsapp.mediaMaxMb(پیشفرض50) - بازنویسی برای هر حساب:
channels.whatsapp.accounts.<id>.mediaMaxMb - تصاویر برای قرارگرفتن در محدودیتها بهطور خودکار بهینه میشوند (تغییر اندازه/پویش کیفیت)، مگر اینکه
forceDocument/asDocumentتحویل بهصورت سند را درخواست کند - در صورت شکست ارسال رسانه، مسیر جایگزین مورد نخست بهجای حذف بیسروصدای پاسخ، یک هشدار متنی ارسال میکند
نقلقول پاسخ
channels.whatsapp.replyToMode نقلقول بومی پاسخ را کنترل میکند (پاسخهای خروجی بهطور مشهود پیام ورودی را نقلقول میکنند):
| مقدار | رفتار |
|---|---|
"off" (پیشفرض) |
هرگز نقلقول نکن؛ بهصورت پیام ساده ارسال کن |
"first" |
فقط نخستین قطعه پاسخ خروجی را نقلقول کن |
"all" |
همه قطعههای پاسخ خروجی را نقلقول کن |
"batched" |
پاسخهای دستهای صفشده را نقلقول کن؛ پاسخهای فوری را بدون نقلقول بگذار |
بازنویسی برای هر حساب: channels.whatsapp.accounts.<id>.replyToMode.
{ channels: { whatsapp: { replyToMode: "first" } } }سطح واکنش
channels.whatsapp.reactionLevel گستره استفاده عامل از واکنشهای ایموجی را کنترل میکند:
| سطح | واکنشهای تأیید | واکنشهای آغازشده توسط عامل |
|---|---|---|
"off" |
خیر | خیر |
"ack" |
بله | خیر |
"minimal" (پیشفرض) |
بله | بله، راهنمایی محافظهکارانه |
"extensive" |
بله | بله، راهنمایی تشویقشده |
بازنویسی برای هر حساب: channels.whatsapp.accounts.<id>.reactionLevel.
{ channels: { whatsapp: { reactionLevel: "ack" } } }واکنشهای تأیید دریافت
channels.whatsapp.ackReaction هنگام دریافت ورودی یک واکنش فوری ارسال میکند که با reactionLevel محدود میشود (وقتی "off" باشد متوقف میشود):
{ channels: { whatsapp: { ackReaction: { emoji: "👀", direct: true, group: "mentions", // always | mentions | never }, }, },}نکات: بلافاصله پس از پذیرش ورودی (پیش از پاسخ) ارسال میشود؛ اگر ackReaction بدون emoji وجود داشته باشد، WhatsApp از ایموجی هویت عامل مسیریابیشده استفاده میکند و در صورت نبود آن به "👀" بازمیگردد (برای نداشتن تأیید، ackReaction را حذف کنید یا emoji: "" را تنظیم کنید)؛ شکستها ثبت میشوند اما تحویل پاسخ را مسدود نمیکنند؛ حالت گروهی mentions فقط در نوبتهای راهاندازیشده با اشاره واکنش نشان میدهد، درحالیکه فعالسازی گروه always این بررسی را دور میزند؛ WhatsApp فقط از channels.whatsapp.ackReaction استفاده میکند (messages.ackReaction قدیمی در اینجا اعمال نمیشود).
واکنشهای وضعیت چرخهعمر
messages.statusReactions.enabled: true را تنظیم کنید تا WhatsApp در طول یک نوبت، بهجای باقیگذاشتن ایموجی ثابت دریافت، واکنش تأیید را جایگزین کند و میان وضعیتهایی مانند در صف، در حال فکر، فعالیت ابزار، Compaction، انجامشده و خطا گردش کند:
{ messages: { statusReactions: { enabled: true, }, },}نکات: channels.whatsapp.ackReaction همچنان واجد شرایطبودن پیامهای مستقیم و گروهها را کنترل میکند؛ وضعیت در صف از همان ایموجی مؤثر واکنشهای تأیید ساده استفاده میکند؛ WhatsApp برای هر پیام یک جایگاه واکنش بات دارد، بنابراین بهروزرسانیهای چرخهعمر واکنش جاری را درجا جایگزین میکنند و پس از وضعیت نهایی انجامشده/خطا، واکنش تأیید را بازمیگردانند.
چندحسابی و اطلاعات احراز هویت
انتخاب حساب و پیشفرضها
شناسههای حساب از channels.whatsapp.accounts میآیند. انتخاب حساب پیشفرض، در صورت وجود، default است؛ در غیر این صورت، نخستین شناسهٔ حساب پیکربندیشده (بهترتیب الفبایی) انتخاب میشود. شناسههای حساب برای جستوجوی داخلی نرمالسازی میشوند.
مسیرهای اعتبارنامه و سازگاری با نسخههای قدیمی
- مسیر احراز هویت فعلی:
~/.openclaw/credentials/whatsapp/<accountId>/creds.json(پشتیبان:creds.json.bak) - احراز هویت پیشفرض قدیمی در
~/.openclaw/credentials/همچنان برای جریانهای حساب پیشفرض شناسایی/مهاجرت میشود
رفتار خروج
openclaw channels logout --channel whatsapp [--account <id>] وضعیت احراز هویت WhatsApp را برای آن حساب پاک میکند. هنگامی که Gateway در دسترس باشد، خروج ابتدا شنوندهٔ فعال آن حساب را متوقف میکند تا نشست پیوندشده پیش از راهاندازی مجدد بعدی، دریافت پیامها را متوقف کند. openclaw channels remove --channel whatsapp نیز پیش از غیرفعالسازی یا حذف پیکربندی حساب، شنوندهٔ فعال را متوقف میکند.
در پوشههای احراز هویت قدیمی، oauth.json حفظ میشود، در حالی که فایلهای احراز هویت Baileys حذف میشوند.
ابزارها، کنشها و نوشتن پیکربندی
- پشتیبانی ابزار عامل شامل کنش واکنش WhatsApp است (
react). - محدودکنندههای کنش:
channels.whatsapp.actions.reactions،channels.whatsapp.actions.polls(کنشهای موجود بهطور پیشفرضtrueهستند)،channels.whatsapp.actions.calls(پیشفرضfalse، MeowCaller را در بالا ببینید). - نوشتن پیکربندی آغازشده از کانال بهطور پیشفرض فعال است؛ آن را از طریق
channels.whatsapp.configWrites: falseغیرفعال کنید.
عیبیابی
پیوند نشده است (نیاز به QR)
نشانه: وضعیت کانال، پیوندنشده بودن را گزارش میکند.
openclaw channels login --channel whatsappopenclaw channels statusپیوندشده اما قطع است / حلقهٔ اتصال مجدد
نشانه: حساب پیوندشده با قطعهای مکرر یا تلاشهای اتصال مجدد.
حسابهای کمفعالیت میتوانند پس از مهلت عادی پیام نیز متصل بمانند؛ نگهبان فقط زمانی راهاندازی مجدد میکند که فعالیت انتقال WhatsApp Web متوقف شود، سوکت بسته شود یا فعالیت سطح برنامه بیش از بازهٔ ایمنی طولانیتر ساکت بماند (مدل زمان اجرا را در بالا ببینید).
راهحل:
openclaw channels status --probeopenclaw doctoropenclaw logs --followopenclaw gateway statusاگر پس از رفع مشکلات اتصال میزبان و زمانبندی، حلقه ادامه داشت، از پوشهٔ احراز هویت حساب پشتیبان بگیرید و دوباره پیوند دهید:
cp -a ~/.openclaw/credentials/whatsapp/<accountId> \ ~/.openclaw/credentials/whatsapp/<accountId>.bakopenclaw channels logout --channel whatsapp --account <accountId>openclaw channels login --channel whatsapp --account <accountId>اگر ~/.openclaw/logs/whatsapp-health.log عبارت Gateway inactive را نشان میدهد، اما openclaw gateway status و openclaw channels status --probe هر دو سالم هستند، openclaw doctor را اجرا کنید. در Linux، doctor دربارهٔ مدخلهای قدیمی crontab که اسکریپت بازنشستهٔ ~/.openclaw/bin/ensure-whatsapp.sh را فراخوانی میکنند هشدار میدهد؛ آن مدخلها را با crontab -e حذف کنید — cron ممکن است محیط گذرگاه کاربر systemd را نداشته باشد و باعث شود آن اسکریپت قدیمی سلامت Gateway را نادرست گزارش کند.
پایان مهلت ورود با QR پشت پراکسی
نشانه: openclaw channels login --channel whatsapp پیش از نمایش یک QR قابلاستفاده، با status=408 Request Time-out یا قطع سوکت TLS شکست میخورد.
ورود WhatsApp Web از محیط استاندارد پراکسی میزبان Gateway استفاده میکند (HTTPS_PROXY، HTTP_PROXY، گونههای حروف کوچک و NO_PROXY). بررسی کنید که فرایند Gateway محیط پراکسی را به ارث میبرد و NO_PROXY با mmg.whatsapp.net مطابقت ندارد.
نبود شنوندهٔ فعال هنگام ارسال
هنگامی که هیچ شنوندهٔ فعال Gateway برای حساب مقصد وجود نداشته باشد، ارسالهای خروجی فوراً شکست میخورند. تأیید کنید که Gateway در حال اجرا و حساب پیوندشده است.
پاسخ در رونوشت ظاهر میشود اما در WhatsApp نه
ردیفهای رونوشت، آنچه عامل تولید کرده است ثبت میکنند؛ تحویل WhatsApp جداگانه بررسی میشود. OpenClaw تنها پس از آنکه Baileys برای دستکم یک ارسال قابلمشاهدهٔ متن یا رسانه، شناسهٔ پیام خروجی برگرداند، پاسخ خودکار را ارسالشده در نظر میگیرد.
واکنشهای تأیید دریافت مستقل از رسیدهای پیش از پاسخ هستند — واکنش موفق ثابت نمیکند که پاسخ متنی/رسانهای بعدی پذیرفته شده است. گزارشهای Gateway را برای auto-reply delivery failed یا auto-reply was not accepted by WhatsApp provider بررسی کنید.
نادیده گرفته شدن غیرمنتظرهٔ پیامهای گروه
به این ترتیب بررسی کنید: groupPolicy، groupAllowFrom/allowFrom، مدخلهای فهرست مجاز groups، محدودسازی اشاره (requireMention + الگوهای اشاره) و کلیدهای تکراری در openclaw.json (مدخلهای بعدی JSON5 مدخلهای قبلی را بازنویسی میکنند — در هر محدوده فقط یک groupPolicy نگه دارید).
اگر channels.whatsapp.groups وجود داشته باشد، WhatsApp همچنان میتواند پیامهای گروههای دیگر را مشاهده کند، اما OpenClaw آنها را پیش از مسیریابی نشست کنار میگذارد. JID گروه را به channels.whatsapp.groups اضافه کنید، یا groups["*"] را اضافه کنید تا همهٔ گروهها پذیرفته شوند، در حالی که مجوز فرستنده زیر کنترل groupPolicy/groupAllowFrom باقی میماند.
هشدار زمان اجرای Bun
Gatewayهای OpenClaw به Node نیاز دارند. Bun رابط برنامهنویسی node:sqlite را که ذخیرهساز وضعیت معیار استفاده میکند ارائه نمیدهد و doctor سرویسهای قدیمی Bun را به Node مهاجرت میدهد.
اعلانهای سیستمی
WhatsApp از اعلانهای سیستمی به سبک Telegram برای گروهها و گفتوگوهای مستقیم، از طریق نگاشتهای groups و direct پشتیبانی میکند.
تفکیک برای پیامهای گروه: ابتدا نگاشت مؤثر groups تعیین میشود — اگر حساب به هر شکلی کلید groups خودش را تعریف کند، نگاشت ریشهٔ groups را بهطور کامل جایگزین میکند (بدون ادغام عمیق). سپس جستوجوی اعلان روی همان نگاشت حاصل اجرا میشود:
- اعلان ویژهٔ گروه (
groups["<groupId>"].systemPrompt): زمانی استفاده میشود که مدخل گروه وجود داشته باشد و کلیدsystemPromptآن تعریف شده باشد. رشتهٔ خالی ("") نویسهٔ عام را سرکوب میکند و هیچ اعلانی اعمال نمیکند. - اعلان نویسهٔ عام گروه (
groups["*"].systemPrompt): زمانی استفاده میشود که مدخل گروه مشخص وجود نداشته باشد، یا بدون کلیدsystemPromptوجود داشته باشد.
تفکیک برای پیامهای مستقیم، از الگوی یکسانی در نگاشت direct و direct["*"] پیروی میکند.
تفاوت با Telegram: در راهاندازی چندحسابی، Telegram مقدار ریشهٔ groups را برای هر حساب سرکوب میکند (حتی حسابهایی که groups مخصوص خود ندارند) تا ربات پیامهای گروههایی را که عضو آنها نیست دریافت نکند. WhatsApp این محافظ را اعمال نمیکند — groups/direct ریشه، صرفنظر از تعداد حسابها، توسط هر حسابی که بازنویسی مخصوص خود را ندارد به ارث برده میشوند. در راهاندازی چندحسابی WhatsApp، اگر اعلانهای مختص هر حساب میخواهید، نگاشت کامل را صریحاً زیر هر حساب تعریف کنید.
رفتار مهم:
channels.whatsapp.groupsهم نگاشت پیکربندی هر گروه است و هم فهرست مجاز گروه در سطح گفتوگو. در محدودهٔ ریشه یا حساب،groups["*"]بهمعنای «همهٔ گروهها پذیرفته میشوند» در آن محدوده است.- فقط زمانی نویسهٔ عام
systemPromptرا اضافه کنید که از قبل میخواهید آن محدوده همهٔ گروهها را بپذیرد. برای آنکه فقط مجموعهٔ ثابتی از شناسههای گروه واجد شرایط بمانند، بهجای استفاده ازgroups["*"]، اعلان را در هر مدخل صریحاً مجازشده تکرار کنید. - پذیرش گروه و مجوز فرستنده بررسیهای جداگانهای هستند.
groups["*"]دامنهٔ گروههایی را که به پردازش گروه میرسند گسترش میدهد؛ همهٔ فرستندگان آن گروهها را مجاز نمیکند — این مورد همچنان توسطgroupPolicy/groupAllowFromکنترل میشود. channels.whatsapp.directبرای پیامهای مستقیم اثر جانبی معادلی ندارد:direct["*"]فقط پس از آنکه یک پیام مستقیم از طریقdmPolicyبههمراهallowFromیا قواعد ذخیرهساز جفتسازی پذیرفته شد، پیکربندی پیشفرض را فراهم میکند.
مثال:
{ channels: { whatsapp: { groups: { // فقط در صورتی استفاده کنید که همهٔ گروهها باید در محدودهٔ ریشه پذیرفته شوند. // برای همهٔ حسابهایی اعمال میشود که نگاشت groups خود را تعریف نمیکنند. "*": { systemPrompt: "اعلان پیشفرض برای همهٔ گروهها." }, }, direct: { // برای همهٔ حسابهایی اعمال میشود که نگاشت direct خود را تعریف نمیکنند. "*": { systemPrompt: "اعلان پیشفرض برای همهٔ گفتوگوهای مستقیم." }, }, accounts: { work: { groups: { // این حساب groups خود را تعریف میکند، بنابراین groups ریشه بهطور کامل // جایگزین میشود. برای حفظ نویسهٔ عام، "*" را اینجا نیز صریحاً تعریف کنید. "120363406415684625@g.us": { requireMention: false, systemPrompt: "بر مدیریت پروژه تمرکز کن.", }, // فقط در صورتی استفاده کنید که همهٔ گروهها باید در این حساب پذیرفته شوند. "*": { systemPrompt: "اعلان پیشفرض برای گروههای کاری." }, }, direct: { // این حساب نگاشت direct خود را تعریف میکند، بنابراین مدخلهای direct ریشه // بهطور کامل جایگزین میشوند. برای حفظ نویسهٔ عام، "*" را اینجا نیز صریحاً تعریف کنید. "+15551234567": { systemPrompt: "اعلان برای یک گفتوگوی مستقیم کاری مشخص." }, "*": { systemPrompt: "اعلان پیشفرض برای گفتوگوهای مستقیم کاری." }, }, }, }, }, },}اشارهگرهای مرجع پیکربندی
مرجع اصلی: مرجع پیکربندی - WhatsApp
| حوزه | فیلدها |
|---|---|
| دسترسی | dmPolicy، allowFrom، groupPolicy، groupAllowFrom، groups |
| تحویل | textChunkLimit، streaming.chunkMode، mediaMaxMb، sendReadReceipts، ackReaction، reactionLevel |
| چندحسابی | accounts.<id>.enabled، accounts.<id>.authDir و دیگر بازنویسیهای مختص حساب |
| عملیات | configWrites، enabled |
| دستهبندی ورودی | messages.inbound.debounceMs، messages.inbound.byChannel.whatsapp |
| رفتار نشست | session.dmScope، historyLimit، dmHistoryLimit، dms.<id>.historyLimit |
| اعلانها | groups.<id>.systemPrompt، groups["*"].systemPrompt، direct.<id>.systemPrompt، direct["*"].systemPrompt |