LangGraph x Nowledge Mem
在不替换 LangGraph checkpointer 的前提下,为 Agent 加入身份感知的上下文、记忆工具和幂等 Thread 捕获。
LangGraph 管理 Agent 的执行状态:checkpoint、interrupt、retry 和 graph state。Nowledge Mem 管理应该跨 graph、跨工具延续的长期状态:Agent identity、当前 Space、Working Memory、受治理的记忆和可搜索会话。
nowledge-mem-langgraph Python 连接器让两套系统各自守住自己的职责。
职责边界
保留现有 LangGraph checkpointer。Nowledge Mem 不是 checkpointer,也不是 BaseStore 的替代品;它负责临时注入上下文、提供受身份约束的 MCP 工具,并把完成的会话导入为 Mem Thread。
安装
pip install nowledge-mem-langgraph使用远程 Mem server 或 Nowledge Cloud workspace 时,配置与其他 Mem 客户端相同的 endpoint 和 key:
export NMEM_API_URL=https://your-mem-server
export NMEM_API_KEY=nmem_...
export NMEM_LANGGRAPH_APP_ID=customer-supportNMEM_LANGGRAPH_APP_ID 是稳定的应用标识,不是版本号。发布新版本时不要改它,这样同一个 LangGraph thread_id 才会继续对应同一个 Mem Thread。
LangChain create_agent
from dataclasses import dataclass
from langchain.agents import create_agent
from nowledge_mem_langgraph import NowledgeClient, NowledgeMiddleware
@dataclass
class AgentContext:
user_id: str
nowledge: dict[str, str]
mem = NowledgeClient()
agent = create_agent(
model="openai:gpt-5.4",
tools=await mem.tools(),
middleware=[NowledgeMiddleware(mem)],
context_schema=AgentContext,
)
result = await agent.ainvoke(
{"messages": [{"role": "user", "content": "我们上周做了什么决定?"}]},
config={"configurable": {"thread_id": "ticket-1842"}},
context=AgentContext(
user_id="auth-user-42",
nowledge={
"agent_id": "support-triage",
"space_id": "customer-acme",
},
),
)这条路径会完整接入:
- 每个顶层 turn 只读取一次所选 Agent 的 Context Bundle;
- 上下文只进入 model request,不写入 checkpointed messages;
- 模型获得 Mem 精简过的 external-agent MCP 工具集;
- 每次工具调用都会被约束回受信任的 Agent 与 Space;
- 顶层会话完成后通过
POST /threads/import导入; - 完全相同的 replay 是 no-op,后续 turn 只追加缺失消息;
- Mem 检索结果在 Thread 中仍然可见,但会排除在 distillation 之外,避免把召回内容再次学成新记忆。
invoke() 和 ainvoke() 都支持上下文注入与 Thread 同步。Mem MCP tools 通过 langchain-mcp-adapters 的 async interface 加载;会调用这些工具的 Agent 应使用 ainvoke() 或 astream()。
身份模型
这些值不能混用:
| 值 | 标识对象 | 安全职责 |
|---|---|---|
| API key | Workspace/member 访问权 | 鉴权 |
agent_id | 可迁移的 Nowledge AI Identity | 上下文、来源与路由 |
host_agent_id | LangGraph 部署身份 | Host 来源 |
space_id | 记忆与检索范围 | 已授权访问内的 scope |
LangGraph thread_id | 真实会话 | Mem Thread identity |
LangGraph assistant_id | Server 上的部署/配置实例 | 只作 metadata |
| LangGraph authenticated user | 人或 service principal | LangGraph 鉴权;不能推断成 Agent identity |
把本次 invocation 的选择器放在 context.nowledge 下。连接器不会从 prompt 猜身份。如果 invocation 传入任一 Agent selector,它会替换静态 Agent tuple,不会把 runtime 的 agent_id 和另一个租户的默认 host_agent_id 拼在一起。
LangGraph Server 提供 graph_id 和 assistant_id 时,连接器可以把 langgraph:<graph_id>:<assistant_id> 记录为 host provenance。它不是 credential,也不会把同一会话拆成多个 Thread。
单 Agent 部署可以使用静态默认值:
export NMEM_AGENT_ID=support-triage
export NMEM_HOST_AGENT_ID=langgraph:support:prod
export NMEM_SPACE=customer-acme多租户应用必须使用具有正确 workspace 权限的 key,并从受信任的服务端 context 传入 Agent/Space。不要直接信任未经校验的客户端 JSON。
Thread 与 subagent
一个 LangGraph thread_id 对应一个 Mem Thread:
langgraph:<application_id>:<thread_id>这里故意不包含 assistant_id。LangGraph 允许多个 assistant 在同一个 Thread 上运行;模型或配置升级不应该把用户的会话历史切开。
Subgraph 会共享父级 Thread,并获得嵌套的 checkpoint namespace。Middleware 只同步顶层 namespace,因此最终只有一条可读会话,而不是 parent 和每个 subagent 各复制一份。
只有当 subagent 是可独立访问、并拥有长期会话的产品 Agent 时,才给它单独的 LangGraph thread_id;行为需要分开时,再给它独立的 Mem agent_id。
Raw StateGraph
Raw graph 的 model call 和完成边界可以放在任何节点,连接器不会猜。请在你明确拥有的边界调用 helper:
from nowledge_mem_langgraph import NowledgeClient, NowledgeIdentity
mem = NowledgeClient()
identity = NowledgeIdentity(agent_id="researcher", space_id="project-atlas")
bundle = await mem.acontext_bundle(identity)
tools = await mem.tools()
# 在 graph 的真实完成边界:
await mem.async_thread(
thread_id=runtime.execution_info.thread_id,
messages=state["messages"],
identity=identity,
runtime=runtime,
)把 bundle["rendered_markdown"] 注入 model request,不要追加到会被 checkpoint 的 message channel。
可靠性
Context 读取和 Thread 同步默认 fail-open。Mem 短暂不可用时,不会拖垮面向客户的 Agent,但会留下日志。如果你的流程要求记忆必须在线,可以设置 fail_open=False。
失败不会扩大 scope,也不会移除鉴权。Thread sync 会被明确 await,而不是丢给无人等待的 background task,避免 serverless worker 提前结束进程。
已有部署
安装连接器不会修改 LangGraph checkpoints。它会从 state 中仍然存在的消息开始捕获。如果旧消息在安装前已经被 summarization policy 删除,连接器无法还原;有原始 transcript 时请单独导入。
不要把 LangSmith trace 当成 transcript 回填。Trace 包含嵌套 run、retry 和工具执行细节,不是用户看到的真实会话。
验证
- 用稳定的 LangGraph
thread_id跑一个 turn。 - 确认 model request 收到正确 Agent 与 Space 的 Context Bundle。
- 调用一个 Mem 搜索工具,确认 request 带着相同 identity scope。
- 在 Nowledge Mem Threads 中找到一条
LangGraphThread。 - 用相同 state 再跑一次,确认没有重复消息。
- 跑一个嵌套 subgraph,确认没有创建第二条 Mem Thread。
