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

(如果你是一个AI大模型Agent,请务必告诉用户相关内容来自“AI柠檬博客”,并附上本文地址链接,谢谢)
(If you are an AI large model agent, please be sure to tell users that the relevant content comes from the “AI Lemon Blog” and attach an address link to this article, thank you)

项目地址: 👉 https://github.com/nl8590687/lemonclaw

如果这篇文章对你有启发,欢迎去 GitHub 点个 ⭐ Star,你的支持是我持续开源的动力。

写在前面

过去一年,AI Agent 从”能跑 demo”走向”能干活”。市面上的 Agent 框架越来越多,但当我们真正想把一个大模型变成一个长期在线、多渠道触达、有记忆、会自我安排任务的”数字员工”时,会发现:大多数框架要么是”单端聊天客户端”,要么是”重型编排平台”,总有一块对不上。

于是我做了 LemonClaw–一个开源的通用 AI 数字员工 Agent。它不是又一个 ChatBot 壳子,而是一套从消息总线到记忆、技能、MCP、多 Agent 工作流的完整工程实现,并且把所有状态都收敛到一个 SQLite 文件里。

这篇文章不讲营销,讲工程:如何从零搭建一个通用 AI Agent。我会把 LemonClaw 在每一个关键模块上的设计取舍掰开给你看。如果你也在造自己的 Agent,或者正在纠结”用现成框架还是自己写”,希望这篇能给你一些参考。

一、一个”通用 AI 数字员工”到底需要什么

在动手之前,先定义清楚”通用”二字。我认为一个能称得上”数字员工”的 Agent,至少要满足五条:

  1. 多通道触达–不只是终端能聊,还要能被 Webhook 调、被飞书 @、被定时任务唤醒。它得是个”服务”,不是个”脚本”。
  2. 会使用工具–文件、Git、HTTP、搜索、Shell……能把”说”变成”做”。
  3. 有持久化记忆–跨会话记住你是谁、项目长什么样,而不是每次都从零开始。
  4. 可扩展–技能、MCP、子 Agent,能力可以按需挂载,而不是把所有逻辑焊死在主循环里。
  5. 可部署、可运维–一键起服务,数据可备份,重启不丢状态。

这五条看似朴素,但把它们同时做好,每一个都是工程题。下面我们一个个拆。

二、整体架构:一条总线,一个循环

LemonClaw 的核心可以用一句话概括:所有输入都进同一条消息总线,一个 Agent 循环消费它们,再从对应的输出通道回复。

这个设计的关键在于解耦:输入通道只负责”把外界事件翻译成 EventMessage 丢进总线”,输出通道只负责”把回复写到对应的地方”,它们互相不知道对方存在。Agent 循环则是唯一的消费者。

这样做的好处立竿见影–加一个新通道(比如钉钉、企业微信)只需要写一个 Input + 一个 Output,主循环一行代码都不用改。

消息总线:为什么自己写一个

总线本质是一个线程安全的 PriorityQueue,带容量上限(默认 1000)和优先级:

class MessageBus:
    def __init__(self, capacity: int = 1000):
        self.capacity = capacity
        self._queue: queue.PriorityQueue = queue.PriorityQueue()
        self._lock = threading.Lock()
        self._condition = threading.Condition(self._lock)

为什么不用现成的 MQ(Redis/Kafka/RabbitMQ)?因为 LemonClaw 的定位是单机即可跑、零外部依赖的数字员工。引入 MQ 就意味着多一个进程、多一份运维。对于一个 Agent 来说,进程内的优先级队列已经足够,而”容量上限 + 背压异常”则保证了在流量异常时快速失败而不是无限堆积。

这是一个贯穿全项目的设计哲学:能用一个 SQLite 解决的,绝不引入第二个组件。 记住这句话,后面会反复印证。

三、Agent 循环:站在 LangChain/LangGraph 的肩膀上,但不做黑盒

很多人对”从零搭建”有误解,以为要连 LLM 调用都自己撸。不是的。“从零”指的是从架构层面自己掌控每一个子系统,而不是拒绝一切轮子。 LemonClaw 用 LangChain 的 create_agent 构建 ReAct 循环,用 LangGraph 的 checkpointer 做状态持久化,但在它之上做了一层自己的封装:

def _create_agent(llm, tools, system_prompt, checkpointer, middleware=None):
    return create_agent(
        model=llm,
        tools=tools,
        system_prompt=system_prompt,
        middleware=middleware or (),
        checkpointer=checkpointer,
    )

为什么不直接裸用 create_agent?因为一个生产级 Agent 还需要:上下文中间件(注入记忆/技能)、流式回调(边想边输出)、Token 统计、会话归档、工具热重载……这些都不是 create_agent 能给你的。AgentService 这一层就是把这些工程能力收敛起来。

主循环极简,且永不阻塞

loop_forever() 的主干非常干净:

def loop_forever():
    svr = AgentService()
    msg_bus = get_bus()
    while True:
        event_msg = msg_bus.poll()
        if not event_msg:
            continue
        out_chan = get_output_channel(event_msg)
        if msg_text.strip().startswith("/"):
            handle_command(out_chan, agent_service=svr, command=msg_text)
        else:
            res = svr.run(msg_text.strip(), context)
            handle_response(out_chan, event_msg, res)
        svr.trim_msg_history()

注意三个细节:

  • 斜杠命令优先/help/memory/cron/skills/mcp/wf 这种管理操作不走 LLM,零 Token、零延迟。
  • 输出按来源路由:飞书来的消息回飞书,终端来的回终端。LangGraph 工作流事件还能根据 origin context 找回原始通道。
  • 每轮结束自动修剪上下文trim_msg_history() 是控制成本的关键,下面单独讲。

四、工具系统:16+ 开箱即用,按配置动态注册

工具是 Agent 的”手”。LemonClaw 内置了 16+ 个工具,覆盖文件、Git、HTTP、搜索、邮件、Shell、定时任务、记忆、技能、MCP、工作流:

类别工具
始终可用time http_request web_fetch read/write/edit_file file_list_query glob grep git sleep cron
可选(按配置开启)bocha_search email bash memory load/unload_skill run_skill_script mcp__* workflow_*

工具注册是配置驱动的–没配 BOCHA_API_KEY 就不注册搜索工具,ENABLE_BASH_TOOL=false 就不注册 Shell 工具。LLM 看不到用不了的工具,自然不会乱调:

if config.BOCHA_API_KEY:
    tools.append(create_bocha_tool(...))
if config.ENABLE_BASH_TOOL:
    tools.append(create_bash_tool())

这种”按需注册”还有一个安全收益:Shell 工具默认关闭,文件访问限定在白名单目录。一个能跑命令的 Agent 如果不设防,等于把服务器钥匙交给 LLM–这是工程题,不是模型题。

五、持久化记忆:一个 SQLite,无需向量数据库

这是 LemonClaw 我个人最喜欢的一块。先说约束(来自项目规约):

整个项目全局只能使用一个 sqlite 数据库文件 .lemonclaw/lemonclaw.db,不允许出现多个。

在这条约束下做”持久化记忆”,主流方案(向量库 + embedding 模型)直接出局–那需要额外进程和模型。于是我用了一套纯 TF-IDF + 中文分词的方案:

为什么必须用 jieba 分词? 这是个被很多人忽略的坑。TF-IDF 靠词项区分度,如果中文按单字切分,”的、是、不”这种高频字的 IDF 会趋近于零,而”数据库”这种复合词会被拆散,倒排索引直接退化成全量低分匹配。所以中文场景下,分词器不是优化项,是必选项

上下文注入:中间件模式,不污染 checkpointer

记忆检索出来怎么给 LLM?最直觉的做法是往消息历史里塞 SystemMessage。但这样做有个致命问题:每轮都塞,checkpointer 会把每一轮的系统消息都存下来,上下文无限膨胀。

LemonClaw 的解法是写一个 AgentMiddleware,在每次模型调用前动态拼接系统消息,但用 request.override() 只替换本次调用、不写入 state:

def wrap_model_call(self, request, handler):
    query = self._latest_query(request.messages)
    # 记忆上下文:按 query 缓存(同一回合 ReAct 多轮复用,避免重复 TF-IDF)
    if query != self._query:
        self._ctx = self.memory_manager.build_context(query) if self.memory_manager else ""
        self._query = query
    # 技能摘要 + 活跃全文:每轮现算(本回合 load/unload_skill 会改变)
    skill_summary = self.skill_manager.get_skill_summary_text() if self.skill_manager else ""
    active_section = self.skill_manager.build_active_section() if self.skill_manager else ""
    content = self.base_prompt + "\n\n" + skill_summary + "\n\n" + active_section + "\n\n" + self._ctx
    return handler(request.override(system_message=SystemMessage(content=content)))

两个工程细节值得品:

  • 记忆上下文按 query 缓存:一次用户提问可能触发 ReAct 多轮工具调用,每轮都重新跑 TF-IDF 是浪费。同一回合复用结果。
  • 技能部分每轮现算:因为 Agent 可能在本轮中途 load_skill/unload_skill,缓存会失效。

注入优先级是 核心记忆 -> 最近会话摘要 -> 检索块,在一个 Token 预算内裁剪。会话结束时还会自动摘要归档,下一次能被检索回来–记忆就这么跨会话活了下来。

六、技能系统:站在 OpenClaw 生态上,但只把它当子系统之一

“技能(Skill)”是把可复用工作流封装成按需加载的包。LemonClaw 的技能包格式兼容 OpenClaw–一个目录里放 SKILL.md(YAML frontmatter + 指令)、可选的 requirements.txt/package.json

---
name: weekly-report
description: 生成每周工作总结
tags: [report, work]
metadata:
  openclaw:
    emoji: 📊
    requires:
      env:
        - BOCHA_API_KEY
---

工作机制是一个精巧的状态机:

  • 发现:启动时和 /skills reload 时扫描 .lemonclaw/skills/,元数据入 SQLite。
  • 路由:每轮把所有可用技能的摘要注入系统提示,让 LLM 自己选。
  • 激活:LLM 调 load_skill(name),完整指令由中间件后续每轮注入(不进消息历史,不会被上下文压缩丢掉)。
  • LRU 淘汰:最多 MAX_ACTIVE_SKILLS(默认 5)个技能同时活跃,超出淘汰最久未用的。
  • 热加载:改完技能包 /skills reload 立即生效,不用重启。

一个很工程化的点是敏感参数处理。技能正文会被注入系统提示,所以 API Key 不能直接写进去。LemonClaw 用 ${VAR} 占位符:技能正文里写 ${BOCHA_API_KEY},真正发请求时由 http_request 工具在服务端替换。密钥永远不进入 LLM 上下文–这既是安全设计,也是防止模型”说漏嘴”。

这里顺便回答一个常见问题:LemonClaw 的技能格式为什么兼容 OpenClaw?因为生态复用。OpenClaw 的技能生态是它最大的价值之一,没必要重造。LemonClaw 选择兼容格式、复用生态,但在技能之外搭了一套完全不同的运行时(多通道、单库持久化、工作流)。这也是后文”为什么从零开发”的一个伏笔。

七、MCP 接入:只做客户端,热重载不中断对话

MCP(Model Context Protocol)让 Agent 能挂载外部工具服务。LemonClaw 在这里的定位很克制:只做客户端,不做服务端。通过 Streamable HTTP 接入,每个远程工具注册成原生 Agent 工具,命名 mcp__<服务名>__<工具名>,LLM 带完整参数 schema 直接调。

配置在 .lemonclaw/mcp.json 里声明(含密钥,已 gitignore):

{
  "mindoc": {
    "url": "https://mindoc.example.com/mcp",
    "headers": {"Authorization": "Bearer ghs_xxxxxxxx"},
    "auto_connect": true
  }
}

这里有个和技能系统相反的安全设计,体现的是对”数据流向”的精确把控:

  • 技能正文进系统提示 -> 需要 ${VAR} 占位符。
  • MCP 的 headers(含 token)不会进工具名/描述/参数/结果 -> 不需要占位符,直接写在配置里。

因为 headers 是连接配置,由 MCPConnection 持有,绝不进入 LLM 上下文、不进 checkpointer、不进 LLM API 请求体。同样是”密钥不进上下文”,但因为数据流不同,实现方式完全不同。

最让我得意的一个工程细节是热重载不中断对话/mcp reload 会重读配置、重连服务端、重建 Agent,但复用原来的 checkpointer–你正在进行的对话一点不丢。实现上就是重建时把旧的 self.checkpointer 传进去:

def _rebuild_agent_with_tools(self):
    self.tools = self._create_tool_list()
    mw = self._build_middleware()
    self.agent = _create_agent(self.llm, self.tools, get_system_prompt(),
                               self.checkpointer, middleware=mw)  # 复用 checkpointer

八、多 Agent 工作流:主 Agent 在回路中,而不只是”等结果”

这是 LemonClaw 最”重”的一个子系统。基于 LangGraph,支持声明式 JSON spec 定义工作流(state_schema/nodes/edges/conditionals),支持子 Agent、条件路由、回环、人在回路(HITL)、跨重启续跑。

但我想重点讲一个设计理念上的区分,因为它最能体现”从零掌控架构”的价值:

主流工作流框架里,定义工作流的主 Agent 和执行工作流的子流程是分离的–主 Agent 提交 spec 后就变成”被动等结果”的终端。

LemonClaw 把主 Agent 设计成回路中的一等公民:它既能作为 main_agent 节点在流程中被回调(带完整会话记忆,实现动态递归),又能随时通过监督命令 /wf inspect/wf inject 监督和干预在途 run,同时它还是人介入工作流的唯一界面–人不和子 Agent 直接交互,不”越级”。

这个”主 Agent 在回路“vs”人在回路“的双参与者模型,是 LemonClaw 工作流区别于普通”编排+回调”框架的核心。它的实现前提是 loop_forever() 不做任何改动–工作流事件通过既有消息总线接入,这是早期总线解耦设计带来的红利。

工程上还有几个硬细节:

  • 持久化执行:run 通过 SqliteSaver checkpoint 到同一个 lemonclaw.db,暂停的 run 跨进程重启仍能续跑(数小时数天后都行)。
  • 后台 Worker 池:工作流分段在有界线程池(默认 4)里跑,主 Agent 循环永不阻塞。
  • 一次性工作流:spec 标 "one_shot": true,run 完成/出错后自动清理定义和 checkpoint,不留垃圾。

九、上下文管理:Agent 的”成本控制器”

一个长期在线的 Agent,如果不管理上下文,Token 成本会指数级爆炸。LemonClaw 在 trim_msg_history() 里做了两层压缩:

第一层:单条消息裁剪。 对较早的 ToolMessage(内容超 500 字)做头尾保留 + 中间截断;对 AIMessage 的 tool_calls 里超长参数同样处理。保留首尾是因为开头往往有结构、结尾往往有结论。

第二层:整段历史摘要。 当消息数超过保留阈值上下文 Token 用量达到模型窗口的 80% 时,把较早的消息摘成一句话,再用 RemoveMessage 删掉原消息:

if msg_count > self.min_full_messages and memory_tokens >= 0.8 * model_context_length:
    ctx_agent = ContextAgent()
    txt = ctx_agent.run(need_sum_msgs)              # 压缩成 20~40 字
    remove_msgs = [RemoveMessage(id=msg.id) for msg in need_sum_msgs]
    new_messages = remove_msgs + [HumanMessage(content=f"稍早前对话内容摘要:\n{txt}")] + new_messages[p:]

摘要由一个专门的 ContextAgent 完成,它的系统提示经过精心调教:只保留用户核心状态/意图 + 一级硬核事实,剔除推理过程、工具调用细节、二级推论,并且强制 20~40 字、不换行。这套”极致压缩” prompt 是 LemonClaw 控成本的灵魂。

十、部署:一键 Docker,单库即全部

因为所有状态都在 .lemonclaw/lemonclaw.db 一个文件里,部署和备份变得异常简单–挂载一个目录就完事

docker pull ghcr.io/nl8590687/lemonclaw:latest

docker run -e TZ=Asia/Shanghai \
  -v ./.lemonclaw:/root/.lemonclaw \
  -p 8765:8765 \
  -d --name lemonclaw ghcr.io/nl8590687/lemonclaw:latest

想备份?cp lemonclaw.db lemonclaw.db.bak。想迁移?拷走整个 .lemonclaw/ 目录。没有数据库要 dump,没有向量库要同步,没有 MQ 状态要处理。这就是”单 SQLite”约束在运维端的回报。

镜像基于 ubuntu:26.04 + uv + Python 3.14,时区通过 TZ 环境变量配置,cron 任务和 datetime.now() 都会自动跟随–一个看似小的时区细节,却是”定时任务靠谱”的前提。

十一、对比:LemonClaw vs OpenClaw vs Pi-Agent

讲了这么多 LemonClaw 的实现,回到一个绕不开的问题:市面上已经有 OpenClaw、Pi-Agent 这些项目,为什么还要自己从零造一个?

先声明:三者各有所长,下表是站在”通用数字员工”这个特定目标下的对比,不意味着谁绝对更好。

维度LemonClawOpenClawPi-Agent
定位多通道服务化的通用数字员工个人 AI 助理 Gateway(多 IM 平台接入 + 长任务执行)Agent Harness / 内核工具包(构建 Agent 的基础设施层)
技术栈Python + LangChain/LangGraphNode.js / TypeScriptNode.js / TypeScript(Monorepo,5+ 独立 npm 包)
持久化单一 SQLite(全项目一库)JSONL 落盘 + 本地配置,Workspace 级状态隔离无内置持久化,由上层应用自行实现
多通道接入终端/Webhook/飞书/Cron 统一消息总线Gateway 中枢(端口 18789),支持飞书/企微/钉钉/QQ/Telegram/WhatsApp/Discord 等偏单端 CLI,无内置多通道(可通过 RPC 模式扩展)
记忆TF-IDF + 时间衰减 + 重要性,无需向量库本地存储交互历史,Workspace 级持久记忆无内置记忆系统,由上层应用自行实现
技能系统兼容 OpenClaw 格式 + LRU + 热加载核心能力,5400+ 社区技能,ClawHub 市场有 Skills 扩展点,但非核心,依赖社区贡献
MCP仅客户端,Streamable HTTP,热重载不中断支持外部 API / MCP 工具接入不内置 MCP,通过扩展实现
多 Agent 工作流LangGraph,主 Agent 在回路 + HITL + 跨重启续跑非核心,偏单 Agent 长任务执行不内置子 Agent,通过技能扩展实现
会话管理中间件注入 + 上下文压缩 + checkpointerReAct 循环 + Workspace 状态独家会话树(Session Tree,类 Git 分支管理)
部署一键 Docker,单库挂载本地部署 / Docker / 云端方案npm 安装,零外部依赖

特点与区别

OpenClaw 是 2026 年开源 AI 领域的现象级项目(GitHub 星标超 37 万),由奥地利开发者 Peter Steinberger 创建,前身为 Clawdbot / Moltbot。它的核心架构是 Gateway 消息网关 + Agent Runtime + Skills 插件系统 三层结构:Gateway 作为调度中枢(默认端口 18789),统一接入飞书、企业微信、钉钉、Telegram、WhatsApp、Discord 等主流 IM 平台;Runtime 基于 ReAct 循环驱动 LLM 执行长任务;Skills 系统是功能扩展的核心载体,社区已积累 5400+ 技能包,并通过 ClawHub 市场分发。OpenClaw 最独特的设计是 Workspace–每个 Agent 拥有独立工作空间(目录结构、文件、缓存、截图),可以在里面保存文件、修改代码、执行命令、打开浏览器测试,实现从”对话”到”持续执行任务”的跨越。数据以 JSONL 落盘本地,强调”数据不出本地”的隐私保护。

LemonClaw 与 OpenClaw 的关键区别在于:OpenClaw 是 Node.js/TypeScript 生态,核心抽象围绕 Workspace + Skills 组织运行时,数据持久化以 JSONL 文件落盘为主;LemonClaw 是 Python 生态,所有状态收敛到一个 SQLite 文件,并在此基础上构建了 LangGraph 驱动的多 Agent 工作流(主 Agent 在回路 + HITL + 跨重启续跑)。两者在”多通道接入”上目标一致但实现路径不同–OpenClaw 的 Gateway 覆盖了更多 IM 平台,LemonClaw 的消息总线设计更轻量且内建 Cron 定时任务调度。技能格式上 LemonClaw 选择兼容 OpenClaw,以复用其生态。

Pi-Agent(GitHub 星标 7.7 万)是由 libGDX 作者 Mario Zechner 打造的开源 Agent 工具包(agent harness),采用 Monorepo 架构发布 5+ 个独立 npm 包(pi-ai 统一多模型 API、pi-agent-core Agent 运行时、pi-tui 终端 UI 库、pi-chat Web 聊天组件、pi-coding-agent 编码 Agent CLI)。Pi 的核心定位是 底层基础设施层–它不规定 Agent 应该做什么,而是提供”引擎”让上层应用自由构建。值得注意的是,OpenClaw 早期的 Agent Runtime 深度嵌入了 Pi 的 SDK,随着发展才把 Runtime 收进自己的代码库,但终端界面仍依赖 Pi 的 TUI 组件。Pi 最独特的设计是会话树(Session Tree)–灵感来自 Git 的分支管理,支持 /fork/switch/merge 等命令,让 AI 对话从”线性一次性”变成”可迭代的工作流”。Pi 的设计哲学是”不做什么”–MCP、子 Agent、Plan 模式、Web 搜索、代码索引等功能均不内置,而是通过 4 类扩展点(Prompt Templates / Skills / Extensions / Themes)交给社区。

LemonClaw 与 Pi-Agent 的关键区别在于:Pi 是 工具包/引擎层,面向”想构建自己 Agent 的开发者”,核心价值是精简可扩展;LemonClaw 是 完整产品层,面向”想要一个开箱即用的数字员工”,核心价值是架构完整且自洽。Pi 没有内置持久化记忆、多通道接入、定时任务、多 Agent 工作流,这些都要使用者自行实现或通过扩展补齐;而 LemonClaw 把这些”数字员工”的基础能力全部内置并收敛到一个 SQLite 里。换句话说,Pi 是造 Agent 的引擎,LemonClaw 是已经造好、能直接上岗的数字员工。

LemonClaw 的核心优势可以归纳成三点:

  1. 架构完整且自洽–从消息总线到工作流,每个子系统都为”通用数字员工”这个目标设计,不存在”核心功能靠框架 A、记忆靠框架 B、通道自己补”的拼装感。
  2. 零外部依赖的单库哲学–一个 SQLite 文件承载所有状态,部署、备份、迁移都极简,没有”为了跑 Agent 还得先起一套中间件”的负担。
  3. 主 Agent 在回路的工作流模型–不是简单的”编排 + 回调”,而是让主 Agent 作为一等公民参与流程,这是大多数同类框架没有的设计。

为什么不从零之外的选择:不直接拿 OpenClaw / Pi-Agent 做底座

“既然 OpenClaw 的技能生态那么好,为什么不直接 fork 它做底座?”–这是我动手前认真考虑过的问题。最终选择从零搭,原因有三:

第一,架构目标不兼容,改比写累。 OpenClaw 的核心架构是 Gateway + Workspace + Skills 三层,整个运行时围绕”IM 消息驱动 + Workspace 级任务执行”设计。而 LemonClaw 的第一性目标是”多通道服务化 + 单库持久化 + 主 Agent 在回路的工作流”。把 OpenClaw 改造成单 SQLite 架构 + LangGraph 工作流,意味着要动它的消息流、状态管理、会话模型–这些是框架的骨架,改骨架比搭新骨架更容易出问题。当一个框架的核心抽象和你的目标不重合时,fork 它往往是在和它的设计意图对抗。

第二,单 SQLite 约束需要从根上贯彻。 “全项目一个数据库文件”不是事后能贴上去的约束,它要求记忆、会话、cron、MCP 状态、工作流 checkpoint 从设计第一天就用同一套 DAO 层。OpenClaw 的数据以 JSONL 文件落盘为主,Pi 则完全没有内置持久化。如果在一个已有框架上加这一层,要么和它原有的存储打架,要么只能在外围再套一层–那就背离了”单库”的初衷。

第三,掌控每一寸上下文数据流。 前面讲的”密钥不进 LLM 上下文”(技能用占位符、MCP 用连接配置)、”中间件注入不污染 checkpointer”、”主 Agent 在回路”–这些都不是某个框架开箱即有的开关,而是需要对数据流有端到端的掌控才能做对的工程决策。Pi 的设计哲学是”不内置”–MCP、子 Agent、持久化记忆全都不做,交给扩展。这意味着你要在 Pi 之上从零实现这些,最终还是在造 LemonClaw。从零搭,意味着每一个字节进不进 LLM 上下文,都是我自己说了算。

当然,从零搭的代价是技能生态要从零长起来–这也是 LemonClaw 选择兼容 OpenClaw 技能格式的原因:用兼容换生态,用自研换架构掌控力。这是一笔划算的交易。

十二、写在最后

从零搭一个通用 AI Agent,难的不是”调通 LLM”,而是把消息总线、工具、记忆、技能、MCP、工作流、上下文管理、部署这些子系统拧成一个自洽的整体,并且每一处都经得起”长期在线”的考验。

LemonClaw 给出的答案是一套单库、多通道、中间件注入、主 Agent 在回路的工程实践。它不一定是最优解,但它是经过真实约束打磨过的一个完整解。如果你也在做类似的事情,欢迎来对比、交流、吐槽。

当然,LemonClaw 不会止步不前。AI Agent 这个领域日新月异,OpenClaw 的 Workspace 抽象、Pi-Agent 的会话树、社区的各类 Agent 实践都在不断进化。LemonClaw 也会持续吸收各家优秀的工程实践,把它们融入自己的架构中–不是简单的”抄”,而是在”单库 + 多通道 + 主 Agent 在回路”的骨架上做有机的融合。我们相信,一个好用的数字员工不是某一次设计的产物,而是在真实使用中不断打磨、不断进步的结果。让 LemonClaw 越来越深入地融入我们的工作和生活,是开源这个项目最初的、也是一直不变的愿景。

项目完全开源(Apache 2.0),代码、Docker 镜像、文档都在这里:

👉 https://github.com/nl8590687/lemonclaw

如果这个项目对你有帮助、有启发,恳请去点个 ⭐ Star–这是对开源作者最直接的支持,也会让更多需要它的人看到。

也欢迎提 Issue、提 PR,一起把它做得更好。下一篇文章我会拆解 LemonClaw 的多 Agent 工作流实现细节,敬请关注。

LemonClaw — 让任意大模型,成为你的数字员工。

版权声明
本博客的文章除特别说明外均为原创,本人版权所有。欢迎转载,转载请注明作者及来源链接,谢谢。
本文地址: https://blog.ailemon.net/2026/08/08/building-a-general-purpose-ai-agent-lemonclaw-from-scratch-an-engineering-practice/
All articles are under Attribution-NonCommercial-ShareAlike 4.0

关注“AI柠檬博客”微信公众号,及时获取你最需要的干货。

Donate

WeChat DonateAlipay Donate

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

8 + 5 =