Skip to main content
Commands, package names, and image names on this page come from the open-source project that Mibyan Desktop is built on, and can differ from the Mibyan Desktop installer. For the supported Mibyan install and update path, see Install and update.
Connect Mibyan to Slack as a bot using Socket Mode. Socket Mode uses WebSockets instead of public HTTP endpoints, so your Mibyan instance doesn’t need to be publicly accessible — it works behind firewalls, on your laptop, or on a private server.
Classic Slack Apps DeprecatedClassic Slack apps (using RTM API) were fully deprecated in March 2025. Mibyan uses the modern Bolt SDK with Socket Mode. If you have an old classic app, you must create a new one following the steps below.

Overview


Step 1: Create a Slack App

The fastest path is to paste a manifest Mibyan generates for you. It declares every built-in slash command (/btw, /stop, /model, …), every required OAuth scope, every event subscription, and enables Socket Mode — all at once.
  1. Generate the manifest. New Slack apps must use Agent view:
    This writes ~/.mibyan/slack-manifest.json and prints paste-in instructions. Existing apps that still use Slack’s legacy Assistant view can omit --agent-view until they are ready to migrate. To populate Slack’s long app description from an existing UTF-8 text or Markdown file, add --long-description-file:
    The file contents are preserved exactly within Slack’s 175–4,000-character range. Use --long-description "..." for inline text instead; the inline and file options are mutually exclusive and cannot be combined with --slashes-only.
  2. Go to https://api.slack.com/apps → Create New App → From an app manifest
  3. Pick your workspace, paste the JSON contents, review, click Next → Create
  4. Skip ahead to Step 6: Install App to Workspace. The manifest handled scopes, events, and slash commands for you.

Option B: From scratch (manual)

  1. Go to https://api.slack.com/apps
  2. Click Create New App
  3. Choose From scratch
  4. Enter an app name (e.g., “Mibyan”) and select your workspace
  5. Click Create App
You’ll land on the app’s Basic Information page. Continue with Steps 2–6 below.

Step 2: Configure Bot Token Scopes

Navigate to Features → OAuth & Permissions in the sidebar. Scroll to Scopes → Bot Token Scopes and add the following:
Missing scopes = missing featuresWithout channels:history and groups:history, the bot will not receive messages in channels — it will only work in DMs. Without files:read, Mibyan can chat but cannot reliably read user-uploaded attachments. These are the most commonly missed scopes.
Optional scopes:

Step 3: Enable Socket Mode

Socket Mode lets the bot connect via WebSocket instead of requiring a public URL.
  1. In the sidebar, go to Settings → Socket Mode
  2. Toggle Enable Socket Mode to ON
  3. You’ll be prompted to create an App-Level Token:
    • Name it something like mibyan-socket (the name doesn’t matter)
    • Add the connections:write scope
    • Click Generate
  4. Copy the token — it starts with xapp-. This is your SLACK_APP_TOKEN
You can always find or regenerate app-level tokens under Settings → Basic Information → App-Level Tokens.

Step 4: Subscribe to Events

This step is critical — it controls what messages the bot can see.
  1. In the sidebar, go to Features → Event Subscriptions
  2. Toggle Enable Events to ON
  3. Expand Subscribe to bot events and add:
  1. Click Save Changes at the bottom of the page
Missing event subscriptions is the #1 setup issueIf the bot works in DMs but not in channels, you almost certainly forgot to add message.channels (for public channels) and/or message.groups (for private channels). Without these events, Slack simply never delivers channel messages to the bot.

Step 5: Enable the Messages Tab

This step enables direct messages to the bot. Without it, users see “Sending messages to this app has been turned off” when trying to DM the bot.
  1. In the sidebar, go to Features → App Home
  2. Scroll to Show Tabs
  3. Toggle Messages Tab to ON
  4. Check “Allow users to send Slash commands and messages from the messages tab”
Without this step, DMs are completely blockedEven with all the correct scopes and event subscriptions, Slack will not allow users to send direct messages to the bot unless the Messages Tab is enabled. This is a Slack platform requirement, not a Mibyan configuration issue.

Step 6: Install App to Workspace

  1. In the sidebar, go to Settings → Install App
  2. Click Install to Workspace
  3. Review the permissions and click Allow
  4. After authorization, you’ll see a Bot User OAuth Token starting with xoxb-
  5. Copy this token — this is your SLACK_BOT_TOKEN
If you change scopes or event subscriptions later, you must reinstall the app for the changes to take effect. The Install App page will show a banner prompting you to do so.

Step 7: Find User IDs for the Allowlist

Mibyan uses Slack Member IDs (not usernames or display names) for the allowlist. To find a Member ID:
  1. In Slack, click on the user’s name or avatar
  2. Click View full profile
  3. Click the ⋮ (more) button
  4. Select Copy member ID
Member IDs look like U01ABC2DEF3. You need your own Member ID at minimum.

Step 8: Configure Mibyan

Add the following to your ~/.mibyan/.env file:
Or run the interactive setup:
Then start the gateway:
Codex reasoning-effort safetyFor Codex-backed Slack peer-agent channels, prefer agent.reasoning_effort: high or lower. xhigh can spend the entire turn in hidden reasoning and never produce visible assistant text; Mibyan now suppresses those incomplete-turn warnings from the thread and keeps the diagnostics in gateway logs.

Step 9: Invite the Bot to Channels

After starting the gateway, you need to invite the bot to any channel where you want it to respond:
The bot will not automatically join channels. You must invite it to each channel individually.

Slash Commands

Every Mibyan command (/btw, /stop, /new, /model, /help, …) is a native Slack slash command — exactly the way they work on Telegram and Discord. Type / in Slack and the autocomplete picker lists every Mibyan command with its description. Under the hood: Mibyan ships with a generated Slack app manifest (see Step 1, Option A) that declares every command in COMMAND_REGISTRY as a slash command. In Socket Mode, Slack routes the command event through the WebSocket regardless of the manifest’s url field.

Agent messaging experience

New Slack apps use Slack’s Agent messaging experience. Existing Mibyan Assistant apps can migrate by regenerating the manifest with --agent-view:
Update the manifest in Features → App Manifest, then reinstall the app if Slack asks. Agent view cannot be reverted to Assistant view, and users may need to hard-refresh Slack after the switch. The generated Agent manifest subscribes to message.im, app_home_opened, and app_context_changed, so Mibyan can identify a Messages-tab DM and receive the user’s active Slack context with a turn. Mibyan only supplies that context as a label; it does not read the viewed channel’s history.

Refreshing slash commands after updates

When Mibyan adds new commands (e.g. after mibyan update), regenerate the manifest and update your Slack app:
Then in Slack:
  1. Open https://api.slack.com/apps → your Mibyan app
  2. Features → App Manifest → Edit
  3. Paste the new contents of ~/.mibyan/slack-manifest.json
  4. Save. Slack will prompt to reinstall the app if scopes or slash commands changed.

Legacy /mibyan <subcommand> still works

For backward compatibility with older manifests, you can still type /mibyan bg run the tests — Mibyan routes it the same way as /bg run the tests. Free-form questions also work: /mibyan what's the weather? is treated as a regular message.

Using commands inside threads (the !cmd prefix)

Slack itself blocks native slash commands inside thread replies — try /queue in a thread and Slack responds with “/queue is not supported in threads. Sorry!” There is no app-side setting that re-enables them; Slack never delivers them to Mibyan. As a workaround, Mibyan recognises a leading ! as an alternate command prefix that works in threads (and anywhere else). Type !queue, !stop, !model gpt-5.4, etc. as a regular thread reply — Mibyan treats it identically to the slash form and replies in the same thread. Only the first token is checked against the known command list, so casual messages like !nice work pass through to the agent unchanged. The bang form also works behind a mention (@Mibyan !stop) and with leading whitespace — both dispatch as commands in threads. Approval prompts (dangerous command / execute_code approval) normally render as interactive buttons. When buttons can’t be delivered and Mibyan falls back to a text prompt, the prompt instructs you to reply with !approve / !deny — the form that works inside threads.

Slash replies are ephemeral

Replies to a native slash command (e.g. /status, /help) are delivered ephemerally — “Only visible to you” — so command output never spams the channel. The “Running /cmd…” placeholder is replaced with the real reply; long replies are chunked into follow-up ephemeral messages. Slack caps the reply flow at 5 posts, so extremely long output is closed with an explicit truncation notice rather than silently dropped. If the primary ephemeral path fails, Mibyan retries via a second ephemeral API path — a slash reply is never posted publicly to the channel as a fallback. (Commands typed as regular messages — !cmd in threads, @Mibyan /cmd — reply as normal visible messages instead.)

Clarify prompts (one-tap buttons)

When the agent needs to ask you a multiple-choice question (the clarify tool), Slack renders it as Block Kit buttons — one tap per option, plus an “✏️ Other…” button that switches to free-text mode (your next typed message becomes the answer). After a tap, the message updates in place to show who answered and what was chosen; further clicks on the same prompt are ignored. Button clicks honor the same user authorization as messages. When the prompt times out (agent.clarify_timeout), the session is reset, or you reply with free text instead of tapping a button, the card is rewritten in place without its buttons (”⏳ This prompt expired…” or “↩️ Clarification cancelled…”); a click on a card orphaned by a gateway restart still tells you to re-ask instead of silently eating the click. Open-ended clarify questions render as a plain question and accept your next typed reply. No configuration needed — this works regardless of the rich_blocks setting.

Advanced: emit only the slash-commands array

If you maintain your Slack manifest by hand and just want the slash command list:
Paste that array into the features.slash_commands key of your existing manifest.

How the Bot Responds

Understanding how Mibyan behaves in different contexts:
In channels, always @mention the bot to start a conversation. Once the bot is active in a thread, you can reply in that thread without mentioning it. Outside of threads, messages without @mention are ignored to prevent noise in busy channels.

Configuration Options

Beyond the required environment variables from Step 8, you can customize Slack bot behavior through ~/.mibyan/config.yaml.

Thread & Reply Behavior

The equivalent environment variable is SLACK_ALLOW_BOTS=none|mentions|all. When both are set, the explicit environment variable takes precedence (the same env-over-YAML rule as every other setting). Avoid all when peer bots can answer each other without an explicit mention, because their own reply policies can still create loops.

Working-State Status Line

While the agent processes a message, Slack shows a status line next to the bot name in the thread. By default Mibyan sets it to is thinking...; customize it with typing_status_text — e.g. a kitten assistant named Ada:
Where the status rendersThe custom status appears in the footer beneath the reply composer (“BotName is thinking…”), not inline in the message list. The inline “Generating response…” / “Finding answers…” lines Slack shows in the message area while an AI app works are Slack’s own rotating indicators — the status API (agents.sessions.setStatus / assistant.threads.setStatus) does not control those, and both can appear at the same time.
The same key customizes Google Chat’s visible working-state marker message (platforms.google_chat.typing_status_text, default "Mibyan is thinking…") — note that on Google Chat it is a real posted message that gets patched into the reply, not an ephemeral status.

Live Status (per-tool)

By default the status line updates live as the agent works: instead of a static is thinking..., it shows what the agent is doing right now — is running pytest tests/…, is reading docs/api.md…, is searching the web for slack api limits…. Between tool calls it reverts to the static text. This rides the existing status-refresh cadence, so it makes no additional Slack API calls, and it works even with tool_progress: off (Slack’s default) — unlike progress bubbles, the status line is ephemeral and leaves nothing behind in the channel. Control it with display.live_status (global or per-platform):

Native Streaming (live-typing replies)

Slack’s Agents & AI Apps feature ships a native streaming surface (chat.startStream / chat.appendStream / chat.stopStream) that renders the reply as a live-typing message — much smoother than the edit-based progressive updates used otherwise. When streaming.enabled is on (transport auto or draft), Mibyan uses native streaming automatically wherever it’s available:
  • The stream starts on the first frame and appends only deltas (the API is append-only). The streamed message is the final message — Mibyan seals it via chat.stopStream instead of posting a duplicate final reply.
  • If your Slack app doesn’t have the AI features enabled (or lacks the assistant:write scope), the first failure is cached and Mibyan falls back to edit-based streaming with a single log warning naming the fix.
  • Opt-in Block Kit (rich_blocks: true) is applied to the sealed message, same as the edit-based finalize path.
No extra configuration is needed beyond enabling streaming:

Native Task Cards (live tool progress)

With platforms.slack.extra.native_task_cards: true, live tool calls render as Slack-native plan/task cards (the same UI Slack’s own AI features use) instead of text progress bubbles: one card per turn, one row per tool call, with per-task running/complete/error states updating in place.
  • Cards are the Slack rendering of tool progress. They work with Slack’s built-in default tool_progress: off. Writing tool_progress: off yourself (globally, under display.platforms.slack, or by cycling /verbose to off) turns cards off as well; new or all keeps them. A null value inherits and is not an “off”. Null also allows the existing environment bridge to supply the mode when no YAML layer sets a non-null value. Changes apply when the next turn resolves its display settings.
  • Cards need a thread. With the card lane active, a chat that has no thread to anchor on (a top-level DM under reply_in_thread: false) shows no tool progress rather than text bubbles under Slack’s default tool_progress: off; if you wrote new or all, that chat gets the editable text progress you asked for. Replies inside an existing thread still get cards.
  • Concurrent calls to the same tool are correlated by real tool-call ID, so parallel web_search calls each get their own row with the right status.
  • Mibyan checks thread eligibility before attempting publication, so a disconnect or timeout cannot turn an unthreaded destination into text fallback.
  • On a supported threaded destination, if the native stream fails for a recoverable reason (API error, rate limit), Mibyan falls back to a single continuously edited text message so progress stays live for the turn. A relay egress refusal of the destination is not recoverable and suppresses progress for the turn.
  • If Slack closes a stream during a long turn, Mibyan opens a fresh card in the same thread with the current task list and keeps updating there. The previous card remains visible.
  • The card stream is stopped exactly once when the turn finalizes, including on interrupt/disconnect, so no dangling live indicator is left behind.

Session Isolation

When true (the default), each user in a shared channel gets their own isolated conversation session. Two people talking to Mibyan in #general will have separate histories and contexts. Set to false if you want a collaborative mode where the entire channel shares one conversation session. Be aware this means users share context growth and token costs, and one user’s /reset clears the session for everyone.

Mention & Trigger Behavior

When to use strict_mentionSet this to true in busy workspaces where Slack’s default “the bot remembers this thread” behavior surprises users — for example, a long tech-support thread where the bot helped at the start and you’d rather it stay silent unless explicitly pinged again. DMs and active interactive sessions are unaffected.
When to use ignore_other_user_mentionsSet this to true when the bot follows busy threads (via thread auto-engagement or free_response_channels) and butts in on messages humans address to each other. It is a narrower tool than strict_mention: plain follow-ups in an engaged thread still get answers; only messages that open by @mentioning another person are skipped. 1:1 DMs are unaffected; group DMs (MPIMs) and channels both apply it, matching the shared-surface policy below. Broadcast tokens (@here, @channel) and channel references address the room, not a person, so they are never skipped.
Silence markers on messages not addressed to the botWhen the bot answers a human message with only a silence token, Mibyan normally posts a short notice instead so a question never goes unanswered. On Slack the token is allowed to stand when the message opened by @mentioning someone else, or was an unmentioned top-level message in a free_response_channels channel that starts its own thread (the default reply_in_thread: true). A 1:1 DM, a mention of the bot, a command, a reaction trigger, or a plain follow-up in a conversation the bot is part of (a thread, or a reply_in_thread: false channel) still gets the notice.
Slack supports both patterns: @mention required to start a conversation by default, but you can opt specific channels out via SLACK_FREE_RESPONSE_CHANNELS (comma-separated channel IDs) or slack.free_response_channels in config.yaml. Once the bot has an active session in a thread, subsequent thread replies do not require a mention. In 1:1 DMs the bot always responds without needing a mention. These gating keys can be set in the top-level slack: block or under platforms.slack.extra; within user YAML, when the same key is set in both, platforms.slack.extra wins and the gateway logs a warning. Administrator-managed pins remain authoritative, and explicit environment settings retain their existing precedence.
Group DMs (MPIMs) are shared surfaces, not 1:1 DMsA 1:1 direct message is a private conversation with one person, so it is mention-exempt. A group DM (MPIM / multi-person DM) is a shared surface — multiple people can see and trigger the bot — so it obeys the same operator controls as a channel: require_mention, strict_mention, free_response_channels, and allowed_channels all apply, and the bot only adds :eyes:/:white_check_mark: reactions when it is actually @mentioned. To let the bot respond freely in a specific group DM, add its channel ID (starts with G) to free_response_channels.

Which mention option do I want?

The gating options compose — each answers a different question: Rules of thumb: strict_mention is the broadest hammer; thread_require_mention quiets busy threads without touching top-level gating; require_mention_channels re-tightens individual channels on an otherwise free-response bot; ignore_other_user_mentions only skips messages explicitly addressed to another person. 1:1 DMs always respond and are unaffected by all of these.

Accepting messages from other bots (allow_bots)

By default Mibyan ignores every message authored by another Slack bot or app (including Workflow Builder posts). For multi-agent workspaces — several Mibyan instances or peer bots collaborating in one channel — opt in with allow_bots:
Env equivalent: SLACK_ALLOW_BOTS=none|mentions|all (the config key wins when both are set). Unknown values are treated as none. How mentions mode gates:
  • A peer-bot message is accepted only when the message itself contains a current @mention of this bot — in its text or its Block Kit blocks. Thread history does not count: a bot having been mentioned earlier in the thread, replies to the bot’s own messages, and active thread sessions do not admit later unmentioned peer-bot messages. This is deliberate — it is what breaks agent-to-agent ack/status loops.
  • Human messages are unaffected; normal mention gating applies to them.
  • Mibyan always ignores its own messages, in every mode, to prevent self-echo loops.
mentions is the recommended mode for bot-to-bot collaboration: each agent must explicitly summon the other per turn. Avoid all unless every peer bot’s own reply policy is loop-safe — two bots that answer everything will answer each other forever. Detection covers labeled bot messages (bot_id, subtype: bot_message), app-originated events, and unlabeled bot users (probed via users.info), so peer Mibyan agents are filtered consistently across workspaces. For strict multi-bot deployments, pair with require_mention: true and strict_mention: true — see the smoke-check profile below.

Treating your own app’s user-token posts as human (api_human_users)

A message posted through the Web API with a user token (xoxp-) is authored by a real person, but it arrives with the posting app_id and no client_msg_id — the same signature Mibyan uses to recognise app posts — so it is dropped as bot traffic. This blocks a common pattern: a custom front-end (an internal dashboard, a mobile shell, a kiosk) that sends messages to Mibyan as the logged-in user. allow_bots: all would let those posts through, but it opens the door to every bot in the channel and weakens the loop protections. Instead, allowlist just the people who use your front-end:
The equivalent environment variable is SLACK_API_HUMAN_USERS (comma-separated). Scope and safety:
  • The allowlist is users only. There is deliberately no app-ID variant: a modern bot token (xoxb-) posts with the same user + app_id shape, so trusting an app would also admit its own bot posts and defeat the loop guard.
  • Events carrying bot_id or subtype: bot_message, or no user at all, are always treated as bot posts regardless of the allowlist.
  • The rest of the pipeline is unchanged: mention gating, allowed_channels, and SLACK_ALLOWED_USERS still apply to the (now human) sender.

Reaction Triggers (reaction_triggers)

By default, emoji reactions are acknowledged and dropped — a 👍 on a bot message does nothing. Set slack.reaction_triggers to route reactions into the agent loop (requires the reactions:read scope plus the reaction_added/reaction_removed bot event subscriptions in your Slack app manifest — regenerate with mibyan slack manifest):
Environment equivalents: SLACK_REACTION_TRIGGERS (true/all or a comma-separated list) and SLACK_REACTION_TRIGGER_TARGET. Behavior:
  • The reaction arrives as a normal agent turn with text reaction:added:👍 / reaction:removed:👍 (common Slack names are translated to unicode; unknown names pass through as-is, e.g. reaction:added:custom-emoji), threaded under the reacted-to message so the agent sees what was reacted to and the turn lands in the same session as a reply would.
  • The reactor becomes the message’s user, so user authorization and allowed_channels gating apply exactly as for typed messages — a random user’s reaction cannot trigger the agent anywhere their message couldn’t.
  • With reaction_triggers: true, only reactions on the bot’s own messages route (approve/acknowledge flows). With an explicit emoji allowlist, the listed emojis route from any message.
  • The bot’s own lifecycle reactions (:eyes: etc.) never feed back.
  • Independent of this opt-in, every human reaction fires the reaction:added/reaction:removed gateway hooks for observers that don’t need agent turns.

Peer-Agent Smoke Check

For multi-bot Slack deployments that rely on strict per-turn mentions, keep the following profile:
After gateway config changes, deploys, or restarts, run this synthetic smoke target:
This target uses in-process synthetic Slack events only. It does not send live Slack messages and does not require real bot tokens by default. Failure buckets:
  • config: test_peer_agent_smoke_preflight_contract caught a profile mismatch (require_mention, strict_mention, allow_bots, or allowed_channels).
  • platform_connectivity: the adapter/client was not initialized, so routing smoke is not a trustworthy signal yet.
  • bot_identity: the adapter never resolved its bot user ID, so current-message mention checks cannot work.
  • routing_logic: the Slack adapter regressed on one of the peer-agent invariants (human mention routing, peer-bot ignore, explicit peer mention admit, or passive ack/status/error suppression).
If this target passes but a live workspace still misroutes messages, investigate Slack token/workspace connectivity and runtime deployment state outside the routing logic itself.

Channel allowlist (allowed_channels)

Restrict the bot to a fixed set of Slack channels — useful when the bot is invited to many channels but should only respond in a few. When set, messages from channels NOT in this list are silently ignored, even if the bot is @mentioned. 1:1 DMs are exempt from this filter, so authorized users can always reach the bot in a direct message. Group DMs (MPIMs) are not exempt — like channels, an MPIM must be on the allowlist (its ID starts with G) or its messages are dropped.
Or via env var (comma-separated):
Behavior:
  • Empty / unset → no restriction (fully backward compatible).
  • Non-empty → channel ID must be on the list, or the message is dropped before any other gating (mention requirement, free_response_channels, etc.) runs.
  • Slack channel IDs start with C (public), G (private), or D (DM). Look them up via the Slack UI’s “Open channel details” → “About” panel, or via the API.
See also: admin/user slash command split.

Unauthorized User Handling

You can also set this globally for all platforms:
The platform-specific setting under slack: takes precedence over the global setting.

Voice Transcription

When true (the default), incoming audio messages are automatically transcribed using the configured STT provider before being processed by the agent.

Full Example


Home Channel

Set SLACK_HOME_CHANNEL to a channel ID where Mibyan will deliver scheduled messages, cron job results, and other proactive notifications. To find a channel ID:
  1. Right-click the channel name in Slack
  2. Click View channel details
  3. Scroll to the bottom — the Channel ID is shown there
Make sure the bot has been invited to the channel (/invite @Mibyan).

Cron delivery targeting

Cron jobs (see the cron guide) can target Slack three ways: Delivery works even when the cron process isn’t co-located with the gateway — Mibyan falls back to a standalone Web API sender using SLACK_BOT_TOKEN. MEDIA: attachments in the cron output are uploaded as native Slack file shares to the same target.

Sending messages and media (send_message)

The agent’s send_message tool accepts the same target shapes: a channel ID (C…/G…), a DM conversation (D…), or a bare user ID (U…/W…), which is resolved to the user’s DM on every send path — text, media, and interactive prompts alike. MEDIA:<path> attachments (images, PDFs, documents) upload as native file shares; when a short message accompanies a single attachment it rides as the file’s caption instead of a separate message. Missing files are reported per-file as warnings rather than failing the whole send.

Multi-Workspace Support

Mibyan can connect to multiple Slack workspaces simultaneously using a single gateway instance. Each workspace is authenticated independently with its own bot user ID.

Configuration

Provide multiple bot tokens as a comma-separated list in SLACK_BOT_TOKEN:
Or in ~/.mibyan/config.yaml:

OAuth Token File

In addition to tokens in the environment or config, Mibyan also loads tokens from an OAuth token file at:
This file is a JSON object mapping team IDs to token entries:
Tokens from this file are merged with any tokens specified via SLACK_BOT_TOKEN. Duplicate tokens are automatically deduplicated.

How it works

  • The first token in the list is the primary token, used for the Socket Mode connection (AsyncApp).
  • Each token is authenticated via auth.test on startup. The gateway maps each team_id to its own WebClient and bot_user_id.
  • When a message arrives, Mibyan uses the correct workspace-specific client to respond.
  • The primary bot_user_id (from the first token) is used for backward compatibility with features that expect a single bot identity.

Voice Messages

Mibyan supports voice on Slack:
  • Incoming: Voice/audio messages are automatically transcribed using the configured STT provider: local faster-whisper, Groq Whisper (GROQ_API_KEY), or OpenAI Whisper (VOICE_TOOLS_OPENAI_KEY)
  • Outgoing: TTS responses are sent as audio file attachments

Per-Channel Prompts

Assign ephemeral system prompts to specific Slack channels. The prompt is injected at runtime on every turn — never persisted to transcript history — so changes take effect immediately.
Keys are Slack channel IDs (find them via channel details → “About” → scroll to bottom). All messages in the matching channel get the prompt injected as an ephemeral system instruction.

Per-Channel Skill Bindings

Auto-load a skill whenever a new session starts in a specific channel or DM. Unlike per-channel prompts (which are injected on every turn), skill bindings inject the skill content as a user message at session start — it becomes part of the conversation history and does not need to be reloaded on subsequent turns. This is ideal for DMs or channels with a dedicated purpose (flashcards, a domain-specific Q&A bot, a support triage channel, etc.) where you don’t want the model’s own skill selector to decide whether to load on every short reply.
Notes:
  • The binding matches by channel ID. For threaded messages in a bound channel, the thread inherits the parent channel’s binding.
  • The skill is loaded only at session start (new session). If you change the binding, run /new for it to take effect.
  • Combine with channel_prompts for per-channel tone/constraints on top of the skill’s instructions.

Troubleshooting

Quick Checklist

If the bot isn’t working in channels, verify all of the following:
  1. ✅ message.channels event is subscribed (for public channels)
  2. ✅ message.groups event is subscribed (for private channels)
  3. ✅ app_mention event is subscribed
  4. ✅ channels:history scope is added (for public channels)
  5. ✅ groups:history scope is added (for private channels)
  6. ✅ App was reinstalled after adding scopes/events
  7. ✅ Bot was invited to the channel (/invite @Mibyan)
  8. ✅ You are @mentioning the bot in your message

Security

Always set SLACK_ALLOWED_USERS with the Member IDs of authorized users. Without this setting, the gateway will deny all messages by default as a safety measure. Never share your bot tokens — treat them like passwords.
  • Tokens should be stored in ~/.mibyan/.env (file permissions 600)
  • Rotate tokens periodically via the Slack app settings
  • Audit who has access to your Mibyan config directory
  • Socket Mode means no public endpoint is exposed — one less attack surface