> Discover all available pages from the documentation index: https://mastra.zisheng.pro/ko/llms.txt # 작업기억 하는 동안[message history](https://mastra.zisheng.pro/ko/docs/memory/message-history)그리고[의미적 회상](https://mastra.zisheng.pro/ko/docs/memory/semantic-recall)Agent가 대화를 기억하도록 돕고, 작업 기억을 통해 상호 작용 전반에 걸쳐 사용자에 대한 지속적인 정보를 유지할 수 있습니다. 작업 Memory는 Agent의 활성 스크래치 패드입니다. 즉, 사용자나 작업에 대해 계속 사용할 수 있는 주요 정보입니다. 대화 중에 사람의 이름, 선호도 또는 기타 중요한 세부 정보를 유지할 수 있습니다. 이는 항상 관련성이 있고 Agent가 항상 사용할 수 있어야 하는 진행 중인 상태를 유지하는 데 유용합니다. [관찰 Memory](https://mastra.zisheng.pro/ko/docs/memory/observational-memory)를 사용한다면 `observationalMemory.observation.manageWorkingMemory`를 통해 OM이 Agent의 작업 Memory를 업데이트하도록 할 수 있습니다. :::tip\[📹 보기] Agent가 상호작용 전반에 걸쳐 지속적인 사용자 컨텍스트를 유지하는 방법을 알아보려면 [Mastra 작업 Memory](https://www.youtube.com/watch?v=UMy_JHLf1n8\&pp=ygUVbWFzdHJhIHdvcmtpbmcgbWVtb3J5)를 시청하세요. ::: 작업 Memory는 두 가지 다른 범위에서 지속될 수 있습니다. - **리소스 범위**(기본값): 동일한 사용자에 대한 모든 대화 스레드에서 Memory가 유지됩니다. - **스레드 범위**: 대화 스레드마다 Memory가 격리됩니다. **요구 사항:**범위 간 전환은 Agent가 다른 범위의 Memory를 볼 수 없음을 의미합니다. 스레드 범위 Memory는 리소스 범위 Memory와 완전히 분리됩니다. ## 빠른 시작 다음은 작업 Memory가 있는 Agent를 설정하는 최소한의 예입니다. ```typescript import { Agent } from '@mastra/core/agent' import { Memory } from '@mastra/memory' // Create agent with working memory enabled const agent = new Agent({ id: 'personal-assistant', name: 'PersonalAssistant', instructions: 'You are a helpful personal assistant.', model: 'openai/gpt-5.6-sol', memory: new Memory({ options: { workingMemory: { enabled: true, }, }, }), }) ``` ## 작동 원리 작업 Memory는 Agent가 지속적으로 관련 정보를 저장하기 위해 시간이 지남에 따라 업데이트할 수 있는 마크다운 텍스트 블록입니다. ## Memory 지속성 범위 작업 Memory는 두 가지 다른 범위에서 작동할 수 있으므로 대화 전반에 걸쳐 Memory가 지속되는 방식을 선택할 수 있습니다. ### 리소스 범위 Memory(기본값) 기본적으로 작업 Memory는 동일한 사용자(resourceId)에 대한 모든 대화 스레드에서 지속되므로 영구 사용자 Memory를 활성화합니다. ```typescript const memory = new Memory({ storage, options: { workingMemory: { enabled: true, scope: 'resource', // Memory persists across all user threads template: `# User Profile - **Name**: - **Location**: - **Interests**: - **Preferences**: - **Long-term Goals**: `, }, }, }) ``` **사용 사례:** - 사용자 선호도를 기억하는 개인 비서 - 고객 상황을 유지하는 고객 서비스 봇 - 학생의 진도를 추적하는 교육용 애플리케이션 ### Agent와 함께 사용 리소스 범위 Memory를 사용한다면 Memory 옵션에 `resource` 매개변수를 전달해야 합니다. ```typescript // Resource-scoped memory requires resource const response = await agent.generate('Hello!', { memory: { thread: 'conversation-123', resource: 'user-alice-456', // Same user across different threads }, }) ``` ### 스레드 범위 Memory 스레드 범위 Memory는 작업 Memory를 개별 대화 스레드로 격리합니다. 각 스레드는 자체적으로 격리된 Memory를 유지합니다. ```typescript const memory = new Memory({ storage, options: { workingMemory: { enabled: true, scope: 'thread', // Memory is isolated per thread template: `# User Profile - **Name**: - **Interests**: - **Current Goal**: `, }, }, }) ``` **사용 사례:** - 별도의 주제에 대한 다양한 대화 - 임시 또는 세션별 정보 - 각 스레드에 작업 Memory가 필요하지만 스레드가 일시적이고 서로 관련되지 않는 Workflow ## 스토리지 어댑터 지원 리소스 범위 작업 Memory에는 다음을 지원하는 특정 스토리지 어댑터가 필요합니다.`mastra_resources` table: ### 지원되는 스토리지 어댑터 - **libSQL** (`@mastra/libsql`) - **포스트그레SQL** (`@mastra/pg`) - **오라클DB** (`@mastra/oracledb`) - **업스태시** (`@mastra/upstash`) - **몽고DB** (`@mastra/mongodb`) ## 맞춤 템플릿 템플릿은 Agent에게 작업 Memory에서 추적하고 업데이트할 정보를 안내합니다. Mastra는 사용자가 템플릿을 제공하지 않을 때 기본 템플릿을 사용합니다. 가장 관련성이 높은 정보를 기억할 수 있도록 Agent 사용 사례에 대한 사용자 지정 템플릿을 정의하세요. 여러 사용자가 공유하는 스레드에 대해서는 다음을 참조하세요.[Multi-user threads](https://mastra.zisheng.pro/ko/docs/memory/multi-user-threads). 다음은 맞춤 템플릿의 예입니다. 이 예에서 Agent는 사용자가 다음 정보가 포함된 메시지를 보내는 즉시 사용자 이름, 위치, 시간대 등을 저장합니다. ```typescript const memory = new Memory({ options: { workingMemory: { enabled: true, template: ` # User Profile ## Personal info - Name: - Location: - Timezone: ## Preferences - Communication Style: [e.g., Formal, Casual] - Project Goal: - Key Deadlines: - [Deadline 1]: [Date] - [Deadline 2]: [Date] ## Session state - Last Task Discussed: - Open Questions: - [Question 1] - [Question 2] `, }, }, }) ``` ## 효과적인 템플릿 디자인 잘 구성된 템플릿은 Agent가 구문 분석하고 업데이트할 수 있도록 정보를 간단하게 유지합니다. 치료하다 보조자가 최신 상태로 유지하기를 원하는 짧은 형식의 템플릿입니다. - **짧고 명확한 레이블을 사용하세요.** 단락이나 매우 긴 제목은 피하세요. 업데이트를 쉽게 읽을 수 있고 잘릴 가능성을 줄이려면 레이블을 간결하게 유지하세요(예: `## Personal Info` 또는 `- Name:`). - **대소문자를 일관되게 사용하세요.** 일관되지 않은 대소문자(`Timezone:`과 `timezone:`)는 업데이트를 어수선하게 만들 수 있습니다. 제목과 글머리표 레이블에 제목식 대문자 표기나 소문자 표기 중 하나를 일관되게 사용하세요. - **자리표시자 텍스트를 최소화하세요.** LLM이 올바른 위치를 채울 수 있도록 `[e.g., Formal]`이나 `[Date]` 같은 힌트를 사용하세요. - **매우 긴 값은 축약하세요.** 짧은 형식만 필요하다면 법적 효력이 있는 전체 텍스트 대신 `- Name: [First name or nickname]`이나 `- Address (short):` 같은 지침을 포함하세요. - **`instructions`에 업데이트 규칙을 명시하세요.** Agent의 `instructions` 필드에서 각 섹션을 언제, 어떻게 채우거나 지울지 직접 지시할 수 있습니다. ### 대체 템플릿 스타일 몇 가지 항목만 필요한 경우 더 짧은 단일 블록을 사용하십시오. ```typescript const basicMemory = new Memory({ options: { workingMemory: { enabled: true, template: `User Facts:\n- Name:\n- Favorite Color:\n- Current Topic:`, }, }, }) ``` 좀 더 서술적인 스타일을 선호한다면 주요 사실을 짧은 단락 형식으로 저장할 수도 있습니다. ```typescript const paragraphMemory = new Memory({ options: { workingMemory: { enabled: true, template: `Important Details:\n\nKeep a short paragraph capturing the user's important facts (name, main goal, current task).`, }, }, }) ``` ## 구조화된 작업 기억 Markdown 템플릿 대신 구조화된 스키마로 작업 Memory를 정의할 수도 있습니다. 이를 통해 추적할 정확한 필드와 유형을 지정할 수 있습니다. [Standard JSON Schema](https://standardschema.dev/json-schema)([Zod](https://zod.dev/), [Valibot](https://valibot.dev/), [ArkType](https://arktype.io/) 등)를 사용할 수 있습니다. 스키마를 사용하면 Agent가 스키마와 일치하는 JSON 객체로 작업 Memory를 확인하고 업데이트합니다. **요구 사항:** `template` 또는 `schema` 중 하나만 지정해야 하며 둘 다 지정할 수는 없습니다. ### 예: 스키마 기반 작업 Memory ```typescript import { z } from 'zod' import { Memory } from '@mastra/memory' const userProfileSchema = z.object({ name: z.string().optional(), location: z.string().optional(), timezone: z.string().optional(), preferences: z .object({ communicationStyle: z.string().optional(), projectGoal: z.string().optional(), deadlines: z.array(z.string()).optional(), }) .optional(), }) const memory = new Memory({ options: { workingMemory: { enabled: true, schema: userProfileSchema, // template: ... (do not set) }, }, }) ``` 스키마가 제공되면 Agent는 작업 Memory를 JSON 개체로 받습니다. 예를 들어: ```json { "name": "Sam", "location": "Berlin", "timezone": "CET", "preferences": { "communicationStyle": "Formal", "projectGoal": "Launch MVP", "deadlines": ["2025-07-01"] } } ``` ### 스키마 기반 Memory에 대한 의미 체계 병합 스키마 기반 작업 Memory는 **병합 의미 체계**를 사용합니다. 즉, Agent는 추가하거나 업데이트할 필드만 포함하면 됩니다. 기존 필드는 자동으로 보존됩니다. - **객체 필드는 깊이 병합됩니다.** 제공된 필드만 업데이트되고 나머지는 변경되지 않은 채 유지됩니다. - **필드를 삭제하려면 `null`로 설정하세요.** 이렇게 하면 Memory에서 해당 필드가 명시적으로 제거됩니다. - **배열은 완전히 교체됩니다.** 배열 필드를 제공하면 기존 배열을 대체합니다. 배열은 요소별로 병합되지 않습니다. ## 템플릿과 스키마 중에서 선택 - Agent가 사용자 프로필이나 스크래치패드 같은 자유 형식의 텍스트 블록으로 Memory를 유지하게 하려면 **template**(Markdown)을 사용하세요. 템플릿은 **교체 의미 체계**를 사용하므로 Agent가 업데이트할 때마다 전체 Memory 콘텐츠를 제공해야 합니다. - JSON으로 검증하고 프로그래밍 방식으로 접근할 수 있는 구조화된 타입 안전 데이터가 필요하다면 **schema**를 사용하세요. `workingMemory.schema` 필드는 `PublicSchema`와 호환되는 모든 스키마(Zod v3, Zod v4, JSON Schema 또는 이미 표준화된 스키마 포함)를 허용합니다. 스키마는 **병합 의미 체계**를 사용하므로 Agent는 업데이트할 필드만 제공하고 기존 필드는 보존됩니다. - 한 번에 하나의 모드만 활성화할 수 있습니다. `template`과 `schema`를 모두 설정하는 것은 지원되지 않습니다. ## 예: 다단계 보존 다음은 짧은 사용자 대화에서 `User Profile` 템플릿이 업데이트되는 방식을 간략히 보여 줍니다. ```nohighlight # User Profile ## Personal info - Name: - Location: - Timezone: --- After user says "My name is **Sam** and I'm from **Berlin**" --- # User Profile - Name: Sam - Location: Berlin - Timezone: --- After user adds "By the way I'm normally in **CET**" --- # User Profile - Name: Sam - Location: Berlin - Timezone: CET ``` 이제 `Sam` 또는 `Berlin`이 작업 Memory에 저장되었으므로 Agent는 나중에 다시 정보를 요청하지 않고 응답에서 이를 참조할 수 있습니다. Agent가 작업 Memory를 예상대로 업데이트하지 않는다면 Agent의 `instructions` 설정에 이 템플릿을 _사용하는 방법_과 _사용할 시점_에 관한 시스템 지침을 추가할 수 있습니다. ## 초기 작업 Memory 설정 Agent는 일반적으로 `updateWorkingMemory` Tool을 통해 작업 Memory를 업데이트하지만, 스레드를 생성하거나 업데이트할 때 초기 작업 Memory를 프로그래밍 방식으로 설정할 수도 있습니다. 매 요청에 전달하지 않고도 Agent가 사용할 수 있도록 사용자 데이터(이름, 선호 사항 또는 기타 정보)를 주입할 때 유용합니다. ### 스레드 메타데이터를 통해 작업 Memory 설정 스레드 생성 시 메타데이터를 통해 초기 작업 Memory를 제공할 수 있습니다.`workingMemory` key: ```typescript // Create a thread with initial working memory const thread = await memory.createThread({ threadId: 'thread-123', resourceId: 'user-456', title: 'Medical Consultation', metadata: { workingMemory: `# Patient Profile - Name: John Doe - Blood Type: O+ - Allergies: Penicillin - Current Medications: None - Medical History: Hypertension (controlled) `, }, }) // The agent will now have access to this information in all messages await agent.generate("What's my blood type?", { memory: { thread: thread.id, resource: 'user-456', }, }) // Response: "Your blood type is O+." ``` ### 프로그래밍 방식으로 작업 Memory 업데이트 기존 스레드의 작업 Memory를 업데이트할 수도 있습니다. ```typescript // Update thread metadata to add/modify working memory await memory.updateThread({ id: 'thread-123', title: thread.title, metadata: { ...thread.metadata, workingMemory: `# Patient Profile - Name: John Doe - Blood Type: O+ - Allergies: Penicillin, Ibuprofen // Updated - Current Medications: Lisinopril 10mg daily // Added - Medical History: Hypertension (controlled) `, }, }) ``` ### 직접 Memory 업데이트 또는`updateWorkingMemory` method directly: ```typescript await memory.updateWorkingMemory({ threadId: 'thread-123', resourceId: 'user-456', // Required for resource-scoped memory workingMemory: 'Updated memory content...', }) ``` ## 읽기 전용 작업 Memory 일부 시나리오에서는 Agent가 작업 Memory 데이터를 수정하지 않고도 작업 Memory 데이터에 액세스할 수 있기를 원할 수 있습니다. 이는 다음과 같은 경우에 유용합니다. - **라우팅 Agent**컨텍스트가 필요하지만 사용자 프로필을 업데이트해서는 안 됩니다. - **서브 Agent**Memory를 참조해야 하지만 소유하지는 않는 다중 Agent 시스템에서 읽기 전용 모드를 활성화하려면 Memory 옵션에서 `readOnly: true`를 설정하세요. ```typescript const response = await agent.generate('What do you know about me?', { memory: { thread: 'conversation-123', resource: 'user-alice-456', options: { readOnly: true, // Working memory is provided but cannot be updated }, }, }) ``` ## 상태 신호 선택(실험적) 기본적으로 작업 Memory는 시스템 메시지의 일부로 Model에 전달됩니다. `useStateSignals: true`를 설정하면 대신 [상태 신호](https://mastra.zisheng.pro/ko/docs/long-running-agents/signals)로 제공할 수 있습니다. ```typescript const memory = new Memory({ storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db' }), options: { workingMemory: { enabled: true, template: '# User\n- name:\n- location:', useStateSignals: true, // experimental: deliver as state signal }, }, }) ``` 변경사항: - **스토리지는 동일합니다.** 동일한 리소스/스레드의 `workingMemory` 필드를 읽고 씁니다. - **Tool은 형태가 같지만 새 이름으로 표시됩니다.** 쓰기는 여전히 동일한 기본 Tool을 통해 이루어집니다. 이 경로에서는 `updateWorkingMemory` 대신 `setWorkingMemory`로 등록됩니다. 이름을 변경하면 기존 제거 필터가 Tool 호출 부분을 제거하지 않으므로 일반 감사 추적으로 유지되고 다음 Model 단계에서 새 값을 자동으로 선택합니다. - **전달 방식만 변경됩니다.** 시스템 Prompt에 포함하는 대신 `Memory`가 현재 작업 Memory를 `stateId: 'working-memory'`인 `state` 신호로 내보내는 `WorkingMemoryStateProcessor`를 자동 연결합니다. 스레드 범위 추적 메타데이터, 동일한 스냅샷을 한 번만 내보내는 `cacheKey` 중복 제거, 오래된 스냅샷이 창 밖으로 밀려날 때 수행되는 `contextWindow.hasSnapshot` 재삽입 등 표준 상태 신호의 이점을 제공합니다. 기본값(`useStateSignals: false`)은 기존 시스템 메시지 동작을 변경하지 않고 유지합니다. 템플릿 작업 Memory `version: 'vnext'`에서는 `useStateSignals`가 지원되지 않습니다. ## 예 - [템플릿을 사용한 작업 Memory](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-template) - [스키마를 사용한 작업 Memory](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-schema) - [리소스별 작업 Memory](https://github.com/mastra-ai/mastra/tree/main/examples/memory-per-resource-example): 리소스 범위 Memory 지속성을 보여주는 완전한 예