跳转到内容

智能体记忆

Memory 让未来的 sandbox-agent 运行能够从先前运行中学习。它独立于 SDK 的对话式会话记忆;后者存储的是消息历史。Memory 会将先前运行中的经验提炼为沙盒工作区中的文件,因此请将生成的记忆工件视为保留数据,并对其应用与工作区相同的敏感性和保留策略。

Memory 可以为未来运行减少三类成本:

  1. 智能体成本:如果智能体完成某个工作流花费了较长时间,下一次运行所需的探索应该会更少。这可以减少 token 使用量并缩短完成时间。
  2. 用户成本:如果用户纠正了智能体或表达了某种偏好,未来运行可以记住这些反馈。这可以减少人工干预。
  3. 上下文成本:如果智能体之前完成过某项任务,而用户希望基于该任务继续工作,用户就不需要再去找之前的线程或重新输入全部上下文。这会让任务描述更简短。

memory() 作为能力添加到沙盒智能体中。

启用记忆
import {
filesystem,
Manifest,
memory,
SandboxAgent,
shell,
} from '@openai/agents/sandbox';
const manifest = new Manifest({
entries: {
'README.md': {
type: 'file',
content: '# Memory demo\n\nA workspace for follow-up runs.\n',
},
},
});
const agent = new SandboxAgent({
name: 'Memory-enabled reviewer',
model: 'gpt-5.5',
instructions:
'Inspect the workspace, verify important claims, and preserve useful lessons for follow-up runs.',
defaultManifest: manifest,
capabilities: [filesystem(), shell(), memory()],
});

如果启用了读取,memory() 就需要 shell(),这样当注入的摘要不足时,智能体就可以读取和搜索记忆文件。当默认启用了实时记忆更新时,它还需要 filesystem(),这样如果智能体发现记忆已过时,或用户要求其更新记忆,智能体就可以更新 memories/MEMORY.md

默认情况下,记忆工件存储在沙盒工作区的 memories/ 下。要在后续运行中复用它们,请通过保持同一个实时沙盒会话,或从持久化的会话状态或快照恢复,来保留并复用整个已配置的记忆目录;全新的空沙盒会从空记忆开始。

memory() 会同时启用记忆读取和记忆生成。对于应当读取记忆但不应生成新记忆的智能体,请使用 memory({ generate: false }):例如内部智能体、子智能体、检查器,或一次性工具智能体,因为这类运行通常不会增加太多有效信号。若运行应为后续生成记忆,但用户不希望当前运行受到现有记忆影响,请使用 memory({ read: null })

配置只读记忆
import { memory } from '@openai/agents/sandbox';
const readOnlyMemory = memory({
read: { liveUpdate: false },
generate: false,
});

记忆读取采用渐进式披露。在运行开始时,SDK 会将一个较小的摘要(memory_summary.md)注入到智能体的开发者提示中,其中包含通常有用的提示、用户偏好以及可用记忆。这为智能体提供了足够的上下文,以判断先前工作是否可能相关。

当先前工作看起来相关时,智能体会在已配置的记忆索引(memoriesDir 下的 MEMORY.md)中搜索当前任务的关键词。只有当任务需要更多细节时,它才会打开已配置 rollout_summaries/ 目录下对应的先前 rollout 摘要。

记忆可能会过时。系统会指示智能体仅将记忆作为参考,并以当前环境为准。默认情况下,记忆读取启用了 liveUpdate,因此如果智能体发现记忆已过时,它可以在同一次运行中更新已配置的 MEMORY.md。如果运行对延迟敏感,且智能体应当只读取记忆而不在运行期间修改它,请禁用实时更新。

运行结束后,沙盒运行时会将该次运行片段追加到一个对话文件中。累积的对话文件会在沙盒会话关闭时进行处理。这些对话文件可能包含用户输入、助手和工具项、中断以及最终输出,因此对于敏感工作负载,请使用合适的记忆存储和保留策略。

记忆生成分为两个阶段:

  1. 阶段 1:对话提取。一个用于生成记忆的模型会处理一个累积的对话文件,并生成对话摘要。系统、开发者和推理内容会被省略。如果对话过长,则会截断以适应上下文窗口,同时保留开头和结尾。它还会生成原始记忆提取:从对话中提炼出的紧凑笔记,供阶段 2 进行整合。
  2. 阶段 2:布局整合。一个整合智能体会读取某个记忆布局的原始记忆,在需要更多证据时打开对话摘要,并将模式提取到 MEMORY.mdmemory_summary.md 中。

默认工作区布局如下:

workspace/
├── sessions/
│ └── <rollout-id>.jsonl
└── memories/
├── memory_summary.md
├── MEMORY.md
├── raw_memories.md
├── raw_memories/
└── rollout_summaries/

您可以使用 memory({ generate: ... }) 配置记忆生成:

配置记忆生成
import { memory } from '@openai/agents/sandbox';
const memoryCapability = memory({
generate: {
maxRawMemoriesForConsolidation: 128,
phaseOneModel: 'gpt-5.4-mini',
phaseTwoModel: 'gpt-5.4',
extraPrompt:
'Prioritize workflow corrections, verification commands, and user preferences.',
},
});

使用 extraPrompt 可以告诉记忆生成器,哪些信号对您的用例最重要,例如对 GTM 智能体来说,客户和公司详情就很重要。

如果最近的原始记忆数量超过 maxRawMemoriesForConsolidation,阶段 2 将只保留最新对话中的记忆,并移除较旧的记忆。新旧依据是对话最后更新时间。这个遗忘机制有助于让记忆反映最新环境。

对于多轮沙盒聊天,请将常规 SDK Session 与同一个实时沙盒会话一起使用:

将一个 SDK 会话与一个沙盒会话配合使用
import { MemorySession, run } from '@openai/agents';
import {
filesystem,
Manifest,
memory,
SandboxAgent,
shell,
} from '@openai/agents/sandbox';
import { UnixLocalSandboxClient } from '@openai/agents/sandbox/local';
const manifest = new Manifest();
const agent = new SandboxAgent({
name: 'Memory-enabled reviewer',
model: 'gpt-5.5',
instructions: 'Inspect the workspace before answering.',
capabilities: [filesystem(), shell(), memory()],
});
const conversation = new MemorySession({ sessionId: 'workspace-review' });
const sandbox = await new UnixLocalSandboxClient().create({ manifest });
try {
await run(agent, 'Analyze data/leads.csv.', {
session: conversation,
sandbox: { session: sandbox },
});
await run(agent, 'Write a follow-up recommendation.', {
session: conversation,
sandbox: { session: sandbox },
});
} finally {
await sandbox.close?.();
}

这两次运行会追加到同一个记忆对话文件中,因为它们传入了相同的 SDK 对话会话,因此共享同一个会话 ID。这不同于沙盒;沙盒标识的是实时工作区,不会用作记忆对话 ID。阶段 1 会在沙盒会话关闭时看到累积的对话,因此它可以从整个交互中提取记忆,而不是将其视为两个孤立的轮次。

如果您希望多次 run(...) 调用变成同一个记忆对话,请在这些调用之间传递一个稳定标识符。当 Memory 将一次运行关联到某个对话时,会按以下顺序解析:

  1. conversationId,当您将其传递给 run(...) 时。
  2. SDK session 的 id,当您传递一个 SDK Session 时。
  3. groupId,当前两者都不存在时。
  4. 每次运行生成的 ID,当不存在稳定标识符时。

使用不同布局为不同智能体隔离记忆

Section titled “使用不同布局为不同智能体隔离记忆”

记忆隔离基于 MemoryLayoutConfig,而不是智能体名称。具有相同布局和相同记忆对话 ID 的智能体会共享一个记忆对话和一份整合后的记忆。布局不同的智能体则会保留各自独立的 rollout 文件、原始记忆、MEMORY.mdmemory_summary.md,即使它们共享同一个沙盒工作区也是如此。

当多个智能体共享一个沙盒,但不应共享记忆时,请使用单独的布局:

使用单独的记忆布局
import { memory } from '@openai/agents/sandbox';
const engineeringMemory = memory({
layout: {
memoriesDir: 'memories/engineering',
sessionsDir: 'sessions/engineering',
},
});
const financeMemory = memory({
layout: {
memoriesDir: 'memories/finance',
sessionsDir: 'sessions/finance',
},
});

这样可以防止一个领域的分析被整合进另一个领域的记忆中,反之亦然。