ReAct核心逻辑
python
while true:
response = llm.generate(messages)
messages.append(response)
if not response.tool_calls:
break
for tool in response.tool_calls:
result = tool.execute()
messages.append(result)
一、会话持久化 session management
并不是每次都把当前会话中全部内容都读一遍写入(读全量然后写入),而是每一条会话记录会以JSONL的形式存储下来,采用追加写的方式,一条没有成功写入不会影响其他行。充分考虑到了性能、容错性。
// JSON形式
[
{"id": 1, "role": "user", "content": "你好"},
{"id": 2, "role": "assistant", "content": "你好!有什么我可以帮你的?"}
]
// JSONL形式
{"id": 1, "role": "user", "content": "你好"}
{"id": 2, "role": "assistant", "content": "你好!有什么我可以帮你的?"}
二、记忆管理 memory management
记忆分层:
OpenClaw 的记忆体系分为两个独立但协同的层次:
瞬时情境层 :memory/YYYY-MM-DD.md 格式的每日日志,采用"仅追加"模式记录当天所有对话。这一层不做任何过滤或压缩,保留原始对话流用于后续回溯。(会话持久化)
持久知识层 :MEMORY.md 作为长期记忆的入口文件,存储经过筛选、压缩和固化的高价值信息。Agent 通过严格的"隐私门控"决定哪些瞬时记忆值得晋升到持久层。
这种分层设计的核心价值在于预压缩------当会话 Token 触及软阈值时,触发静默的"智能体回合",强制模型在遗忘前进行主动认知结晶。换句话说,OpenClaw 不会等到上下文爆满才被动处理,而是在关键节点主动触发记忆沉淀。
记忆检索
采用工具调用的方式主动搜索记忆,向量数据库多种语义搜索匹配并且综合排序。
而不是每次都把所有保存的长期记忆加到system prompt中。
TypeScript
tools = [{name: "memory_search", description: "搜索记忆"}]
OpenClaw 摒弃了传统的 RRF(倒数排名融合),采用保留原始分数幅度信号的混合检索策略:
- 向量检索(70% 权重) :利用 sqlite-vec 进行余弦相似度计算,捕获语义层面的相关性
- 关键词检索(30% 权重) :利用 SQLite FTS5 进行精准匹配,确保专有名词不被遗漏
这种权重分配背后的洞察是:在多数 Agent 场景中,"意思相近"比"用词相同"更重要,但完全放弃关键词匹配会导致技术术语丢失。
三、上下文管理 context management
1.上下文裁剪
工具调用返回的结果过于冗杂,会占用大量的上下文空间,但是模型根据工具调用返回的头部和尾部信息就能推测出大致完整内容,因此,将模型返回结果的头部和尾部保留,中间部分裁掉。
TypeScript
function pruning(params: string): string {
const result = params.tool_result;
if(result.length <= 4000){
return result;
}
const head = result.slice(0:1500);
const tail = result.slice(-1500);
return `${head}\n...\n${tail}, raw result length = ${result.length}`};
}
2. 上下文压缩
上下文内容过多时就可以考虑上下文压缩。
TypeScript
function compactContent(context: string): string{
const totalToken = estimate(context);
if(totalToken <= maxToken * 0.75) {
return context;
}
const summary = compactContext(context);
return summary;
}
四、网关设计
总体架构:各种消息渠道 -> 网关层 -> 运行时层 -> 能力层。
网关层:
1.多渠道接入:
将各个渠道的消息每个渠道通过 ChannelDock 适配器统一抽象:
TypeScript
// src/channels/dock.ts
type ChannelDock = {
id: ChannelId;
capabilities: ChannelCapabilities; // 支持的能力
streaming?: ChannelDockStreaming; // 流式输出
groups?: ChannelGroupAdapter; // 群组管理
threading?: ChannelThreadingAdapter; // 线程支持
};
不管消息来自哪个渠道,经过适配之后进入统一处理流水线
2.消息路由引擎:
路由引擎决定每条消息该交给哪个 Agent 、归属哪个会话:
(来源渠道,对话对象)
TypeScript
// src/routing/resolve-route.ts
type ResolveAgentRouteInput = {
channel: string; // 来源渠道
accountId?: string; // 账号 ID
peer?: RoutePeer; // 对话对象
guildId?: string; // Discord 服务器
memberRoleIds?: string[]; // 角色级路由
};
匹配优先级:精确 Peer 绑定 > Guild/Team > 账号 > 渠道 > 默认路由。你可以配置"Discord 的某个服务器用 Agent A,Telegram 私聊用 Agent B"。
3.安全门控
消息到达 Agent 前经过多层检查:发送者白名单、@提及门控、命令权限控制、入站防抖。
五、skill设计
渐进式加载
TypeScript
┌─────────────────────────────────────────┐
│ Level 1: 元数据(始终在上下文中) │
│ name + description ≈ 100 tokens/skill │
│ 50 个 Skill ≈ 5000 tokens │
└──────────────┬──────────────────────────┘
│
AI 判断:"这个 Skill 和当前任务相关"
│
┌──────────────▼──────────────────────────┐
│ Level 2: SKILL.md 正文(触发后加载) │
│ 具体命令、参数、工作流 < 5000 words │
└──────────────┬──────────────────────────┘
│
AI 判断:"需要更多细节" / "需要执行脚本"
│
┌──────────────▼──────────────────────────┐
│ Level 3: 附属资源(按需加载/执行) │
│ scripts/ → 直接执行,不占上下文 │
│ references/ → 读取到上下文 │
│ bin/ → 直接调用,不占上下文 │
└─────────────────────────────────────────┘
参考文章原链接:
https://juejin.cn/post/7601946979606609947?searchId=20260824101926DE98416F6DFD00EB75FA#heading-3
https://juejin.cn/post/7614513113812156466?searchId=202609131118047AB08AE3711F1E2D804E
Openclaw的记忆:https://juejin.cn/post/7644628777114042420