> ## Documentation Index
> Fetch the complete documentation index at: https://langchain-zh.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 长期记忆

> 为 LangChain 智能体添加长期记忆，实现跨对话和会话的数据存储与回忆

长期记忆使您的智能体能够跨不同对话和会话存储并回忆信息。
与仅限于单个线程的[短期记忆](/oss/javascript/langchain/short-term-memory)不同，长期记忆可跨线程持久保存，并可在任意时刻被回忆。

长期记忆构建于 [LangGraph 存储](/oss/javascript/langgraph/persistence#memory-store)之上，该存储将数据保存为按命名空间和键组织的 JSON 文档。

## 使用方法

要为智能体添加长期记忆，请创建一个存储并将其传递给 [`create_agent`](https://reference.langchain.com/javascript/langchain/index/createAgent)：

<Tabs>
  <Tab title="InMemoryStore">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createAgent } from "langchain";
    import { InMemoryStore } from "@langchain/langgraph";

    // InMemoryStore 将数据保存到内存字典中。在生产环境中使用基于数据库的存储。
    const store = new InMemoryStore();

    const agent = createAgent({
      model: "claude-sonnet-4-6",
      tools: [],
      store,
    });
    ```
  </Tab>

  <Tab title="PostgreSQL">
    ```shell theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    npm install @langchain/langgraph-checkpoint-postgres
    ```

    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createAgent } from "langchain";
    import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres/store";

    const DB_URI =
      process.env.POSTGRES_URI ??
      "postgresql://postgres:postgres@localhost:5442/postgres?sslmode=disable";
    const store = PostgresStore.fromConnString(DB_URI);
    await store.setup();

    const agent = createAgent({
      model: "claude-sonnet-4-6",
      tools: [],
      store,
    });
    ```
  </Tab>
</Tabs>

随后，工具可通过 `runtime.store` 参数从存储中读取数据或向存储写入数据。具体示例请参阅[在工具中读取长期记忆](#read-long-term-memory-in-tools)和[从工具写入长期记忆](#write-long-term-memory-from-tools)。

<Tip>
  若需深入了解记忆类型（语义记忆、情景记忆、程序性记忆）及记忆写入策略，请参阅[记忆概念指南](/oss/javascript/concepts/memory#long-term-memory)。
</Tip>

## 记忆存储

LangGraph 将长期记忆作为 JSON 文档存储在[存储](/oss/javascript/langgraph/persistence#memory-store)中。

每条记忆都组织在自定义的 `namespace`（类似于文件夹）和唯一的 `key`（类似于文件名）之下。命名空间通常包含用户或组织 ID 或其他便于信息组织的标签。

这种结构支持记忆的层次化组织。跨命名空间的搜索则通过内容过滤器实现。

<Tabs>
  <Tab title="InMemoryStore">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { InMemoryStore } from "@langchain/langgraph";

    const embed = (texts: string[]): number[][] => {
      // 替换为实际的嵌入函数或 LangChain 嵌入对象
      return texts.map(() => [1.0, 2.0]);
    };

    // InMemoryStore 将数据保存到内存字典中。在生产环境中请使用基于数据库的存储。
    const store = new InMemoryStore({ index: { embed, dims: 2 } });
    const userId = "my-user";
    const applicationContext = "chitchat";
    const namespace = [userId, applicationContext];

    await store.put(namespace, "a-memory", {
      rules: [
        "User likes short, direct language",
        "User only speaks English & TypeScript",
      ],
      "my-key": "my-value",
    });

    // 通过 ID 获取 "memory"
    const item = await store.get(namespace, "a-memory");

    // 在此命名空间中搜索 "memories"，按内容等价性过滤，按向量相似度排序
    const items = await store.search(namespace, {
      filter: { "my-key": "my-value" },
      query: "language preferences",
    });
    ```
  </Tab>

  <Tab title="PostgreSQL">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres/store";

    const embed = (texts: string[]): number[][] => {
      return texts.map(() => [1.0, 2.0]);
    };

    const DB_URI =
      process.env.POSTGRES_URI ??
      "postgresql://postgres:postgres@localhost:5442/postgres?sslmode=disable";
    const store = PostgresStore.fromConnString(DB_URI, {
      index: { embed, dims: 2 },
    });
    await store.setup();

    const userId = "my-user";
    const applicationContext = "chitchat";
    const namespace = [userId, applicationContext];

    await store.put(namespace, "a-memory", {
      rules: [
        "User likes short, direct language",
        "User only speaks English & TypeScript",
      ],
      "my-key": "my-value",
    });

    const item = await store.get(namespace, "a-memory");
    const items = await store.search(namespace, {
      filter: { "my-key": "my-value" },
      query: "language preferences",
    });
    ```
  </Tab>
</Tabs>

有关记忆存储的更多信息，请参阅[持久化](/oss/javascript/langgraph/persistence#memory-store)指南。

## 在工具中读取长期记忆

<Tabs>
  <Tab title="InMemoryStore">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, tool, type ToolRuntime } from "langchain";
    import { InMemoryStore } from "@langchain/langgraph";

    // InMemoryStore 将数据保存到内存字典中。在生产环境中使用基于数据库的存储。
    const store = new InMemoryStore();
    const contextSchema = z.object({
      userId: z.string(),
    });

    // 使用 put 方法向存储写入示例数据
    await store.put(
      ["users"], // 用于对相关数据进行分组的命名空间（用户数据的 users 命名空间）
      "user_123", // 命名空间内的键（以用户 ID 为键）
      {
        name: "John Smith",
        language: "English",
      }, // 要存储的给定用户的数据
    );

    const getUserInfo = tool(
      // 查找用户信息。
      async (_, runtime: ToolRuntime<unknown, z.infer<typeof contextSchema>>) => {
        // 访问存储 - 与提供给 `createAgent` 的相同
        const userId = runtime.context.userId;
        if (!userId) {
          throw new Error("userId is required");
        }
        // 从存储检索数据 - 返回包含值和元数据的 StoreValue 对象
        const userInfo = await runtime.store.get(["users"], userId);
        return userInfo?.value ? JSON.stringify(userInfo.value) : "Unknown user";
      },
      {
        name: "getUserInfo",
        description: "Look up user info by userId from the store.",
        schema: z.object({}),
      },
    );

    const agent = createAgent({
      model: "claude-sonnet-4-6",
      tools: [getUserInfo],
      contextSchema,
      // 将存储传递给代理 - 使代理在运行工具时能够访问存储
      store,
    });

    // 运行代理
    const result = await agent.invoke(
      { messages: [{ role: "user", content: "look up user information" }] },
      { context: { userId: "user_123" } },
    );

    console.log(result.messages.at(-1)?.content);

    /**
     * 输出：
     * 用户信息：
     * - **姓名：** John Smith
     * - **语言：** English
     */
    ```
  </Tab>

  <Tab title="PostgreSQL">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, tool, type ToolRuntime } from "langchain";
    import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres/store";

    const DB_URI =
      process.env.POSTGRES_URI ??
      "postgresql://postgres:postgres@localhost:5442/postgres?sslmode=disable";
    const store = PostgresStore.fromConnString(DB_URI);
    await store.setup();

    const contextSchema = z.object({ userId: z.string() });

    await store.put(["users"], "user_123", {
      name: "John Smith",
      language: "English",
    });

    const getUserInfo = tool(
      async (_, runtime: ToolRuntime<unknown, z.infer<typeof contextSchema>>) => {
        const userId = runtime.context.userId;
        if (!userId) throw new Error("userId is required");
        const userInfo = await runtime.store.get(["users"], userId);
        return userInfo?.value ? JSON.stringify(userInfo.value) : "Unknown user";
      },
      {
        name: "getUserInfo",
        description: "Look up user info by userId from the store.",
        schema: z.object({}),
      },
    );

    const agent = createAgent({
      model: "claude-sonnet-4-6",
      tools: [getUserInfo],
      contextSchema,
      store,
    });

    await agent.invoke(
      { messages: [{ role: "user", content: "look up user information" }] },
      { context: { userId: "user_123" } },
    );
    ```
  </Tab>
</Tabs>

<a id="write-long-term" />

## 从工具写入长期记忆

<Tabs>
  <Tab title="InMemoryStore">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { tool, createAgent, type ToolRuntime } from "langchain";
    import { InMemoryStore } from "@langchain/langgraph";

    // InMemoryStore 将数据保存到内存字典中。在生产环境中请使用基于数据库的存储。
    const store = new InMemoryStore();

    const contextSchema = z.object({
      userId: z.string(),
    });

    // Schema 定义了 LLM 用户信息的结构
    const UserInfo = z.object({
      name: z.string(),
    });

    // 允许代理更新用户信息的工具（适用于聊天应用程序）
    const saveUserInfo = tool(
      async (
        userInfo: z.infer<typeof UserInfo>,
        runtime: ToolRuntime<unknown, z.infer<typeof contextSchema>>,
      ) => {
        const userId = runtime.context.userId;
        if (!userId) {
          throw new Error("userId is required");
        }
        // 在 store 中存储数据（命名空间，键，数据）
        await runtime.store.put(["users"], userId, userInfo);
        return "Successfully saved user info.";
      },
      {
        name: "save_user_info",
        description: "Save user info",
        schema: UserInfo,
      },
    );

    const agent = createAgent({
      model: "claude-sonnet-4-6",
      tools: [saveUserInfo],
      contextSchema,
      store,
    });

    // 运行代理
    await agent.invoke(
      { messages: [{ role: "user", content: "My name is John Smith" }] },
      // 上下文中传递的 userId，用于识别正在更新谁的信息
      { context: { userId: "user_123" } },
    );

    // 您可以直接访问 store 以获取值
    const result = await store.get(["users"], "user_123");
    console.log(result?.value); // 输出：{ name: "John Smith" }
    ```
  </Tab>

  <Tab title="PostgreSQL">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { tool, createAgent, type ToolRuntime } from "langchain";
    import { PostgresStore } from "@langchain/langgraph-checkpoint-postgres/store";

    const DB_URI =
      process.env.POSTGRES_URI ??
      "postgresql://postgres:postgres@localhost:5442/postgres?sslmode=disable";
    const store = PostgresStore.fromConnString(DB_URI);
    await store.setup();

    const contextSchema = z.object({ userId: z.string() });

    const UserInfo = z.object({ name: z.string() });

    const saveUserInfo = tool(
      async (
        userInfo: z.infer<typeof UserInfo>,
        runtime: ToolRuntime<unknown, z.infer<typeof contextSchema>>,
      ) => {
        const userId = runtime.context.userId;
        if (!userId) throw new Error("userId is required");
        await runtime.store.put(["users"], userId, userInfo);
        return "Successfully saved user info.";
      },
      { name: "save_user_info", description: "Save user info", schema: UserInfo },
    );

    const agent = createAgent({
      model: "claude-sonnet-4-6",
      tools: [saveUserInfo],
      contextSchema,
      store,
    });

    await agent.invoke(
      { messages: [{ role: "user", content: "My name is John Smith" }] },
      { context: { userId: "user_123" } },
    );

    const result = await store.get(["users"], "user_123");
    console.log(result?.value);
    ```
  </Tab>
</Tabs>

***

<div className="source-links">
  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/i18n\zh-CN\oss\langchain\long-term-memory.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>

  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>
</div>
