GuideMessage Gateway (Beta)

Message Gateway (Beta)

Security Warning — Read Before Enabling

The Message Gateway gives anyone who can message your bot the ability to create Agor sessions and interact with autonomous coding agents. This effectively grants full access to the target worktree, the host machine (to the extent the agent can access it), and any connected services (MCP servers, APIs, credentials).

This is a beta feature. Use at your own risk and with caution:

  • Assume full access. Anyone who can DM your Slack bot can prompt the agent to read, write, and execute code on the worktree. Treat this as giving them SSH access to that environment.
  • Sandbox everything you can. Run the daemon in a container, use restricted permission modes (supervised or manual), limit MCP server exposure, and avoid mounting sensitive host directories.
  • Restrict bot access. In Slack, limit who can DM the bot. Consider creating a private Slack workspace or restricting the bot to specific users via Slack’s app distribution settings.
  • Use dedicated worktrees. Don’t point channels at worktrees containing production code or credentials. Create isolated worktrees specifically for gateway use.
  • Audit regularly. Monitor sessions created by the gateway. All activity is logged in Agor’s session transcripts.
  • Rotate credentials. Periodically rotate your Slack bot tokens and channel keys through the Settings UI.
  • Don’t run as root. The daemon and agents should never run as root. Use Agor’s Unix isolation modes for additional sandboxing.

The Message Gateway connects external messaging platforms to Agor’s agent sessions. DM your Slack bot, and Agor spins up a fresh coding session on the right worktree with the right agent — then streams responses back into the same thread. Follow-up messages continue the conversation in the same session.

Currently Slack-only. Discord, WhatsApp, and Telegram connectors are planned.

What is a Channel?

A Channel is a portal into a worktree. It defines:

  • A home worktree — the persistent worktree where every session spawned by this channel will operate. Think of it as a command center, like an agor-openclaw worktree that supervises a project.
  • An agentic tool configuration — which coding agent to use (Claude Code, Codex, Gemini, OpenCode), which model, permission mode, and which MCP servers to attach.
  • Platform credentials — bot token, app token, and other secrets needed to send and receive messages (encrypted at rest).

You can create multiple channels for the same or different worktrees. For example:

  • “Optimus Prime” — Claude Code (Opus 4.6) on your main agor-openclaw worktree, with Slack + GitHub MCP servers
  • “Scout” — Claude Code (Sonnet 4.5) on a lighter review worktree, trust mode, no MCP servers
  • “Codex Runner” — Codex on a superset-frontend worktree for quick JS tasks

Each channel gets a unique channel key (a UUID) that authenticates inbound messages. The Slack integration uses Socket Mode, so no public webhook URLs are needed.

How It Works

When a message arrives from a platform (e.g., a Slack DM), the gateway processes it through a simple pipeline:

  1. Authenticate. The gateway looks up the channel by its key and verifies it’s enabled.
  2. Map thread to session. If this is a new thread, create a fresh Agor session on the channel’s target worktree with the channel’s agentic tool configuration. If this thread has been seen before, route to the existing session.
  3. Send prompt. The message text is sent to the session via Agor’s standard prompt flow — task creation, executor spawn, the full pipeline.
  4. Agent runs. The coding agent (Claude Code, Codex, etc.) processes the prompt with full access to the worktree, MCP servers, and any configured tools.
  5. Route response back. When the agent produces a response, Agor’s outbound routing hook intercepts it and posts it back into the same platform thread. Markdown is converted to platform-native formatting (e.g., Slack mrkdwn).
  6. Repeat. Follow-up messages in the same thread continue the same session — the agent has full conversation history.
Slack DM                    Agor Daemon                    Agent
────────                    ───────────                    ─────
  │                              │                           │
  │  "Fix the login bug"         │                           │
  ├─────────────────────────────>│                           │
  │                              │  Create session           │
  │                              │  + thread mapping          │
  │                              │                           │
  │                              │  Send prompt              │
  │                              ├──────────────────────────>│
  │                              │                           │
  │                              │        Agent response     │
  │                              │<──────────────────────────┤
  │   "I've fixed the login..."  │                           │
  │<─────────────────────────────┤                           │
  │                              │                           │
  │  "Can you also add tests?"   │                           │
  ├─────────────────────────────>│                           │
  │                              │  Route to same session    │
  │                              ├──────────────────────────>│
  │                              │                           │

The outbound routing is a lightweight after-hook on message creation. For sessions without a gateway mapping (the vast majority), it’s a single database lookup that returns immediately — effectively a no-op.

Setting Up Slack Integration

1. Create a Slack App

  1. Go to api.slack.com/apps and create a new app.
  2. Under OAuth & Permissions, add the chat:write bot scope.
  3. Under App Home, enable the Messages Tab and check “Allow users to send Slash commands and messages from the messages tab.”
  4. Under Event Subscriptions, subscribe to the message.im bot event.
  5. Under Socket Mode, enable Socket Mode and generate an App-Level Token (xapp-...).
  6. Install the app to your workspace and note the Bot User OAuth Token (xoxb-...).

2. Create a Channel in Agor

  1. Open Settings (gear icon) and navigate to the Gateway tab.
  2. Click Add Channel.
  3. Fill in:
    • Name — Give it a memorable name (e.g., “Optimus Prime”).
    • Channel Type — Select slack.
    • Target Worktree — Pick the worktree where sessions will run.
    • Bot Token — Paste the xoxb-... token.
    • App Token — Paste the xapp-... token (required for receiving DMs via Socket Mode).
  4. Optionally expand Agentic Tool Configuration to customize the agent, model, permission mode, and MCP servers for sessions created by this channel.
  5. Save. The daemon will immediately start a Socket Mode listener for this channel.

3. DM Your Bot

Open Slack, find your bot under Apps, and send it a message. You should see system debug messages confirming session creation, followed by the agent’s response — all in the same DM thread.

Agentic Tool Configuration

Each channel can define its own agent configuration, overriding the user’s defaults:

SettingDescriptionDefault
AgentWhich coding tool to use (Claude Code, Codex, Gemini, OpenCode)Claude Code
ModelModel alias or specific model IDUser’s default
Permission ModeHow the agent handles tool approvals (trust, auto, supervised, manual)Agent’s default
MCP ServersWhich MCP servers the agent can accessNone

The gateway resolves configuration with a fallback chain: channel config > user defaults > system defaults. This means you only need to configure what you want to override.

Architecture

The gateway is built as a set of loosely coupled components:

  • Gateway Service (/gateway) — Orchestrates inbound routing (platform to session) and outbound routing (session to platform). Custom FeathersJS service.
  • Gateway Channels (/gateway-channels) — CRUD for channel configurations with encrypted credential storage.
  • Thread-Session Map (/thread-session-map) — Persists the mapping between platform thread IDs and Agor session IDs.
  • Connector Layer — Platform-agnostic GatewayConnector interface with a registry pattern. Adding a new platform means implementing sendMessage() and optionally startListening().
  • Outbound Hook — FeathersJS after.create hook on the messages service. Fire-and-forget; never blocks message creation.

Adding a New Platform

The connector interface is intentionally minimal:

interface GatewayConnector {
  readonly channelType: ChannelType;
  sendMessage(req: { threadId: string; text: string }): Promise<string>;
  startListening?(callback: (msg: InboundMessage) => void): Promise<void>;
  stopListening?(): Promise<void>;
  formatMessage?(markdown: string): string;
}

Implement this interface, register it in the connector registry, and the gateway service handles the rest — authentication, thread mapping, session lifecycle, and outbound routing all work automatically.

Best Practices

  • Use trust or auto mode for unattended agents. If you want the agent to operate without human approval on each tool call, set the permission mode accordingly.
  • Attach relevant MCP servers. A Slack-connected agent that also has GitHub MCP can create PRs, check CI status, and post updates — all from a DM.
  • One worktree per concern. Create separate channels for different projects or responsibilities rather than funneling everything through one worktree.
  • Name channels descriptively. When you have multiple channels, names like “Frontend Review Bot (Sonnet)” are much more useful than “Channel 1.”
  • Keep credentials rotated. Bot tokens and app tokens are encrypted at rest, but rotate them periodically through the channel edit UI.

Troubleshooting

  • “Sending messages to this app has been turned off.” Enable the Messages Tab in your Slack app’s App Home settings, and subscribe to the message.im bot event.
  • Bot doesn’t respond to DMs. Check that Socket Mode is enabled, the app_token is set in the channel config, and the daemon logs show [gateway] Socket Mode listener started for channel "...".
  • Agent session created but no response. Verify that the coding agent (Claude Code, etc.) is authenticated inside the daemon’s environment. Check daemon logs for executor errors.
  • Response appears in logs but not in Slack. The bot_token may lack the chat:write scope, or the bot may not have permission to DM the user. Check Slack app permissions.
  • Infinite message loop. The connector filters out bot messages (bot_id or subtype: bot_message). If you see loops, check that your Slack app’s bot user is properly configured.
  • Worktree Scheduler — Automate recurring work on worktrees (complements gateway for event-driven vs. time-driven automation).
  • Agor MCP Server — Give gateway-spawned agents full self-awareness and orchestration capabilities.
  • Agent SDK Comparison — Choose the right coding agent for your channel’s use case.
  • Spawned Subsessions — Gateway-created sessions can themselves spawn child sessions for parallel work.
BSL 1.1 © 2026 Maxime Beauchemin