跳转到内容

上下文引擎

一个 上下文引擎 控制着 OpenClaw 如何为每次运行构建模型上下文:包括包含哪些消息、如何压缩旧的历史记录以及如何管理跨子代理边界的上下文。

OpenClaw 内置了 OpenClawlegacy 引擎并默认使用它 —— 大多数用户无需更改此设置。仅当您需要不同的组装、压缩或跨会话记忆行为时,才安装并选择插件引擎。

  1. 检查当前启用的引擎

    Terminal window
    openclaw doctor
    # or inspect config directly:
    cat ~/.openclaw/openclaw.json | jq '.plugins.slots.contextEngine'
  2. 安装插件引擎

    上下文引擎插件的安装方式与任何其他 OpenClaw 插件相同。

    Terminal window
    openclaw plugins install @martian-engineering/lossless-claw
  3. 启用并选择引擎

    openclaw.json
    {
    plugins: {
    slots: {
    contextEngine: "lossless-claw", // must match the plugin's registered engine id
    },
    entries: {
    "lossless-claw": {
    enabled: true,
    // Plugin-specific config goes here (see the plugin's docs)
    },
    },
    },
    }

    安装并配置后,请重启网关。

  4. 切换回旧版引擎(可选)

    contextEngine 设置为 "legacy"(或完全移除该键 —— "legacy" 为默认值)。

每次 OpenClaw 运行模型提示时,上下文引擎都会在四个生命周期点参与其中:

1. 摄取

当新消息添加到会话时调用。引擎可以在其自己的数据存储中存储或索引该消息。

2. 组装

在每次模型运行之前调用。引擎返回一组符合 token 预算的有序消息(以及可选的 systemPromptAddition)。

3. 压缩

当上下文窗口已满,或用户运行 /compact 时调用。引擎会对旧历史进行摘要以释放空间。

4. 回合后

在运行完成后调用。引擎可以持久化状态、触发后台压缩或更新索引。

对于捆绑的非 ACP Codex harness,OpenClaw 通过将组装的上下文投影到 Codex 开发者指令和当前回合提示中来应用相同的生命周期。Codex 仍然拥有其原生线程历史记录和原生压缩器。

OpenClaw 调用两个可选的子代理生命周期钩子:

在子运行开始之前准备共享上下文状态。该钩子接收父/子会话密钥、`contextMode`(`isolated` 或 `fork`OpenClaw)、可用的转录 ID/文件以及可选的 TTL。如果它返回一个回滚句柄,当准备成功后生成失败时,OpenClaw 会调用它。 当子代理会话完成或被清理时进行清理。

assemble 方法可以返回一个 systemPromptAdditionOpenClaw 字符串。OpenClaw 会将其前置到该次运行的系统提示词中。这允许引擎注入动态的记忆指导、检索指令或上下文感知提示,而无需静态工作区文件。

内置的 legacyOpenClaw 引擎保留了 OpenClaw 的原始行为:

  • 摄取 (Ingest):无操作(会话管理器直接处理消息持久化)。
  • 组装 (Assemble):直通(运行时中现有的清理 → 验证 → 限制管道处理上下文组装)。
  • Compact:委托给内置的摘要压缩,它会对旧消息创建单个摘要并保持最近的消息不变。
  • After turn:无操作。

旧版引擎不注册工具,也不提供 systemPromptAddition

当未设置 plugins.slots.contextEngine(或将其设置为 "legacy")时,将自动使用此引擎。

插件可以使用插件 API 注册上下文引擎:

import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
export default function register(api) {
api.registerContextEngine("my-engine", (ctx) => ({
info: {
id: "my-engine",
name: "My Context Engine",
ownsCompaction: true,
},
async ingest({ sessionId, message, isHeartbeat }) {
// Store the message in your data store
return { ingested: true };
},
async assemble({ sessionId, messages, tokenBudget, availableTools, citationsMode }) {
// Return messages that fit the budget
return {
messages: buildContext(messages, tokenBudget),
estimatedTokens: countTokens(messages),
systemPromptAddition: buildMemorySystemPromptAddition({
availableTools: availableTools ?? new Set(),
citationsMode,
}),
};
},
async compact({ sessionId, force }) {
// Summarize older context
return { ok: true, compacted: true };
},
}));
}

工厂 ctx 包含可选的 configagentDirworkspaceDir 值,以便插件可以在第一个生命周期钩子运行之前初始化每个代理或每个工作区的状态。

然后在配置中启用它:

{
plugins: {
slots: {
contextEngine: "my-engine",
},
entries: {
"my-engine": {
enabled: true,
},
},
},
}

必需成员:

成员类型用途
info属性引擎 ID、名称、版本以及它是否拥有压缩权
ingest(params)方法存储单条消息
assemble(params)方法为模型运行构建上下文(返回 AssembleResult
compact(params)方法摘要/缩减上下文

assemble 返回一个 AssembleResult,其中包含:

发送给模型的有序消息。 引擎对组装后的上下文中总 Token 的估计。OpenClaw 将其用于压缩阈值决策和诊断报告。 附加到系统提示之前。 控制运行程序使用哪种 Token 估计进行抢占性溢出 预检查。默认为 `"assembled"`,这意味着仅检查 已组装提示的估计值 - 适用于返回 窗口化、自包含上下文的引擎。仅当您的 组装视图可能在底层 转录中隐藏溢出风险时,才将其设置为 `"preassembly_may_overflow"`; 然后,运行程序在决定 是否进行抢先压缩时,会取已组装估计值 和组装前(非窗口化)会话历史估计值中的最大值。无论哪种方式,您返回的 消息仍然是模型所看到的内容 - `promptAuthority` 仅影响预检查。

compact 返回一个 CompactResult。当压缩轮换活动 transcript 时,result.sessionIdresult.sessionFile 识别下一次重试或回合必须使用的后继 会话。

可选成员:

成员类型用途
bootstrap(params)方法初始化会话的引擎状态。在引擎首次看到会话时(例如,导入历史记录)调用一次。
ingestBatch(params)方法作为批次摄取已完成的回合。在运行完成后调用,一次性包含该回合的所有消息。
afterTurn(params)方法运行后的生命周期工作(持久化状态,触发后台压缩)。
prepareSubagentSpawn(params)方法在子会话开始之前为其设置共享状态。
onSubagentEnded(params)方法在子代理结束后进行清理。
dispose()方法释放资源。在网关关闭或插件重新加载期间调用 - 而非针对每个会话。

ownsCompaction 控制是否在运行期间启用 Pi 内置的尝试中自动压缩:

ownsCompaction: true

引擎拥有压缩行为。OpenClaw 针对该运行禁用 Pi 的内置自动压缩,引擎的 compact() 实现负责 /compact、溢出恢复压缩以及它想要在 afterTurn()OpenClaw 中执行的任何主动压缩。当它预测完整的 transcript 将会溢出时,恢复路径会在提交另一个 prompt 之前调用活动引擎的 compact()

ownsCompaction: false or unset

Pi 的内置自动压缩仍可能在 prompt 执行期间运行,但活动引擎的 compact() 方法仍会被调用以进行 /compact 和溢出恢复。

这意味着有两种有效的插件模式:

实现您自己的压缩算法并设置 ownsCompaction: true

对于非自有引擎,空操作(no-op)的 compact() 是不安全的,因为它会禁用该引擎插槽正常的 /compact 和溢出恢复压缩路径。

{
plugins: {
slots: {
// Select the active context engine. Default: "legacy".
// Set to a plugin id to use a plugin engine.
contextEngine: "legacy",
},
},
}

压缩

压缩是上下文引擎的职责之一。传统引擎委托给 OpenClaw 的内置摘要功能。插件引擎可以实现任何压缩策略(DAG 摘要、向量检索等)。

Memory plugins

Memory 插件 (plugins.slots.memory) 与上下文引擎是分开的。Memory 插件提供搜索/检索功能;上下文引擎控制模型看到的内容。它们可以协同工作——上下文引擎可能会在组装过程中使用 Memory 插件数据。如果插件引擎需要使用活动的 memory 提示路径,应优先使用来自 openclaw/plugin-sdk/corebuildMemorySystemPromptAddition(...),它会将活动的 memory 提示部分转换为准备好前置的 systemPromptAddition。如果引擎需要更低级别的控制,仍然可以通过 buildActiveMemoryPromptSection(...)openclaw/plugin-sdk/memory-host-core 获取原始行。

Session pruning

无论激活哪个上下文引擎,内存中修剪旧工具结果的操作仍然会运行。

  • 使用 openclaw doctor 来验证您的引擎是否正确加载。
  • 如果切换引擎,现有会话将继续使用其当前历史记录。新引擎将接管未来的运行。
  • 引擎错误会被记录并在诊断中显示。如果插件引擎注册失败或无法解析选定的引擎 ID,OpenClaw 不会自动回退;运行将失败,直到您修复插件或将 plugins.slots.contextEngine 切换回 "legacy"
  • 对于开发,请使用 openclaw plugins install -l ./my-engine 来链接本地插件目录而无需复制。