openai-agents-python 沙箱 Agent 记忆机制全解:让每次运行都站在上一次的肩膀上
2026/9/12 1:19:50 网站建设 项目流程

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 记忆回答"这个项目/任务有什么值得记住的规律"。两者互补,可以同时使用。

记忆能为未来运行降低三类成本:

  1. Agent 成本:如果 Agent 上次完成某个工作流花了很长时间,下一次运行就不需要那么多探索,从而减少 token 消耗和完成时间。
  2. 用户成本:如果用户纠正过 Agent 或表达过偏好,未来的运行能记住这些反馈,减少人工干预。
  3. 上下文成本:如果 Agent 之前完成过某个任务、用户想在此基础上继续,就不需要翻找旧对话或重新输入全部上下文,任务描述可以更短。

注意:沙箱 Agent 目前处于Beta 阶段。API、默认值和所支持的能力在正式发布(GA)前可能变化,未来还会加入更多高级特性。

完整的两轮运行示例(修复 bug → 生成记忆 → 恢复快照 → 后续验证运行使用记忆)见 examples/sandbox/memory.py;多轮、多 Agent、带独立记忆布局的示例见 examples/sandbox/memory_multi_agent_multiturn.py。

启用记忆:把 Memory() 加入 capabilities

启用记忆非常简单:给SandboxAgentcapabilities列表加上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中做了硬性校验:readgenerate至少开启一个,否则抛出ValueError("Memory requires at least one ofreadorgenerate.")layout.memories_dirlayout.sessions_dir必须是相对沙箱工作区根目录的非空路径、不能是绝对路径、不能包含..越界。

记忆文件的默认位置与复用条件

默认情况下,记忆产物存放在沙箱工作区的memories/目录下。要在后续运行中复用它们,必须保留并复用整个配置的 memories 目录,方式有两种:

  • 保持同一个 live sandbox 会话;
  • 从持久化的 session state 或快照(snapshot)恢复。

一个全新的空沙箱,记忆是空的。

只读与只写两种模式

Memory()默认同时开启读取生成记忆。但某些场景下你可能只想用其中一半能力:

  • Memory(generate=None):只读不写。适合内部 Agent、子 Agent、检查器(checker)或一次性工具 Agent——它们的运行本身不产生太多值得沉淀的信号;
  • Memory(read=None):只写不读。本次运行要为将来生成记忆,但用户不希望本次运行被已有记忆影响。

在 capabilities/memory.py 中,readgenerate分别对应MemoryReadConfigMemoryGenerateConfig两个配置对象,设None即关闭对应方向。

读取记忆:渐进式披露(progressive disclosure)

记忆读取采用渐进式披露策略,避免把全部历史一股脑塞给模型:

  1. 运行开始时,SDK 把一份简短摘要memory_summary.md(包含通用技巧、用户偏好和可用记忆的索引)注入 Agent 的 developer prompt。这份摘要在 capabilities/memory.py 中从memories_dir/memory_summary.md读取,并经过 token 截断(上限_MEMORY_SUMMARY_MAX_TOKENS = 15_000)。它给 Agent 足够的上下文判断"之前的工作是否可能与当前任务相关"。
  2. 当相关工作看起来相关时,Agent 在配置的记忆索引MEMORY.md(位于memories_dir下)中按当前任务的关键词搜索。
  3. 只有当任务确实需要更多细节时,才打开配置的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.mdmemory_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.mdMEMORY.md是最终消费的产物,raw_memories.mdphase_two_selection.jsonraw_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_consolidation256Phase 2 整合时考虑的最大近期原始记忆条数。若近期原始记忆超过该值,只保留来自最新会话的记忆、移除更早的;"新近"按会话最后更新时间判定。这是一种遗忘机制,帮助记忆始终反映最新环境。取值必须大于 0 且不超过 4096,否则抛ValueError
phase_one_model"gpt-5.4-mini"Phase 1 单 rollout 抽取使用的模型
phase_one_model_settingsModelSettings(reasoning=Reasoning(effort="medium"))Phase 1 的模型设置,接受ModelSettings实例或其字段的字典
phase_two_model"gpt-5.5"Phase 2 记忆整合使用的模型
phase_two_model_settingsModelSettings(reasoning=Reasoning(effort="medium"))Phase 2 的模型设置
extra_promptNone追加到抽取与整合 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 示例 注释也印证了这一逻辑):

  1. conversation_id——当你显式传给Runner.run(...)时;
  2. session.session_id——当你传入 SDKSession(如SQLiteSession)时;
  3. RunConfig.group_id——以上都没有时;
  4. 生成的每运行独立 ID——没有任何稳定标识符时。

也就是说,想要多轮共享一份记忆,最省事的方式就是复用同一个 SDKSession

用不同布局隔离不同 Agent 的记忆

记忆隔离基于MemoryLayoutConfig而不是 Agent 名称

  • 布局相同 + 记忆会话 ID 相同的 Agent → 共享一个记忆会话和一份整合后的记忆;
  • 布局不同的 Agent → 即使共用同一个沙箱工作区,也会各自保留独立的 rollout 文件、原始记忆、MEMORY.mdmemory_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/gtmmemories/engineering+sessions/engineering

同布局冲突的保护

在 memory/manager.py 中还有一个值得注意的细节:同一个沙箱会话内,如果多个Memory能力要复用同一个memories_dirsessions_dir但生成配置不同,会抛出UserError,提示要么换一个memories_dir做隔离、要么用相同布局来共享记忆。同时,同会话内相同布局的多个Memory会共享同一个记忆生成管理器(manager.py),保证一致性与幂等。

实战闭环:从修复到复用的两轮示例

把以上机制串起来,一个典型的记忆闭环长这样(完整代码见 examples/sandbox/memory.py):

  1. Run 1:Agent 在沙箱中修复report.py的发票总额计算 bug,运行结束、沙箱会话关闭时触发后台记忆生成,产出memories/MEMORY.mdmemory_summary.mdraw_memories/rollout_summaries/等产物;
  2. 恢复快照:用await client.resume(sandbox.state)从持久化的快照恢复一个新沙箱会话,工作区连同memories/一起保留;
  3. 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询