为什么需要会话回溯

OpenClaw 的会话不会自动消失,但也不会自动排队等你翻。日子久了,sidebar 里全是 main、cron:xxxx、group:xxxx,光看名字根本想不起哪次聊过「halo 主题 500 排障」。

粗暴办法是滚动聊天记录——但 cron 任务和子会话根本不在你眼前。正确姿势是用三个核心工具组成一条流水线:

  1. sessions_list —— 先拿到「有哪些会话」的清单(可过滤、可分页)。
  1. sessions_search —— 拿着关键词全文搜,直接命中某条消息。
  1. sessions_history —— 用搜到的 sessionKey / messageId 把上下文原文读出来。

下面每一步的参数都来自本机 tool_describe 的真实返回,不编造。

第一步:sessions_list 列出并缩小范围

sessions_list 是「元数据-only」的清单,默认每条只返回 key、agentId、kind、channel、archived、pinned 等字段,不会把整段对话灌进来,所以先拿它做筛选最省 token。

常用过滤参数(均为可选):

  • kinds:数组,取值 main / group / cron / hook / node / other。只想看定时任务就传 ["cron"]。
  • group / pinned:按自定义分组、是否钉置顶过滤。
  • agentId / workspaceDir / projectId:按智能体或工作区缩圈。
  • search:直接按会话标签/显示名做文本过滤(注意它搜的是元数据,不是消息正文;正文搜索交给下一步)。
  • activeOnly / activeMinutes:只看最近 N 分钟活跃过的。
  • includeLastMessage + messageLimit:把每条会话的最后几条消息预览也带回来,方便肉眼确认。
  • 分页:limit(默认 100,上限 200)+ offset,用返回的 hasMore / nextOffset 继续翻。

一个真实例子:我只想翻「最近 7 天里,名字带 nginx 的会话」:

{
  "search": "nginx",
  "activeMinutes": 10080,
  "includeLastMessage": true,
  "messageLimit": 1
}

返回的每条 sessions 里有 key(后续 history 要用的 sessionKey)、derivedTitle(若开了 includeDerivedTitles)、lastMessagePreview。先凭这些锁定目标 key,再进第二步精搜。

实战踩坑提醒:relationship=owned|created|involving 是按「请求用户身份」筛的,没有可信用户身份时不可用。别在本机 agent 自己跑的时候指望它只给你自己的会话——默认它就是列出可见会话。

第二步:sessions_search 全文命中

sessions_list 的 search 只扫元数据,正文搜要靠 sessions_search。它返回的是「匹配到的消息片段」,每条带:

  • sessionKey / sessionId:定位用。
  • messageId:精确那一条。
  • snippet:命中上下文片段。
  • score:相关度。
  • role:user 还是 assistant。

参数就三个,都很克制:

  • query(必填,字符串,最长 4096):要搜的词,例如 "nginx 反代 443"。
  • limit:结果条数,1–25,默认 10。
  • sessionKey:可选,限定只在某个会话里搜。
{
  "query": "nginx 反代 证书",
  "limit": 10
}

返回里如果某条 sessionId 非空,说明它来自某个具体 transcript。这时要带着 sessionId 去读 history(见下一步),否则只传 sessionKey 读最新尾部即可。

实战踩坑提醒:归档会话的 transcript 默认不进搜索(archivedTranscriptsExcluded 会告诉你被排除几条)。要搜归档里的旧事,先确认它没被排除,或改用 sessions_list 带 archived:"all" 把归档行也列出来再针对性 history。

第三步:sessions_history 读原文上下文

拿到 sessionKey(+ 可选 messageId / sessionId)后,用 sessions_history 把真实对话读出来。它有几种读法:

  • 只传 sessionKey:返回该会话最新尾部(limit 默认几条,上限 1000)。
  • 加 messageId:以那条消息为中心开窗,offset 被忽略,limit 约束窗口大小——最适合「搜到一条,看它前后在聊啥」。
  • 加 sessionId:当 messageId 属于某个具体 transcript 时必须传,否则读最新尾部。
  • includeTools:把工具调用消息也带回来(排障时很有用,能看到当时跑了什么命令)。
  • offset:对未锚定的历史做普通分页;配 hasMore / nextOffset 往后翻。
{
  "sessionKey": "agent:main:cron:6276...",
  "messageId": "msg_01H...",
  "limit": 20,
  "includeTools": true
}

返回结构里有 messages(数组,元素结构由实现决定)、truncated / contentTruncated / contentRedacted(脱敏与截断标记)、bytes(体量)、pendingInputs(那些被接受但排在模型历史之外的输入)。排障时特别要看 contentRedacted —— 如果为 true,说明原文里有被遮盖的敏感内容,你拿到的不是全貌。

实战踩坑提醒:Cancelled/interrupted inputs never replay automatically。如果 pendingInputs 里某条是 interrupted 或 cancelled 状态,它不会自动重放,你得自己判断当时到底执行到哪一步。别以为 history 里「没看到」就等于「没发生」。

一条完整流水线串起来

把三步合起来,真实工作流是:

  1. sessions_list(search:"nginx", includeLastMessage:true)→ 拿到候选 key 列表。
  1. 对最像的那个 key 跑 sessions_search(query:"反代 443", sessionKey:key)→ 命中 messageId。
  1. sessions_history(sessionKey:key, messageId:..., includeTools:true)→ 读出当时完整的排障对话和执行的命令。

这样你从「好像聊过 nginx」到「精确到那天的第几句话、跑了哪条 openssl 命令」,三步搞定,不用翻聊天框,也不用在几十个 cron 会话里盲找。

和其他记忆工具怎么选

  • 想找「某次具体对话说了啥」→ 本文三件套(sessions_*)。
  • 想找「我长期记住的偏好/决策」→ memory_search / memory_get(读 MEMORY.md、USER.md)。
  • 想找「外部频道里的某段讨论」→ conversations_list / conversations_search。
  • 想找「还没加载的工具怎么用」→ tool_search + tool_call。

分工很清楚:会话回溯管「对话现场」,记忆系统管「沉淀结论」。

小结

OpenClaw 的会话回溯不是靠人肉滚动,而是 sessions_list(列)→ sessions_search(搜)→ sessions_history(读)的三段式。关键记住三点:list 的 search 只扫元数据、正文搜交给 search 工具;history 读锚点消息要带 messageId(+ 必要时 sessionId);contentRedacted 和 pendingInputs 状态决定你拿到的是全貌还是残影。把这套用在「上周那次排障现在又要复现」的场景,效率直接拉满。


扫码关注公众号,获取更多 OpenClaw 实操技巧:

公众号二维码