用Rust从零写了一个类OpenClaw工具CrabClaw,开发手记


title: 用Rust从零写了一个类OpenClaw工具CrabClaw,开发手记

用Rust从零写了一个类OpenClaw工具CrabClaw,开发手记

花了10天时间,73个commit,13000多行Rust代码,我从零做了一个类OpenClaw的Agentic AI工具,叫CrabClaw(螃蟹钳,取Rust的吉祥物螃蟹的意思)。

这篇文章记录一下整个开发过程,包括为什么选Rust、架构设计思路、和现有工具的对比。

为什么要造这个轮子

主要原因有两个。

第一,学习目的。我一直想深入理解OpenClaw这类工具的内部工作原理——它是怎么管理上下文的、怎么跟模型交互的、工具调用链是怎么串起来的。看源码是一种方式,但自己写一遍理解会深刻得多。

第二,我觉得用Rust实现有一些独特的优势,这个后面详细说。

在开发之前,我研究了几个已有的类似项目:Nanobot是一个极简的实现,代码量很小但功能也有限;Bub做了一些有意思的交互设计;Zeroclaw则更偏向框架层面。这些项目给了我不少启发。

为什么选Rust而不是Node.js

OpenClaw本身是用TypeScript/Node.js写的,大部分社区项目也是JS系的。我选Rust主要考虑以下几点:

性能。在处理大量文件的场景下,比如全项目代码搜索、大文件解析,Rust的性能优势非常明显。我测试过一个中型项目(约5万行代码),CrabClaw的全文搜索比Node.js方案快了3到5倍。

内存安全。这类工具需要长时间运行、频繁做IO操作,Rust的所有权机制让你在编译期就能排除大部分内存相关的bug。我在开发过程中基本没遇到过内存泄漏问题。

单二进制部署。编译出来就是一个可执行文件,不需要安装Node.js运行时、不需要npm install一堆依赖。分发和部署都特别方便。用户下载一个文件就能跑。

代价呢? 开发速度慢。同样的功能用Node.js可能两三天就写完了,Rust需要五六天。编译器的各种检查有时候会让你很抓狂,尤其是处理异步和生命周期的时候。

架构设计

CrabClaw的核心架构分成几层:

交互层:负责终端的输入输出、命令解析、渲染。用了ratatui做终端UI,crossterm处理终端事件。

会话管理层:管理对话历史、上下文窗口、消息的序列化和反序列化。这一层参考了OpenClaw的设计,但做了一些简化。

工具系统:这是最复杂的一层。每个工具(文件读写、搜索、Shell命令执行等)都实现一个统一的trait,工具调用通过一个调度器来管理。Rust的trait系统在这里用起来非常舒服,类型安全让你不用担心运行时的类型错误。

模型适配层:目前支持OpenAI兼容的API和Anthropic的API。抽象了一个统一的接口,切换模型只需要改配置。

开发过程中的一些收获

第一个收获是对上下文管理的理解。OpenClaw能用起来的关键不是模型有多强,而是它的上下文管理做得很好——什么时候该把文件内容塞进上下文、什么时候该截断、怎么保持对话的连贯性。自己实现一遍之后才真正理解这里面的取舍。

第二个收获是工具调用的可靠性。模型返回的工具调用参数经常是不规范的——JSON格式不对、参数缺失、类型不匹配。你需要做大量的容错处理。这部分代码占了总代码量的将近20%。

第三个收获是Rust的async确实难。处理并发的工具调用、流式响应、取消操作这些场景时,Rust的异步模型比JS复杂太多了。Pin、Future、生命周期标注搅在一起,有好几次我盯着编译错误看了一个小时才搞明白。

和OpenClaw、FastClaw的对比

老实说,功能完整度上CrabClaw跟OpenClaw没法比。OpenClaw有庞大的社区、完善的Skill生态和几百个contributors的代码。CrabClaw一个人做了10天,能实现核心功能就不错了。

但在某些方面CrabClaw有自己的特点:

启动速度:CrabClaw启动几乎是瞬间的,OpenClaw需要几秒钟加载Node.js运行时和依赖。

资源占用:运行时内存占用大概是OpenClaw的三分之一到四分之一。

部署便捷:一个二进制文件,没有外部依赖。

FastClaw用Go写的,思路跟CrabClaw类似——追求轻量和高性能。但FastClaw更侧重于做一个精简版的OpenClaw,而CrabClaw更偏向于探索不同的架构可能性。

给想造轮子的开发者的建议

如果你也想做类似的项目,几个建议:

先把OpenClaw用透。你需要深入理解它是怎么工作的,哪些设计是精妙的,哪些是历史包袱。不理解原版就去造轮子,大概率会重复踩坑。

选一个明确的差异化方向。不要试图做一个"更好的OpenClaw",而是在某个具体方面做到更好。比如更快、更轻量、更好的离线支持、更好的隐私保护等等。

控制范围。这种项目的功能点非常多,很容易做着做着就膨胀了。先做核心功能,跑起来再说。

多看别人的实现。Nanobot、Bub、Zeroclaw、FastClaw这些项目都值得学习,每个项目都有值得借鉴的设计。

CrabClaw目前还是一个学习项目,代码已经开源了。如果你对Rust+AI工具开发感兴趣,欢迎来看看代码或者提PR。

你们有用Rust做过AI相关的项目吗?或者有造过类似轮子的经历?来评论区聊聊你们的经验。

Rust开发者来聊聊。13000行代码10天,这个速度说明楼主Rust功底很扎实。

关于Rust做AI工具的几点补充:

  1. async确实是最大的痛点。我之前用tokio做一个类似的项目,光是处理流式响应+取消操作就搞了三天。Pin<Box>这种类型签名看一眼就头大。不过一旦搞定了,运行时的稳定性确实比Node.js好很多。

  2. 单二进制部署是杀手级优势。我之前给团队部署OpenClaw,光是搞Node.js版本和npm依赖就折腾了半天。CrabClaw下载一个文件就能跑,这个体验差距太大了。

  3. 建议考虑WASM编译。Rust编译成WASM可以在浏览器里跑,这样就能做一个Web版的CrabClaw,不需要用户安装任何东西。这个方向很有想象空间。

  4. 关于工具调用的容错处理占20%代码量这点——跟我的经验一致。模型返回的JSON格式经常是坏的,括号不匹配、多一个逗号、字符串没闭合,各种奇葩情况。这块确实需要大量的防御性代码。

4 个赞

CrabClaw这个名字起得好哈哈,Rust社区的命名都跟螃蟹有关系

2 个赞

「先把OpenClaw用透再造轮子」这个建议太重要了。我见过不少人连OpenClaw都没怎么用就去造轮子,最后做出来的东西连OpenClaw的基本功能都不如。造轮子的前提是你真正理解了原版的设计取舍,知道哪些是精妙的设计、哪些是妥协、哪些是可以改进的。

2 个赞

从架构角度聊一下。楼主的四层架构(交互层、会话管理、工具系统、模型适配)跟OpenClaw是类似的,但Rust的trait系统在工具系统这层确实比JS的接口/继承更优雅。

我想补充一个OpenClaw架构里不太为人知但很巧妙的设计:上下文压缩策略。当对话历史超过模型的上下文窗口时,OpenClaw不是简单地截断最早的消息,而是会对历史消息做摘要压缩——保留关键信息但减少token数。这个设计对长时间编码会话很重要,不知道CrabClaw有没有实现类似的机制?

另外建议考虑加入工具调用的并行执行。有些工具调用之间是独立的(比如同时读取三个文件),Rust的async天然适合做这种并发优化,能显著提升响应速度。

4 个赞

开源地址在哪?想去看看代码学习一下

AI项目不确定性大,别用瀑布模型管

MVP先跑通再迭代,别想一步到位