에이전트 메모리
메모리를 사용하면 이후 샌드박스 에이전트 실행에서 이전 실행으로부터 학습할 수 있습니다. 이는 메시지 기록을 저장하는 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.6-sol', 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.6-sol', 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', },});이렇게 하면 한 도메인의 분석이 다른 도메인의 메모리로 통합되는 것을 방지하며, 그 반대의 경우도 마찬가지입니다.