使用 Hindsight 为 OpenAI Agents SDK 接入长期记忆:retain / recall / reflect 工具实战指南
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
导读
本文讲解如何在 OpenAI Agents SDK 中通过hindsight-openai-agents包接入 Hindsight 长期记忆能力:该包把 Hindsight 的 retain(存储)、recall(检索)、reflect(综合推理)三个核心操作封装成符合 Agents SDK 规范的FunctionTool实例,可直接传入Agent(tools=[...]),让 Agent 在多次对话之间保留、召回并反思用户偏好与事实,而不是每次运行都从空白开始。读完本文,你将掌握包的安装与客户端配置、工具的构建与挂载、memory_instructions()系统提示词自动注入、基于bank_id与 tags 的记忆隔离,以及一套可复现的验证流程。
快速答案(Quick answer)
pip install hindsight-openai-agents openai-agents。- 创建指向你 Hindsight 后端的
Hindsight客户端,并创建一个 bank。- 用
create_hindsight_tools(client=client, bank_id="...")构建工具。- 将工具传给
Agent(tools=tools)—— 该 Agent 即获得 retain、recall、reflect 三个记忆工具。- 验证后续运行能召回先前运行所存储的内容。
前置条件
开始之前,请确认具备:
- Python 3.10 或更高版本(见 pyproject.toml 中的
requires-python = ">=3.10"); - 一个可访问的 Hindsight 后端:Hindsight Cloud,或自托管服务器(本仓库提供了完整的自托管方案,例如 docker/standalone 与 docker/docker-compose 下的各种部署编排);
- 已安装 OpenAI Agents SDK(
openai-agents,版本不低于 0.7.0)。
Step 1:安装集成包
将集成包与 Agents SDK 一起安装:
pip install hindsight-openai-agents openai-agentshindsight-openai-agents会同时拉入openai-agents与hindsight-client两个依赖(见 pyproject.toml 的dependencies段),因此一次安装即可同时获得记忆工具与 Hindsight 异步客户端。
Step 2:创建客户端与记忆库(bank)
把Hindsight客户端指向你的后端,然后创建 Agent 将要使用的记忆库。acreate_bank是幂等操作,因此每次启动时调用都是安全的:
from hindsight_client import Hindsight client = Hindsight(base_url="http://localhost:8888") await client.acreate_bank(bank_id="user-123")如果使用 Hindsight Cloud,可通过HINDSIGHT_API_KEY环境变量配置 API 密钥,或在configure()中显式传入(详见下文 Step 4 全局配置)。
源码补充:客户端解析逻辑。集成包在 _client.py 中实现了统一的客户端解析函数resolve_client,其优先级为:显式传入的client参数 > 全局configure()配置 > 环境变量与默认值。当既没有显式客户端也没有全局配置时,会回退到默认 API 地址https://api.hindsight.vectorize.io(定义于 config.py 的DEFAULT_HINDSIGHT_API_URL),并直接读取HINDSIGHT_API_KEY环境变量 —— 也就是说,只设置环境变量、完全不调用configure()也能工作。自托管用户则显式覆盖 URL 即可。客户端构造时还带有timeout=30.0与形如hindsight-openai-agents/<version>的user_agent。对应的单元测试位于 tests/test_tools.py,覆盖了"无配置时默认指向 Cloud""环境变量读取 API Key""显式 URL 覆盖全局配置"等场景。
Step 3:构建工具并挂载到 Agent
用create_hindsight_tools()创建记忆工具并传入你的Agent:
import asyncio from agents import Agent, Runner from hindsight_client import Hindsight from hindsight_openai_agents import create_hindsight_tools async def main(): client = Hindsight(base_url="http://localhost:8888") await client.acreate_bank(bank_id="user-123") tools = create_hindsight_tools(client=client, bank_id="user-123") agent = Agent( name="assistant", instructions=( "You are a helpful assistant with long-term memory. " "Use hindsight_retain to store important facts. " "Use hindsight_recall to search memory before answering." ), tools=tools, ) result = await Runner.run(agent, "Remember that I prefer dark mode") print(result.final_output) # Hindsight 以异步方式处理保留内容(事实抽取、实体消解、embedding 生成)。 # 短暂等待可确保记忆在下次召回前可被搜索到。生产环境中, # 只有在同一脚本里 retain 与 recall 紧邻执行时才需要该延迟。 await asyncio.sleep(3) result = await Runner.run(agent, "What are my UI preferences?") print(result.final_output) await client.aclose() asyncio.run(main())Agent 将获得三个可调用的工具(完整定义见 tools.py):
hindsight_retain—— 将信息存储到长期记忆。参数仅一个content字符串,成功后返回"Memory stored successfully.";hindsight_recall—— 在长期记忆中检索相关信息,返回带编号的匹配记忆列表(形如1. ...、2. ...),若无结果返回"No relevant memories found.";hindsight_reflect—— 基于存储的记忆综合出有推理依据的回答,而非返回原始事实列表。
工具如何调用记忆:从 FunctionTool 到 Hindsight 核心 API
三个工具直接映射到 Hindsight 的核心操作,并由 OpenAI Agents SDK 根据你的 instructions 决定何时调用:
- Retain:Agent 调用
hindsight_retain时,内容被存储到指定 bank。Hindsight 随后异步执行事实抽取(fact extraction)、实体消解(entity resolution)与 embedding 生成,因此存储与可检索之间存在短暂延迟。 - Recall:Agent 调用
hindsight_recall时,会在 bank 中检索相关事实,再据此作答。 - Reflect:Agent 调用
hindsight_reflect时,Hindsight 会根据已存储的记忆综合出一个有推理依据的回答。
源码细节。在 tools.py 中,三个工具分别调用异步客户端的aretain、arecall、areflect方法(对应 hindsight-client 中的同名异步方法)。由于 Agents SDK 本身是 async-native 且由工具驱动,这套设计可以在其异步运行时内无缝工作。每个工具都做了异常包装:底层调用失败时抛出集成包定义的HindsightError(见 errors.py),错误信息以Retain failed:/Recall failed:/Reflect failed:为前缀。Agents SDK 会捕获工具抛出的异常并将其转为错误字符串返回给 Agent,使其能够优雅地继续处理失败。
测试佐证。集成包自带两层测试:单元测试 tests/test_tools.py 用 mock 客户端验证了三个工具的默认生成、按需裁剪、参数透传(tags、metadata、budget、max_tokens、types、include_entities、response_schema 等)以及异常时的错误字符串返回;端到端测试 tests/test_e2e.py 则面向真实 Hindsight 服务器,验证retain → recall往返、reflect从记忆综合出包含原文要点的回答、空 bank 召回返回空提示,以及memory_instructions()把召回记忆注入系统提示词。
让记忆自动注入:memory_instructions()
如果不希望依赖 Agent 显式调用 recall,可以使用memory_instructions()在每轮对话中自动把相关记忆注入系统提示词。它返回一个与Agent(instructions=...)兼容的异步可调用对象;每一轮它会自动召回相关记忆并追加到你的基础指令之后,若召回失败或没有结果,则优雅地回退为仅使用base_instructions:
from hindsight_openai_agents import create_hindsight_tools, memory_instructions agent = Agent( name="assistant", instructions=memory_instructions( client=client, bank_id="user-123", base_instructions="You are a helpful assistant with long-term memory.", ), tools=create_hindsight_tools( client=client, bank_id="user-123", include_recall=False, # recall 由 memory_instructions 处理 ), )源码细节。memory_instructions()的实现(tools.py 中的_instructions)在每轮调用时执行一次arecall,将命中的记忆格式化为编号列表(默认最多 5 条,可用max_results调整),再以"\n\nRelevant memories:\n"为前缀拼接到base_instructions之后(prefix参数可自定义)。需要注意:OpenAI Agents SDK 的instructions参数接受str | Callable | None,不接受列表,因此该函数返回的是单个可组合的可调用对象,而非列表。
工具选择与记忆隔离
按需裁剪工具
通过include_retain、include_recall、include_reflect三个开关只保留需要的工具:
tools = create_hindsight_tools( client=client, bank_id="user-123", include_retain=True, include_recall=True, include_reflect=False, # 去掉 reflect )用 tags 划分记忆
用 tags 按主题、会话或用户对记忆做分区:
tools = create_hindsight_tools( client=client, bank_id="user-123", tags=["source:chat", "session:abc"], recall_tags=["source:chat"], recall_tags_match="any", )其中tags会在 retain 存储时打标,recall_tags与recall_tags_match控制召回时的过滤条件。tags_match支持any/all/any_strict/all_strict四种匹配模式(默认any),其中*_strict后缀的严格模式在 Hindsight 的标签语义下要求更严格的匹配规则。
更细粒度的参数
create_hindsight_tools还支持按工具细分的参数(完整参考见 README.md 的 Configuration Reference 表格):
| 参数 | 默认值 | 说明 |
|---|---|---|
bank_id | 必填 | Hindsight 记忆库 ID |
client | None | 预先配置好的 Hindsight 客户端 |
hindsight_api_url | None | API 地址(未提供 client 时使用) |
api_key | None | API 密钥(未提供 client 时使用) |
budget | "mid" | recall/reflect 的预算级别(low/mid/high) |
max_tokens | 4096 | recall 结果的最大 token 数 |
tags | None | 存储记忆时应用的标签 |
recall_tags | None | 检索时用于过滤的标签 |
recall_tags_match | "any" | 标签匹配模式(any/all/any_strict/all_strict) |
retain_metadata | None | retain 操作的默认元数据字典 |
retain_document_id | None | retain 的默认 document_id(用于分组/upsert 记忆) |
recall_types | None | 事实类型过滤(world/experience/observation) |
recall_include_entities | False | 在 recall 结果中包含实体信息 |
reflect_context | None | reflect 操作的附加上下文 |
reflect_max_tokens | None | reflect 结果的 max tokens(默认回退到max_tokens) |
reflect_response_schema | None | 用于约束 reflect 输出格式的 JSON schema |
reflect_tags | None | reflect 使用的标签过滤(默认回退到recall_tags) |
reflect_tags_match | None | reflect 的标签匹配模式(默认回退到recall_tags_match) |
include_retain | True | 是否包含 retain(存储)工具 |
include_recall | True | 是否包含 recall(检索)工具 |
include_reflect | True | 是否包含 reflect(综合)工具 |
全局配置:configure()
如果不想在每次调用时都传 client,可以只配置一次,之后创建工具时无需再传:
from hindsight_openai_agents import configure, create_hindsight_tools configure( hindsight_api_url="http://localhost:8888", api_key="your-api-key", # 或设置 HINDSIGHT_API_KEY 环境变量 budget="mid", # 召回预算:low/mid/high max_tokens=4096, # 召回结果的最大 token 数 tags=["env:prod"], # 存储记忆时打的标签 recall_tags=["scope:global"], # 召回时过滤的标签 recall_tags_match="any", # 标签匹配模式 ) # 之后无需再传 client tools = create_hindsight_tools(bank_id="user-123")源码细节。configure()(config.py)会把连接地址、密钥与默认参数写入模块级全局配置_global_config。create_hindsight_tools与memory_instructions在解析参数时遵循"显式参数优先于全局配置,全局配置优先于内置默认值"的规则(例如effective_budget、effective_max_tokens的解析逻辑)。测试 tests/test_tools.py 中的TestConfigFallback也验证了"无显式参数时使用全局配置、显式参数覆盖全局配置"的行为。配套还提供了get_config()与reset_config()用于读取与重置全局配置。
验证记忆确实生效
推荐按以下顺序验证:
- 构建工具并挂载到 Agent;
- 让 Agent 运行一次,存入一条值得记住的事实;
- 等待几秒,使已保留内容变为可搜索状态;
- 用关于该事实的问题再次运行 Agent;
- 确认回答反映了你存储的内容。
例如:
- 第一次运行:"Remember that I prefer dark mode"
- 第二次运行:"What are my UI preferences?"
如果第二次运行能答出之前的偏好,说明配置已生效。仓库中的端到端测试 tests/test_e2e.py 实现了同样思路的自动化验证:先retain一条技术栈事实,再以轮询方式(_recall_until_nonempty,最多 12 次、每次间隔 1 秒)等待召回结果命中PostgreSQL/us-east-1等关键词。这些测试默认跳过,设置HINDSIGHT_API_URL指向可达的 Hindsight 服务器后,通过-m requires_real_llm即可运行。
常见错误与规避
忘记创建 bank
首次使用前必须用acreate_bank创建记忆库。该操作幂等,因此每次启动时都调用是安全的(见 hindsight-client 中的acreate_bank实现)。
过早测试 recall
保留的内容是异步处理的(事实抽取、实体消解、embedding 生成需要时间)。如果同一脚本里 retain 与 recall 紧邻执行,应加短暂等待,确保记忆可搜索后再召回。测试代码中的轮询辅助函数_recall_until_nonempty正是对这种异步延迟的工程化处理。
期望召回却没有指示 Agent
如果依赖工具方式,Agent 只有在自行决定时才会召回。请在指令中明确要求"回答前先召回记忆",或改用memory_instructions()让每一轮自动注入记忆。
在同一个 bank 里混入无关记忆
每个 bank 都是相互隔离的记忆存储。为每个 Agent 或用户分配独立的bank_id,或在共享 bank 内用 tags 对记忆分区。
生产模式建议
错误处理
工具出错时抛出的HindsightError会被 Agents SDK 自动捕获并转为错误字符串返回给 Agent,使 Agent 能根据错误信息决定如何继续(例如改用其他信息源或如实告知用户)。
bank 生命周期
创建 bank 后再使用,不再需要时清理:
async def main(): client = Hindsight(base_url="http://localhost:8888") # 创建 bank(幂等) await client.acreate_bank(bank_id="user-123") tools = create_hindsight_tools(client=client, bank_id="user-123") # ... 使用工具 ... # 可选:不再需要时删除 bank await client.adelete_bank(bank_id="user-123")多 Agent 工作流
给每个 Agent 独立的 bank 实现私有记忆,或共享同一个 bank 实现团队共享记忆:
# 每个 Agent 独立记忆 researcher_tools = create_hindsight_tools(client=client, bank_id="researcher-memory") writer_tools = create_hindsight_tools(client=client, bank_id="writer-memory") # 跨 Agent 共享记忆 shared_tools = create_hindsight_tools( client=client, bank_id="team-shared", tags=["team:content"], )FAQ
我需要 Hindsight Cloud 吗?
不需要。自托管的 Hindsight 服务器同样适用 —— 只需把Hindsight客户端指向你服务器的base_url即可。
每次调用都必须传 client 吗?
不需要。调用一次configure()配置 API 地址与密钥,之后即可不传 client 创建工具,它们会使用全局配置。
这能与异步的 Agents SDK 运行时一起工作吗?
可以。工具直接使用异步 Hindsight 客户端(aretain、arecall、areflect),能够在 Agents SDK 的异步运行时内无缝执行。
多 Agent 之间如何隔离记忆?
为每个 Agent 分配独立的bank_id实现私有记忆,或跨 Agent 共享bank_id实现共享记忆;tags 可在 bank 内部进一步对记忆分区。
深入阅读
- 集成包源码入口:hindsight_openai_agents/__init__.py,工具实现见 tools.py;
- 完整参数参考与生产模式示例:README.md;
- Hindsight 异步客户端 API(
acreate_bank、aretain、arecall、areflect、adelete_bank等):hindsight_client.py; - 单元测试与端到端测试:tests/test_tools.py、tests/test_e2e.py;
- 自托管部署方式可参考 docker/standalone 与 docker/docker-compose 下的编排文件,例如 docker/docker-compose/external-pg/docker-compose.yaml。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考