从零搭建一个通用 AI Agent:LemonClaw 的工程实践

从零搭建一个通用 AI Agent:LemonClaw 的工程实践

💡 原文中文,约12100字,阅读约需29分钟。
📝

内容提要

LemonClaw是一个开源通用AI数字员工Agent,采用单SQLite文件存储所有状态,支持多通道消息接入、记忆、技能、MCP及多Agent工作流。其设计强调解耦与工程化,如消息总线、按需工具注册、TF-IDF记忆检索、密钥不进入LLM上下文等。相比OpenClaw和Pi-Agent,LemonClaw提供完整产品层,内置持久化记忆与定时任务,部署简单,适合开箱即用的数字员工场景。

🔎

延伸解读

单文件存储的运维红利

LemonClaw 将所有状态收敛到一个 SQLite 文件,部署时只需挂载目录,备份用 cp 命令即可完成,迁移也只需拷贝整个目录。相比依赖外部 MQ、向量库的框架,这种设计显著降低了运维复杂度,尤其适合个人或小团队快速部署和长期维护。

密钥不进上下文的双重实现

LemonClaw 在技能和 MCP 两个场景都确保密钥不进入 LLM 上下文,但实现方式不同:技能用占位符在请求时替换,MCP 则把密钥放在连接配置中。这种精细的数据流控制,既防止模型泄露敏感信息,也避免污染上下文,是工程化安全设计的典型示例。

中文记忆检索的分词必要性

LemonClaw 采用 TF-IDF 加 jieba 分词实现记忆检索,因为中文按单字切分会导致高频字 IDF 趋零、复合词被拆散,检索效果大打折扣。这一细节提醒开发者,在中文场景下分词器是必选项,而非可选项,直接影响记忆功能的实用性。

主 Agent 在回路的设计差异

LemonClaw 的工作流将主 Agent 作为回路中的一等公民,既能被回调,也能监督干预子流程,而主流框架中主 Agent 提交 spec 后往往被动等待。这种设计让人机协作更灵活,但实现前提是消息总线的解耦,体现了架构决策的连锁效应。

Q&A

LemonClaw是什么?它有哪些核心特性?

LemonClaw是一个开源的通用AI数字员工Agent,它采用单SQLite文件存储所有状态,支持多通道消息接入、持久化记忆、技能系统、MCP(模型上下文协议)以及多Agent工作流。其设计强调解耦与工程化,例如使用消息总线、按需工具注册、TF-IDF记忆检索,并确保密钥不进入LLM上下文。

LemonClaw的消息总线是如何设计的?为什么不用现成的MQ?

LemonClaw的消息总线是一个线程安全的PriorityQueue,带容量上限(默认1000)和优先级。所有输入事件都进入总线,由Agent循环消费。它不用现成的MQ(如Redis/Kafka/RabbitMQ)是因为LemonClaw定位为单机即可运行、零外部依赖的数字员工,引入MQ会增加运维复杂度。进程内队列已足够,且容量上限和背压异常能保证快速失败。

LemonClaw如何实现持久化记忆?为什么使用TF-IDF和jieba分词?

LemonClaw使用纯TF-IDF和中文分词(jieba)实现持久化记忆,所有状态存储在一个SQLite文件中。使用jieba分词是因为中文按单字切分会导致高频字IDF趋近于零,复合词被拆散,倒排索引退化,所以分词是必选项。记忆检索通过中间件动态注入系统消息,不写入checkpointer,避免上下文膨胀。

LemonClaw的技能系统是如何工作的?它如何兼容OpenClaw?

LemonClaw的技能系统将可复用工作流封装成按需加载的包,格式兼容OpenClaw(包含SKILL.md、requirements.txt等)。技能通过状态机管理,支持加载、卸载和热重载。敏感参数使用${VAR}占位符,在请求时由工具替换,确保密钥不进入LLM上下文。兼容OpenClaw是为了复用其技能生态。

LemonClaw如何支持MCP?它的安全设计是怎样的?

LemonClaw作为MCP客户端,通过Streamable HTTP接入外部工具服务,每个远程工具注册为原生Agent工具。配置在mcp.json中,包含密钥。安全设计上,连接配置(如headers)由MCPConnection持有,绝不进入LLM上下文、checkpointer或LLM API请求体。支持热重载,且不中断对话。

LemonClaw的多Agent工作流有什么独特之处?

LemonClaw的多Agent工作流基于LangGraph,支持声明式JSON spec定义,包括子Agent、条件路由、回环、人在回路(HITL)和跨重启续跑。独特之处在于主Agent是回路中的一等公民,既能作为节点被回调,又能通过命令监督和干预在途运行,同时是人介入工作流的唯一界面。

LemonClaw如何管理上下文以避免Token爆炸?

LemonClaw通过trim_msg_history()进行两层压缩:第一层对较早的ToolMessage和AIMessage的tool_calls进行裁剪,保留首尾;第二层当消息数超过阈值且Token用量达到模型窗口80%时,将较早消息摘要成20-40字,并用RemoveMessage删除原消息。摘要由专门的ContextAgent完成,只保留核心状态和硬核事实。

LemonClaw与OpenClaw和Pi-Agent相比有哪些区别?

LemonClaw是完整产品层,面向开箱即用的数字员工,内置持久化记忆、多通道接入、定时任务和多Agent工作流,所有状态收敛到一个SQLite文件。OpenClaw是Node.js生态,核心是Workspace和Skills,数据以JSONL落盘;Pi-Agent是工具包/引擎层,面向开发者,不内置持久化记忆、多通道等,需要自行实现。

为什么LemonClaw选择从零开发而不是基于OpenClaw或Pi-Agent?

原因有三:一是架构目标不兼容,OpenClaw的核心抽象与LemonClaw的单库、多通道、主Agent在回路的目标不匹配,改造成本高;二是单SQLite约束需要从根上贯彻,现有框架难以适配;三是需要掌控每一寸上下文数据流,确保密钥不进LLM上下文等安全设计,这些需要端到端的掌控。

LemonClaw如何部署和备份?

LemonClaw通过Docker部署,只需挂载一个目录即可。备份只需复制lemonclaw.db文件,迁移则拷贝整个.lemonclaw/目录。镜像基于ubuntu:26.04,时区通过TZ环境变量配置,确保定时任务准确。

🏷️

标签

➡️

继续阅读