Set up email and chat-widget channels together
A common onboarding shape for a new customer: they want both an email channel for ticket-style threads and a chat-widget channel for their website. This skill orchestrates both — it doesn't reproduce the per-channel detail, it points to the per-channel skills for the specifics.
Read alongside:
skill://conv/setup-email-channel— full SMTP/IMAP config detail.skill://conv/setup-chat-widget— widget key minting + push transcript flow.skill://conv/escalate-to-human— once a human is involved, how the external bot yields.
TL;DR
conv_list_channels— see whether any channel exists for this org.- Email channel:
conv_email_setup_channel→conv_email_test_channelto verify. - Widget channel:
conv_widget_create_channel→ store thewidgetKeyserver-side. conv_list_channelsagain to confirm both areactive: true.- (Optional)
conv_create_topicper topic so the inbox has Billing / Support / Bug topics ready.
Step 1 — check current state
{ "name": "conv_list_channels", "arguments": {} }
Lists existing channels and their active flag. If the org already has an email or widget channel, skip the corresponding step.
Step 2 — email channel
Per skill://conv/setup-email-channel, gather:
fromAddress— the real mailbox the customer controls.- Outbound mode:
smtp(host, port, secure, username, password) ormailer(Munin's configured Resend). - Inbound mode:
imap(host, port, secure, username, password, mailbox), or skip if the customer will forward to aMUNIN_EMAIL_REPLY_DOMAINaddress.
Then:
{
"name": "conv_email_setup_channel",
"arguments": {
"name": "Acme Support",
"config": {
"addressing": { "fromAddress": "support@acme.com", "fromName": "Acme Support" },
"outbound": { "provider": "smtp", "host": "smtp.acme.com", "port": 587, "secure": false, "username": "support@acme.com", "password": "<plaintext, encrypted server-side>" },
"inbound": { "host": "imap.acme.com", "port": 993, "secure": true, "username": "support@acme.com", "password": "<plaintext>", "mailbox": "INBOX" }
}
}
}
The response includes the channel id. Passwords come back as •••• — they're encrypted via pgcrypto and never re-emitted.
Verify:
{ "name": "conv_email_test_channel", "arguments": { "channelId": "<emailChannelId>" } }
Returns { smtp: 'ok'|'error: …', imap: 'ok'|'error: …'|'not configured' }. Don't proceed if SMTP fails — outbound mail will silently dead-letter. IMAP failures are softer (you can fall back to forwarding).
Step 3 — widget channel
Per skill://conv/setup-chat-widget:
{
"name": "conv_widget_create_channel",
"arguments": {
"name": "acme-storefront-bot",
"originAllowlist": ["https://www.acme.com", "https://shop.acme.com"]
}
}
Response includes widgetKey: "mn_widget_..." — shown once. Hand it to the customer's developer to store server-side. Rotate later via conv_widget_rotate_key if it leaks.
originAllowlist is enforced on every push from the widget endpoint; setting it correctly here saves a CORS bug report later.
If the customer wants escalation webhooks (their bot should yield when a human in Munin replies), point them at skill://conv/escalate-to-human — handoff uses the standard conversation.message.sent webhook, not a widget-specific one.
Step 4 — confirm
{ "name": "conv_list_channels", "arguments": {} }
Both channels should appear with active: true. If either is active: false, the test/setup didn't complete — re-run that channel's flow.
Step 5 — seed topics (optional)
Topics are conversation labels that route inbound messages to the right humans. Create the starter set with conv_create_topic, one call per topic:
{ "name": "conv_create_topic", "arguments": { "name": "Billing" } }
{ "name": "conv_create_topic", "arguments": { "name": "Bug report" } }
{ "name": "conv_create_topic", "arguments": { "name": "Feature request" } }
{ "name": "conv_create_topic", "arguments": { "name": "Account access" } }
What NOT to do
- Don't try to assign channels to a team at create time. Channels are org-scoped; routing happens per-conversation via
conv_assign_conversation. There's no "channel owner" field. - Don't paste the widget key into the customer's repo or a Slack message. Treat it like a password — it's shown once because the server only stores its hash.
- Don't skip
conv_email_test_channel. A bad SMTP password silently fails on the first delivery attempt and looks like a customer-side problem when really it's a config error. - Don't enable the widget without an
originAllowlist. An empty list means anyone can POST to the widget endpoint with the key — fine for staging, embarrassing in production.
Related
skill://conv/setup-email-channel— detailed SMTP/IMAP config.skill://conv/setup-chat-widget— push transcript flow + key minting.skill://conv/escalate-to-human— webhook-based handoff.skill://playbooks/support-desk-launch— full support desk stand-up across conv + crm + kb.