Clawdbot 的核心是决策:如何理解收到的消息,并决定下一步做什么。
这篇文档解释两件事:
- 意图识别:Clawdbot 如何区分“需要精确执行的指令”和“需要理解与规划的开放式任务”。
- Memory Search:当任务需要回忆信息时,Clawdbot 如何从长期记忆中高效检索相关片段(
memory_search/memory_get)。
本文遵循“认知带宽友好”原则:先看标题和图,需要时再读正文。
Repo: clawdbot/clawdbot
0) 一句话心智模型
用规则处理确定性指令,用 LLM 处理开放式任务。
一、高层组件概览
总体架构
下图展示了 Clawdbot 的核心组件及其交互关系,从消息输入到最终行动。
flowchart TD
In[Channel 输入<br/>Channel Plugins] --> GW[Gateway / Runtime]
GW --> AR[决策层 Auto-reply<br/>识别意图与执行指令]
AR -->|控制意图| Ctrl[执行控制命令<br/>status model stop]
AR -->|任务意图| Agent[任务层 Agent<br/>理解 规划 执行]
Agent --> Tools[工具层 Tools<br/>提供扩展能力]
Tools --> Memory[记忆工具<br/>memory_search memory_get]
Tools --> Exec[执行工具<br/>exec browser]
Tools --> Cron[定时工具<br/>cron]
Ctrl --> Out[Channel 回复或动作]
Agent --> Out
Out --> In
- Channel Plugins:负责与具体平台(如 Discord、Slack)交互,收发消息和执行平台特定动作。
- Auto-reply:决策流水线,负责识别消息意图,判断是否响应、是否为指令,以及是否授权。
- Agent:当任务需要理解和规划时,由它组装 prompt、调用 LLM,并管理工具的执行。
- Tools:为
Agent提供扩展能力,例如使用memory_search检索记忆、使用exec执行代码等。
消息 → 决策 → 行动
此流程展示了一条消息从接收到响应的完整生命周期,分为三个主要阶段。
flowchart TD
subgraph A[阶段一 消息]
M1[Channel 原始消息] --> M2[标准化封装<br/>Envelope]
end
subgraph B[阶段二 决策]
M2 --> D1[Auto-reply 决策]
D1 --> D2{需要回应}
D2 -- 否 --> Z1[忽略]
D2 -- 是 --> D3{是指令}
D3 -- 是 --> C1[执行控制命令]
D3 -- 否 --> D4{已授权}
D4 -- 否 --> Z2[拒绝或沉默]
D4 -- 是 --> A1[启动 Agent]
end
subgraph C[阶段三 行动]
A1 --> T1{调用工具}
T1 -- 是 --> S1[执行工具<br/>memory_search browser exec]
T1 -- 否 --> R1[生成回复]
S1 --> R1
C1 --> R1
R1 --> O1[发送回复或执行动作]
end
O1 --> M1
各阶段的输入与输出
- 消息阶段
- 输入:来自平台的原始事件,例如消息文本、附件、发送者、上下文等。
- 输出:标准化的消息对象
Envelope,屏蔽平台差异。
- 决策阶段
- 输入:
Envelope与运行时上下文,例如是否被@、是否私聊、权限状态等。 - 输出:一个明确的决策分支:忽略、执行指令、或启动
Agent。
- 输入:
- 行动阶段
- 输入:来自决策层的具体指令,或来自
Agent的执行计划。 - 输出:可见的副作用,例如发送回复、调用工具、创建定时任务。
- 输入:来自决策层的具体指令,或来自
二、意图识别:Clawdbot 实际上做了什么
Clawdbot 的意图识别是分层的,旨在兼顾效率与智能。
- 规则层 控制意图:通过固定规则快速、可靠地识别命令,实现确定性行为。
- LLM 层 任务意图:如果消息不是命令,则交由
Agent利用 LLM 的理解能力来推断任务。
2.1 控制意图:用规则识别指令
Clawdbot 将两类文本模式视为控制意图:
- 整条消息是命令:例如
/status或stop。通过hasControlCommand将消息标准化后,与命令注册表进行精确匹配。 - 消息中包含指令 token:通过
hasInlineCommandTokens使用宽泛的正则表达式进行快速粗筛。此步骤允许误判,目的是尽早识别可能需要立即处理的消息,而无需等待 LLM。
这种设计的目的是保证核心控制命令的可靠性,并避免在明显无需 Agent 的消息上浪费 LLM 资源。
2.2 触发条件:何时响应消息
Clawdbot 并非对所有消息都响应。它依赖 Auto-reply 流水线中的触发逻辑来决定是否行动。
常见的触发条件包括:
- 消息明确指向 bot,例如被@、在私聊中、或在已激活的群聊中。
- 消息包含控制命令或疑似指令。
在其他情况下,它会保持沉默,以避免干扰。
2.3 任务意图:用 LLM 理解开放式任务
当一条消息通过所有前置检查并被分派给 Agent 时,任务意图的识别就交给了 LLM。
Agent会结合system prompt与历史消息来理解用户的完整任务。system prompt中可以包含硬性规定,例如“当需要回忆信息时,必须先调用memory_search再调用memory_get”。
总结:控制意图由规则系统处理,任务意图由 LLM 处理。
三、搜索:memory_search 为什么快
memory_search 是 Clawdbot 赋予 Agent 的可检索长期记忆。当任务需要回忆“我们上次讨论过什么”或“找到那个 TODO”时,Agent 会先用 memory_search 在记忆文件中定位相关片段,再用 memory_get 安全地读取原文。这确保了回复建立在事实之上,而不是凭空猜测。
这里的“快”,来自高效的索引与混合检索机制。
3.1 工具接口:memory_search 与 memory_get
Agent 通过两个工具与记忆系统交互:
memory_search:输入查询query,可选maxResults与minScore,返回相关片段的列表,包含路径、行号与分数。memory_get:根据memory_search返回的路径与行号范围,安全地读取原始内容。
3.2 索引结构:SQLite + FTS + 向量
每个 Agent 的记忆存储在独立的 SQLite 数据库中,路径为 ~/.clawdbot/memory/{agentId}.sqlite。
其核心表结构包括:
chunks:内容分块表,存储 Markdown 内容块、文件路径及起止行号。chunks_fts:全文检索表,使用 FTS5 提供关键词检索与 BM25 排序。chunks_vec:向量索引表,使用 sqlite-vec 存储 embedding 向量并进行相似度检索。embedding_cache:embedding 缓存表,避免对相同内容重复计算 embedding。
索引构建流水线
下图描述了从源文件到可搜索索引的完整处理流程。
flowchart TD
subgraph Src[数据源]
A[源文件<br/>MEMORY.md 与 memory 目录]
C[可选源<br/>会话转录]
end
subgraph Proc[处理与存储]
B[内容分块]
D[计算 embedding]
E[写入 SQLite]
end
subgraph Idx[索引与缓存]
F[创建 FTS 索引]
G[创建向量索引]
H[写入 embedding 缓存]
end
I[文件监听] --> B
A --> B
C --> B
B --> D
D --> E
E --> F
E --> G
E --> H
3.4 查询流程:混合检索如何工作
MemoryIndexManager.search 方法采用混合检索策略,结合了关键词和语义搜索的优点:
- 关键词搜索:首先,使用 FTS5 快速召回包含相关关键词的候选片段。
- 向量搜索:然后,将
query文本向量化,在 sqlite-vec 中进行语义相似度检索。 - 融合排序:最后,按预设权重融合两路结果,并根据
minScore过滤,得到最终排序列表。
查询时序图
此图展示了当 Agent 调用 memory_search 时,各组件间的交互顺序。
sequenceDiagram
participant Agent
participant Tool as memory_search
participant Manager as MemoryIndexManager
participant DB as SQLite
participant Emb as Embeddings
Agent->>Tool: tool call query
Tool->>Manager: search query
Manager->>Manager: sync if needed
Manager->>DB: keyword search
Manager->>Emb: embed query
Emb-->>Manager: query vector
Manager->>DB: vector search
Manager->>Manager: merge results
Manager-->>Tool: top snippets
Tool-->>Agent: JSON results
3.5 新鲜度:Watcher 与增量同步
为了在不阻塞用户查询的前提下保持索引最新,系统采用异步、增量的更新机制:
- 文件监听:通过
chokidar监听记忆文件的变化,触发增量索引。 - 防抖处理:合并短时间内发生的多次文件修改,避免不必要的重复索引。
- 后台同步:索引过程在后台进行,最大程度减少对前台查询性能的影响。
四、代码阅读入口
- 理解命令与指令识别:
- 从
src/auto-reply/command-detection.ts与commands-registry.data.ts开始。
- 从
- 添加新的快捷指令:
- 参考
src/auto-reply/reply/directive.parse.test.ts中的测试用例。
- 参考
- 调整搜索排序或权重:
- 查看
src/memory/hybrid.ts与src/memory/manager.ts。
- 查看
- 修改分块大小或 embedding 配置:
- 默认值与解析逻辑位于
src/agents/memory-search.ts。
- 默认值与解析逻辑位于
五、核心术语
- 控制意图:可通过固定规则解析的命令或指令。
- 任务意图:需要由 LLM 推理和理解的开放式任务。
- FTS5:SQLite 内置的全文搜索引擎。BM25 是其默认使用的相关性排序算法。
- sqlite-vec:一个为 SQLite 提供向量相似度搜索功能的开源扩展。
- 混合检索:一种结合了关键词搜索与向量语义搜索的策略,旨在提高检索的准确性和相关性。
附录:关键文件地图
- 命令检测:
src/auto-reply/command-detection.ts - Memory 工具:
src/agents/tools/memory-tool.ts - Memory 配置:
src/agents/memory-search.ts - Memory 管理器:
src/memory/manager.ts - 混合检索逻辑:
src/memory/hybrid.ts