#新手小白也能轻松搞定龙虾🦞 team!你要做的只有两步

我想把 OpenClaw 接入 Telegram,搞三个 Bot:一个主脑、一个写代码、一个写文章。群里 @ 谁谁干活,多优雅。

结果就是花了 13个 小时,踩了 6 个坑,心态崩了三次。

BotFather 在哪?Group ID 怎么拿?Token 存哪?为什么三个 Bot 互相串号?为什么日志疯狂报错 ?

每个问题都能搜到答案,但答案散落在不同的地方,还互相矛盾。我像个无头苍蝇,试 A 错,试 B 错,试 C 对但不知道为啥对。

当我终于搞定让bot跑起来之后,

我意识到:

这 13个小时本可以压缩到 10 分钟,这个事情本来应该让openclaw🦞来做。

所以我写了这篇同时面向人类和openclaw🦞的教程。

你要做的就三步,就算是新手小白也能轻松搞定。

---

#第一步——找 BotFather 拿 Token

在 Telegram 搜索框输入 @BotFather,开始对话,输入 /newbot

它问你名字,随便取。然后问用户名,必须以 _bot 结尾,而且全局唯一。被占用就重试,试到通过。

BotFather 甩给你一串 Token:123456789:ABCdef...

这串 Token 是你的 Bot 身份证,保存好。

重复三次,拿到三个 Bot 的 Token。
然后输入框发送/setprivacy,依次点选agent名称,发送DISABLED完成3个agent权限的设置

---

#第二步——拿 Group ID

把 Bot 拉进任意一个群,发一条消息。

然后对话框找到 @raw_data_bot,输入/start,转发一条群消息

看到 返回的 chat.id,就是 Group ID。比如 -1232456780

保存这个 ID。

---

#第三步——让龙虾帮你配置

前面两步是准备工作,真正的配置不用你动手。

打开你的 OpenClaw 对话,把下面这段发给它:

AI 执行部分(请参考全流程严格执行)

把下面这段发给你的 AI,填好 7 个参数,它会自动跑完整流程。

## 🎯 任务:一键配置 OpenClaw 接入 Telegram 多 Agent

你是 OpenClaw 配置工程师,请严格按步骤执行并输出每步结果。

### 0) 先填参数(7个)

TELEGRAM_GROUP_ID=<你的群ID,负数>
BOT_DEFAULT_USERNAME=<主Bot用户名,不带@>
BOT_CODER_USERNAME=<Coder Bot用户名,不带@>
BOT_WRITER_USERNAME=<Writer Bot用户名,不带@>
BOT_DEFAULT_TOKEN=<主Bot Token>
BOT_CODER_TOKEN=<Coder Bot Token>
BOT_WRITER_TOKEN=<Writer Bot Token>

---

### 1) 环境变量与备份(必须先做)

export OPENCLAW_HOME="$HOME/.openclaw"
export CONFIG_FILE="$OPENCLAW_HOME/openclaw.json"
export TELEGRAM_GROUP_ID="<TELEGRAM_GROUP_ID>"
export BOT_DEFAULT_USERNAME="<BOT_DEFAULT_USERNAME>"
export BOT_CODER_USERNAME="<BOT_CODER_USERNAME>"
export BOT_WRITER_USERNAME="<BOT_WRITER_USERNAME>"
export BOT_DEFAULT_TOKEN="<BOT_DEFAULT_TOKEN>"
export BOT_CODER_TOKEN="<BOT_CODER_TOKEN>"
export BOT_WRITER_TOKEN="<BOT_WRITER_TOKEN>"

cp "$CONFIG_FILE" "$CONFIG_FILE.bak.$(date +%s)"
echo "backup ok: $CONFIG_FILE.bak.*"


### 2) 自动写入 Telegram 多 Bot 配置(Python)

python3 - <<'PY'
import json, os

cfg_path = os.environ["CONFIG_FILE"]
gid = os.environ["TELEGRAM_GROUP_ID"]
u0 = os.environ["BOT_DEFAULT_USERNAME"]
u1 = os.environ["BOT_CODER_USERNAME"]
u2 = os.environ["BOT_WRITER_USERNAME"]
t0 = os.environ["BOT_DEFAULT_TOKEN"]
t1 = os.environ["BOT_CODER_TOKEN"]
t2 = os.environ["BOT_WRITER_TOKEN"]

with open(cfg_path, "r", encoding="utf-8") as f:
cfg = json.load(f)

#channels.telegram

channels = cfg.setdefault("channels", {})
tg = channels.setdefault("telegram", {})
tg["enabled"] = True
tg.setdefault("dmPolicy", "pairing")
tg.setdefault("groupPolicy", "allowlist")

accounts = tg.setdefault("accounts", {})
accounts["default"] = {
"name": "main", "enabled": True, "botToken": t0,
"dmPolicy": "pairing", "groupPolicy": "allowlist",
"commands": {"native": False, "nativeSkills": False},
"groups": {gid: {"requireMention": True}}
}
accounts["coder"] = {
"name": "coder", "enabled": True, "botToken": t1,
"dmPolicy": "pairing", "groupPolicy": "allowlist",
"commands": {"native": False, "nativeSkills": False},
"groups": {gid: {"requireMention": True}}
}
accounts["writer"] = {
"name": "writer", "enabled": True, "botToken": t2,
"dmPolicy": "pairing", "groupPolicy": "allowlist",
"commands": {"native": False, "nativeSkills": False},
"groups": {gid: {"requireMention": True}}
}

#bindings(只重建 telegram coder/writer 的绑定)

bindings = cfg.setdefault("bindings", [])
bindings = [
b for b in bindings
if not (b.get("match", {}).get("channel") == "telegram" and b.get("match", {}).get("accountId") in ("coder", "writer"))
]
bindings += [
{"agentId": "coder", "match": {"channel": "telegram", "accountId": "coder"}},
{"agentId": "writer", "match": {"channel": "telegram", "accountId": "writer"}}
]
cfg["bindings"] = bindings

#plugins.telegram enabled

plugins = cfg.setdefault("plugins", {})
allow = plugins.setdefault("allow", [])
if "telegram" not in allow:
allow.append("telegram")
entries = plugins.setdefault("entries", {})
entries.setdefault("telegram", {})
entries["telegram"]["enabled"] = True

#agents.list mentionPatterns(精准@路由,防 no-mention)

agents = cfg.setdefault("agents", {})
alist = agents.setdefault("list", [])

def get_or_create_agent(agent_id, default_obj):
for a in alist:
if a.get("id") == agent_id:
return a
alist.append(default_obj)
return default_obj

coder = get_or_create_agent("coder", {
"id": "coder", "name": "coder",
"workspace": os.path.join(os.environ["OPENCLAW_HOME"], "workspace"),
"agentDir": os.path.join(os.environ["OPENCLAW_HOME"], "agents/coder/agent"),
"model": "bailian/kimi-k2.5"
})
writer = get_or_create_agent("writer", {
"id": "writer", "name": "writer",
"workspace": os.path.join(os.environ["OPENCLAW_HOME"], "workspace"),
"agentDir": os.path.join(os.environ["OPENCLAW_HOME"], "agents/writer/agent"),
"model": "bailian/kimi-k2.5"
})

coder["groupChat"] = {"mentionPatterns": [f"@{u1}"]}
writer["groupChat"] = {"mentionPatterns": [f"@{u2}"]}

with open(cfg_path, "w", encoding="utf-8") as f:
json.dump(cfg, f, ensure_ascii=False, indent=2)
f.write(" ")
print("✅ config updated:", cfg_path)
PY


### 3) Session 索引修复(正确处理 OpenClaw 结构)

python3 - <<'PY'
import json, glob, os, time, shutil

root = os.path.join(os.environ["OPENCLAW_HOME"], "agents")
for sp in glob.glob(os.path.join(root, "*/sessions/sessions.json")):
sdir = os.path.dirname(sp)
with open(sp, "r", encoding="utf-8") as f:
data = json.load(f)
changed = 0
for _, v in data.items():
sf = v.get("sessionFile")
sid = v.get("sessionId")
# 统一成相对文件名
if isinstance(sf, str) and sf.strip():
b = os.path.basename(sf.strip())
if sf != b:
v["sessionFile"] = b
changed += 1
elif isinstance(sid, str) and sid.strip():
v["sessionFile"] = sid.strip() + ".jsonl"
changed += 1
# 缺文件就补空
sf2 = v.get("sessionFile")
if isinstance(sf2, str) and sf2.strip():
p = os.path.join(sdir, sf2)
if not os.path.exists(p):
open(p, "a", encoding="utf-8").close()
if changed:
bak = sp + f".bak.relfix.{int(time.time())}"
shutil.copy2(sp, bak)
with open(sp, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
f.write(" ")
print("✅ fixed:", sp, "backup:", bak)
else:
print("✅ ok:", sp)
PY


### 4) 人格隔离规则(防子 Agent 读 main SOUL)

cat > "$OPENCLAW_HOME/workspace/AGENTS.md" <<'EOF'

#Persona Boundaries

  • main -> SOUL.md + IDENTITY.md (workspace root)
  • coder -> agents/coder/SOUL.md + agents/coder/IDENTITY.md
  • writer -> agents/writer/SOUL.md + agents/writer/IDENTITY.md

Rules:

  • Child agents must NOT read root SOUL.md
  • WebUI default session is main, so it follows root SOUL.md
  • EOF
    echo "✅ persona boundary file updated"


### 5) 校验 + 重启 + 状态检查

python3 -m json.tool "$CONFIG_FILE" >/dev/null && echo "✅ json valid"
openclaw gateway restart
openclaw gateway status --json
openclaw channels status --json
openclaw channels logs --channel telegram --lines 200 --json


### 6) 人工验收(让用户发消息)

请用户做 6 条测试:
- 群里:@<BOT_CODER_USERNAME> 回1(只 coder 回)
- 群里:@<BOT_WRITER_USERNAME> 回2(只 writer 回)
- 群里:@<BOT_DEFAULT_USERNAME> 回3(只 main 回)
- 私聊 coder:/start + 测试123
- 私聊 writer:/start + 测试123
- 私聊 default:/start + 测试123

### 7) 失败时应急(只重置某个子 Agent 群会话)

#改成 coder 或 writer

export AGENT_ID="writer"
python3 - <<'PY'
import json, os, time, shutil

agent = os.environ["AGENT_ID"]
gid = os.environ["TELEGRAM_GROUP_ID"]
sp = f"{os.environ['OPENCLAW_HOME']}/agents/{agent}/sessions/sessions.json"

with open(sp, "r", encoding="utf-8") as f:
data = json.load(f)

key = f"agent:{agent}:telegram:group:{gid}"
if key in data:
bak = sp + f".bak.reset.{int(time.time())}"
shutil.copy2(sp, bak)
data.pop(key, None)
with open(sp, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
f.write(" ")
print("✅ removed:", key, "backup:", bak)
else:
print("ℹ️ key not found:", key)
PY

openclaw gateway restart


### 8) 完成输出模板(让 AI 按这个格式回)

- 已改文件列表
- 每条命令执行结果(成功/失败)
- 当前 gateway/channels 状态摘要
- 验收是否通过(通过/未通过)
- 如未通过,下一步具体动作

---

🦞 **OpenClaw 进阶系列**:← 前置 [[../20260311-你的龙虾🦞总是失忆?给我三分钟手把手教它记|MemOS记忆]] | [[../20260306-OpenClaw新手教程:从零搭建AI日报小助手|AI日报]]
🔁 更多场景:[[../20260327-从工作到生活-普通人的OpenClaw全方位实用案例|全方位实用案例]]
🔁 后继者:[[../20260410Hermes究竟是什么?普通人可以怎么用|Hermes]] | [[../20260411弃坑OpenClaw_转投Hermes|弃坑转投Hermes]]