首页 / 正文

Openclaw API 被封后,照样在 Discord 里用 Claude Code:用 Bot + ACP 搭一条“聊天式编程通道”

Mooko
发布于 2026-04-21 · 5分钟阅读
1287 浏览
0 点赞 暴击点赞!

Openclaw API 被封后,怎么继续用 Claude Code?

你现在遇到的情况很典型:Claude 订阅还能用,Openclaw API 调用被封了,很多自动化脚本直接断粮。

解决思路也很直接:

  • 别跟 API 死磕,走订阅可用的通道
  • 把 CC 变成 Discord Bot,让它在频道里收消息、回消息
  • 用 ACP 把“Discord 消息”变成“CC 能理解的任务”

搭好之后的体验是什么?

  • 你在 Discord 里丢一句:“把这个报错修了,顺便加单测”
  • CC 回你 patch、解释、命令
  • 甚至可以让其他 agent 在同一个频道里把任务接力下去

下面按可执行步骤来。🧰


你要准备的东西

账号与权限

  • 一个 Discord 账号
  • 你有权限管理的 Discord 服务器(或者自己建一个)
  • Claude Code(CC)可运行的环境(本机 / 服务器都行)

你要跑的组件(建议这样拆)

  • Discord Bot:负责收发 Discord 消息
  • ACP Bridge(桥接服务):负责把消息转成 ACP 请求,再把结果发回 Discord
  • Claude Code:真正干活的“写代码的人”

一句话:Bot 不直接懂代码,它只负责搬运。懂代码的是 CC。


步骤 1:把 CC 配成一个 Discord Bot(先把 Bot 搞出来)

1)创建 Bot

  1. 打开 Discord Developer Portal:https://discord.com/developers/applications
  2. New Application 新建应用
  3. Bot 标签页
  4. Add Bot
  5. Bot Token 复制出来(这玩意等同密码,别发群里)

建议顺手做两件事:

  • 关掉 Public Bot(不想被路人拉走就关)
  • 打开需要的 Privileged Gateway Intents(至少要 Message Content,后面才读得到文本)

2)给 Bot 配权限(别小气,不然各种“收不到消息”)

常用权限:

  • View Channels
  • Send Messages
  • Read Message History
  • Manage Threads(可选)
  • Use Slash Commands(如果你想用 /cc 这种)

步骤 2:把 Bot 邀请进你的服务器

  1. Developer Portal → OAuth2URL Generator
  2. Scopes 勾:
    • bot
    • applications.commands(要 slash 命令就勾)
  3. Permissions 勾上前面那套
  4. 复制生成的邀请链接
  5. 打开链接 → 选择服务器 → 授权

进你的 Discord 服务器看看成员列表,Bot 出现就 OK。


步骤 3:用 ACP 打通“Discord ↔ CC”的消息通道

你原始思路里提到的核心点就是这个:

通过 ACP 协议,CC 可以在 Discord 里接受和回复其他 agent 和主人的消息

ACP 在这里干嘛?

把它想象成一套“快递单格式”:

  • Discord 发来一句话
  • Bridge 把它包装成 ACP 任务(带上 channel、user、上下文)
  • CC 处理完把结果再按 ACP 格式回传
  • Bridge 再把结果发回 Discord

你要实现的关键能力就两条:

  • 从 Discord 读消息
  • 把消息转发给 CC(ACP 请求)并拿回结果

推荐落地方式:一个最小可用的 Bridge(Python 例子)

你可以用 Node.js / Go / Python,逻辑都一样。下面用 Python 写得清爽一点。

安装依赖

pip install -U discord.py aiohttp

配置环境变量

export DISCORD_BOT_TOKEN="你的token"
export ACP_ENDPOINT="http://127.0.0.1:9000/acp"  # 你自己的 ACP 服务地址
export CC_ALLOWED_CHANNELS="123,456"             # 只允许这些频道触发,防止乱入

Bridge 主程序(示例)

import os
import json
import aiohttp
import discord

TOKEN = os.environ["DISCORD_BOT_TOKEN"]
ACP_ENDPOINT = os.environ["ACP_ENDPOINT"]
ALLOWED = set(x.strip() for x in os.getenv("CC_ALLOWED_CHANNELS", "").split(",") if x.strip())

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)

async def call_acp(payload: dict) -> str:
    async with aiohttp.ClientSession() as session:
        async with session.post(ACP_ENDPOINT, json=payload, timeout=300) as resp:
            resp.raise_for_status()
            data = await resp.json()
            return data.get("text", "(空响应)")

@client.event
async def on_message(message: discord.Message):
    if message.author.bot:
        return

    # 限制频道,别让全服都能叫它干活
    if ALLOWED and str(message.channel.id) not in ALLOWED:
        return

    content = message.content.strip()

    # 触发规则:以 !cc 或 @bot 开头
    is_mention = client.user in message.mentions if client.user else False
    if not (content.startswith("!cc") or is_mention):
        return

    # 清理触发前缀
    if content.startswith("!cc"):
        prompt = content[len("!cc"):].strip()
    else:
        prompt = content.replace(f"<@{client.user.id}>", "").strip()  # type: ignore

    if not prompt:
        await message.channel.send("你要我干啥?给一句清晰的需求,比如:`!cc 帮我把这段代码改成异步`")
        return

    await message.channel.typing()

    acp_payload = {
        "type": "task",
        "source": "discord",
        "channel_id": str(message.channel.id),
        "user": {
            "id": str(message.author.id),
            "name": message.author.name
        },
        "text": prompt,
        "context": {
            "message_id": str(message.id),
            "guild_id": str(message.guild.id) if message.guild else None
        }
    }

    try:
        reply = await call_acp(acp_payload)
    except Exception as e:
        await message.channel.send(f"桥接挂了:{e}")
        return

    # Discord 单条消息有长度限制,简单切片
    chunks = [reply[i:i+1800] for i in range(0, len(reply), 1800)]
    for c in chunks:
        await message.channel.send(c)

client.run(TOKEN)

你会发现:这段程序完全不关心“Claude 怎么跑”。

它只干一件事:把 Discord 消息扔给 ACP Endpoint,再把返回值贴回 Discord。


那 ACP Endpoint 怎么接到 Claude Code?

这部分你有两种常见路线:

路线 A:CC 本身就提供 ACP Server

有就直接用。

  • ACP_ENDPOINT 指向它
  • 你只需要维护 Discord Bridge

路线 B:自己写一个“ACP → CC”的适配器

适合你用的是本地 CC CLI、或者某个订阅可用的交互方式。

适配器要做的事:

  • 收到 ACP 的 JSON
  • text 丢给 CC(比如调用 CLI、web driver、或你已有的接口)
  • 把 CC 输出包装成 { "text": "..." } 回去

你如果已经有一个能调用 CC 的脚本,这一步就是“套个 HTTP 外壳”。


频道里怎么用(给你一套顺手的指令格式)

日常对话

!cc 帮我把这个函数改成可测试的,顺便补 3 个单测

让它按你的约定输出(强烈建议)

!cc 你输出要按这个格式:
1) 问题判断
2) 修改方案
3) 代码 diff
4) 运行命令

代码审查场景(最爽)

你把一段代码贴进去,然后说:

!cc 只挑“会出事故”的点,按严重程度排序,给修复 diff

避坑清单(踩一次就想骂人那种)

  • Bot 收不到消息:没开 Message Content Intent,或者没给 View/Read History 权限。
  • 全服都能使唤 CC:没做频道白名单。上面代码用 CC_ALLOWED_CHANNELS 就是为了拦人。
  • Token 泄露:别写进代码仓库。用环境变量,泄露就立刻去 Portal 重置。
  • 回复被截断:Discord 有长度限制。记得切片,或发成文件。
  • 上下文乱:同一频道多人并发会串。想严谨就按 thread_iduser_id 做会话隔离。
  • 被刷屏:加频率限制。最简单是对 user 做 cooldown。

你要发给 Discord agent 的那句话(照抄就能用)

把下面这段直接丢给你现有的 Discord agent:

配置 ACP 让我们能直接在 Discord 里跟 Claude Code 对话。

目标:把 Claude Code 挂成 Discord Bot,通过 ACP 做消息桥接。

要求:

  1. 给出 Bot 创建与邀请步骤(含权限与 intents)
  2. 给出一个最小可用的 Bridge:监听指定频道消息(白名单),触发前缀 !cc 或 @mention
  3. Bridge 把消息封装成 ACP JSON POST 到 ACP_ENDPOINT,拿到返回后发回频道(处理 Discord 长度限制)
  4. 给出会话隔离建议(按 thread 或 user),以及安全建议(token、权限、限流)

你输出:配置清单 + 可直接运行的示例代码 + 自检步骤(怎么确认每一段链路通了)。


如果你告诉我你现在的 CC 是“本地 CLI”还是“某个订阅交互入口”,我可以把 ACP Endpoint 适配器 那段也补成可直接跑的版本(含 Docker/pm2 守护)。

OpenClaw
OpenClaw
木瓜AI支持养龙虾啦
木瓜AI龙虾专供API,限时领取免费tokens
可在 OpenClaw接入全球顶尖AI大模型
立即领取