Agent Skills: langgraph-memory (JavaScript/TypeScript)

LangGraph 中的内存:短期(线程范围)vs 长期(跨线程)内存,使用检查点器和存储

UncategorizedID: evanfang0054/cc-system-creator-scripts/langgraph-memory

Install this agent skill to your local

pnpm dlx add-skill https://github.com/evanfang0054/cc-system-creator-scripts/tree/HEAD/skills/langchain-skills/langgraph-memory

Skill Files

Browse the full folder contents for langgraph-memory.

Download Skill

Loading file tree…

skills/langchain-skills/langgraph-memory/SKILL.md

Skill Metadata

Name
langgraph-memory
Description
LangGraph 中的内存:短期(线程范围)vs 长期(跨线程)内存,使用检查点器和存储

langgraph-memory (JavaScript/TypeScript)


name: langgraph-memory description: LangGraph 中的内存 - 短期(线程范围)vs 长期(跨线程)内存,使用检查点器和存储

概述

LangGraph 为 Agent 提供两种类型的内存:

  • 短期内存:线程范围,通过检查点器管理
  • 长期内存:跨线程,通过存储管理

决策表:内存类型

| 类型 | 范围 | 持久化 | 使用场景 | |------|-------|-------------|----------| | 短期 | 单个线程 | 通过检查点器 | 对话历史 | | 长期 | 跨线程 | 通过存储 | 用户偏好、事实 |

代码示例

短期内存(线程范围)

import { MemorySaver, StateGraph, StateSchema, ReducedValue, START, END } from "@langchain/langgraph";
import { z } from "zod";

const State = new StateSchema({
  messages: new ReducedValue(
    z.array(z.string()).default(() => []),
    { reducer: (current, update) => current.concat(update) }
  ),
});

const respond = async (state: typeof State.State) => {
  // 访问对话历史
  const history = state.messages;
  return { messages: [`I remember ${history.length} messages`] };
};

const checkpointer = new MemorySaver();

const graph = new StateGraph(State)
  .addNode("respond", respond)
  .addEdge(START, "respond")
  .addEdge("respond", END)
  .compile({ checkpointer });

// 第一轮
const config = { configurable: { thread_id: "user-1" } };
await graph.invoke({ messages: ["Hello"] }, config);

// 第二轮 - 记住第一轮
await graph.invoke({ messages: ["How are you?"] }, config);
// 响应: "I remember 3 messages" (Hello, 响应, How are you?)

长期内存(跨线程)

import { InMemoryStore } from "@langchain/langgraph";

// 创建长期内存存储
const store = new InMemoryStore();

// 保存用户偏好(在所有线程中可用)
const userId = "alice";
const namespace = [userId, "preferences"];

await store.put(
  namespace,
  "language",
  { preference: "short, direct responses" }
);

// 在任何线程中检索
const getUserPrefs = async (state, config) => {
  const store = config.store;
  const userId = state.userId;
  const namespace = [userId, "preferences"];

  const prefs = await store.get(namespace, "language");
  return { preferences: prefs };
};

// 使用存储编译
const graph = builder.compile({
  checkpointer,
  store,
});

// 在不同线程中使用
const thread1 = { configurable: { thread_id: "thread-1" } };
const thread2 = { configurable: { thread_id: "thread-2" } };

// 两个线程访问相同的长期内存
await graph.invoke({ userId: "alice" }, thread1);  // 获取偏好
await graph.invoke({ userId: "alice" }, thread2);  // 相同的偏好

存储操作

import { InMemoryStore } from "@langchain/langgraph";

const store = new InMemoryStore();

// Put(创建/更新)
await store.put(
  ["user-123", "facts"],
  "location",
  { city: "San Francisco", country: "USA" }
);

// Get
const item = await store.get(["user-123", "facts"], "location");
console.log(item);  // { city: 'San Francisco', country: 'USA' }

// 带过滤器搜索
const results = await store.search(
  ["user-123", "facts"],
  { filter: { country: "USA" } }
);

// Delete
await store.delete(["user-123", "facts"], "location");

在节点中访问存储

import { BaseStore } from "@langchain/langgraph";

const myNode = async (state, config: { store: BaseStore }) => {
  const store = config.store;
  const namespace = [state.userId, "memories"];

  // 检索过去的记忆
  const memories = await store.search(namespace, { query: "preferences" });

  // 保存新记忆
  await store.put(
    namespace,
    "new_fact",
    { fact: "User likes TypeScript" }
  );

  return { processed: true };
};

const graph = builder.compile({
  checkpointer,
  store,
});

组合短期和长期内存

const smartNode = async (state, config) => {
  const store = config.store;

  // 短期:对话上下文
  const recentMessages = state.messages.slice(-5);  // 最近 5 条消息

  // 长期:用户档案
  const userId = state.userId;
  const profile = await store.get([userId, "profile"], "info");

  // 使用两者生成个性化响应
  const response = await generateResponse(recentMessages, profile);

  return { messages: [response] };
};

const graph = new StateGraph(State)
  .addNode("respond", smartNode)
  .addEdge(START, "respond")
  .addEdge("respond", END)
  .compile({ checkpointer, store });

持久化存储(生产环境)

import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres";

// 在生产环境中使用 PostgreSQL
const store = await PostgresStore.fromConnString(
  "postgresql://user:pass@localhost/db"
);

const graph = builder.compile({
  checkpointer,
  store,
});

边界

您能够配置的

✅ 使用检查点器进行短期内存 ✅ 使用存储进行长期内存 ✅ 命名空间组织 ✅ 搜索和过滤记忆 ✅ 通过 config 在节点中访问存储 ✅ 选择存储后端

您不能配置的

❌ 跨线程共享短期内存 ❌ 修改内存序列化格式 ❌ 存储机制内部

注意事项

1. 短期需要检查点器

// ❌ 错误 - 没有检查点器,没有内存
const graph = builder.compile();  // 消息丢失!

// ✅ 正确
const checkpointer = new MemorySaver();
const graph = builder.compile({ checkpointer });

2. 长期需要存储

// ❌ 错误 - 试图在没有存储的情况下共享数据
// 仅靠检查点器无法访问来自其他线程的数据!

// ✅ 正确 - 使用存储
const store = new InMemoryStore();
const graph = builder.compile({ checkpointer, store });

3. 通过 Config 访问存储

// ❌ 错误 - 存储不可用
const myNode = async (state) => {
  store.put(...);  // ReferenceError!
};

// ✅ 正确 - 通过 config 访问
const myNode = async (state, config) => {
  const store = config.store;
  await store.put(...);
};

4. InMemoryStore 不用于生产环境

// ❌ 错误 - 重启时数据丢失
const store = new InMemoryStore();  // 仅内存!

// ✅ 正确 - 使用持久化后端
import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres";
const store = await PostgresStore.fromConnString("postgresql://...");

5. 始终 Await 存储操作

// ❌ 错误
const item = store.get(namespace, key);
console.log(item);  // Promise!

// ✅ 正确
const item = await store.get(namespace, key);
console.log(item);

相关链接