Skip to main content

OpenClaw

OpenClaw is an open-source AI agent that connects to messaging platforms like WhatsApp, Telegram, Slack, and Discord. With Roam, you can run your agent directly inside Roam chat — users DM it, mention it in groups, and pull it into threads, the same way they would any teammate.

This guide is mostly about that — running an OpenClaw bot in Roam chat. There are two flavors of bot (Personal and Org); pick whichever fits your use case and follow the matching section. You can run both side by side on the same OpenClaw install.

If you'd rather drive OpenClaw from another surface (Telegram, Slack, terminal) and only need it to read or write Roam data, jump to Use Roam as a data source from another surface at the bottom.

Prerequisites

  • A running OpenClaw instance
  • A Roam workspace where you can create either a Personal Access Token (for a Personal Bot) or an API Key (for an Org Bot)

Pick your bot

Personal BotOrg Bot
Acts asYou (the user who created the token).Its own persona (e.g. "OnCallBot"), owned by the workspace.
Who can talk to itOnly you. Other users can't DM it or mention it.Anyone in the workspace can DM it, @-mention it, or pull it into a thread.
In groupsCannot be added as a member. Only sees messages where you explicitly @-mention it in your own chats.Can be added as a member of any group (required for private groups). In public groups, mentions work without membership.
Token typePersonal Access Token (rmp-…).API Key (rmk-…).
Best forPersonal workflows — research, summarizing your own meetings, drafting messages on your own data.Team workflows — on-call assistant, FAQ bot, status reports, anything everyone needs to talk to.

Run both at once if you need both — see Run multiple bots from one OpenClaw install.

How access control works (read this first)

OpenClaw used to require a per-sender pairing challenge before the bot would respond to a DM. That's no longer the default. The current model is intentionally simple:

  • A Personal Bot responds only to its owner. Automatic — the plugin discovers the owner from /v1/token.info at startup and drops every inbound from anyone else, on every surface. No setup needed; no allowlist to maintain. An adversary who creates a private group and adds the bot still gets dropped.
  • An Org Bot responds to anyone who can reach it in the workspace. No per-sender approval — the security boundary is workspace membership (and, for private groups, who's been added to that group). This matches how bots in Slack, Discord, and Telegram work at the protocol level.

If you need a hard sender allowlist on an Org Bot, set allowFrom (for DMs) or groupAllowFrom (for groups) on the account — see Restricting which users can talk to the bot. Pairing is still available as an explicit opt-in (dmPolicy: "pairing") for operators who want a UX-driven approval flow, but it's no longer recommended.

Set up a Personal Bot

A Personal Bot acts as you. You can DM it for one-on-one help, or @-mention it from groups you're in to pull it into a conversation on your own behalf. It can't be added to groups as a member, and other users can't talk to it directly.

1. Create a Personal Access Token in Roam

Prerequisite: Your workspace admin must enable Personal Access Tokens (see Admin Policy for Personal Access).

  1. In Roam, open User Settings > Developer.
  2. Click Create Personal Access Token.
  3. Name it (e.g. "OpenClaw").
  4. Select the permissions to grant — at minimum Chat Send and Chat Read so the agent can send and receive messages. Add Meetings Read if you want it to access your meetings.
  5. Upload an avatar image — this is the picture shown next to the agent's messages in Roam chat.
  6. Click Create Token. Copy both the token (starts with rmp-…) and the webhook signing secret shown on the confirmation screen — you'll need both in the next step.

2. Approve the token

If your workspace requires admin approval for personal access (the default), an admin must approve the new token before it can be used:

  1. In Roam, open Roam Administration > Developer > Personal Access Tokens.
  2. Find the new token and click Approve.

If your workspace is set to Auto-approve, skip this step. See Admin Policy for Personal Access.

3. Install the channel plugin

In your OpenClaw instance:

openclaw plugins install @roamhq/openclaw-roam

4. Configure the plugin

Set the token, webhook signing secret, and webhook URL under channels.roam.accounts.default:

openclaw config set channels.roam.accounts.default.apiKey         "$TOKEN"
openclaw config set channels.roam.accounts.default.webhookSecret "$WHSEC"
openclaw config set channels.roam.accounts.default.webhookUrl https://YOUR_HOST/roam-webhook

Replace https://YOUR_HOST/roam-webhook with the public URL of your OpenClaw instance — the plugin registers a local listener at that URL's path and automatically subscribes Roam to deliver messages there on startup. If your OpenClaw instance is only accessible on a private network during development, tools like ngrok or Cloudflare Tunnel can expose it temporarily.

The accounts.default prefix keeps room for running multiple bots later without restructuring config.

Apply the changes:

openclaw daemon restart

Every config change in this guide takes effect after a gateway restart.

5. Verify

Send a direct message to your bot in Roam. It should reply.

6. Using the bot from groups you're in

To pull the bot into a conversation in a group you're already part of, just @-mention it. The bot's webhook fires for that single message; it replies in-thread under your mention so the conversation stays scoped.

The bot ignores everyone except you, automatically:

  • It cannot be added as a member of any group (Roam restricts PAT bots to user-typed accounts).
  • Even when other users in a group try to @-mention or DM it, the plugin drops their messages — it discovers your user ID from /v1/token.info at startup and responds only to that ID. Same rule on every surface; no allowlist to maintain.

If you want a bot that anyone can talk to, you want an Org Bot — see the next section.

Set up an Org Bot

An Org Bot is its own persona — anyone in the workspace can DM it for help, @-mention it from any chat to pull it into a thread, or add it as a member of a channel where it responds to every message (your choice).

1. Create an API Key in Roam

You'll need workspace-admin access for this step.

  1. As a Roam admin, open Roam Administration > Developer.
  2. Create a new API Client and select API Key as the authorization type.
  3. Give it a name (e.g. "OnCallBot") and select the scopes for what the bot will do — at minimum:
    • chat:send_message — Send messages
    • chat:read — List groups it's added to
    • chat:history — Read recent messages in those groups (used for context)
  4. Add additional scopes as needed: meetings:read, recordings:read, transcript:read, groups:read, etc.
  5. Upload an avatar image and set a display name — this is what users see in Roam chat.
  6. Click Create. Copy both the token (rmk-…) and the webhook signing secret.

You'll add the bot to specific groups later in Verify, once the OpenClaw side is wired up.

2. Install the channel plugin

If you haven't already:

openclaw plugins install @roamhq/openclaw-roam

3. Register an agent profile for the bot

Each bot gets its own agent — its own workspace directory, its own identity, its own system prompt. Pick an agentId (short string, used internally) and a workspace directory:

mkdir -p /Users/you/openclaw-orgbot-agent

openclaw config set agents.list '[
{"id":"main","default":true,"workspace":"/Users/you/jarvis"},
{"id":"orgbot","name":"orgbot","workspace":"/Users/you/openclaw-orgbot-agent","identity":{"name":"OnCallBot","emoji":"🚨"}}
]' --strict-json

agents.list is an array; openclaw config set replaces it wholesale, so pass the full list including every existing agent (preview the current list with openclaw config get agents.list). identity.name is what Roam users see as the agent's display name in chat.

4. Register the Roam account and bind it to the agent

ACCOUNT_ID=orgbot

openclaw config set channels.roam.accounts.$ACCOUNT_ID.apiKey "$ORG_TOKEN"
openclaw config set channels.roam.accounts.$ACCOUNT_ID.webhookSecret "$ORG_WHSEC"
openclaw config set channels.roam.accounts.$ACCOUNT_ID.webhookUrl https://YOUR_HOST/roam-webhook-$ACCOUNT_ID
openclaw config set channels.roam.accounts.$ACCOUNT_ID.enabled true

The webhook path must be /roam-webhook-<accountId> for non-default accounts (the plugin registers exactly one listener per account at that path). You can reuse the same public host as another bot — both terminate at the same gateway, on different paths.

Bind the new account to the new agent (so inbound from this account routes to its own agent rather than falling through to the default):

openclaw config set bindings '[
{"agentId":"orgbot","comment":"OnCallBot Roam account","match":{"channel":"roam","accountId":"orgbot"}}
]' --strict-json

bindings is a top-level config array; same rule as agents.listconfig set replaces, so include every existing binding.

Apply:

openclaw daemon restart

In openclaw logs, you should see a Roam webhook monitor start and a Roam webhooks subscribed line for the new account. The Roam bot persona line confirms the bot identity the plugin will use for self-message filtering:

[orgbot]  Roam bot persona: OnCallBot  (rmk-… bot id)

5. Pick a channel response mode

An Org Bot in a channel can respond in one of two modes:

  • Proactive — bot replies to every message in the channel. Best for narrow-purpose channels (e.g. an #alerts channel where every message is something the bot should triage). Requires requireMention: false and that the bot be a member of the group.
  • Mention-only — bot replies only when @-mentioned. Best for general channels where the bot is one tool among many.

Out of the box, the bot answers in any group it can hear (defaults are groupPolicy: "open" and mention-only). If that's what you want, you're done — add the bot to the group in Roam and it'll respond to @-mentions there.

To opt into proactive mode for a specific group, add an entry under the org account's groups map:

openclaw config patch --stdin <<EOF
{
"channels": {
"roam": {
"accounts": {
"$ACCOUNT_ID": {
"groups": {
"GROUP_ID": { "requireMention": false, "replyInThread": true }
}
}
}
}
}
}
EOF

openclaw daemon restart

GROUP_ID is the group's ID, found at the bottom of the group's Group Settings page in Roam.

What each field does:

  • groups.GROUP_ID — per-group overrides for the named group. Anything you don't set falls back to defaults.
  • requireMention: false — bot reacts to every message in this group, not only @-mentions. Default is true (mention-only).
  • replyInThread: true — bot replies in a new thread under the triggering message (or the existing thread if the message is already in one). Strongly recommended for proactive bots to avoid cluttering the channel top-level.1

Want stricter group access (only specific groups respond)? Set groupPolicy: "allowlist" and list groups explicitly — see Restricting which users can talk to the bot below.

6. Give the bot a persona

A new bot has no behavior of its own — it'll respond like a generic assistant. Set systemPromptOverride on its agent profile so the bot knows who it is and what to do.

Because agents.list is an array (not a map keyed by id), there's no openclaw config set agents.list[orgbot].systemPromptOverride shorthand. Either edit ~/.openclaw/openclaw.json directly, or pull-modify-push the array:

$EDITOR ~/.openclaw/openclaw.json
# Find the entry for your agentId, add "systemPromptOverride": "..."
openclaw daemon restart

Or:

openclaw config get agents.list > /tmp/agents.json
# Edit /tmp/agents.json
openclaw config set agents.list "$(cat /tmp/agents.json)" --strict-json
openclaw daemon restart

Here's a starter prompt for an SRE-style bot that investigates Datadog alerts:

You are OpenClaw SRE, an on-call assistant living in a Roam channel. Every
message in this channel is typically a Datadog alert. Your job is to
investigate and report.

When a new alert arrives:
1. Extract the monitor name, the failing condition, the affected service /
host / tag(s), and the alert time window.
2. Investigate using the `datadog` MCP server: monitor details, metrics for
the affected service around the alert time, related logs, recent deploys.
3. Reply with a concise, well-structured investigation:
- **Summary** — one sentence: what's wrong and the likely cause.
- **Evidence** — specific metric values, log excerpts, exact times.
- **Suggested next steps** — what a human on-call would do next.
4. Keep replies tight. No filler.
5. If you can't form a hypothesis, say so plainly — list what you looked at.
6. If a message is clearly not an alert, respond only if you can help;
otherwise stay silent.
7. Never claim a fix is applied. You investigate and report; humans act.

When asked who you are, say you are OpenClaw SRE.

Wire up tools (e.g. Datadog MCP)

For a proactive investigator-style bot to be useful, give it tools. OpenClaw supports both stdio MCP servers (local processes) and HTTP MCP servers (remote endpoints). Configure them globally under mcp.servers and they become available to every agent — including your new one.

Datadog's remote MCP server, authed with API key + Application key in headers:

openclaw mcp set datadog '{
"url": "https://mcp.datadoghq.com/api/unstable/mcp-server/mcp",
"transport": "streamable-http",
"headers": {
"DD-API-KEY": "<your-api-key>",
"DD-APPLICATION-KEY": "<your-application-key>"
}
}'
openclaw daemon restart

Get the credentials in Datadog:

  • API key — Organization Settings → API Keys → New Key.
  • Application key — Personal Settings → Application Keys → New Key. Scope it to the read endpoints the bot needs (monitors_read, metrics_read, logs_read, events_read).

For the EU site, use mcp.datadoghq.eu; for other sites, see Datadog's regional URL list.

Auth caveats: OpenClaw's MCP config supports command/args/env (stdio) and url/transport/headers (HTTP), but doesn't run an interactive OAuth flow for remote MCP servers. If a server requires OAuth, run a local stdio MCP proxy that handles the OAuth dance and exposes the same tools over stdio.

7. Verify

  1. DM the bot. Open a direct message with the new bot in Roam and send it a hello. It should reply with the persona you set.
  2. Add the bot to a group. Go to Group Settings for the group you want it to live in and add the new bot as a member. (Required for private groups; for public groups, mentioning the bot from anywhere already triggers it.)
  3. Post a message. In proactive mode, post any message — the bot replies in a new thread. In mention-only mode, @-mention the bot — same result.
  4. Pull it into a thread. From another chat the bot isn't a member of, @-mention it inside an existing thread. The bot replies in that same thread.

If something feels off, two log filters worth knowing:

# Did this account see the message?
openclaw logs --follow --plain 2>&1 | grep "roam\[orgbot\]"

# Did the agent reach Datadog (or whatever MCP server)?
openclaw logs --follow --plain 2>&1 | grep -i "datadog\|mcp"

Drop-reason log lines prefix the account id (roam[default]: / roam[orgbot]:) so you can tell exactly which bot dropped a message and why.

Caveats for proactive bots

  • Self-message loop protection comes from the bot's identity. When the bot posts a reply, Roam delivers that outbound back via the webhook (the bot is technically a participant in its own chat). The plugin filters these out by comparing sender against the bot's address ID, which is fetched at startup via /v1/token.info. If that call fails, the log will say Could not fetch bot identity from token.info; self-message filtering disabled — in that state, with requireMention: false, the bot will loop on its own replies. Fix the token.info issue (check token scopes and approval) before enabling proactive mode.

  • Every message in the channel triggers a turn. If the channel is busy, agent runs queue up and tokens burn fast. Watch agents.defaults.maxConcurrent and consider adding a systemPrompt per-group that tells the agent when not to reply.

  • Session/memory model. By default, the channel maps to a single session — the bot has full context of the channel as one long conversation. For high-traffic channels you may want shorter context windows or a different session-scoping strategy.

  • Tokens stored in plaintext. OpenClaw stores the API key directly in ~/.openclaw/openclaw.json. For shared-host deployments, consider using apiKeyFile instead (point at a file with mode 0600 that only the gateway user can read).

Restricting which users can talk to the bot

Org bots are open to the workspace by default. To restrict them, opt into one or both allowlists:

Restrict senders in DMs. Set dmPolicy: "allowlist" (or "pairing" if you want a UX-driven approval flow) and list the user IDs allowed to DM the bot:

openclaw config set channels.roam.accounts.orgbot.dmPolicy allowlist
openclaw config set channels.roam.accounts.orgbot.allowFrom \
'["USER_ID_1","USER_ID_2"]' --strict-json
openclaw daemon restart

Restrict senders in groups. Same shape, group-side:

openclaw config set channels.roam.accounts.orgbot.groupPolicy allowlist
openclaw config set channels.roam.accounts.orgbot.groupAllowFrom \
'["USER_ID_1","USER_ID_2"]' --strict-json
openclaw daemon restart

Restrict to specific groups. Setting groupPolicy: "allowlist" also turns the groups map into a strict allowlist — only listed groups are allowed; unlisted groups are dropped silently.

USER_ID is a Roam user ID, not a group ID. Most setups don't need any of this — workspace membership is usually a sufficient boundary for Org Bots.

Run multiple bots from one OpenClaw install

You can run a Personal Bot and an Org Bot (or any combination) side by side from one OpenClaw instance. Each is its own account in the channel config, with its own webhook path, its own token, and optionally its own agent profile.

Set up each bot using the matching section above. The pieces fit together as follows:

channels.roam.accounts.default          ← Personal Bot (rmp-…)
channels.roam.accounts.orgbot ← Org Bot (rmk-…)
channels.roam.accounts.<anotherId> ← additional bot

bindings: [
{ match: { channel: "roam", accountId: "orgbot" }, agentId: "orgbot" },
{ match: { channel: "roam", accountId: "anotherId" }, agentId: "another" },
// unbound accounts fall through to the default agent
]

agents.list: [
{ id: "main", default: true, workspace: "/Users/you/jarvis" },
{ id: "orgbot", workspace: "/Users/you/openclaw-orgbot-agent", identity: {...} },
{ id: "another", workspace: "/Users/you/another-agent", identity: {...} },
]

Webhook paths

AccountPath
default/roam-webhook
Any named account/roam-webhook-<accountId>

All paths terminate at the same gateway port — the plugin de-multiplexes by path. Configure each in Roam separately when you create the token (the plugin auto-subscribes on startup using the webhookUrl you set).

Routing inbound to the right agent

If you don't bind an account to an agent, inbound from that account goes to the default agent (agents.list[].default: true). That's often what you want for a Personal Bot — it shares your main agent's workspace and memory. For an Org Bot you almost always want a separate agent profile (its own workspace directory and persona) bound via bindings.

Verifying all bots came up

After openclaw daemon restart, you should see one Roam webhook monitor start and one Roam bot persona line per account in openclaw logs:

[default]  Roam webhook monitor starting
[default] Roam webhooks subscribed
[default] Roam bot persona: You (rmp-…)
[orgbot] Roam webhook monitor starting
[orgbot] Roam webhooks subscribed
[orgbot] Roam bot persona: OnCallBot (rmk-…)

If an account's monitor doesn't start, double-check that enabled isn't set to false and that the webhook URL/path is unique across accounts.

Use Roam as a data source from another surface

If you don't need a chat experience in Roam — you're driving OpenClaw from Telegram, Slack, the terminal, etc. — and just want the agent to read or write Roam data (meetings, transcripts, chat history, sending the occasional message), install the Roam skill instead of the channel plugin.

clawhub install roam

Configure your token by either telling the agent to save it on first use, or setting it manually in ~/.openclaw/openclaw.json:

{
"env": {
"ROAM_API_KEY": "YOUR_API_TOKEN"
}
}

Use either a Personal Access Token (acts as you) or an Org API Key (acts as the org bot persona) — same trade-offs as in Pick your bot. No restart needed; the environment is read per session.

What you can ask the agent to do

Once the skill is installed, try:

  • "Summarize my meetings from this week."
  • "What did we decide about pricing in last week's meeting?"
  • "What action items came out of the product review?"
  • "Send a message to Engineering: deploy is complete."
  • "Post the weekly standup summary to General."

The skill uses the Roam API to list meetings, retrieve transcripts, run AI-powered transcript analysis, send messages, and browse chat history. See the API documentation for a complete endpoint reference.

Skill + channel plugin together

If you install both the channel plugin and the skill, the plugin auto-exports channels.roam.<account>.apiKey as ROAM_API_KEY at runtime, so the skill picks up the same token as the bot — no separate API key setup needed.

Footnotes

  1. replyInThread defaults to false today. A planned plugin change makes it default to true when requireMention: false so proactive bots get threading automatically; mention-only bots keep the default of replying at top level.