One Bot, Many Tasks: Full Workspace x Telegram Setup Guide

4 min read

Ever asked your assistant to "organize today's journal" and then watched it touch files from your work project instead?

That is what happens when workspaces are not configured correctly. This guide fixes that in one go.

What You'll Learn

  • Understand the full flow: group → assistant → workspace
  • Initialize multiple workspaces
  • Configure Agents + Bindings completely
  • Verify that the setup really works

The Overall Idea

The target architecture is simple:

Telegram Group A  →  Assistant A  →  Workspace A (touch only these files)
Telegram Group B  →  Assistant B  →  Workspace B (touch only these files)
Direct messages   →  Main assistant → Main workspace

To make that happen, you need three steps: create workspaces → define agents → define bindings.


Step 1: Create the Workspaces

Each assistant needs its own directory. Initialize them with:

openclaw setup --workspace "~/.openclaw/workspace-main"
openclaw setup --workspace "~/.openclaw/workspace-project-a"
openclaw setup --workspace "~/.openclaw/workspace-project-b"

Each workspace gets the necessary files automatically, such as AGENTS.md, SOUL.md, and IDENTITY.md.

💡 If the directory does not exist yet, the command creates it for you. If you cloned an existing workspace from Git, you can skip initialization and just point to the path in Config.


Step 2: Configure Agents and Bindings

Open Control UI → Config → Raw JSON and add the following structure.

Scenario A: Same bot, different groups, different workspaces

{
  "agents": {
    "list": [
      { "id": "main",      "name": "Main",      "workspace": "~/.openclaw/workspace-main",      "default": true },
      { "id": "project-a", "name": "Project A", "workspace": "~/.openclaw/workspace-project-a" },
      { "id": "project-b", "name": "Project B", "workspace": "~/.openclaw/workspace-project-b" }
    ]
  },
  "bindings": [
    { "agentId": "project-a", "match": { "channel": "telegram", "peer": { "kind": "group", "id": "-1001234567890" } } },
    { "agentId": "project-b", "match": { "channel": "telegram", "peer": { "kind": "group", "id": "-1009876543210" } } },
    { "agentId": "main",      "match": { "channel": "telegram" } }
  ],
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "your bot token",
      "dmPolicy": "pairing",
      "groups": { "*": { "requireMention": true } }
    }
  }
}

How do you find the group ID?

  1. Send any message in the group
  2. Run openclaw logs --follow and look for chat.id
  3. Or forward the message to @userinfobot

Scenario B: Different bot accounts, different workspaces

If you have multiple bot tokens, each bot can map to its own assistant and workspace:

{
  "agents": {
    "list": [
      { "id": "main",   "name": "Main Bot",   "workspace": "~/.openclaw/workspace-main",   "default": true },
      { "id": "alerts", "name": "Alerts Bot", "workspace": "~/.openclaw/workspace-alerts" }
    ]
  },
  "bindings": [
    { "agentId": "main",   "match": { "channel": "telegram", "accountId": "default" } },
    { "agentId": "alerts", "match": { "channel": "telegram", "accountId": "alerts" } }
  ],
  "channels": {
    "telegram": {
      "enabled": true,
      "accounts": {
        "default": { "botToken": "123456:ABC...", "dmPolicy": "pairing" },
        "alerts":  { "botToken": "987654:XYZ...", "dmPolicy": "allowlist", "allowFrom": ["tg:yourTelegramId"] }
      }
    }
  }
}

⚠️ When using multiple accounts, do not keep a top-level botToken. Put everything inside accounts.


Step 3: Save and Verify

From the Web UI: click Save / Apply on the Config page.

If you edit the file directly: save ~/.openclaw/openclaw.json. The Gateway usually hot-reloads, but if you are unsure, restart it:

openclaw gateway

How to verify

  • Send a message in each Telegram group and confirm the correct assistant replies
  • Run openclaw doctor for a quick health check

Key Points to Remember

Goal How
Create a new workspace openclaw setup --workspace "path"
Different group → different workspace Match peer: { kind: "group", id: "groupId" } in bindings
Different bot → different workspace Use channels.telegram.accounts with accountId in bindings
Bindings seem ignored Put the specific rules first; matching is first-hit-wins