帮你快速理解、总结文档立即下载

使用 Agent 记忆服务

最近更新时间:2026-09-04 18:15:01
我的收藏
Agent 记忆服务是云数据库 PostgreSQL 为 AI 应用提供的托管式长期记忆能力。本文介绍如何通过 REST API 完成记忆的写入、检索、更新与删除,并以 MCP、Function Calling、REST 直连三种方式将记忆能力接入您的 Agent 应用。

功能简介

什么是 Agent 记忆服务

大语言模型本身是无状态的:会话一结束,模型就会“忘记”用户的偏好、历史决策和上下文信息。Agent 记忆服务解决的核心问题,就是让 AI 应用具备跨会话的长期记忆
服务接收对话内容后,由腾讯云大模型服务平台托管的模型自动完成事实提取、摘要结构化与向量化,将值得记住的信息持久化到您的云数据库 PostgreSQL 实例中(基于 pgvector 向量索引);在后续交互时,再通过语义检索把相关记忆召回,供应用注入到 Prompt 中,实现“越用越懂用户”的体验。
与自行搭建“向量库 + 缓存 + 图库”的多组件方案相比,Agent 记忆服务以云数据库 PostgreSQL 实例为统一存储底座,模型调用与向量索引全部托管,您只需面向一组简洁的 REST API 编程,无需运维额外中间件。
说明:
Agent 记忆服务是基于开源项目 mem0 构建的托管服务,使用方式完全兼容社区用法。熟悉 mem0 的开发者可以零成本迁移:社区的调用示例、SDK 封装与集成模式均可直接复用;同时免去自行部署和运维 LLM、Embedding、向量库的成本,模型与存储均由腾讯云托管。

核心概念

概念
说明
记忆(Memory)
从对话中提取出的结构化事实,例如用户偏好、身份信息、历史决策等。每条记忆拥有唯一 ID 与内容哈希(hash),并记录创建与更新时间
user_id
用户维度标识。用于区分不同终端用户的记忆,是最常用的隔离维度
agent_id
Agent 维度标识。同一用户在不同 Agent(如客服 Agent、代码 Agent)下的记忆相互隔离
run_id
运行实例维度标识。用于区分不同会话批次或任务执行过程产生的记忆
记忆事件(event)
写入操作的处理结果,取值:ADD(新增)、UPDATE(更新已有记忆)、DELETE(删除冲突记忆)、NOOP(无需变更)
说明:
三个隔离维度可按业务需要组合使用,但每次写入至少需提供其中一个。不同维度下的记忆互不干扰,检索时也仅在指定维度范围内进行。

工作原理

Agent 记忆服务的工作过程分为写入链路与召回链路两部分:
1. 提交对话:应用将一轮对话的 messages 数组提交至记忆服务。
2. 事实提取:托管大模型自动识别值得记住的事实,并比对已有记忆决定 ADD / UPDATE / DELETE。
3. 向量化存储:记忆文本生成向量后持久化至云数据库 PostgreSQL(pgvector 索引)。
4. 语义检索:应用以自然语言发起检索,返回相关度最高的记忆及相似度得分。
5. 上下文注入:应用将召回的记忆拼入 Prompt,供大模型生成个性化回复。
6. 记忆回写:本轮对话再次提交至记忆服务,形成记忆闭环。

适用场景

场景
记忆服务解决什么
建议的维度设计
AI 编程助手
跨会话记住项目技术栈、代码规范、目录约定,无需每次重新交代
user_id + agent_id
智能客服
记住客户历史工单、产品版本、沟通偏好,避免重复询问
user_id
运维助手
记住实例清单、变更窗口偏好、历史故障根因
user_id + agent_id
个人助理
记住长期目标、日程习惯、个人偏好
user_id
多 Agent 协作
各角色积累各自领域经验,共享用户画像
共享 user_id,独立 agent_id
长流程任务 Agent
多步骤任务中保持中间结论,任务结束批量回收
user_id + run_id

准备工作

开通记忆服务

记忆服务依赖云数据库 PostgreSQL 实例与 AgenticBase 套餐(提供 tencentdb_ai AI 扩展插件),请确认两者已就绪后,通过以下任一方式开通记忆服务:
开通方式
操作入口
适用场景
控制台开通
AgenticBase 详情页的「mem0 记忆服务」区域,选择 LLM 模型、填入 Embedding API Key 后单击「开启应用」
手动操作、首次开通
云 API 开通
调用 OpenMem0Service 接口
自动化、CI/CD 与批量开通
Skill 一句话部署
在 CodeBuddy / WorkBuddy 等 AI 客户端中安装 PostgreSQL Skill,用自然语言下达开通指令
对话式操作,一轮对话完成部署
通过 PostgreSQL Skill 一句话部署
TencentDB PostgreSQL Skill 是面向云数据库 PostgreSQL 的任务型技能包,其中的 mem0 部署技能(tencent-pg-mem0-deploy)可将开通流程简化为一句自然语言指令:
示例输入:
帮我给广州 postgres-abc12345 开通 mem0,AgenticBaseId 用 agenticbase-xxxxx,Embedding Key 从环境变量 TENCENT_TOKENHUB_API_KEY 读取
其中 Embedding API Key 为开通的必填参数(sk- 开头),需提前在 腾讯云大模型服务平台 TokenHub 的 Embedding 模型详情页创建,并通过环境变量 TENCENT_TOKENHUB_API_KEY 或密钥管理服务注入。请勿在聊天、URL、日志或代码仓库中粘贴真实 Key。技能收到指令后会自动完成以下动作,无需您逐步操作:
1. 解析必要信息:自动提取地域、实例 ID、AgenticBaseId、模型等非敏感参数;若未检测到 Embedding API Key,会提示您配置运行时环境变量,不会要求在聊天中提供凭证。
2. 预检查:先查询实例适配性和 mem0 当前状态,避免重复开通。
3. 执行并轮询:目标明确且无阻塞时直接执行开通动作,持续轮询直到服务就绪。
4. 返回结果:输出实例信息、执行的操作、TaskId、耗时与最终结果。
除开通外,该技能同样支持「关闭 mem0 服务」「获取可用地址」等指令。Skill 包可通过 GitHub、ClawHub 或 SkillHub 获取,安装到 CodeBuddy / WorkBuddy 等客户端后即可使用。
说明:
Skill 遵循「先查后写」原则:所有场景都会先查询当前状态再判断是否执行写动作,高风险动作需您确认后才会执行;Embedding API Key 等凭证仅从运行时环境读取,不会写入聊天记录、URL、日志或仓库文件。
通过云 API 开通
记忆服务的开通、关闭与详情查询通过以下三个云 API 完成。相关接口动作已纳入 腾讯云 CAM 权限文档;当前产品文档尚未提供完整的接口参数详情页,具体参数与可用性请以 API Explorer 实际展示为准:
接口名
功能
频率限制
OpenMem0Service
开启实例的记忆服务
20 次/秒
CloseMem0Service
关闭实例的记忆服务
20 次/秒
DescribeMem0Service
查询记忆服务详情(含服务地址)
20 次/秒
公共请求参数(三个接口通用):
参数
取值
请求域名
postgres.tencentcloudapi.com
API 版本
2017-03-12
签名方法
TC3-HMAC-SHA256(v3 签名)
请求方法
POST
Content-Type
application/json
说明:
推荐使用 API Explorer(OpenMem0Service) 在线调试,可自动生成 TC3 签名与多语言 SDK 代码,避免手写签名逻辑出错。
OpenMem0Service
CloseMem0Service
DescribeMem0Service
开启指定实例的记忆服务。
输入参数
参数
必填
类型
说明
DBInstanceId
String
PostgreSQL 实例 ID,如 postgres-paxanz0n
AgenticBaseId
String
AgenticBase 套餐 ID,如 agenticbase-2a7vajd1(需先开通)
LLMModel
String
用于事实提取的 LLM,可选值见下方模型列表
EmbeddingApiKey
String
TokenHub Embedding 服务的 API Key(sk- 开头),获取方式见 上文 Skill 部分说明
LLMModel 可选值
系列
可选值
自动路由
auto(推荐首选,由平台自动路由到合适的模型)
DeepSeek
deepseek-v4-flash、deepseek-v4-pro
GLM
glm-5、glm-5-turbo、glm-5.1
Kimi
kimi-k2.5、kimi-k2.6
MiniMax
minimax-m2.5、minimax-m2.7
选择建议:不确定时选 auto;抽取质量优先选 -pro / 高版本型号;抽取延迟与成本优先选 -flash / -turbo 型号。变更模型会导致新旧记忆的提取风格不一致,建议在正式使用前确定,避免上线后频繁切换。
输出参数
TaskId(任务 ID)、RequestId(请求 ID)。开通为异步任务,可通过 DescribeMem0Service 轮询状态。
请求示例
POST / HTTP/1.1
Host: postgres.tencentcloudapi.com
Content-Type: application/json
X-TC-Action: OpenMem0Service
<公共请求参数>

{
"DBInstanceId": "postgres-paxanz0n",
"AgenticBaseId": "agenticbase-2a7vajd1",
"LLMModel": "auto",
"EmbeddingApiKey": "sk-xxxxxxxx"
}
关闭指定实例的记忆服务。
输入参数
参数
必填
类型
说明
DBInstanceId
String
PostgreSQL 实例 ID
输出参数
TaskId(任务 ID)、RequestId(请求 ID)。
请求示例
POST / HTTP/1.1
Host: postgres.tencentcloudapi.com
Content-Type: application/json
X-TC-Action: CloseMem0Service
<公共请求参数>

{
"DBInstanceId": "postgres-pax**z0n"
}
注意:
关闭后服务状态变为 none,记忆接口不再可用。关闭前请确认已完成数据处置:记忆数据如仍有价值,建议先通过 GET /memories 按维度导出,或对实例做一次备份。
查询指定实例的记忆服务详情,服务访问地址(InnerAddress)通过该接口获取。输入仅需 DBInstanceId。
返回字段
字段
类型
说明
Status
String
运行状态:creating(开通中)/ running(运行中)/ deleting(关闭中)/ none(未开通)
InnerAddress
String
记忆服务访问地址,如172.16.32.14:8000,即本文中的 <服务地址>
CreateTime / UpdateTime
String
服务创建时间 / 最后更新时间
AgenticBaseId
String
关联的 AgenticBase 套餐 ID
LLMMode
String
LLM 提供方,取值 tokenhub
LLMModel
String
当前使用的 LLM 模型
EmbeddingModel
String
当前使用的 Embedding 模型
EmbeddingDims
Integer
向量维度,固定1024
PGDatabaseName
String
记忆数据所在数据库,固定 mem0
PGUserName
String
记忆服务使用的数据库账号,固定 mem0_user
NetworkAccessList
Array
网络信息(DBInstanceNetInfo 数组)
请求示例
POST / HTTP/1.1
Host: postgres.tencentcloudapi.com
Content-Type: application/json
X-TC-Action: DescribeMem0Service
<公共请求参数>

{
"DBInstanceId": "postgres-pax**z0n"
}
建议将该接口纳入自动化流程,作为部署 Agent 前的前置健康检查:Status 为 running 时取 InnerAddress 使用;为 creating 时等待1 - 2分钟后重查(开通通常3 - 5分钟内完成)。

获取服务地址

开通完成后,通过控制台或 DescribeMem0Service 云 API 查询服务详情,获取返回中的 InnerAddress(形如172.16.x.x:8000的内网地址);使用 Skill 部署时,也可以直接通过「获取 mem0 可用地址」指令查询。
本文所有示例统一以 http://<服务地址> 表示该地址,请替换为实际值。服务地址为 VPC 内网地址,请确保调用方与实例网络互通(同 VPC 直连、云联网等)。

认证状态说明

说明:
记忆服务当前处于 needsSetup=true 状态,所有接口无需携带任何认证头即可访问,不需要 access_token,也不需要 API Key。您可以通过 GET /auth/setup-status 确认当前认证状态:
curl -s http://<服务地址>/auth/setup-status

# 返回
{"needsSetup":true}
当前版本不提供注册、登录类端点,调用时仅需携带 Content-Type: application/json。
若后续服务完成初始化设置,认证将变为强制,届时需改用 API Key 或 Bearer Token 调用,请关注产品动态并及时调整调用方式。
注意:
由于当前接口无需认证,任何可访问服务地址的调用方都能读写全部记忆数据。请务必保证服务仅在内网可达:通过安全组仅放通 Agent 所在网段,严禁将服务端口通过公网 CLB、NAT 映射或反向代理暴露到公网

快速上手

本节用四个步骤带您走完一条完整的记忆链路:写入 → 检索 → 查看 → 删除。以下示例统一使用 curl,无需任何认证头。

写入第一条记忆

提交一段对话,服务自动从中提取事实:
curl -s -X POST http://<服务地址>/memories \\
-H "Content-Type: application/json" \\
-d '{
"messages": [
{"role": "user", "content": "我叫张三,是一名后端工程师,喜欢用 Python。"}
],
"user_id": "zhangsan"
}'
预期返回(服务提取出事实,以 ADD 事件写入):
{
"results": [
{"id": "a1b2c3d4-...", "memory": "张三是一名后端工程师", "event": "ADD"},
{"id": "e5f6a7b8-...", "memory": "张三喜欢用 Python", "event": "ADD"}
]
}

语义检索记忆

用自然语言提问,通过 filters 限定范围、top_k 控制返回条数:
curl -s -X POST http://<服务地址>/search \\
-H "Content-Type: application/json" \\
-d '{"query": "张三用什么编程语言?", "filters": {"user_id": "zhangsan"}, "top_k": 3}'
{
"results": [
{
"id": "e5f6a7b8-...",
"memory": "张三喜欢用 Python",
"score": 0.537,
"user_id": "zhangsan",
"attributed_to": "user"
}
]
}

查看该用户的全部记忆

curl -s "http://<服务地址>/memories?user_id=zhangsan"

删除记忆

# 删除单条(替换为实际 memory_id)
curl -s -X DELETE http://<服务地址>/memories/a1b2c3d4-...

# 返回
{"message": "Memory deleted successfully"}
至此,您已完成一次完整的记忆读写闭环。接下来可以按需查阅各接口的详细说明。

记忆操作指南

写入记忆

POST /memories
从对话中自动提取并存储值得记住的事实。请求体字段如下:
字段
类型
是否必填
说明
messages
array
对话消息数组,元素为 {"role": "...", "content": "..."}
user_id
string
三选一(至少一个)
用户维度
agent_id
string
Agent 维度
run_id
string
运行实例维度
metadata
object
自定义元数据,便于业务侧标记与筛选
infer
boolean
是否使用大模型推断事实,默认 true;设为 false 时原文存储
memory_type
string
记忆类型标记,用于业务侧分类管理
prompt
string
自定义提取指令,引导模型按您的要求提取事实
写入时附加元数据与多维度的示例:
curl -s -X POST http://<服务地址>/memories \\
-H "Content-Type: application/json" \\
-d '{
"messages": [{"role": "user", "content": "客服场景:用户希望 24 小时内回复。"}],
"user_id": "zhangsan",
"agent_id": "customer-service",
"metadata": {"source": "crm", "vip_level": "gold"}
}'

语义检索

POST /search
按语义相关度召回记忆,是将记忆注入 Prompt 的主要入口。请求体字段如下:
字段
类型
是否必填
说明
query
string
检索查询,支持自然语言
filters
object
检索范围过滤,如 {"user_id": "...", "agent_id": "..."},建议始终携带以缩小搜索域
top_k
int
返回条数,默认10
threshold
float
相似度阈值,低于该值的结果将被过滤,默认0.1
explain
boolean
是否返回评分详情,用于调试检索效果,详见 进阶能力
说明:
检索的返回条数参数为 top_k,范围过滤请使用 filters 对象(顶层直接传 user_id 的写法已废弃,请勿在新代码中使用)。

查询记忆列表

GET/memories
按维度过滤返回记忆列表,支持 user_id、agent_id、run_id 三个查询参数(可组合):
# 某用户的全部记忆
curl -s "http://<服务地址>/memories?user_id=zhangsan"

# 某用户在某 Agent 下的记忆
curl -s "http://<服务地址>/memories?user_id=zhangsan&agent_id=customer-service"
返回结构为 {"results": [...]},每条记忆包含 id、memory、hash、metadata、created_at、updated_at、归属维度及 attributed_to(归属类型)等字段。
GET /memories/{memory_id} 可读取单条记忆的完整内容。

更新与删除

PUT /memories/{memory_id} —— 修正某条记忆的文本:
curl -s -X PUT http://<服务地址>/memories/a1b2c3d4-... \\
-H "Content-Type: application/json" \\
-d '{"text": "用户是 VIP 金卡客户,偏好电话和邮件沟通"}'

# 返回
{"message": "Memory updated successfully!"}
DELETE /memories/{memory_id} —— 删除单条;DELETE /memories?user_id=... —— 清空某维度下全部记忆:
# 清空某用户的全部记忆
curl -s -X DELETE "http://<服务地址>/memories?user_id=zhangsan"
注意:
按维度清空记忆的请求不带 memory_id,一旦执行将删除该维度下所有记忆,请确认参数中的维度标识无误后再调用。

追溯变更历史

GET /memories/{memory_id}/history
返回某条记忆从创建到当前的完整变更轨迹,可用于审计与问题排查:
curl -s http://<服务地址>/memories/a1b2c3d4-.../history
每条历史记录包含 old_memory / new_memory(变更前后内容)、event(ADD / UPDATE / DELETE)、is_deleted 等字段,完整还原记忆的演变过程。

记忆的行为特性

理解以下服务行为,有助于您设计更合理的记忆写入与检索逻辑。
重复内容自动去重
服务通过内容哈希(hash)检测重复。提交完全相同的内容时不会重复存储,接口返回空结果 {"results":[]},这是正常现象,不代表写入失败。
infer=false:原文存储且不去重
写入时设置 "infer": false 将跳过大模型事实提取,消息原文原样存储,且不进行去重——相同内容多次提交会产生多条重复记忆。适用于需要保留对话原文的场景,请按需评估存储膨胀风险。
冲突信息采用 ADD-only 策略
遇到前后矛盾的信息时(例如先存“喜欢用 Python”,后存“改用 Go”),服务不会修改旧记忆,而是新增一条记录新事实,两条记忆并存,依靠时间维度区分新旧。应用侧如需“只保留最新事实”,可结合更新时间或变更历史自行处置旧记忆。
检索机制说明
当前版本启用的是语义向量检索,默认相似度阈值 threshold=0.1。通过 explain 模式可以看到 bm25_score(关键词匹配)与 entity_boost(实体加成)恒为 0,即关键词与实体信号暂未参与评分。
说明:
中文查询时,词面直接命中的记忆(如查询“张三”命中包含名字的记忆)可能比语义更相关的记忆得分更高,这是当前检索机制下的正常现象。如对排序效果有更高要求,可通过调整 threshold、优化 query 表述或在应用侧做二次排序来改善。

组织记忆的三种维度

合理使用隔离维度是设计记忆系统的关键。三种维度的典型定位如下:
维度
定位
典型用法
user_id
长期画像
记录终端用户的偏好、习惯、身份信息,伴随用户全生命周期。
agent_id
业务能力边界
同一用户在不同 Agent(客服、助手、代码评审)下的记忆互不串扰。
run_id
会话级暂存
记录某次任务执行过程的中间结论,任务结束后可整体清理。
常见组合模式:
单 Agent 应用:仅使用 user_id,结构最简单。
多 Agent 平台:user_id + agent_id 组合,实现“同一用户、不同 Agent 各有记忆”。
任务型 Agent:在上述基础上叠加 run_id,将单次任务的临时记忆与长期记忆分离,任务结束后调用 DELETE /memories?run_id=... 清理。
维度之外,还可通过 metadata 为记忆附加业务标签(如来源系统、客户等级),在应用侧实现更细粒度的筛选逻辑。

接入您的 Agent

调通接口不等于 Agent 会用记忆。真正落地时需要回答一个问题:谁来决定什么时候读写记忆?记忆服务提供三种接入方式,对应三种答案。

接入方式总览

接入方式
读写时机由谁决定
适用 Agent 形态
改造成本
推荐度
MCP 接入
大模型自主判断
支持 MCP 的现成客户端:Claude Code、Cursor、CodeBuddy 等
低(零业务代码,仅改配置)
推荐
Function Calling 接入
大模型自主判断
自研 Agent、已具备函数调用能力的 LLM 应用
中(注册2 - 3个工具)
灵活
REST API 直连
代码固定编排
对一致性有硬要求的生产 Agent,每轮必召回、必沉淀
中高(改造对话主循环)
生产推荐
选型建议:
使用现成客户端(IDE 编程助手、对话客户端)→ 选 MCP 接入。
自研 Agent 且能接受“模型偶尔忘了查记忆”→ 选 Function Calling 接入。
线上业务、要求每轮对话一定召回并沉淀 → 选 REST API 直连,在代码中固定编排;如需支持用户显式说“记住这个”,可叠加 Function Calling 的写入工具。

通过 MCP 接入

MCP(Model Context Protocol)是 Agent 客户端接入外部工具的通用协议。接入后,记忆读写变成 Agent 可自动发现和调用的“工具”。由于服务无需认证,配置只需一项核心信息:服务地址
通用 MCP 配置
JSON
{
"mcpServers": {
"tencent-memory": {
"url": "http://<服务地址>/mcp",
"type": "streamable-http"
}
}
}
字段
说明
url
MCP 端点,格式 http://<服务地址>/mcp(注意包含 /mcp 路径)
type
传输类型 streamable-http(Streamable HTTP,基于 JSON-RPC 2.0)。各客户端对类型字段的写法不完全统一(如 http、streamable-http),请以所用客户端的文档为准
说明:
当前服务未启用认证,MCP 配置中无需填写 headers 或任何凭证。安全保障依赖内网地址与网络访问控制。
各客户端配置位置
客户端
配置方式
说明
Claude Code
项目根目录 .mcp.json,或执行 claude mcp add
团队共享可提交到代码仓库
Cursor
.cursor/mcp.json 或 MCP 配置界面
编辑器内置 MCP 管理
CodeBuddy
MCP 配置界面
可视化添加 streamable-http 服务器
注意:
MCP 配置不会热加载。修改配置后请完全重启客户端或新建会话(GUI 类客户端需彻底退出后再启动),否则 Agent 看不到记忆工具。
MCP 工具清单
MCP 暴露的工具与 REST 端点一一对应,Agent 无需理解 HTTP 细节:
MCP 工具
对应 REST 端点
功能
add_memory
POST /memories
创建记忆(自动提取事实)
search_memories
POST /search
语义检索记忆
get_memories
GET /memories
获取记忆列表
get_memory
GET /memories/{id}
获取单条记忆
update_memory
PUT /memories/{id}
更新单条记忆
delete_memory
DELETE /memories/{id}
删除单条记忆
delete_all_memories
DELETE /memories
删除某维度下全部记忆
get_memory_history
GET /memories/{id}/history
获取记忆变更历史
reset_memory
POST /reset
重置全部记忆(危险操作)
验证接入
配置生效后,在对话中直接测试:
1. 发送:请记住:我的项目数据库是云数据库 PostgreSQL,生产环境在广州地域。 若 Agent 调用了记忆写入工具并成功返回,说明接入完成。
2. 新开一个会话,追问:我的项目数据库是什么? Agent 应能通过检索记忆给出正确答案——这验证了跨会话记忆闭环。
让 Agent 主动使用记忆
MCP 只解决“能不能调”,不解决“愿不愿调”。默认情况下模型往往只在用户明确说“记住”时才写记忆。要做到自动召回与自动沉淀,建议在项目规则文件(如 AGENTS.md 或客户端的自定义指令)中补充约束:
AGENTS.md 示例
## 长时记忆使用规约

本项目已接入 tencent-memory 记忆服务,请严格遵循:

1. 回答前先召回:当问题涉及项目约定、技术选型、个人偏好或历史决策时,
先调用 search_memories 检索相关记忆,再组织回答;不要凭空假设。
2. 形成结论后沉淀:确定技术选型、明确表达偏好、排查出根因时,
调用 add_memory 记录一条简洁事实。
3. 一条记忆只讲一件事:使用陈述句,避免写入大段过程描述。
4. 结论变化时先纠正:发现旧记忆已过时,先定位记忆 ID,
再用 update_memory 更新或 delete_memory 删除,不要直接追加矛盾记忆。
5. 禁止写入敏感信息:密码、密钥、证书、身份证号等一律不得写入记忆。

通过 Function Calling 接入

自研 Agent 通常已具备 Function Calling 能力,此时无需引入 MCP,把记忆能力注册为工具即可。工具描述直接决定模型的调用准确率——关键技巧是在 description 中同时写清“什么时候调用”和“什么时候不要调用”:
工具声明示例(JSON Schema)
[
{
"type": "function",
"function": {
"name": "recall_memory",
"description": "检索用户的长期记忆。当问题涉及用户身份、偏好、历史决策、项目约定,或出现「我之前说过」「还记得吗」等指代时必须调用。纯计算、纯代码生成类问题不要调用。",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "检索语句,建议保留用户原话中的关键实体"},
"top_k": {"type": "integer", "description": "返回条数", "default": 5}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "remember_fact",
"description": "把一条对后续会话仍有价值的事实写入长期记忆。仅在用户表达稳定偏好、确认技术方案、给出长期约束时调用。寒暄、临时数值、中间结果不要写入。禁止写入密钥等敏感信息。",
"parameters": {
"type": "object",
"properties": {
"content": {"type": "string", "description": "一句话陈述句,只描述一件事"},
"metadata": {"type": "object", "description": "可选业务标签"}
},
"required": ["content"]
}
}
}
]
工具的内部实现即调用 POST /search 与 POST /memories,可复用下文 REST 直连中的客户端封装。

通过 REST API 直连

生产环境的推荐集成模式为三步闭环:检索记忆 → 生成回复 → 回写记忆,由代码固定编排,保证每轮对话一定会召回、一定会沉淀。
Python
Node.js
Java
Go
PHP
完整可运行示例
import requests

BASE_URL = "http://<服务地址>" # 替换为 DescribeMem0Service 返回的 InnerAddress


class MemoryClient:
"""Agent 记忆服务客户端封装(当前版本无需认证头)"""

def __init__(self, base_url: str):
self.base_url = base_url.rstrip("/")
self.headers = {"Content-Type": "application/json"}

def add(self, messages, user_id=None, agent_id=None, run_id=None, metadata=None):
payload = {"messages": messages}
if user_id: payload["user_id"] = user_id
if agent_id: payload["agent_id"] = agent_id
if run_id: payload["run_id"] = run_id
if metadata: payload["metadata"] = metadata
r = requests.post(f"{self.base_url}/memories", json=payload, headers=self.headers)
r.raise_for_status()
return r.json()

def search(self, query, user_id=None, agent_id=None, top_k=5, threshold=None):
filters = {}
if user_id: filters["user_id"] = user_id
if agent_id: filters["agent_id"] = agent_id
payload = {"query": query, "top_k": top_k, "filters": filters}
if threshold is not None: payload["threshold"] = threshold
r = requests.post(f"{self.base_url}/search", json=payload, headers=self.headers)
r.raise_for_status()
return r.json()["results"]


def chat_with_memory(client: MemoryClient, message: str, user_id: str):
# 1. 检索相关记忆
memories = client.search(message, user_id=user_id, top_k=3)
memory_context = "\\n".join(f"- {m['memory']}" for m in memories)

# 2. 将记忆注入 Prompt,调用您的大模型
# prompt = f"以下是用户的历史记忆:\\n{memory_context}\\n\\n用户说:{message}"
# reply = your_llm_call(prompt)
reply = "(此处替换为大模型生成的回复)"

# 3. 回写本轮对话,沉淀新记忆(生产环境建议异步执行,见下文工程原则)
client.add(
[
{"role": "user", "content": message},
{"role": "assistant", "content": reply},
],
user_id=user_id,
)
return reply


if __name__ == "__main__":
client = MemoryClient(BASE_URL)
client.add(
[{"role": "user", "content": "我叫张三,是一名后端工程师,喜欢用 Python。"}],
user_id="zhangsan",
)
chat_with_memory(client, "您还记得我是做什么工作的吗?", user_id="zhangsan")
const BASE_URL = "http://<服务地址>";
const headers = { "Content-Type": "application/json" };

// 写入记忆
async function addMemory(messages, userId) {
const res = await fetch(`${BASE_URL}/memories`, {
method: "POST",
headers,
body: JSON.stringify({ messages, user_id: userId }),
});
return res.json();
}

// 检索记忆(注意使用 filters + top_k)
async function searchMemory(query, userId) {
const res = await fetch(`${BASE_URL}/search`, {
method: "POST",
headers,
body: JSON.stringify({ query, filters: { user_id: userId }, top_k: 5 }),
});
return (await res.json()).results;
}
JDK 15+(文本块语法),无需第三方依赖
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class MemoryDemo {
static final String BASE_URL = "http://<服务地址>";

public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();

// 写入记忆
String addBody = """
{"messages":[{"role":"user","content":"我叫张三,是一名后端工程师。"}],"user_id":"zhangsan"}""";
HttpRequest addReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/memories"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(addBody))
.build();
System.out.println(client.send(addReq, HttpResponse.BodyHandlers.ofString()).body());

// 检索记忆(注意使用 filters + top_k)
String searchBody = """
{"query":"张三的职业","filters":{"user_id":"zhangsan"},"top_k":3}""";
HttpRequest searchReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/search"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(searchBody))
.build();
System.out.println(client.send(searchReq, HttpResponse.BodyHandlers.ofString()).body());
}
}
仅使用标准库
package main

import (
"bytes"
"fmt"
"io"
"net/http"
)

const baseURL = "http://<服务地址>"

func post(path, body string) string {
resp, err := http.Post(baseURL+path, "application/json", bytes.NewBufferString(body))
if err != nil {
panic(err)
}
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
return string(data)
}

func main() {
// 写入记忆
fmt.Println(post("/memories",
`{"messages":[{"role":"user","content":"我叫张三,是一名后端工程师。"}],"user_id":"zhangsan"}`))

// 检索记忆(注意使用 filters + top_k)
fmt.Println(post("/search",
`{"query":"张三的职业","filters":{"user_id":"zhangsan"},"top_k":3}`))
}
依赖 cURL 扩展
<?php
$baseUrl = "http://<服务地址>";

function post($url, $payload) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}

// 写入记忆
echo post("$baseUrl/memories", [
"messages" => [["role" => "user", "content" => "我叫张三,是一名后端工程师。"]],
"user_id" => "zhangsan",
]);

// 检索记忆(注意使用 filters + top_k)
echo post("$baseUrl/search", [
"query" => "张三的职业",
"filters" => ["user_id" => "zhangsan"],
"top_k" => 3,
]);

记忆注入的工程原则

无论采用哪种接入方式,将召回的记忆注入 Prompt 时都建议遵循以下原则:
原则
做法
原因
放 system 段,不放 user 消息
记忆块拼进 system prompt
避免模型把历史事实误当成本轮新诉求
声明时效优先级
显式写明“与本轮陈述冲突时以本轮为准”
服务采用 ADD-only 策略,同一主题可能并存新旧事实
控制注入量
用 top_k + threshold 限制条数与相关度
注入过多低相关记忆会稀释上下文、推高 token 成本
沉淀异步化
写入操作放后台线程/队列执行
写入需经大模型提取,耗时明显高于检索,同步执行会拖慢每轮响应
召回失败可降级
检索异常时本轮按无记忆处理并记录日志
记忆是增强能力,不应成为对话主链路的单点故障

进阶能力

检索解释模式

在检索请求中设置 explain: true,每条返回的记忆会附带 score_details 字段,展示各评分信号明细,便于调优检索效果:
curl -s -X POST http://<服务地址>/search \\
-H "Content-Type: application/json" \\
-d '{"query": "用户的饮食偏好", "filters": {"user_id": "zhangsan"}, "top_k": 3, "explain": true}'
score_details 包含 semantic_score(语义相似度)、bm25_score(关键词匹配,当前恒为 0)、entity_boost(实体加成,当前恒为 0)、final_score(综合评分)与生效的 threshold。

自定义记忆提取指令

POST /generate-instructions 可根据您的业务场景描述,自动生成一套记忆提取指令(custom_instructions)及配套测试消息,用于定制事实提取的侧重点:
curl -s -X POST http://<服务地址>/generate-instructions \\
-H "Content-Type: application/json" \\
-d '{"use_case": "customer support chatbot that remembers user preferences"}'

实体管理与级联清理

GET /entities 可列出全部 user_id / agent_id / run_id 及其记忆数量,用于盘点记忆分布;DELETE /entities/{entity_type}/{entity_id} 可级联删除某实体下的全部记忆(entity_type 取值为 user、agent、run):
# 盘点记忆分布
curl -s http://<服务地址>/entities

# 用户注销后清理其全部记忆
curl -s -X DELETE "http://<服务地址>/entities/user/zhangsan"

请求日志

GET /requests 可查看服务收到的请求记录,便于排查调用链路与审计。

重置全部记忆

POST /reset 会清空服务上的所有记忆。
警告:
/reset 与不带维度的 DELETE /memories 属于高危操作,执行后数据不可恢复。请在调用前进行二次确认,并通过网络层(安全组)限制可发起此类调用的来源。

安全与运维建议

1. 网络隔离优先:当前版本接口无需认证,服务地址严禁暴露公网。安全组仅放通 Agent 所在网段或安全组,不要使用 0.0.0.0/0。
2. 维度必传:检索与删除操作务必携带明确的维度参数(filters / 查询参数),防止越权读取或误删其他用户的数据。
3. 危险操作管控:对 /reset、按维度清空、级联删除等操作建立审批或二次确认机制。
4. 敏感数据评估:记忆中可能包含用户画像与业务决策,写入前请评估数据敏感性,避免写入密码、密钥等凭证类信息。
5. 审计追溯:结合请求日志(GET /requests)、记忆变更历史接口与云数据库 PostgreSQL 的数据库审计能力,满足合规审计要求。
6. 定期治理:对长期未命中的记忆、临时 run_id 维度的记忆定期清理,控制存储规模并保持检索质量。
7. 关注认证状态变化:服务完成初始化后认证将转为强制,请通过 GET /auth/setup-status 关注状态,提前规划调用方式切换。

错误码速查

状态码
含义
处理建议
400
请求参数错误
检查请求体字段是否完整:写入时至少提供一个隔离维度;检索时使用 top_k 与 filters 而非旧参数名。
404
资源不存在
检查 memory_id 是否正确,记忆可能已被删除。
409
资源冲突
按返回信息调整请求内容后重试。
500
服务端错误
稍后重试;持续出现时请检查模型服务配置(如 Embedding Key 是否有效),或 提交工单 处理。
说明:
当前服务处于 needsSetup=true 状态,接口不做身份校验,因此不会返回 401 / 403。若调用失败,请优先排查网络连通性(安全组、VPC)而非凭证问题。

常见问题

Q:写入记忆后返回 {"results":[]},是失败了吗?

A:不是。这表示提交的内容与已有记忆完全重复,服务通过内容哈希自动去重,未产生新记忆。可通过 GET /memories?user_id=... 确认记忆是否已存在。

Q:写入记忆后,检索不到如何处理?

A:请确认如下情况并参考处理。
确认检索时 filters 中的维度标识与写入时一致,记忆仅在所属维度内可被检索。
默认相似度阈值为0.1,若显式设置了更高的 threshold,可适当降低后再试。
注意检索参数为 top_k 和 filters 对象,使用旧参数名(limit、顶层 user_id)可能不生效。

Q:配置了 MCP,但 Agent 看不到记忆工具如何处理?

A:请确认如下情况并参考处理。
确认配置中的 url 包含 /mcp 路径,且服务地址从当前客户端环境可达。
MCP 配置不会热加载,修改后请完全重启客户端或新建会话。
各客户端对 type 字段的取值写法不同(streamable-http / http),请以客户端文档为准。

Q:Agent 接入了记忆工具,但很少主动调用?

A:这是模型行为问题而非接入问题。请在项目规则文件或系统提示词中加入明确的使用规约(何时召回、何时沉淀、禁止写入敏感信息),可参考 让 Agent 主动使用记忆 一节的示例。

Q:用户更新了偏好,为什么旧记忆还在?

A:服务对冲突信息采用 ADD-only 策略:新事实以新增方式记录,旧记忆保留。如需清理,可根据变更历史或更新时间定位旧记忆后调用删除接口。

Q:用户注销账号后,如何清理其全部记忆?

A:调用 DELETE /entities/user/<user_id> 级联删除该用户维度下的全部记忆,满足数据合规要求。

Q:如何验证服务是否正常可用?

A:按顺序执行三步验证:
1. GET / 返回 HTTP 200,确认服务在线(网络层)。
2. GET /configure 返回配置信息,确认接口可用(应用层)。
3. 写入一条测试记忆再删除(可用专用 user_id 如 __healthcheck__),确认读写链路与模型调用正常。
在线接口文档可访问 http://<服务地址>/docs 查看,支持交互式测试。

相关文档