1. 飞书机器人跑不起来?先看清 OpenClaw 的部署链路
OpenClaw 是一个开源的 AI 代理框架,能接入飞书、Telegram 等聊天平台,把大模型能力变成你团队里的一个机器人。它适合想在飞书里搭一个能对话、能执行任务的助手的开发者,尤其是那些不想从零写消息回调、又希望本地或服务器上可控部署的人。我这次要做的,是把 OpenClaw 用 Docker 和 pnpm 完整跑起来,并让飞书机器人真正收到消息、返回回执。
很多人卡住的地方不是代码,而是环境。Node.js 版本不对、pnpm 没装、Docker 镜像拉不下来、飞书应用权限没开,任何一个环节出问题,机器人就是沉默的。所以这篇教程按“环境准备 → 依赖安装 → 容器化 → 飞书配置 → 启动验证 → 排错”的顺序走,每一步都给可复制的命令和配置。你跟着做,最后应该能在飞书里给机器人发一条消息,然后看到它回复。
先明确几个核心概念。OpenClaw 本身是一个 Node.js 项目,所以需要 Node.js 运行时;pnpm 是它的包管理器,比 npm 快且省磁盘;Docker 用来把整个运行环境打包,避免“我本地能跑,服务器上不行”的问题。飞书这边,你需要创建一个企业自建应用,拿到 App ID 和 App Secret,并开启机器人能力。这三块拼起来,才是一个完整的飞书机器人。
我试过在 macOS 和 Ubuntu 上分别部署,最大的感受是:Node.js 版本一定要锁在 22.x LTS。低于 18 会直接报错,20 虽然能跑但某些依赖会警告。pnpm 的版本倒不挑,但建议用最新稳定版。Docker 部署时,网络问题比配置问题更常见,所以下面会给出国内镜像加速的写法。
2. TaoToken 前置:模型接入与 API Key 准备
OpenClaw 自己不带模型,它需要你提供一个兼容 OpenAI 接口的模型服务。你可以用本地 Ollama,也可以用云端 API。如果你手头没有现成的模型 Key,或者想统一管理多个模型的调用,TaoToken 是一个可以用的入口。它提供兼容 OpenAI 格式的 API,你拿到 Base URL 和 Key 之后,填进 OpenClaw 的配置里就行。
具体操作是这样的:打开 TaoToken 的 API Keys 页面,创建一个新的 Key,复制下来。然后你会用到两个地址:Base URL 是https://taotoken.net/api,模型 ID 根据你选的模型填,比如gpt-4o或者claude-3-5-sonnet。这三个东西——Base URL、Key、Model ID——在后面配置 OpenClaw 时会反复用到,建议先记在一个文本文件里。
如果你只是想先验证流程,不想折腾模型,也可以用 Ollama 本地跑一个。Ollama 的 Base URL 是http://localhost:11434/v1,Key 随便填一个非空字符串就行,模型 ID 写你ollama list里看到的名称。但要注意,Ollama 在 Docker 容器里访问宿主机服务时,地址不能写localhost,得写host.docker.internal(macOS/Windows)或者宿主机的局域网 IP(Linux)。
TaoToken 的好处是它把模型调用统一成 OpenAI 格式,OpenClaw 不需要为每个模型单独适配。你可以在配置里写多个 provider,然后按需切换。比如白天用云端模型处理复杂任务,晚上用本地 Ollama 跑简单对话。这种灵活性在团队场景里很实用。
拿到 Key 之后,不要直接硬编码在代码里。OpenClaw 支持.env文件,你把OPENAI_API_KEY和OPENAI_BASE_URL写进去,然后在配置文件里引用环境变量。这样既安全,也方便在不同环境之间迁移。下面一节会给出具体的.env和docker-compose.yml写法。
3. 可复制配置:Dockerfile、pnpm 脚本与飞书应用参数
这一节是核心,所有配置都可以直接复制。先看项目结构。假设你已经把 OpenClaw 的代码克隆到本地:
git clone https://github.com/openclaw/openclaw.git cd openclaw然后创建.env文件:
cp .env.example .env编辑.env,填入你的模型信息:
OPENAI_API_KEY=你的TaoTokenKey OPENAI_BASE_URL=https://taotoken.net/api OPENAI_MODEL=gpt-4o FEISHU_APP_ID=cli_xxxxxxxx FEISHU_APP_SECRET=xxxxxxxxxxxxxxxx FEISHU_VERIFICATION_TOKEN=xxxxxxxx FEISHU_ENCRYPT_KEY=xxxxxxxx飞书的这四个参数,需要你去飞书开放平台创建企业自建应用后获取。App ID 和 App Secret 在“凭证与基础信息”里;Verification Token 和 Encrypt Key 在“事件订阅”里。注意,事件订阅的请求地址先随便填一个,等 Docker 跑起来后再改成你的公网地址或者内网穿透地址。
接下来是Dockerfile。OpenClaw 官方可能已经提供了,但为了确保 pnpm 和 Node.js 版本正确,我建议用下面这个:
FROM node:22-alpine RUN corepack enable && corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile COPY . . RUN pnpm build EXPOSE 3000 CMD ["pnpm", "start"]这个 Dockerfile 做了几件事:基于 Node.js 22 Alpine 镜像,启用 corepack 来管理 pnpm,先复制依赖文件安装依赖(利用 Docker 缓存),再复制源码构建,最后暴露 3000 端口并启动。如果你不需要构建,可以去掉pnpm build,直接pnpm start。
然后是docker-compose.yml:
version: '3.8' services: openclaw: build: . container_name: openclaw restart: unless-stopped ports: - "3000:3000" env_file: - .env volumes: - ./data:/app/data extra_hosts: - "host.docker.internal:host-gateway"extra_hosts这一行是为了让容器内能访问宿主机的 Ollama。如果你只用云端模型,可以删掉。volumes把数据目录挂载出来,避免容器重启后会话丢失。
飞书应用这边,你需要在开放平台做几件事。第一,开启机器人能力。第二,在“权限管理”里添加im:message、im:message:send_as_bot、im:chat:readonly等权限。第三,在“事件订阅”里添加im.message.receive_v1事件。第四,把请求地址填成你的服务地址,比如https://你的域名/webhook/feishu。如果你在本地跑,可以用内网穿透工具生成一个临时地址,但注意不要用任何违规的网络工具,直接用云服务器或者公司内网映射就行。
配置完成后,启动容器:
docker-compose up -d查看日志:
docker-compose logs -f如果看到Server listening on port 3000和Feishu bot initialized,说明启动成功。
4. 验证请求:启动日志检查与飞书消息回执
容器跑起来后,先别急着在飞书里发消息。第一步是检查日志里有没有报错。常见的成功日志长这样:
[INFO] Loading config from .env [INFO] Model provider: openai (https://taotoken.net/api) [INFO] Feishu app initialized: cli_xxxxxxxx [INFO] Webhook server listening on 0.0.0.0:3000 [INFO] OpenClaw ready如果看到Error: Cannot find module或者EACCES,说明依赖没装好或者权限有问题。如果是401 Unauthorized,检查你的 TaoToken Key 是否正确。如果是Feishu verification failed,检查 Verification Token 和 Encrypt Key 是否和飞书后台一致。
日志没问题后,在飞书里找到你的机器人,发一条“你好”。然后回到终端看日志:
[INFO] Received message from user: ou_xxxxxxxx [INFO] Sending to model: gpt-4o [INFO] Model response: 你好!有什么可以帮你的? [INFO] Reply sent to Feishu如果看到这几行,说明消息链路通了。飞书里应该也能收到机器人的回复。如果没有回复,先检查飞书事件订阅的请求地址是否可达。你可以在服务器上curl一下自己的 webhook 地址:
curl -X POST https://你的域名/webhook/feishu -H "Content-Type: application/json" -d '{"type":"url_verification","challenge":"test"}'如果返回{"challenge":"test"},说明 webhook 正常。如果超时,检查防火墙和端口映射。
还有一个验证点是模型调用。你可以直接在容器里执行一个测试脚本:
docker exec -it openclaw pnpm run test:model如果项目没有这个脚本,可以手动发一个请求:
docker exec -it openclaw curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-4o","messages":[{"role":"user","content":"test"}]}'如果返回正常的 JSON,说明模型侧没问题。
5. 常见错排查:401、local proxy failed 与 reading choices
部署过程中最容易遇到的几个报错,我一个个说。
401 Unauthorized:这个通常出现在模型调用环节。原因可能是 Key 过期、Base URL 写错、或者模型 ID 不存在。先检查.env里的OPENAI_API_KEY有没有多余空格,再确认OPENAI_BASE_URL是https://taotoken.net/api而不是带/v1的地址(有些框架会自动拼/v1)。如果用的是 TaoToken,去控制台确认 Key 的状态是“启用”。
local proxy failed:这个报错说明 OpenClaw 尝试通过本地代理访问外部服务,但代理没起来或者配置不对。如果你没有用代理,检查.env里有没有HTTP_PROXY或HTTPS_PROXY变量,有就删掉。如果你确实需要代理,确保代理地址是容器内可达的。但注意,任何涉及违规网络工具的代理都不能用,这里只讨论正常的网络配置。
reading choices:这个报错一般出现在模型返回格式不对的时候。OpenClaw 期望 OpenAI 格式的响应,里面有一个choices数组。如果模型返回的是其他格式,就会报Cannot read property 'choices' of undefined。解决办法是确认你的模型服务兼容 OpenAI 接口。TaoToken 是兼容的,Ollama 也是兼容的,但有些自建服务可能需要加一个适配层。
OAuth 相关报错:如果你在飞书配置里用了 OAuth 授权,可能会遇到invalid redirect_uri或者app ticket expired。检查飞书后台的“安全设置”里,重定向 URL 是否和你的服务地址一致。另外,App Ticket 需要定期刷新,OpenClaw 一般会自动处理,但如果日志里频繁出现,可以重启容器。
端口被占用:Error: listen EADDRINUSE: address already in use :::3000。说明 3000 端口被其他程序占了。改docker-compose.yml里的端口映射,比如3001:3000,然后重启。
pnpm install 失败:如果卡在resolving packages,可能是网络问题。在Dockerfile里加一行RUN pnpm config set registry https://registry.npmmirror.com/,然后再pnpm install。
飞书消息重复回复:检查事件订阅里有没有重复添加im.message.receive_v1。另外,OpenClaw 默认会处理消息去重,但如果你的服务部署了多个实例,需要加 Redis 做共享去重。
6. 语义一致 CTA:从跑通到长期编码
机器人跑通之后,你可能会想把它用在更复杂的场景里,比如让它在飞书里执行代码任务、查询文档、或者做长期的项目助手。这时候,模型的稳定性和调用成本就变得重要了。TaoToken 的 Coding Plan 适合这种长期编码场景,它提供固定的模型调用额度,你不用每次手动充 Key,也不用担心突然限流。
如果你只是想验证模型对话效果,可以直接用 TaoToken 的模型对话页面,快速测试不同模型的回复质量。如果你需要管理多个项目的 API Key,控制台里的 API Keys 页面可以创建和吊销 Key,方便团队协作。
接入文档里有详细的接口说明和示例代码,包括如何配置 Base URL、如何传参、如何处理流式响应。Claude Code 的 Anthropic 兼容接口也有专门说明,如果你用 Claude 系列模型,可以直接参考。
最后说一个实用技巧:把 OpenClaw 的日志输出到文件,然后配一个简单的日志轮转。这样出问题的时候,你可以回溯最近几天的消息记录,快速定位是模型侧还是飞书侧的问题。具体做法是在docker-compose.yml里加一个 logging 配置:
logging: driver: "json-file" options: max-size: "10m" max-file: "3"这样日志不会无限增长,也不会把磁盘写满。跑通之后,你可以把整个docker-compose.yml和.env备份一份,下次换服务器直接复制过去,五分钟就能重新起来。