에이전트 메모리
메모리를 사용하면 향후 샌드박스 에이전트 실행이 이전 실행으로부터 학습할 수 있습니다. 이는 메시지 기록을 저장하는 SDK의 대화형 세션 메모리와는 별개입니다. 메모리는 이전 실행에서 얻은 교훈을 샌드박스 작업 영역의 파일로 요약해 저장하므로, 생성된 메모리 아티팩트는 보존 데이터로 취급하고 작업 영역에 사용하는 것과 동일한 민감도 및 보존 정책을 적용하세요.
메모리는 향후 실행에서 세 가지 비용을 줄일 수 있습니다.
- 에이전트 비용: 에이전트가 워크플로를 완료하는 데 오래 걸렸다면, 다음 실행에서는 탐색이 덜 필요해야 합니다. 이를 통해 토큰 사용량과 완료 시간을 줄일 수 있습니다.
- 사용자 비용: 사용자가 에이전트를 수정했거나 선호 사항을 표현했다면, 향후 실행에서 해당 피드백을 기억할 수 있습니다. 이를 통해 사람의 개입을 줄일 수 있습니다.
- 컨텍스트 비용: 에이전트가 이전에 어떤 작업을 완료했고 사용자가 그 작업을 기반으로 계속 진행하려는 경우, 사용자가 이전 스레드를 찾거나 모든 컨텍스트를 다시 입력할 필요가 없어야 합니다. 이렇게 하면 작업 설명이 더 짧아집니다.
메모리 활성화
섹션 제목: “메모리 활성화”샌드박스 에이전트에 기능으로 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/ 디렉터리 아래의 해당 이전 롤아웃 요약을 엽니다.
메모리는 오래될 수 있습니다. 에이전트는 메모리를 가이드로만 취급하고 현재 환경을 신뢰하도록 지시됩니다. 기본적으로 메모리 읽기에는 liveUpdate가 활성화되어 있으므로, 에이전트가 오래된 메모리를 발견하면 같은 실행에서 구성된 MEMORY.md를 업데이트할 수 있습니다. 예를 들어 실행이 지연 시간에 민감한 경우처럼, 에이전트가 실행 중에 메모리를 읽되 수정해서는 안 될 때는 라이브 업데이트를 비활성화하세요.
메모리 생성
섹션 제목: “메모리 생성”실행이 끝나면 샌드박스 런타임은 해당 실행 세그먼트를 대화 파일에 추가합니다. 누적된 대화 파일은 샌드박스 세션이 닫힐 때 처리됩니다. 이러한 대화 파일에는 사용자 입력, 어시스턴트 및 도구 항목, 인터럽션(중단 처리), 최종 출력이 포함될 수 있으므로, 민감한 워크로드에는 적절한 메모리 저장소와 보존 정책을 사용하세요.
메모리 생성에는 두 단계가 있습니다.
- 1단계: 대화 추출. 메모리 생성 모델이 누적된 대화 파일 하나를 처리하고 대화 요약을 생성합니다. 시스템, 개발자, 추론 콘텐츠는 생략됩니다. 대화가 너무 길면 컨텍스트 창에 맞도록 잘리며, 시작과 끝은 보존됩니다. 또한 2단계에서 통합할 수 있도록 대화에서 얻은 간결한 메모인 원문 메모리 추출물도 생성합니다.
- 2단계: 레이아웃 통합. 통합 에이전트가 하나의 메모리 레이아웃에 대한 원문 메모리를 읽고, 더 많은 근거가 필요할 때 대화 요약을 열며, 패턴을 추출해
MEMORY.md와memory_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을 동일한 라이브 샌드박스 세션과 함께 사용하세요.
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(...) 호출을 하나의 메모리 대화로 만들고 싶다면, 해당 호출 전반에 안정적인 식별자를 전달하세요. 메모리가 실행을 대화와 연결할 때는 다음 순서로 결정합니다.
run(...)에 전달한 경우conversationId- SDK
Session을 전달한 경우 SDKsessionID - 위 항목이 모두 없는 경우
groupId - 안정적인 식별자가 없는 경우 실행별로 생성된 ID
서로 다른 에이전트의 메모리 격리를 위한 서로 다른 레이아웃 사용
섹션 제목: “서로 다른 에이전트의 메모리 격리를 위한 서로 다른 레이아웃 사용”메모리 격리는 에이전트 이름이 아니라 MemoryLayoutConfig를 기준으로 합니다. 레이아웃과 메모리 대화 ID가 같은 에이전트는 하나의 메모리 대화와 하나의 통합된 메모리를 공유합니다. 레이아웃이 다른 에이전트는 같은 샌드박스 작업 영역을 공유하더라도 별도의 롤아웃 파일, 원문 메모리, MEMORY.md, memory_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', },});이렇게 하면 한 도메인의 분석이 다른 도메인의 메모리로 통합되는 것을 방지하고, 그 반대도 방지할 수 있습니다.