项目架构

本文面向开发者,介绍 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)循环,每个会话请求在独立任务中处理:

  1. 携带当前工具描述和对话上下文向 LLM 发送请求。

  2. 解析 LLM 返回的 tool-call 响应。

  3. 将工具调用分发至对应 Capability 并收集结果。

  4. 将结果追加为工具响应,进入下一轮推理。

  5. 当 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_run Capability 执行

    • 知识型:无脚本,仅向 LLM 注入上下文并解锁对应 cap_groups

  • vfs:/session/ 中持久化维护每个会话的激活列表,实现 Session 隔离

详见 Skill 系统

Lua 执行引擎

通过 lua_run (同步)和 lua_run_async (异步)Capability 对外暴露,核心设计要点:

  • 每次调用均创建独立的 lua_State,运行间无共享全局状态

  • Lua VM 运行在独立的 8 KB 任务栈中(非调用方栈),防止脚本解析时栈溢出

  • 沙盒移除 ioosdebugloadloadfiledofile 及 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/           每会话激活列表、记忆及运行时状态
└── ...                配置文件、收件箱附件等