k
korAI
고급 전체
🔥 고급2026-04-1511분

장기 메모리 아키텍처 — 에이전트가 어제 일을 기억하게 만들기

매 세션 처음부터 설명하는 에이전트는 가짜다. 요약·팩트 추출·벡터 인덱스 3단 메모리 설계.

agentmemory

세 층위의 메모리

| 층위 | 저장소 | 용도 | 주기 | |-----|-------|------|------| | Working | 현재 컨텍스트 창 | 진행 중 대화 | 세션 | | Episodic | SQL 로그 + 요약 | 과거 대화 기록 | 며칠~몇 달 | | Semantic | 벡터 DB | 추출된 팩트 | 영구 |

워킹 → 에피소딕 압축

세션이 끝나거나 N턴을 넘으면 Haiku가 요약을 만들어 저장.

async function summarizeSession(turns: Turn[]): Promise<string> {
  const msg = await client.messages.create({
    model: "claude-haiku-4-5",
    max_tokens: 400,
    messages: [{
      role: "user",
      content: `아래 대화를 3~5문장으로 요약. 사용자 선호, 언급된 고유명사, 미해결 과제는 반드시 포함.\n\n${turns.map(t => `${t.role}: ${t.content}`).join("\n")}`,
    }],
  })
  return (msg.content[0] as any).text
}

에피소딕 → 시맨틱 팩트 추출

요약에서 재사용 가능한 사실만 뽑아 영구 저장.

const FACTS_TOOL = {
  name: "save_facts",
  input_schema: {
    type: "object",
    properties: {
      facts: {
        type: "array",
        items: {
          type: "object",
          properties: {
            subject:   { type: "string" },  // 예: "user"
            predicate: { type: "string" },  // 예: "prefers"
            object:    { type: "string" },  // 예: "dark mode"
            confidence:{ type: "number" },
          },
          required: ["subject", "predicate", "object", "confidence"],
        },
      },
    },
    required: ["facts"],
  },
}

const msg = await client.messages.create({
  model: "claude-sonnet-4-6",
  tools: [FACTS_TOOL],
  tool_choice: { type: "tool", name: "save_facts" },
  max_tokens: 1024,
  messages: [{
    role: "user",
    content: `이 대화 요약에서 재사용 가능한 사실만 추출:\n\n${summary}`,
  }],
})

const facts = (msg.content.find(c => c.type === "tool_use") as any).input.facts
for (const f of facts) {
  await vectorDB.upsert({
    id: hashOf(f),
    text: `${f.subject} ${f.predicate} ${f.object}`,
    metadata: f,
  })
}

조회: 관련 기억 소환

새 세션 시작 시 최근 요약 3개 + 현재 쿼리로 벡터 검색한 팩트 상위 10개를 system 프롬프트에 주입.

const context = {
  recent_summaries: await db.query("select summary from sessions where user_id = $1 order by created_at desc limit 3", [userId]),
  relevant_facts: await vectorDB.search({ query: userMessage, topK: 10, filter: { subject: "user" } }),
}

메모리 위생

  1. 충돌 해결 — 같은 subject+predicate이면 최신이 승리 (또는 confidence 가중)
  2. 망각 — 오래되고 확신 낮은 팩트는 주기적으로 삭제
  3. 사용자 열람 — "내가 너에 대해 아는 것" 페이지로 투명성 제공
  4. 민감정보 필터 — 팩트 추출 단계에서 PII 거르기

체크리스트

  • [ ] 세션 요약 자동화
  • [ ] 팩트는 tool use로 구조화
  • [ ] 벡터 DB에 metadata 저장
  • [ ] 충돌 해결 로직
  • [ ] 사용자가 기억 열람/삭제 가능