项目架构
本文面向开发者,介绍 Ameba-Claw 的整体结构、核心组件及文件系统布局。
架构概览
Ameba-Claw 采用三层架构,用户输入经由 Agent 推理层处理后,由底层 Capability 执行层完成实际操作:
┌──────────────────────────────────────────────────────┐
│ 用户输入层 │
│ Telegram / Feishu / WeChat / QQ / WebUI / AT Serial │
└──────────────────────┬───────────────────────────────┘
│
┌──────────────────────▼───────────────────────────────┐
│ Agent 推理层 │
│ claw_agent — ReAct 循环(LLM + tool calls) │
└──────────────────────┬───────────────────────────────┘
│
┌──────────────────────▼───────────────────────────────┐
│ Capability 执行层 │
│ Lua 引擎 / 文件系统 / 板级硬件 / 调度器 │
└──────────────────────────────────────────────────────┘
消息通过 IM 渠道(或串口 AT 接口)进入,claw_agent 启动 ReAct 推理循环:LLM 决策下一步调用哪个 Capability,对应 Capability 执行后将结果作为工具响应反馈给 LLM,循环持续直到 LLM 生成最终回复。
核心组件
claw_agent
实现 ReAct(Reasoning + Acting)循环,每个会话请求在独立任务中处理:
携带当前工具描述和对话上下文向 LLM 发送请求。
解析 LLM 返回的 tool-call 响应。
将工具调用分发至对应 Capability 并收集结果。
将结果追加为工具响应,进入下一轮推理。
当 LLM 产生最终回复时,将其发送给用户。
Watchdog 任务监控心跳时间戳。若 7 分钟内未收到任何 tool-call 心跳(表明某个 Capability 挂起或 LLM 请求卡死),Watchdog 将通过 sys_reset() 触发软复位。
Capability 系统
Capability 是注册在 C 层的可调用工具,LLM 通过 tool-call 接口直接调用。每个 Capability 具有唯一的 id、JSON 输入 Schema 和执行函数。开发者也可通过 AT+CLAW=cap,<id> 或在 Lua 脚本中使用 cap.call() 来调用。
Capability 按功能划分为 cap_group。部分组默认对 LLM 隐藏,需激活对应 Skill 后方可解锁——例如 board 组需激活 board_hardware_info Skill 后才可见。
详见 Capability 系统。
Skill 管理器
管理 rolfs:/skills/ (内置)和 vfs:/skills/ (用户创建)下的 Skill 目录。Skill 管理器负责:
解析
SKILL.md元数据,提取名称、描述、cap_groups依赖及 LLM 系统提示注入内容区分两类 Skill:
脚本型:包含
scripts/main.lua,由lua_runCapability 执行知识型:无脚本,仅向 LLM 注入上下文并解锁对应
cap_groups
在
vfs:/session/中持久化维护每个会话的激活列表,实现 Session 隔离
详见 Skill 系统。
Lua 执行引擎
通过 lua_run (同步)和 lua_run_async (异步)Capability 对外暴露,核心设计要点:
每次调用均创建独立的
lua_State,运行间无共享全局状态Lua VM 运行在独立的 8 KB 任务栈中(非调用方栈),防止脚本解析时栈溢出
沙盒移除
io、os、debug、load、loadfile、dofile及 raw 访问原语同步默认超时 30 秒;取消钩子每执行 500 条 Lua 指令触发一次
异步任务提供 4 个 job 槽(最多 2 个并发,与同步共享),每个 job 带 2 KB 环形日志,可通过
lua_job_get增量读取
详见 Lua 模块参考。
IM 分发器
接收所有支持渠道的消息——Telegram、Feishu(飞书)、WeChat(微信)、QQ、本地 WebUI、串口 AT 接口——并将其封装为标准 claw_agent_request_t 提交至 Agent 循环。每个渠道运行独立的接收任务,并将回复路由回对应的来源会话。
文件系统布局
Ameba-Claw 使用两个独立的 littlefs 分区。
rolfs:/
只读固件分区,嵌入在应用程序二进制中,随 OTA 原子更新,运行时不可写入。
rolfs:/
├── skills/ 内置 Skill 包
│ └── <name>/
│ ├── SKILL.md Skill 元数据 + 说明文档
│ └── scripts/ 脚本型 Skill 入口(main.lua)
├── docs/ Lua 模块 API 快速参考文档(.md)
└── lib/ Lua 共享库(可在 Skill 脚本中 require)
vfs:/
可读写 Flash 分区,重启和断电后数据持久保留。
vfs:/
├── skills/ 用户创建的 Skill 包
│ └── <name>/
│ ├── SKILL.md
│ └── scripts/main.lua
├── scripts/ 持久化的用户应用脚本(不在 Skill 目录中)
├── tmp/ 临时脚本(每次启动时清空)
├── session/ 每会话激活列表、记忆及运行时状态
└── ... 配置文件、收件箱附件等