Skip to content

记忆(Memory)

跨会话持久化的键值记忆:模型通过 tool call 写入,已有记忆在编译时自动注入 payload。记忆通过 tool call(create_memory / modify_memory)修改,compile() 时自动注入到 payload 中。

typescript
import { InMemoryStore, VFSMemoryStore } from "@context-chef/core";

const chef = new ContextChef({
  memory: {
    store: new InMemoryStore(), // ephemeral (testing)
    // store: new VFSMemoryStore(dir),   // persistent (production)
  },
});

// In your agent loop, intercept memory tool calls:
for (const toolCall of response.tool_calls) {
  if (toolCall.function.name === "create_memory") {
    const { key, value, description } = JSON.parse(toolCall.function.arguments);
    await chef.getMemory().createMemory(key, value, description);
  } else if (toolCall.function.name === "modify_memory") {
    const { action, key, value, description } = JSON.parse(toolCall.function.arguments);
    if (action === "update") {
      await chef.getMemory().updateMemory(key, value, description);
    } else {
      await chef.getMemory().deleteMemory(key);
    }
  }
}

// Direct read/write (developer use, bypasses validation hooks)
await chef.getMemory().set("persona", "You are a senior engineer", {
  description: "The agent's persona and role",
});
const value = await chef.getMemory().get("persona");

// On compile():
// - Memory tools (create_memory, modify_memory) are auto-injected into payload.tools
// - Existing memories are injected as <memory> XML between systemPrompt and history

Memory 位置 —— memoryPlacement

控制易变的 <memory> 数据块在编译产物中的落点。默认 'after_system'(向后兼容)。如果你在用 Anthropic prompt caching 且 cache breakpoint 打在 history 上,切换到 'before_history_tail',这样 memory 变化就不会击穿 history 的缓存了。

typescript
const chef = new ContextChef({
  memory: {
    store: new VFSMemoryStore(dir),
    memoryPlacement: 'before_history_tail',
  },
});
Placement三明治顶部最后一条 user 消息适用场景
'after_system'(默认)INSTRUCTION + <memory> 数据合并成一条 role: 'system'不动简单 agent;不依赖 system 参数之后的 cache breakpoint
'before_history_tail'仅 INSTRUCTION(稳定,可缓存)在原 user 内容后追加 <memory> 数据块你希望 history(或更靠前的 system)上的 cache breakpoint 在每轮 memory 变化时都能命中

这个拆分把稳定的使用说明留在三明治顶部享受缓存,把易变的数据块送到对话末尾。Anthropic / Gemini adapter 会把所有 role: 'system' 提取到 top-level system 参数 —— 选 'before_history_tail' 后,数据块改留在 messages 里,任何打在消息流更早位置的 cache breakpoint 都不再把变化的 memory 文本算进 hash。

如果动态状态也注入到末尾(dynamicStatePlacement: 'last_user'),最后一条 user 消息内部顺序是:原内容 → <memory><dynamic_state><implicit_context> → 锚定句。如果动态状态走独立 system message(dynamicStatePlacement: 'system'),memory 仍然注入到 user 末尾,但不会带锚定句。