Clawdbot(Moltbot)源码部署全实测:从环境搭建到 WebChat 验证,避坑指南收好

一、为啥折腾 Clawdbot?

最近刷技术圈总刷到 Clawdbot(后来也叫 Moltbot),说是能搭私人 AI 助手,支持 WhatsApp、Telegram 这些常用通道,还能跑在自己设备上,不用依赖第三方服务 ------ 想着拉下来测试一下功能,顺便研究一下其源码的实现。

于是拉上 GitHub 仓库https://github.com/openclaw/openclaw,打算从源码部署试试,过程里踩了不少坑,干脆整理成记录,给同样想折腾的朋友避避坑。

二、源码部署前的准备:Windows 环境优先选 WSL2

一开始想直接用 Windows CMD 部署,结果装依赖时各种报错,查仓库文档才发现 Windows 推荐用 WSL2(Ubuntu/Debian 镜像就行),后续操作全在 WSL2 里完成:

  1. 启用 WSL2:先在 Windows 功能里勾 "适用于 Linux 的 Windows 子系统" 和 "虚拟机平台",重启后装 Ubuntu 22.04(微软应用商店直接搜)

  2. 配置 WSL2:打开 Ubuntu 终端,先更系统源(换阿里源,不然后续装包巨慢),再 sudo apt update && sudo apt upgrade -y

  3. 装 Git:sudo apt install git,验证 git --version,避免后续拉仓库出错

我没有执行这一步,导致后面构建项目报错,后面有其他的解决方案。

三、Node.js 安装:别踩 "版本不够" 的坑

仓库文档说要 Node≥22,这里使用nvm管理环境,并切换到node最新版本。

注意:不要用22以下的,在pnpm install会报错。

四、拉取源码 & 装依赖

1、安装依赖

复制代码
git clone https://github.com/openclaw/openclaw.git
cd openclaw

pnpm install

在安装依赖时候会报错:

问题分析

node-llama-cpp 的 postinstall 脚本失败,错误码 3221225477 通常表示:

访问冲突或权限问题或Windows 上缺少必要的构建工具

node-llama-cpp 是可选依赖,仅用于本地嵌入。如果使用远程嵌入(如 OpenAI),可忽略该错误。项目会回退到远程嵌入。故注释掉 package.json 里面的 node-llama-cpp的依赖,重新进行 pnpm install

2、构建项目

前面安装依赖没问题之后,先构建ui

复制代码
pnpm ui:build

构建项目

复制代码
pnpm build

这是由于OpenClaw 在 Windows 上推荐使用 WSL2。在原生 Windows 上构建需要 bash。检查是否有 Git Bash 可用,或创建一个 Node.js 版本的构建脚本:

此处在项目的/script 目录下创建一个 nodejs版本的构建脚本 bundle-a2ui.mjs,代码如下:

javascript 复制代码
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { promises as fs } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
import { promisify } from "node:util";

const spawnAsync = promisify(spawn);

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const ROOT_DIR = path.resolve(__dirname, "..");
const HASH_FILE = path.join(ROOT_DIR, "src/canvas-host/a2ui/.bundle.hash");
const OUTPUT_FILE = path.join(ROOT_DIR, "src/canvas-host/a2ui/a2ui.bundle.js");
const A2UI_RENDERER_DIR = path.join(ROOT_DIR, "vendor/a2ui/renderers/lit");
const A2UI_APP_DIR = path.join(ROOT_DIR, "apps/shared/OpenClawKit/Tools/CanvasA2UI");

async function checkDirExists(dir) {
  try {
    const stat = await fs.stat(dir);
    return stat.isDirectory();
  } catch {
    return false;
  }
}

async function walk(entryPath, files = []) {
  const st = await fs.stat(entryPath);
  if (st.isDirectory()) {
    const entries = await fs.readdir(entryPath);
    for (const entry of entries) {
      await walk(path.join(entryPath, entry), files);
    }
    return files;
  }
  files.push(entryPath);
  return files;
}

function normalize(p) {
  return p.split(path.sep).join("/");
}

async function computeHash() {
  const inputPaths = [
    path.join(ROOT_DIR, "package.json"),
    path.join(ROOT_DIR, "pnpm-lock.yaml"),
    A2UI_RENDERER_DIR,
    A2UI_APP_DIR,
  ];

  const files = [];
  for (const inputPath of inputPaths) {
    try {
      const stat = await fs.stat(inputPath);
      if (stat.isDirectory() || stat.isFile()) {
        await walk(inputPath, files);
      }
    } catch {
      // Path doesn't exist, skip
    }
  }

  files.sort((a, b) => normalize(a).localeCompare(normalize(b)));

  const hash = createHash("sha256");
  for (const filePath of files) {
    const rel = normalize(path.relative(ROOT_DIR, filePath));
    hash.update(rel);
    hash.update("\0");
    const content = await fs.readFile(filePath);
    hash.update(content);
    hash.update("\0");
  }

  return hash.digest("hex");
}

async function runCommand(command, args, options = {}) {
  return new Promise((resolve, reject) => {
    const proc = spawn(command, args, {
      ...options,
      stdio: "inherit",
      shell: false,
    });
    proc.on("close", (code) => {
      if (code === 0) {
        resolve();
      } else {
        reject(new Error(`Command failed with exit code ${code}`));
      }
    });
    proc.on("error", reject);
  });
}

async function main() {
  try {
    // Docker builds exclude vendor/apps via .dockerignore.
    // In that environment we must keep the prebuilt bundle.
    if (!(await checkDirExists(A2UI_RENDERER_DIR)) || !(await checkDirExists(A2UI_APP_DIR))) {
      console.log("A2UI sources missing; keeping prebuilt bundle.");
      process.exit(0);
    }

    const currentHash = await computeHash();
    let shouldBuild = true;

    try {
      const previousHash = await fs.readFile(HASH_FILE, "utf-8");
      const outputExists = await fs
        .access(OUTPUT_FILE)
        .then(() => true)
        .catch(() => false);

      if (previousHash.trim() === currentHash && outputExists) {
        console.log("A2UI bundle up to date; skipping.");
        shouldBuild = false;
      }
    } catch {
      // Hash file doesn't exist, need to build
    }

    if (shouldBuild) {
      console.log("Building A2UI bundle...");
      await runCommand("pnpm", ["-s", "exec", "tsc", "-p", path.join(A2UI_RENDERER_DIR, "tsconfig.json")]);
      await runCommand("pnpm", ["-s", "exec", "rolldown", "-c", path.join(A2UI_APP_DIR, "rolldown.config.mjs")]);
      await fs.writeFile(HASH_FILE, currentHash, "utf-8");
      console.log("A2UI bundle built successfully.");
    }
  } catch (error) {
    console.error("A2UI bundling failed. Re-run with: pnpm canvas:a2ui:bundle");
    console.error("If this persists, verify pnpm deps and try again.");
    console.error(error);
    process.exit(1);
  }
}

main();

重新构建项目 pnpm build

构建完成。

六、配置 OpenClaw

直接跑向导 pnpm openclaw onboard --install-daemon

进来这个提示,先按照yes和quickstart方式快速配置

**配置模型:**这里选择智谱AI


配置api-key

配置channel

支持接入不同的app,这里没有不支持微信等国内的生态,暂时先跳过,使用webchat测试。

配置skills

可选的内置skills很多,注意,这里按空格选中,选好之后,按回车保存。

但选择对应的skills后,很多需要配置对应的key才能使用,这个需要提前在对应的网站申请key。

配置Hooks:

先跳过,暂时不用。

启动Gateway service

保存好上面配置后,会自动启动网关服务。

同时ui应用也会启动,至此配置完成

七、发送消息没有响应

第一次启动配置完后,发现发送消息并没有得到响应,控制台也没有报错。

后来发现是我的GLM4.7 限额了。这时候可以直接修改 openclaw.json配置文件进行修改配置。

改为flash模型

后续所有和openclaw agent相关的配置都可以通过修改该文件,不需要重复进入向导配置。

注意:修改后记得重启 gateway service ,否则不生效。
pnpm openclaw gateway restart --allow-unconfigured

可使用 openclaw status查看网关启动状态

八、常用命令

  1. 查看状态:openclaw status(快速看 Gateway 和通道是否在线)

  2. 发送测试消息:openclaw message send --to 自己的手机号(带国家码,比如 + 86138xxxxxxx) --message "测试 Clawdbot",能收到消息说明通道没问题

  3. 重置会话:openclaw agent --reset(对话卡顿时用)

  4. 检查问题:openclaw doctor(神器!会提示配置和环境的问题,比如 DM 策略风险、依赖缺失)

  5. 更新版本:openclaw update --channel stable(新手别更 dev 通道,不稳定)

九、WebChat 测试

由于没有接入其他channel,这里直接用原生的ui webchat进行测试。

测试调用工具读取文件的能力

测试其 Computer Use的能力

直接写入文件到系统。



可见其调用工具,Computer use能力还是比较强的

相关推荐
yhdata2 小时前
医疗零部件领域新宠:超声波精密清洗系统,市场规模近29.14亿元
大数据·人工智能
CV@CV2 小时前
自动驾驶传感器融合技术解析——L4级落地的核心支撑
人工智能·机器学习·自动驾驶
L_Jason先生2 小时前
高效利用 Coding Agent 进行规约驱动开发 (SDD):原理、实践与未来洞察
人工智能·驱动开发·知识图谱
2501_942191772 小时前
RetinaNet与伪装目标检测:提升模型识别能力的实战指南
人工智能·目标检测·目标跟踪
2501_941333102 小时前
【工业视觉检测】基于YOLOv8的皮带输送机关键部件检测与识别系统完整实现
人工智能·yolo·视觉检测
yukai080082 小时前
【最后203篇系列】036 MDP学习思考
人工智能·学习
大模型玩家七七2 小时前
安全对齐不是消灭风险,而是重新分配风险
android·java·数据库·人工智能·深度学习·安全
格林威2 小时前
Baumer相机电池极耳对齐度检测:提升叠片工艺精度的 5 个实用方案,附 OpenCV+Halcon 实战代码!
人工智能·opencv·机器学习·计算机视觉·视觉检测·工业相机·堡盟相机
2501_941329722 小时前
基于Centernet的甜菜幼苗生长状态识别与分类系统
人工智能·分类·数据挖掘