openai-agents-python 沙箱 Agent 记忆机制全解:让每次运行都站在上一次的肩膀上
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
Sandbox Agent 记忆(Agent memory)是 openai-agents-python 为沙箱代理提供的一项能力:它把过往运行中沉淀的经验、用户偏好与修复过程蒸馏成工作区内的记忆文件,让后续运行自动"复习"历史、减少探索成本。本文基于 docs/sandbox/memory.md 展开,结合 capabilities/memory.py、config.py、memory/manager.py 等源码与 examples/sandbox/memory.py 完整示例,讲透记忆的启用、读取、生成、多轮会话与多 Agent 隔离,读完你就能在自己的沙箱工作流中落地"一次修复、永久受益"的记忆机制。
什么是 Sandbox Agent 记忆
在沙箱(sandbox)场景中,一个 Agent 往往需要执行"修 bug、写回归测试、分析数据、做 GTM 调研"这类多步任务。如果没有记忆,每次运行都要从零开始探索工作区、重新踩一遍坑。Sandbox Agent 记忆正是为解决这个问题而生:
记忆让未来的沙箱 Agent 运行能从之前的运行中学习。它与 SDK 的会话(
Session)记忆是两回事——后者存储的是消息历史(message history),而前者把过往运行中提炼出的经验教训(lessons)蒸馏成沙箱工作区中的文件。
也就是说,Session 记忆回答"我们刚才聊了什么",Agent 记忆回答"这个项目/任务有什么值得记住的规律"。两者互补,可以同时使用。
记忆能为未来运行降低三类成本:
- Agent 成本:如果 Agent 上次完成某个工作流花了很长时间,下一次运行就不需要那么多探索,从而减少 token 消耗和完成时间。
- 用户成本:如果用户纠正过 Agent 或表达过偏好,未来的运行能记住这些反馈,减少人工干预。
- 上下文成本:如果 Agent 之前完成过某个任务、用户想在此基础上继续,就不需要翻找旧对话或重新输入全部上下文,任务描述可以更短。
注意:沙箱 Agent 目前处于Beta 阶段。API、默认值和所支持的能力在正式发布(GA)前可能变化,未来还会加入更多高级特性。
完整的两轮运行示例(修复 bug → 生成记忆 → 恢复快照 → 后续验证运行使用记忆)见 examples/sandbox/memory.py;多轮、多 Agent、带独立记忆布局的示例见 examples/sandbox/memory_multi_agent_multiturn.py。
启用记忆:把 Memory() 加入 capabilities
启用记忆非常简单:给SandboxAgent的capabilities列表加上Memory()即可。从 memory.py 示例 看,一个"会读、会写记忆"的 Agent 通常同时具备三项能力:
from pathlib import Path import tempfile from agents.sandbox import LocalSnapshotSpec, SandboxAgent from agents.sandbox.capabilities import Filesystem, Memory, Shell agent = SandboxAgent( name="Memory-enabled reviewer", instructions="Inspect the workspace and preserve useful lessons for follow-up runs.", capabilities=[Memory(), Filesystem(), Shell()], ) with tempfile.TemporaryDirectory(prefix="sandbox-memory-example-") as snapshot_dir: sandbox = await client.create( manifest=manifest, snapshot=LocalSnapshotSpec(base_path=Path(snapshot_dir)), )为什么需要Shell()和Filesystem()?看 capabilities/memory.py 中required_capability_types()的实现就清楚了:
- 只要read(读取)开启,就要求
Shell()——当注入的摘要信息不够用时,Agent 需要能读取和搜索记忆文件; - 当live update(实时更新)开启(默认开启)时,还要求
Filesystem()——Agent 发现记忆过期或用户要求更新记忆时,需要能就地修改memories/MEMORY.md。
同时 capabilities/memory.py 在model_post_init中做了硬性校验:read和generate至少开启一个,否则抛出ValueError("Memory requires at least one ofreadorgenerate.");layout.memories_dir和layout.sessions_dir必须是相对沙箱工作区根目录的非空路径、不能是绝对路径、不能包含..越界。
记忆文件的默认位置与复用条件
默认情况下,记忆产物存放在沙箱工作区的memories/目录下。要在后续运行中复用它们,必须保留并复用整个配置的 memories 目录,方式有两种:
- 保持同一个 live sandbox 会话;
- 从持久化的 session state 或快照(snapshot)恢复。
一个全新的空沙箱,记忆是空的。
只读与只写两种模式
Memory()默认同时开启读取和生成记忆。但某些场景下你可能只想用其中一半能力:
Memory(generate=None):只读不写。适合内部 Agent、子 Agent、检查器(checker)或一次性工具 Agent——它们的运行本身不产生太多值得沉淀的信号;Memory(read=None):只写不读。本次运行要为将来生成记忆,但用户不希望本次运行被已有记忆影响。
在 capabilities/memory.py 中,read和generate分别对应MemoryReadConfig与MemoryGenerateConfig两个配置对象,设None即关闭对应方向。
读取记忆:渐进式披露(progressive disclosure)
记忆读取采用渐进式披露策略,避免把全部历史一股脑塞给模型:
- 运行开始时,SDK 把一份简短摘要
memory_summary.md(包含通用技巧、用户偏好和可用记忆的索引)注入 Agent 的 developer prompt。这份摘要在 capabilities/memory.py 中从memories_dir/memory_summary.md读取,并经过 token 截断(上限_MEMORY_SUMMARY_MAX_TOKENS = 15_000)。它给 Agent 足够的上下文判断"之前的工作是否可能与当前任务相关"。 - 当相关工作看起来相关时,Agent 在配置的记忆索引
MEMORY.md(位于memories_dir下)中按当前任务的关键词搜索。 - 只有当任务确实需要更多细节时,才打开配置的
rollout_summaries/目录下对应的历史运行摘要(prior rollout summaries)。
记忆会过期:live_update 机制
记忆可能过时。Agent 被明确指示:把记忆当作参考而非真理,以当前环境为准。默认情况下记忆读取开启了live_update,因此如果 Agent 发现记忆过期,可以在同一次运行中就更新配置的MEMORY.md。这一点在 memory/prompts.py 的MEMORY_LIVE_UPDATE_INSTRUCTIONS中有非常明确的约束:
- 记忆与当前工作区状态、工具输出、环境或用户反馈冲突时,当前证据优先;
- 发现记忆过期后,必须用本地证据核实正确替换内容,用当前证据继续任务,并在同一轮内、最终回复之前更新
MEMORY.md——这是任务完成的一部分,不是可选的清理。
而MemoryReadConfig(live_update=False)则让 Agent 只读不修:prompt 会换成MEMORY_READ_ONLY_INSTRUCTIONS = "Never update memories. You can only read them."。何时关掉实时更新?memory.py 示例 的注释给出建议:当运行对延迟敏感时,关闭它可以省去记忆修复的几秒开销;但代价是过时记忆的"欠账"会累积到下一次 consolidation,而那次 consolidation 未必能发现过期;同时 Agent 也无法在运行中响应用户"记住这件事/修改记忆"的即时要求。
生成记忆:两阶段管线
记忆生成是异步、后台的。机制如下:
- 每次运行结束后,沙箱运行时把该运行段(run segment)追加到一个会话(conversation)文件中;
- 累积的会话文件在沙箱会话关闭时被处理。
从 memory/manager.py 的类注释可以确认这条链路:SandboxMemoryGenerationManager在沙箱会话期间把运行段追加到按 rollout 组织的 JSONL 文件,会话关闭时对每个 rollout 执行 phase-1 抽取,再做一次 phase-2 consolidation。enqueue_result负责把运行结果序列化入队,flush在会话关闭时被调用(通过register_pre_stop_hook注册,见 manager.py),最终触发两阶段处理。
Phase 1:会话抽取(conversation extraction)
一个"记忆生成模型"处理一个累积的会话文件,生成:
- 会话摘要(conversation summary):系统内容(system)、开发者内容(developer)和推理内容(reasoning)会被剔除;会话太长时会被截断以适配上下文窗口,保留开头和结尾;
- 原始记忆摘录(raw memory extract):从会话中提炼的紧凑笔记,供 Phase 2 整合。
Phase 2:布局整合(layout consolidation)
一个整合 Agent 读取某个记忆布局(memory layout)的全部原始记忆,需要更多证据时打开对应的会话摘要,然后把规律提炼写入MEMORY.md和memory_summary.md。
默认工作区布局
workspace/ ├── sessions/ │ └── <rollout-id>.jsonl └── memories/ ├── memory_summary.md ├── MEMORY.md ├── raw_memories.md (intermediate) ├── phase_two_selection.json (intermediate) ├── raw_memories/ (intermediate) │ └── <rollout-id>.md ├── rollout_summaries/ │ └── <rollout-id>_<slug>.md └── skills/其中sessions/下是按 rollout 组织的 JSONL 会话文件(文件名规则见 manager.py:rollout ID 必须是仅含字母、数字、.、_、-的文件安全 ID);memories/下的memory_summary.md、MEMORY.md是最终消费的产物,raw_memories.md、phase_two_selection.json、raw_memories/、rollout_summaries/是中间产物。skills/目录为技能类记忆预留。
MemoryGenerateConfig:配置生成行为
用MemoryGenerateConfig可以微调记忆生成:
from agents.sandbox import MemoryGenerateConfig from agents.sandbox.capabilities import Memory memory = Memory( generate=MemoryGenerateConfig( max_raw_memories_for_consolidation=128, extra_prompt="Pay extra attention to what made the customer more satisfied or annoyed", ), )关键参数(定义见 config.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
max_raw_memories_for_consolidation | 256 | Phase 2 整合时考虑的最大近期原始记忆条数。若近期原始记忆超过该值,只保留来自最新会话的记忆、移除更早的;"新近"按会话最后更新时间判定。这是一种遗忘机制,帮助记忆始终反映最新环境。取值必须大于 0 且不超过 4096,否则抛ValueError |
phase_one_model | "gpt-5.4-mini" | Phase 1 单 rollout 抽取使用的模型 |
phase_one_model_settings | ModelSettings(reasoning=Reasoning(effort="medium")) | Phase 1 的模型设置,接受ModelSettings实例或其字段的字典 |
phase_two_model | "gpt-5.5" | Phase 2 记忆整合使用的模型 |
phase_two_model_settings | ModelSettings(reasoning=Reasoning(effort="medium")) | Phase 2 的模型设置 |
extra_prompt | None | 追加到抽取与整合 prompt 中的开发者自定义指导。用于告诉记忆生成器哪些信号对你的场景最重要——比如 GTM Agent 应重点关注客户与公司细节 |
extra_prompt使用建议(来自 config.py 与 memory.py 示例 的注释):除了标准的用户偏好、失败恢复、任务摘要信号外,用少量针对性 bullet 或短段落说明额外要保留的细节;尽量控制在约 5k token 以内、通常越短越好。因为 Phase 1 的生成模型已经接收了内置大 prompt 加截断会话的完整上下文,过长的 extra prompt 会挤占你真正希望它总结的证据空间。
多轮对话:SDK Session 与沙箱会话的组合
多轮沙箱对话的正确姿势是:把普通 SDKSession和同一个 live sandbox 会话一起使用。这样模型能看见之前的轮次,记忆也能把多轮当作一次对话来抽取:
from agents import Runner, SQLiteSession from agents.run import RunConfig from agents.sandbox import SandboxRunConfig conversation_session = SQLiteSession("gtm-q2-pipeline-review") sandbox = await client.create(manifest=agent.default_manifest) async with sandbox: run_config = RunConfig( sandbox=SandboxRunConfig(session=sandbox), workflow_name="GTM memory example", ) await Runner.run( agent, "Analyze data/leads.csv and identify one promising GTM segment.", session=conversation_session, run_config=run_config, ) await Runner.run( agent, "Using that analysis, write a short outreach hypothesis.", session=conversation_session, run_config=run_config, )两次运行都传入同一个 SDK 会话(session=conversation_session),因此共享同一个session.session_id,两次运行会追加到同一个记忆会话文件。这不同于SandboxRunConfig(session=sandbox)中的 sandbox 参数——后者标识的是 live 工作区,不用作记忆会话 ID。当沙箱会话关闭时,Phase 1 看到的是累积的完整对话,能从整个交流中抽取记忆,而不是两个孤立的 turn。
记忆会话 ID 的解析顺序
如果希望多个Runner.run(...)调用归入同一个记忆会话,就在这些调用中传入一个稳定标识符。记忆把运行与会话关联时,按以下顺序解析(memory.py 示例 注释也印证了这一逻辑):
conversation_id——当你显式传给Runner.run(...)时;session.session_id——当你传入 SDKSession(如SQLiteSession)时;RunConfig.group_id——以上都没有时;- 生成的每运行独立 ID——没有任何稳定标识符时。
也就是说,想要多轮共享一份记忆,最省事的方式就是复用同一个 SDKSession。
用不同布局隔离不同 Agent 的记忆
记忆隔离基于MemoryLayoutConfig,而不是 Agent 名称:
- 布局相同 + 记忆会话 ID 相同的 Agent → 共享一个记忆会话和一份整合后的记忆;
- 布局不同的 Agent → 即使共用同一个沙箱工作区,也会各自保留独立的 rollout 文件、原始记忆、
MEMORY.md和memory_summary.md。
多个 Agent 共享一个沙箱但不该共享记忆时,为每个 Agent 配置独立的布局:
from agents import SQLiteSession from agents.sandbox import MemoryLayoutConfig, SandboxAgent from agents.sandbox.capabilities import Filesystem, Memory, Shell gtm_agent = SandboxAgent( name="GTM reviewer", instructions="Analyze GTM workspace data and write concise recommendations.", capabilities=[ Memory( layout=MemoryLayoutConfig( memories_dir="memories/gtm", sessions_dir="sessions/gtm", ) ), Filesystem(), Shell(), ], ) engineering_agent = SandboxAgent( name="Engineering reviewer", instructions="Inspect engineering workspaces and summarize fixes and risks.", capabilities=[ Memory( layout=MemoryLayoutConfig( memories_dir="memories/engineering", sessions_dir="sessions/engineering", ) ), Filesystem(), Shell(), ], ) gtm_session = SQLiteSession("gtm-q2-pipeline-review") engineering_session = SQLiteSession("eng-invoice-test-fix")MemoryLayoutConfig只有两个字段(见 config.py):memories_dir(默认"memories",整合后记忆文件的目录)和sessions_dir(默认"sessions",按 rollout 组织的 JSONL 产物目录)。上例中 GTM 分析的记忆不会被整合进工程 bug 修复的记忆,反之亦然——这正是 examples/sandbox/memory_multi_agent_multiturn.py 演示的场景:同一个沙箱工作区内,GTM analyst 与 Engineering fixer 各用一套memories/gtm+sessions/gtm、memories/engineering+sessions/engineering。
同布局冲突的保护
在 memory/manager.py 中还有一个值得注意的细节:同一个沙箱会话内,如果多个Memory能力要复用同一个memories_dir或sessions_dir但生成配置不同,会抛出UserError,提示要么换一个memories_dir做隔离、要么用相同布局来共享记忆。同时,同会话内相同布局的多个Memory会共享同一个记忆生成管理器(manager.py),保证一致性与幂等。
实战闭环:从修复到复用的两轮示例
把以上机制串起来,一个典型的记忆闭环长这样(完整代码见 examples/sandbox/memory.py):
- Run 1:Agent 在沙箱中修复
report.py的发票总额计算 bug,运行结束、沙箱会话关闭时触发后台记忆生成,产出memories/MEMORY.md、memory_summary.md、raw_memories/、rollout_summaries/等产物; - 恢复快照:用
await client.resume(sandbox.state)从持久化的快照恢复一个新沙箱会话,工作区连同memories/一起保留; - Run 2:同一个 Agent 在新会话中面对"为上次修的 bug 补回归测试"的提示——它会在运行开始时自动读到注入的
memory_summary.md摘要,必要时搜索MEMORY.md并打开rollout_summaries/,基于上次的经验直接定位文件、快速完成测试编写,而不再从零探索。
示例还提供了一个实用的调试手段:_print_memory_tree会打印生成的全部记忆产物树和内容,方便你验证记忆确实落盘、内容是否符合预期。
小结与使用建议
- 默认配置即合理:
Memory()+Filesystem()+Shell()三件套默认支持读、写、实时更新记忆,开箱即用; - 按角色裁剪能力:子 Agent、检查器用
Memory(generate=None)避免噪音记忆;临时任务用Memory(read=None)防止被旧记忆带偏; - 多轮对话务必复用 SDK Session,让多轮运行归入同一个记忆会话,Phase 1 才能从完整对话中抽取;
- 多 Agent 共享沙箱时用
MemoryLayoutConfig隔离布局,让 GTM 分析与工程修复的记忆井水不犯河水; extra_prompt要短而精,聚焦你最在意的信号(客户满意度、bug 根因、失败恢复步骤等),别用长篇大论挤占模型对会话证据的注意力;max_raw_memories_for_consolidation是遗忘旋钮:环境变化快就调小,让记忆更快反映最新状态。
Sandbox Agent 记忆是让沙箱工作流从"每次冷启动"走向"热启动"的关键基础设施。配合 docs/sandbox/guide.md 的沙箱整体指南和 docs/sessions/index.md 的 SDK 会话文档,你可以把它与消息历史记忆组合使用,构建出真正具备长期学习能力的多 Agent 系统。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考