以编程方式使用文档

内存使您的智能体能够在对话中学习和改进。Deep Agents 将内存作为一等公民,通过文件系统支持的内存实现:智能体将内存作为文件进行读写,您可以通过以下方式控制这些文件的存储位置 后端.

内存工作原理

  1. **指向智能体的内存文件。** 创建智能体时将文件路径传递给 memory= 。您还可以通过以下方式传递 技能 通过 skills= 用于过程记忆(可重用的指令,告诉智能体 *如何* 执行任务)。 后端 控制文件的存储位置和访问权限。
  2. **智能体读取内存。** 智能体可以在启动时将内存文件加载到系统提示中,也可以在对话期间按需读取。例如, 技能 使用按需加载:智能体在启动时仅读取技能描述,然后在匹配任务时才读取完整的技能文件。这样可以保持上下文精简,直到需要某个功能时才加载。
  3. **智能体更新内存(可选)。** 当智能体学习到新信息时,它可以使用内置 edit_file 工具更新内存文件。更新可以在对话期间进行(默认设置),也可以通过以下方式在对话之间的后台进行 后台整合。更改会被持久化,并在下次对话中可用。并非所有内存都是可写的:开发者定义的 技能组织策略 通常是只读的。详见 只读与可写内存

两种最常见的模式是 智能体作用域内存 (所有用户共享)和 用户作用域内存 (每个用户隔离)。

作用域内存

智能体内存可以设置作用域,使相同的内存文件可被所有使用该智能体的用户访问,或者使内存文件每个用户独立。

智能体作用域内存

为代理赋予其自身的持久身份,随时间演变。代理作用域的记忆在所有用户之间共享,因此代理通过每次对话建立自己的角色、积累的知识和学到的偏好。当它与用户交互时,会发展专业知识、完善方法并记住有效的内容。它还可以学习和更新 技能 当拥有写权限时。

关键在于后端命名空间:将其设置为 (assistant_id,) 意味着此代理的每次对话都读取和写入同一记忆文件。

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/AGENTS.md"],
    skills=["/skills/"],
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (
                    rt.server_info.assistant_id,  # [!code highlight]
                ),
            ),
            "/skills/": StoreBackend(
                namespace=lambda rt: (
                    rt.server_info.assistant_id,  # [!code highlight]
                ),
            ),
        },
    ),
)

Full example: seed memory and invoke

用初始记忆填充存储,然后跨两个线程调用代理以查看它记住并更新所学内容。

from langchain_core.utils.uuid import uuid7

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from deepagents.backends.utils import create_file_data
from langgraph.store.memory import InMemoryStore

store = InMemoryStore()  # Use platform store when deploying to LangSmith

# Seed the memory file
store.put(
    ("my-agent",),
    "/memories/AGENTS.md",
    create_file_data("""## Response style
- Keep responses concise
- Use code examples where possible
"""),
)

# Seed a skill
store.put(
    ("my-agent",),
    "/skills/langgraph-docs/SKILL.md",
    create_file_data("""---
name: langgraph-docs
description: Fetch relevant LangGraph documentation to provide accurate guidance.
---

# langgraph-docs

Use the fetch_url tool to read https://docs.langchain.com/llms.txt, then fetch relevant pages.
"""),
)

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/AGENTS.md"],
    skills=["/skills/"],
    backend=lambda rt: CompositeBackend(
        default=StateBackend(rt),
        routes={
            "/memories/": StoreBackend(
                rt, namespace=lambda rt: ("my-agent",)
            ),
            "/skills/": StoreBackend(
                rt, namespace=lambda rt: ("my-agent",)
            ),
        },
    ),
    store=store,
)

# Thread 1: the agent learns a new preference and saves it to memory
config1 = {"configurable": {"thread_id": str(uuid7())}}
agent.invoke(
    {"messages": [{"role": "user", "content": "I prefer detailed explanations. Remember that."}]},
    config=config1,
)

# Thread 2: the agent reads memory and applies the preference
config2 = {"configurable": {"thread_id": str(uuid7())}}
agent.invoke(
    {"messages": [{"role": "user", "content": "Explain how transformers work."}]},
    config=config2,
)

用户作用域记忆

为每个用户提供自己的记忆文件。代理记住每个用户的偏好、上下文和历史,而核心代理指令保持不变。如果存储在用户作用域的后端中,用户也可以拥有用户特有的 技能 如果存储在用户作用域的后端中。

命名空间使用 (user_id,) 因此每个用户获得记忆文件的独立副本。用户 A 的偏好永远不会泄漏到用户 B 的对话中。

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/preferences.md"],
    skills=["/skills/"],
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/skills/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
        },
    ),
)

Full example: isolated memory across users

为每个用户预先填充记忆,并以两个不同的用户身份调用代理。每个用户只能看到自己的偏好。

from langchain_core.utils.uuid import uuid7

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from deepagents.backends.utils import create_file_data
from langgraph.store.memory import InMemoryStore


store = InMemoryStore()  # Use platform store when deploying to LangSmith

# Seed preferences for two users
store.put(
    ("user-alice",),
    "/memories/preferences.md",
    create_file_data("""## Preferences
- Likes concise bullet points
- Prefers Python examples
"""),
)
store.put(
    ("user-bob",),
    "/memories/preferences.md",
    create_file_data("""## Preferences
- Likes detailed explanations
- Prefers TypeScript examples
"""),
)

# Seed a skill for Alice
store.put(
    ("user-alice",),
    "/skills/langgraph-docs/SKILL.md",
    create_file_data("""---
name: langgraph-docs
description: Fetch relevant LangGraph documentation to provide accurate guidance.
---

# langgraph-docs

Use the fetch_url tool to read https://docs.langchain.com/llms.txt, then fetch relevant pages.
"""),
)

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=["/memories/preferences.md"],
    skills=["/skills/"],
    backend=lambda rt: CompositeBackend(
        default=StateBackend(rt),
        routes={
            "/memories/": StoreBackend(
                rt,
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/skills/": StoreBackend(
                rt,
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
        },
    ),
    store=store,
)

# When deployed, each authenticated request resolves
# `rt.server_info.user.identity` to the calling user, so Alice and Bob
# automatically see only their own preferences.
agent.invoke(
    {"messages": [{"role": "user", "content": "How do I read a CSV file?"}]},
    config={"configurable": {"thread_id": str(uuid7())}},
)

高级用法

除了记忆路径和作用域的基本配置选项外,你还可以为记忆配置更高级的参数:

维度它回答的问题选项
**持续时间**它持续多久?Short-term (单次对话)或 long-term (跨对话)
**信息类型**它是什么类型的信息?情景记忆 (过去的经历), 程序性 (指令和技能),或 语义性 (事实)
**作用域**谁可以查看和修改它?用户, 代理, or 组织
**更新策略**何时写入记忆?对话期间(默认)或 对话之间
**检索**如何读取记忆?加载到提示词中(默认)或按需(例如, 技能)
**代理权限**代理是否可以写入记忆?Read-write (默认)或 read-only (用于共享策略)

情景记忆

情景记忆存储过去经历的记录:发生了什么、按什么顺序发生、以及结果如何。与语义记忆(存储在文件中的事实和偏好,如 AGENTS.md)不同,情景记忆保留了完整的对话上下文,使智能体能够回想起 *问题是如何解决的,而不仅仅是* 从中 *学到了什么* 。

深度智能体已经使用 检查点 ,这是支持情景记忆的机制:每次对话都作为检查点线程持久化保存。

为了让过去的对话可搜索,请将线程搜索包装在一个工具中。 user_id 是从运行时上下文而不是作为参数传递的:

from langgraph_sdk import get_client
from langchain.tools import tool, ToolRuntime

client = get_client(url="")


@tool
async def search_past_conversations(query: str, runtime: ToolRuntime) -> str:
    """Search past conversations for relevant context."""
    user_id = runtime.server_info.user.identity  # [!code highlight]
    threads = await client.threads.search(
        metadata={"user_id": user_id},
        limit=5,
    )
    results = []
    for thread in threads:
        history = await client.threads.get_history(thread_id=thread["thread_id"])
        results.append(history)
    return str(results)

你可以通过调整元数据过滤器来按用户或组织范围限定线程搜索:

# Search conversations for a specific user
threads = await client.threads.search(
    metadata={"user_id": user_id},
    limit=5,
)

# Search conversations across an organization
threads = await client.threads.search(
    metadata={"org_id": org_id},
    limit=5,
)

这对于执行复杂多步骤任务的智能体很有用。例如,一个编码智能体可以回顾过去的调试会话,直接跳到可能的根本原因。

组织级记忆

组织级记忆遵循与用户级记忆相同的模式,但使用组织级命名空间而不是用户级命名空间。用于跨组织内所有用户和智能体都应适用的策略或知识。

组织记忆通常是 **read-only** 的,以防止通过共享状态进行提示注入。参见 只读记忆与可写记忆 了解详情。

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    memory=[
        "/memories/preferences.md",
        "/policies/compliance.md",
    ],
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/policies/": StoreBackend(
                namespace=lambda rt: (rt.context.org_id,),
            ),
        },
    ),
)

从你的应用程序代码中填充组织记忆:

from langgraph_sdk import get_client
from deepagents.backends.utils import create_file_data

client = get_client(url="")

await client.store.put_item(
    (org_id,),
    "/compliance.md",
    create_file_data("""## Compliance policies
- Never disclose internal pricing
- Always include disclaimers on financial advice
"""),
)

使用 权限 来强制组织级记忆为只读,或使用 策略钩子 进行自定义验证逻辑。

后台整合

默认情况下,智能体在对话期间写入记忆(热路径)。另一种方式是将记忆 **在对话之间** 作为后台任务处理,这有时称为 **休眠时间计算**。一个单独的深度智能体会审查最近的对话,提取关键事实,并将其与现有记忆合并。

方法优点缺点
**热路径** (对话期间)记忆立即可用,对用户透明增加延迟,智能体必须多任务处理
**后台** (对话之间)无用户-facing延迟,可跨多个对话综合记忆在下次对话前不可用,需要第二个智能体

对于大多数应用,热路径已足够。在需要减少延迟或提高跨多个对话的记忆质量时,添加后台整合。

推荐模式是部署一个 **整合智能体** 与主智能体并行运行——一个读取最近对话历史、提取关键事实并将其合并到记忆存储中的深度智能体——并按 定时计划选择一个能反映用户实际与智能体交互频率的节奏:每天流量稳定的聊天产品可能每几小时合并一次,而每周只使用几次的工具只需要每天或每周运行一次。合并频率远超用户对话频率只会白白消耗 token 进行空操作。

合并智能体

合并智能体会读取最近的对话历史,并将关键事实合并到记忆存储中。将其与主智能体一起注册在 langgraph.json:

from datetime import datetime, timedelta, timezone

from deepagents import create_deep_agent
from langchain.tools import tool, ToolRuntime
from langgraph_sdk import get_client

sdk_client = get_client(url="")


@tool
async def search_recent_conversations(query: str, runtime: ToolRuntime) -> str:
    """Search this user's conversations updated in the last 6 hours."""
    user_id = runtime.server_info.user.identity  # [!code highlight]

    since = datetime.now(timezone.utc) - timedelta(hours=6)
    threads = await sdk_client.threads.search(
        metadata={"user_id": user_id},
        updated_after=since.isoformat(),
        limit=20,
    )
    conversations = []
    for thread in threads:
        history = await sdk_client.threads.get_history(
            thread_id=thread["thread_id"]
        )
        conversations.append(history["values"]["messages"])
    return str(conversations)


agent = create_deep_agent(
    model="google_genai:gemini-3.5-flash",
    system_prompt="""Review recent conversations and update the user's memory file.
Merge new facts, remove outdated information, and keep it concise.""",
    tools=[search_recent_conversations],
)
{
  "dependencies": ["."],
  "graphs": {
    "agent": "./agent.py:agent",
    "consolidation_agent": "./consolidation_agent.py:agent"
  },
  "env": ".env"
}

Cron

A cron 任务 按固定计划运行合并智能体。智能体会搜索最近的对话并将其合成到记忆中。让计划与使用模式相匹配,使合并运行大致跟踪实际活动。

graph LR
    Store[(Memory store)] -.->|reads| Conv1[Conversation 1]
    Store -.->|reads| Conv2[Conversation 2]
    Cron[Cron schedule] -->|periodic| Agent[Consolidation agent]
    Agent -->|writes| Store

    classDef trigger fill:#F6FFDB,stroke:#6E8900,stroke-width:2px,color:#2E3900
    classDef process fill:#E5F4FF,stroke:#006DDD,stroke-width:2px,color:#030710
    classDef output fill:#EBD0F0,stroke:#885270,stroke-width:2px,color:#441E33
    classDef schedule fill:#FDF3FF,stroke:#7E65AE,stroke-width:2px,color:#504B5F

    class Conv1,Conv2 trigger
    class Agent process
    class Store output
    class Cron schedule

使用 cron 任务安排合并智能体:

from langgraph_sdk import get_client

client = get_client(url="")

cron_job = await client.crons.create(
    assistant_id="consolidation_agent",
    schedule="0 */6 * * *",
    input={"messages": [{"role": "user", "content": "Consolidate recent memories."}]},
)

有关使用后台进程部署智能体的更多信息,请参阅 投入生产.

只读内存与可写内存

默认情况下,智能体可以读取和写入内存文件。对于组织策略或合规规则等共享状态,您可能希望将内存设为 **read-only** ,以便智能体可以引用它但不能修改它。这可以防止通过共享内存进行提示注入,并确保只有您的应用程序代码控制文件中的内容。

权限用例工作原理
**Read-write** (默认)用户偏好、智能体自我改进、习得的 技能智能体通过 edit_file 工具更新文件
**Read-only**组织策略、合规规则、共享知识库、开发者定义的 技能通过应用程序代码或 Store API填充。使用 权限 拒绝写入特定路径,或 策略钩子 进行自定义验证逻辑。

安全注意事项: 如果一个用户可以写入另一个用户读取的内存,恶意用户可能会将指令注入共享状态。要缓解此问题:

  • 默认使用用户范围 (user_id) 除非您有特定原因需要共享
  • - 使用 **只读内存** 处理共享策略(通过应用程序代码填充,而非智能体)
  • - 添加 **human-in-the-loop** 在智能体写入共享内存之前进行验证。使用 中断 要求对敏感路径的写入进行人工审批。

要强制只读内存,请使用 权限 来声明性地拒绝对特定路径的写入。对于自定义验证逻辑(速率限制、审计日志、内容检查),请使用 后端策略钩子.

并发写入

多个线程可以并行写入内存,但对 **同一文件** 的并发写入可能导致后写者胜出的冲突。对于用户范围的内存,这种情况很少见,因为用户通常一次只有一个活跃的对话。对于代理范围或组织范围的内存,请考虑使用 后台合并 来序列化写入,或将内存结构化为每个主题的独立文件以减少争用。

实际上,如果写入因冲突而失败,LLM 通常足够智能,能够重试或优雅地恢复,因此单次丢失的写入不会是灾难性的。

同一部署中的多个代理

要在共享部署中为每个代理提供独立的内存,请添加 assistant_id 到命名空间:

StoreBackend(
    namespace=lambda rt: (
        rt.server_info.assistant_id,  # [!code highlight]
        rt.server_info.user.identity,
    ),
)

使用 assistant_id 单独使用,如果您只需要代理级隔离而无需用户级作用域。