现在做 AI Agent,大家很容易遇到一个问题:
Agent 每次都像第一次见你。
比如昨天你告诉 AI:
text
ShiyuAdmin 后端主要使用 Go,
数据库是 MySQL,
Redis 做缓存。
今天再问:
我那个后台项目用什么缓存?
如果没有长期记忆,模型只能回答:
text
我不知道你说的是哪个项目。
最简单的解决办法当然是:
text
聊天记录
↓
Embedding
↓
Vector Database
↓
每次对话前搜索历史
但前面我们已经讲过,这种方式有明显局限。
因为真实长期记忆里需要处理:
text
实体
关系
时间
冲突
旧事实
新事实
来源
多跳关系
所以 Graphiti 这类:
text
Temporal Context Graph
开始变得有意思。
但即使 Graphiti 已经帮我们构建好了:
text
Entity
Fact
Episode
Temporal Edge
仍然还有一个非常现实的问题:
Codex、Claude、Cursor、Agent 到底怎么使用这些记忆?
你总不能给每个 Agent 都重新写:
python
graphiti.search(...)
graphiti.add_episode(...)
graphiti.retrieve_episodes(...)
这时候:
MCP
就非常适合。
Graphiti 当前项目中就提供了一套实验性的:
text
Graphiti MCP Server
项目:
text
https://github.com/getzep/graphiti
它做的事情可以一句话概括:
把"长期记忆能力"包装成 AI Agent 可以直接调用的 MCP Tools。
整个架构:
text
Claude / Codex / Cursor / AI Agent
↓
MCP
↓
Graphiti MCP Server
↓
Temporal Context Graph
↓
Neo4j / FalkorDB
今天我们就把这条链完整拆开。
一、为什么"有一个记忆数据库"还不够?
假设我们已经建立:
text
Neo4j
里面保存:
text
User
├── worksOn → ShiyuAdmin
├── uses → Mac mini
└── prefers → Go
ShiyuAdmin
├── uses → Go
├── uses → MySQL
└── uses → Redis
是不是 AI 就自动拥有记忆了?
不是。
因为 Agent 根本不知道:
text
什么时候应该搜索?
怎么搜索?
搜 Entity 还是 Fact?
什么时候应该写新记忆?
什么时候更新已有事实?
也就是说:
数据库只是 Storage。
还缺:
Tool Interface。
二、普通程序怎么使用数据库?
传统后端:
text
Application
↓
Repository
↓
MySQL
比如:
python
user = db.get_user(1001)
但是 Agent 不会主动调用你的:
python
get_user()
除非你把它:
暴露成 Tool。
MCP 的作用就在这里。
三、MCP 可以简单理解成什么?
这里不讲复杂协议。
先用一句最简单的话:
MCP 是 AI Agent 调用外部能力的一种标准接口。
例如一个 Agent 可以拥有:
text
search_files
send_email
query_database
search_memory
add_memory
这些 Tools。
Agent 根据当前任务:
text
自己判断
什么时候调用。
四、把长期记忆变成 MCP Tool
以前 Agent:
text
用户问题
↓
LLM
↓
回答
现在:
text
用户问题
↓
LLM
↓
发现需要过去的信息
↓
search_memory_facts
↓
Graphiti
↓
返回历史 Fact
↓
LLM
↓
回答
这就产生了真正的:
Memory-Augmented Agent。
五、Graphiti MCP Server 暴露了哪些能力?
当前 Graphiti MCP Server 已经把大量 Graphiti 功能包装成 MCP Tools。
其中很核心的几个可以理解成:
text
add_memory
添加一段新记忆。
text
search_nodes
搜索实体。
text
search_memory_facts
搜索事实 / Relationship。
text
add_triplet
直接写一条结构化事实。
以及 Episode、Group、Graph 管理等能力。
对于普通 Agent 来说,最重要的其实先掌握:
写记忆 + 查实体 + 查事实
这三个。
六、第一个 Tool:add_memory
假设用户说:
ShiyuAdmin 现在后端使用 Go,Redis 做缓存。
Agent 可以调用:
text
add_memory
把这段内容写入 Graphiti。
注意:
add_memory 并不是简单把字符串存数据库。
它背后会进入 Graphiti 的 Episode Pipeline。
大致:
text
Raw Text
↓
Episode
↓
Entity Extraction
↓
Entity Resolution
↓
Relationship Extraction
↓
Fact Deduplication
↓
Temporal Update
↓
Context Graph
最终可能形成:
text
ShiyuAdmin
→ USES
→ Go
以及:
text
ShiyuAdmin
→ USES
→ Redis
七、为什么这里叫 Episode?
Graphiti 中一个很重要的概念就是:
text
Episode
可以把它理解成:
一次原始信息输入。
比如:
text
一条聊天
一封邮件
一段会议记录
一条 CRM 更新
一个 JSON 事件
一个系统状态
都可以是 Episode。
八、Episode 和 Fact 有什么区别?
Episode:
text
"ShiyuAdmin 后端用 Go,
Redis 用来做缓存。"
这是:
原始信息。
Graphiti 从里面抽:
text
ShiyuAdmin USES Go
text
ShiyuAdmin USES Redis
这是:
Fact。
所以:
text
Episode
↓
Extraction
↓
Fact
以后如果 Fact 有问题:
text
还能追溯原始 Episode。
九、这对 Agent 为什么重要?
普通 Vector Memory 往往只存:
text
text
embedding
但 Graphiti:
text
Episode
Entity
Edge
Temporal Metadata
都有。
Agent 以后问:
为什么你认为 ShiyuAdmin 用 Redis?
理论上可以继续:
text
Fact
↓
Episode
↓
原始聊天
找到来源。
这就是:
Provenance。
十、第二个 Tool:search_nodes
用户说:
我之前那个后台项目......
问题来了:
text
"那个后台项目"
到底指谁?
可能是:
text
ShiyuAdmin
也可能:
text
另一个项目。
这种情况下,Agent 可以先:
搜 Entity。
也就是:
text
search_nodes
十一、Node Search 搜的是什么?
搜索:
text
后台项目
可能返回:
text
ShiyuAdmin
Admin Platform
Payment Backend
每个 Node 可能有:
text
UUID
Name
Type
Summary
Attributes
于是 Agent 可以结合上下文判断:
text
用户大概率指 ShiyuAdmin。
这一步其实就是:
Entity Grounding。
十二、为什么不能直接 search_memory_facts?
当然也可以。
但很多问题最好先确认:
text
"这个名字到底对应哪个现实实体?"
例如:
text
我的 Mac
可能:
text
Mac mini
MacBook Pro
先搜索 Node:
text
Device
找到具体实体,
再围绕 Node 查询 Fact。
这样:
不容易串台。
十三、这和我们上一篇 Graphiti Hybrid Retrieval 正好接上
Graphiti 当前搜索会结合:
text
Semantic Search
+
BM25
+
Graph Context
所以:
text
search_nodes("我那个后台项目")
并不是简单:
text
字符串 LIKE。
而是可以利用:
text
名称
摘要
Embedding
关键词
图结构
共同查找。
十四、第三个 Tool:search_memory_facts
Node 找到以后,
下一步:
ShiyuAdmin 用什么缓存?
这其实不是在找实体,
是在找:
Relationship / Fact。
所以调用:
text
search_memory_facts
Query:
text
ShiyuAdmin cache technology
可能返回:
text
ShiyuAdmin uses Redis as cache.
以及:
text
ShiyuAdmin uses MySQL as relational database.
第一条显然更加相关。
十五、Fact Search 和 Node Search 要分清
可以这么记。
Node Search:
找"谁"或者"什么东西"。
例如:
text
ShiyuAdmin 是哪个 Entity?
Fact Search:
找"它们之间发生了什么"。
例如:
text
ShiyuAdmin 使用什么技术?
text
谁负责 PaymentService?
text
Mac mini 安装了什么?
十六、Agent 查询流程就清晰了
比如用户问:
我之前那个后台项目数据库用什么?
Agent 可以:
text
Step 1
search_nodes("后台项目")
返回:
text
ShiyuAdmin
然后:
text
Step 2
search_memory_facts(
"ShiyuAdmin database"
)
返回:
text
ShiyuAdmin uses MySQL.
最后:
text
Step 3
LLM 回答:
你之前提到 ShiyuAdmin 使用 MySQL。
这就是:
Entity → Fact 两阶段 Memory Retrieval。
十七、为什么 MCP 特别适合这种操作?
因为对于 Agent 来说:
text
search_nodes
和:
text
search_memory_facts
只是两个 Tool。
它不用知道:
text
Neo4j Query
FalkorDB
Embedding Index
BM25
Graph Traversal
这些底层细节。
它只需要知道:
text
什么时候调用什么工具。
十八、这和微服务其实很像
传统架构:
text
Order Service
↓
User Service API
↓
User Database
Order Service 不需要:
text
直接连接 User DB。
类似地:
text
AI Agent
↓
Memory MCP
↓
Graphiti
↓
Graph DB
Agent 不需要:
text
直接操作 Neo4j。
这就是:
Memory Service 化。
十九、Graphiti MCP Server 怎么跑?
当前项目提供:
text
mcp_server
目录。
最简单的开发环境可以使用 Docker Compose。
例如:
bash
git clone https://github.com/getzep/graphiti.git
cd graphiti/mcp_server
然后:
bash
docker compose up
当前默认方案可以启动:
text
Graphiti MCP Server
+
FalkorDB
服务。
二十、HTTP MCP Endpoint
当前 README 提供的默认 HTTP MCP 地址为:
text
http://localhost:8000/mcp/
架构:
text
MCP Client
↓ HTTP
localhost:8000/mcp/
↓
Graphiti MCP
↓
FalkorDB
对于支持 HTTP MCP 的 Agent,
配置会非常简单。
二十一、概念上的 MCP Client 配置
例如:
json
{
"mcpServers": {
"graphiti-memory": {
"transport": "http",
"url": "http://localhost:8000/mcp/"
}
}
}
以后 Agent 就可以看到:
text
add_memory
search_nodes
search_memory_facts
add_triplet
...
这些 Tools。
二十二、还支持 stdio 模式
如果客户端更适合:
text
stdio MCP
也可以:
text
Agent
↓
启动本地进程
↓
Graphiti MCP Server
也就是说 Graphiti MCP Server 不一定非要:
text
长期跑 HTTP 服务。
本地开发场景可以走:
text
stdio。
二十三、HTTP 和 stdio 怎么选?
简单记。
本机个人使用:
text
stdio
通常方便。
例如:
text
桌面 Agent
↓
本地 Graphiti
如果多个客户端共享:
text
HTTP
更合理。
例如:
text
Codex
Claude
Cursor
内部 Agent
↓
Graphiti MCP
↓
共享 Memory Graph
二十四、但是这里马上会出现一个大问题
如果:
text
Codex
Claude
Cursor
都使用同一个 Memory Graph,
它们的数据是不是应该全部混一起?
未必。
例如:
text
工作项目
和:
text
个人生活
最好可能分开。
Graphiti 有:
group_id。
二十五、group_id 可以理解成 Memory Namespace
例如:
text
group_id = work
保存:
text
ShiyuAdmin
Codex
GitHub
服务器
另外:
text
group_id = personal
保存:
text
旅行
设备
日常偏好
这样搜索:
text
只查 work
就不会把:
text
personal
记忆混进来。
二十六、企业场景 group_id 更重要
比如 SaaS:
text
Customer A
Customer B
Customer C
不能共享一张没有隔离的 Context Graph。
可以:
text
group_id = tenant-a
group_id = tenant-b
group_id = tenant-c
形成:
Memory Namespace Isolation。
二十七、也可以按 Agent 分组
例如:
text
coding-agent
只保存:
text
代码
仓库
错误
技术方案
text
content-agent
保存:
text
文章选题
标题
内容偏好
素材
这样:
text
不同 Agent
拥有不同:
Memory Context。
二十八、add_triplet 又是干什么的?
有时候我们不需要:
text
LLM 从一段文字中自动抽取。
因为业务程序已经明确知道事实。
例如:
text
ShiyuAdmin
USES
Redis
这条关系:
text
100% 已知。
那么可以直接:
text
add_triplet
而不是:
text
生成一段自然语言
↓
add_memory
↓
LLM 再抽一次
二十九、这在结构化系统同步时非常重要
例如 GitHub API 已经告诉你:
json
{
"repository": "ShiyuAdmin",
"language": "Go"
}
根本不需要 LLM 理解。
直接:
text
ShiyuAdmin
→ MAIN_LANGUAGE
→ Go
即可。
三十、所以写 Memory 有两条路线
第一条:
Unstructured
text
聊天
邮件
文档
↓
add_memory
↓
LLM Extraction
↓
Graph
第二条:
Structured
text
API
Database
System Event
↓
add_triplet
↓
Graph
这两种一起用,
比所有数据都先变成自然语言再抽取:
合理得多。
三十一、例如 GitHub Agent
GitHub webhook:
text
PR #102 merged
系统已经知道:
text
Repo
PR
Author
Status
可以直接结构化写图。
例如:
text
ShiyuAdmin
→ HAS_PR
→ PR-102
text
PR-102
→ STATUS
→ Merged
甚至:
text
PR-102
→ AUTHORED_BY
→ Developer-A
根本不需要 LLM。
三十二、但 PR 描述可以再走 add_memory
例如:
text
这个 PR 修复 RBAC 中
部门数据权限继承的问题。
里面有:
text
自然语言知识。
可以:
text
add_memory
让模型继续抽:
text
RBAC
DepartmentDataScope
Bug
Solution
所以:
Structured + Unstructured
可以一起进入 Context Graph。
三十三、这才是企业 Agent 真正的数据来源
不是只有:
text
Chat History。
而是:
text
Chat
Email
GitHub
CRM
Database
Calendar
Slack
Documents
System Events
全部进入:
text
Context Graph。
然后 Agent:
text
通过 MCP
统一查询。
三十四、这就出现一个非常有意思的架构
text
Gmail
│
GitHub
│
Slack
│
CRM
│
User Chat
│
↓
Memory Pipeline
↓
Graphiti
↓
Context Graph
↑
│ MCP
┌─────┼─────┐
↓ ↓ ↓
Codex Claude Cursor
所有 Agent:
共享同一套事实层。
这才是真正意义上的:
Shared Agent Memory。
三十五、MCP 让"记忆"从模型能力变成基础设施
没有 MCP 时:
text
App A
自己写 Graphiti SDK
App B
再写一次
App C
再写一次
最后:
text
三套 Memory Integration。
有 MCP:
text
Graphiti
↓
MCP Server
所有客户端:
text
统一调用。
这就是标准接口的价值。
三十六、Agent 什么时候应该 add_memory?
这个问题比代码更重要。
千万不要:
text
用户每说一句话
↓
全部 add_memory
比如:
text
哈哈
好的
谢谢
今天天气不错
全部存进去,
Memory 很快变垃圾场。
三十七、什么值得长期记?
我一般建议至少优先这些类型:
text
Preference
Requirement
Project
Decision
Problem
Solution
Procedure
Relationship
Important Event
例如:
text
以后 Go 示例优先。
这是:
text
Preference。
值得记。
text
ShiyuAdmin 使用 MySQL。
这是:
text
Project Fact。
值得记。
text
这个 502 最后是 Nginx upstream 配错。
这是:
text
Problem + Solution。
很值得记。
三十八、什么不一定值得?
text
今天吃了一个苹果。
如果不是:
text
饮食记录 Agent
就没必要。
所以:
Memory Write 也需要 Policy。
三十九、可以在 Agent Prompt 里定义 Memory Policy
例如:
text
当用户提供以下信息时,
考虑调用 add_memory:
1. 稳定偏好
2. 项目事实
3. 长期目标
4. 已确认决策
5. 问题及最终解决方案
6. 需要未来继续使用的上下文
不要保存:
1. 普通寒暄
2. 临时无意义信息
3. 重复信息
这样 Agent 会更加克制。
四十、为什么不能让 Agent 什么都记?
因为长期记忆的核心指标不是:
Memory Count。
而是:
Signal-to-Noise Ratio。
也就是:
text
真正有价值的记忆
÷
全部记忆
比例。
如果:
text
10 万条 Memory
里面:
text
9 万条无关聊天。
检索只会越来越差。
四十一、Memory Search 也要有策略
同样不要:
text
每个问题都 search_memory。
比如用户问:
Python list 怎么排序?
这是:
text
通用知识。
没必要查长期记忆。
但用户问:
我之前那个项目 Redis 的问题怎么解决的?
明显有:
text
我之前
那个项目
这种 Personal Context Signal。
就应该:
text
search memory。
四十二、所以 Agent 实际上还需要一个 Memory Router
概念:
python
def should_search_memory(
query: str
) -> bool:
memory_signals = [
"之前",
"上次",
"我的",
"我们之前",
"那个项目",
"你还记得"
]
return any(
signal in query
for signal in memory_signals
)
实际当然不会这么简单。
LLM 可以自己判断。
但核心是:
Memory Retrieval 也应该按需发生。
四十三、Node Search 和 Fact Search 还能组合
比如:
上次那个 Redis 出问题的项目最后怎么修好的?
第一步:
text
search_nodes
找:
text
Redis
或者相关:
text
Project。
第二步:
text
search_memory_facts
围绕:
text
Problem
Solution
查关系。
第三步:
text
组合答案。
四十四、这就是 Tool Chaining
Agent:
text
search_nodes
↓
search_memory_facts
↓
get_episode_entities
↓
Answer
一个 Tool 的结果:
text
成为下一个 Tool 的输入。
这比:
text
一次 Vector Search
强很多。
四十五、get_episode_entities 有什么用?
假设搜索得到一个 Fact:
text
Redis 连接失败
→ SOLVED_BY
→ 修改 Docker Compose
你想知道:
这条 Fact 最初从哪段聊天产生?
可以通过 Episode UUID:
text
get_episode_entities
去查看:
text
某个 Episode
到底产生了哪些 Entity 和 Edge。
这是:
Memory Provenance Debugging。
四十六、这个功能对排查错误记忆很重要
比如 Agent 突然说:
你项目使用 MongoDB。
但你明明没说过。
排查:
text
search_memory_facts("MongoDB")
找到:
text
ShiyuAdmin uses MongoDB
再:
text
找到 Episode 来源。
结果发现原文:
text
"ShiyuAdmin 并没有使用 MongoDB。"
说明:
text
Extraction 出错。
这样就知道问题:
不在 Retrieval,而在 Ingestion。
四十七、Memory 系统一定要能 Debug
很多人做:
text
长期记忆
只有两个接口:
text
add
search
完全不够。
真实系统还需要:
text
查看 Fact
查看 Entity
查看来源
删除错误记忆
重新抽取
隔离 Group
重建 Index
Graphiti MCP Server 当前就已经暴露了不少:
text
Graph Maintenance
相关能力。
四十八、但危险工具不能随便让 Agent 调
比如:
text
clear_graph
这种 Tool。
如果生产环境直接暴露给 Agent:
text
风险很高。
一次错误决策:
text
整个 Memory Graph 清空。
所以 MCP 工具应该:
分权限。
四十九、我会把 Memory Tools 分三档
低风险
text
search_nodes
search_memory_facts
get_episode
可以让 Agent 自由调用。
中风险
text
add_memory
add_triplet
delete_episode
根据场景限制。
高风险
text
clear_graph
destroy_graph
大规模删除
应该:
text
人工确认
或者干脆:
text
不给普通 Agent。
五十、这其实就是 Tool Authorization
未来 Agent 系统一定要区分:
text
能读什么
能写什么
能删什么
MCP 只是:
text
暴露 Tool。
并不意味着:
text
所有 Tool 都应该无条件开放。
五十一、远程部署还要考虑认证
如果 Graphiti MCP Server:
text
http://localhost:8000/mcp/
只在:
text
本机
问题不大。
如果部署:
text
公网服务器。
千万别:
text
直接裸奔。
因为里面存的是:
长期上下文。
可能包括:
text
企业项目
个人偏好
历史对话
系统关系
业务事实
这些往往非常敏感。
五十二、更合理的部署
text
Internet
↓
Cloudflare Access / VPN / Auth
↓
Reverse Proxy
↓
Graphiti MCP
↓
Graph DB
或者:
text
Tailscale
↓
Private MCP Endpoint
尽量:
不公开暴露。
五十三、Memory Graph 和普通数据库一样需要备份
别因为:
text
这是 AI Memory
就觉得:
text
丢了再生成。
随着系统运行半年:
text
Episode
Entity Resolution
Fact Updates
Temporal History
会越来越有价值。
所以要考虑:
text
Backup
Restore
Migration
Retention
这就是:
Memory Infrastructure。
五十四、Graphiti MCP Server 还支持不同 Graph Backend
当前项目可以配:
text
FalkorDB
也可以:
text
Neo4j。
开发环境:
text
FalkorDB
相对轻量。
如果:
text
已有 Neo4j
也可以直接接。
所以 MCP Server 本身并不强迫 Agent:
text
知道数据库类型。
五十五、这就是抽象层的价值
上层:
text
search_memory_facts
保持不变。
底层:
text
Neo4j
以后换:
text
FalkorDB
Agent 根本不用改 Prompt。
因为它只看到:
text
MCP Tool Contract。
五十六、和传统 Repository Pattern 很像
后端开发中:
text
Service
↓
Repository Interface
↓
MySQL / PostgreSQL
AI 世界:
text
Agent
↓
MCP Tool
↓
Graphiti
↓
Neo4j / FalkorDB
本质上都是:
解耦。
五十七、再来看一个完整 Agent 流程
用户第一次说:
我以后写后台案例尽量优先使用 Go。
Agent:
text
判断:
稳定偏好
调用:
text
add_memory
Graph:
text
User
→ PREFERS
→ Go
几天后用户说:
帮我写个后台接口示例。
Agent:
text
判断:
回答可能受用户偏好影响。
调用:
text
search_memory_facts(
"user backend programming language preference"
)
得到:
text
User prefers Go.
于是生成:
go
func main() {
...
}
而不是:
java
public static void main...
这才叫:
Personalized Agent。
五十八、注意:Memory 不应该替代当前用户要求
即使历史记忆说:
text
User prefers Go.
但用户今天明确说:
这次用 Python 写。
那么:
text
当前明确要求
应该高于:
text
历史偏好。
所以 Context 优先级应该:
text
Current Instruction
>
Current Conversation
>
Retrieved Memory
>
General Default
这一点非常重要。
五十九、否则 Memory 会"绑架"用户
比如历史:
text
喜欢暗色 UI。
今天用户说:
做个白色极简页面。
Agent 不能因为:
text
Memory = Dark Mode
就坚持:
text
黑色页面。
Memory 是:
Context。
不是:
Command。
六十、Memory 写入也要避免"推测当事实"
用户说:
我可能以后会用 Rust。
不能直接存:
text
User
→ PREFERS
→ Rust
因为:
text
可能
不是:
text
已经决定。
更合理:
text
User
→ CONSIDERING
→ Rust
或者:
text
不写长期事实。
这又回到:
Schema 和 Fact Quality。
六十一、Agent 写 Memory 前最好做一个判断
可以考虑四个问题:
text
1. 这条信息未来还会有用吗?
2. 这是明确事实还是推测?
3. 它会稳定一段时间吗?
4. 当前图里是不是已经存在?
全部比较合理:
text
再写。
否则:
text
不写。
六十二、可以把 Memory Write 做成两阶段
第一阶段:
text
Agent 提议保存。
例如:
json
{
"memory_candidate":
"User prefers Go for backend examples",
"importance": 0.91
}
第二阶段:
text
Memory Service
自己:
text
Dedup
Entity Resolution
Conflict Check
Temporal Update
然后才入图。
不要让 LLM:
直接 INSERT。
六十三、MCP 只是"工具接口",Memory Policy 仍然要自己设计
这是非常值得强调的。
安装 Graphiti MCP Server:
text
不会自动让你的 Agent
拥有完美长期记忆。
你仍然需要定义:
text
什么时候写
什么时候查
查什么
哪些 Group
哪些 Tool 可以用
什么信息值得长期保存
这才是真正:
Agent Memory Architecture。
六十四、一个比较完整的 Memory Agent 架构
text
User
↓
LLM / Agent
↓
Intent Router
│
├── General Knowledge
│ ↓
│ 直接回答
│
├── Need Past Context
│ ↓
│ MCP search_nodes
│ ↓
│ search_memory_facts
│
└── New Long-term Fact
↓
MCP add_memory
↓
Graphiti
↓
Entity Resolution
↓
Fact Extraction
↓
Temporal Update
↓
Context Graph
这样:
text
写
和:
text
读
都闭环了。
六十五、如果再加其他 MCP 就更有意思
例如 Agent 同时连接:
text
GitHub MCP
Gmail MCP
Calendar MCP
Graphiti Memory MCP
用户问:
我上周和客户讨论的接口改动,现在代码实现了吗?
Agent 可以:
text
1.
Memory MCP
↓
找到客户讨论内容
2.
GitHub MCP
↓
查询对应 Issue / PR
3.
对比
↓
判断是否已经实现
这就是真正:
Cross-Tool Agent。
六十六、Memory MCP 在这里扮演什么角色?
GitHub:
text
告诉你代码现在是什么。
Gmail:
text
告诉你邮件说过什么。
Calendar:
text
告诉你发生过哪些会议。
而 Memory:
text
负责把这些长期关联起来。
可以理解成:
Agent 的 Context Backbone。
六十七、比如一次客户需求
邮件:
text
客户要求增加批量导出。
写入 Graph:
text
CustomerA
→ REQUIRES
→ BatchExport
GitHub:
text
Issue-102
implements
BatchExport
后来 PR:
text
PR-205
closes
Issue-102
最终 Graph:
text
CustomerA
↓ REQUIRES
BatchExport
↓ implementedBy
Issue-102
↓ closedBy
PR-205
用户问:
客户 A 上次提的批量导出做完了吗?
Agent 可以:
text
沿图直接查。
这比单纯:
text
搜索过去邮件
强很多。
六十八、这就是 MCP + Knowledge Graph 真正有意思的结合
MCP:
text
解决 Agent 怎么调用能力。
Knowledge Graph:
text
解决信息怎么长期连接。
LLM:
text
解决自然语言理解与推理。
三个结合:
text
LLM
+
MCP
+
Context Graph
就开始形成:
Stateful Agent。
也就是:
有状态的 AI Agent。
六十九、为什么未来 Agent 一定越来越需要 Stateful?
现在很多 Agent:
text
执行完一次任务
↓
结束
下次:
text
又从零开始。
但现实工作不是这样。
项目会持续:
text
几周
几个月
几年。
客户关系会持续。
代码项目会持续。
用户偏好会持续。
所以 Agent 未来必须知道:
text
昨天做了什么
现在做到哪
之前为什么这么决定
哪些问题已经解决
当前真实状态是什么
这就是:
Long-term State。
七十、Graphiti MCP Server 提供的本质不是"多几个 Tool"
而是:
把 Context Graph 变成 Agent 可访问的长期状态服务。
也就是:
text
Agent
↓
Tool
↓
Memory Service
↓
Context Graph
这是一个很值得研究的架构方向。
七十一、如果自己部署,我会怎么分环境?
开发:
text
Graphiti MCP
+
本地 FalkorDB
+
stdio / localhost HTTP
先验证:
text
写入
检索
去重
时序
个人长期使用:
text
Graphiti MCP
+
持久化数据库
+
Tailscale / 本地网络
多个设备共享。
企业:
text
Agent Gateway
↓
Authentication / Authorization
↓
Memory MCP
↓
Graphiti Cluster
↓
Graph Database
再加:
text
Tenant Isolation
Audit
Backup
Monitoring
七十二、生产环境还需要看一个指标:写入吞吐
Graphiti Episode Ingestion:
text
不只是一次数据库 INSERT。
它可能包含:
text
LLM Entity Extraction
Embedding
Entity Resolution
Dedup
Fact Extraction
Summarization
所以:
text
add_memory
天然比:
text
search
更重。
当前 MCP Server 也提供:
text
SEMAPHORE_LIMIT
这类并发配置,用来控制 Episode Processing 并发,避免 LLM Provider 出现 429。
所以:
Memory Write 是一个 Pipeline。
不是普通 KV 写入。
七十三、大量历史数据不要同步逐条慢慢等
比如第一次导入:
text
10000 条历史聊天。
如果前端:
text
一条 add_memory
等完
再下一条
会很慢。
更合理:
text
Queue
↓
Background Ingestion
↓
Graph Construction
也就是:
写入异步化。
而读取:
text
search
需要:
text
低延迟。
读写特性并不一样。
七十四、这也是为什么 Graphiti MCP Server 当前采用 Queue-Based Episode Processing
也就是说:
text
MCP 请求
↓
Episode Queue
↓
Extraction Pipeline
可以更好控制:
text
并发
LLM Rate Limit
吞吐
这种设计非常适合 Memory Ingestion。
七十五、最后给一个完整使用场景
假设用户对 Agent 说:
text
ShiyuAdmin 的权限问题已经解决了。
之前的 Bug 是部门权限继承时
没有正确合并父部门的数据范围。
最终改成递归计算部门树后解决。
Agent 判断:
text
这是长期有价值的:
Project
Problem
Solution
于是:
text
add_memory
Graphiti 抽:
text
ShiyuAdmin
→ HAS_PROBLEM
→ DepartmentPermissionInheritanceBug
text
DepartmentPermissionInheritanceBug
→ SOLVED_BY
→ RecursiveDepartmentTreeCalculation
Episode 保留:
text
原始描述。
三个月后:
用户:
ShiyuAdmin 之前那个部门权限 Bug 怎么解决的?
Agent:
text
search_nodes(
"ShiyuAdmin"
)
找到项目。
再:
text
search_memory_facts(
"ShiyuAdmin department permission bug solution"
)
返回:
text
DepartmentPermissionInheritanceBug
SOLVED_BY
RecursiveDepartmentTreeCalculation
最后回答:
之前的问题是父部门数据范围没有正确合并,最后通过递归计算部门树并合并数据范围解决。
这时候 AI 不再只是:
"回忆一段聊天"。
而是在:
查询过去形成的结构化经验。
这才是长期 Agent Memory 真正有价值的地方。
总结
如果只使用 Graphiti SDK:
text
你的程序拥有长期记忆能力。
但把 Graphiti 包成:
text
MCP Server
以后:
text
Codex
Claude
Cursor
各种 Agent
都可以共享这套能力。
整个架构:
text
Agent
↓
MCP
├── add_memory
├── search_nodes
├── search_memory_facts
├── add_triplet
└── provenance / maintenance tools
↓
Graphiti
↓
Episode
↓
Entity
↓
Temporal Fact
↓
Context Graph
↓
Neo4j / FalkorDB
MCP 解决:
"Agent 怎么调用记忆"。
Graphiti 解决:
"记忆怎么组织、更新和检索"。
两者组合以后:
text
Memory
不再是某一个模型内部的特殊能力,
而变成:
一套可以被不同 Agent 共享的基础设施。
这也是我觉得 MCP 真正有价值的一个方向:
不是给 AI 装更多花哨工具,而是把原本散落在不同系统里的能力,变成 Agent 可以稳定调用的标准服务。
如果只记住一句话:
Graphiti 负责让 AI"长期记住",MCP 负责让不同 AI Agent"都能调用这份记忆"。
项目地址:
text
https://github.com/getzep/graphiti
这就从:
text
单次聊天机器人
真正开始走向:
text
Stateful AI Agent
也就是: