출처 https://www.youtube.com/watch?v=y6WUw2_Hhrs · 채널 LangChain · 길이 12:58 포맷 LangChain 발표자(Jake)의 제품 설명 + 라이브 데모. 앞부분은 다이어그램 슬라이드로 “에이전트 메모리”를 정의하고, 뒷부분은 LangSmith UI와 노트북 코드로 NOVA라는 금융 어시스턴트를 만들어 Engine이 트레이스에서 메모리를 고쳐 주는 과정을 시연한다. 원본 자막: 2026-06-25-langsmith-engine-agent-traces-durable-memory (raw/transcripts)

한눈에 보는 요약

  • 대부분의 에이전트는 “학습하지 않고 흔적만 남긴다.” 상호작용이 끝나면 트레이스는 저장되지만 에이전트의 행동은 그대로라, 내일 같은 상황이 오면 같은 실수를 반복한다. 목표는 트레이스 → 신호(signal) → 메모리 → 다음 실행으로 이어지는 지속 학습 루프(continual learning loop)다.
  • 에이전트 메모리는 작업 메모리(단기) + 장기 메모리로 나뉜다. 단기는 현재 실행의 대화·도구 결과·스크래치패드(실행이 끝나면 사라짐), 장기는 실행을 가로질러 남는 것으로 Semantic(아는 것) / Episodic(겪은 것) / Procedural(행동 방식) 세 갈래다. 실행 중엔 장기→작업으로 retrieve, 실행 후 의미 있는 신호는 작업→장기로 write.
  • 루프를 닫는 건 백그라운드의 “지능적 프로세스”다. 트레이스 신호를 메모리 업데이트로 자동 변환한다 — 패턴 포착 → 근본 원인 → 수정 제안 → 검증. LangSmith에서 이 역할을 하는 게 Engine(Detect → Diagnose → Fix → Evaluate)이다.
  • 메모리는 Context Hub에 산다. Engine이 고친 결과(AGENTS.md, 재사용 가능한 skill 파일, 환경별 버전)를 git 기반으로 버전 관리하는 Context Hub에 커밋하고, 다음 실행에서 에이전트가 그 컨텍스트를 다시 끌어온다 — “같은 에이전트, 더 나은 메모리.”
  • 데모: NOVA(금융 어시스턴트)를 LangChain Deep Agents로 만든다. memory_path(AGENTS.md = 핵심 메모리 프로필)와 skills_path(어휘·차트·통화 포맷 스킬)를 지정하고, StateBackend(스레드 상태 = 스크래치패드)와 CompositeBackend(/memories/에 Context Hub를 마운트해 지속 메모리, 그 밖은 임시)로 “임시는 로컬, 장기는 Context Hub”를 분리한다.
  • Engine을 붙이면 트레이스에서 이슈가 자동으로 뜬다. 코드 레포 + Context Hub 레포를 연결하고 관심 카테고리(Context and Memory, 스킬 파일 정확성 등)를 고르면, Engine이 트레이싱 프로젝트를 훑어 Agent Overview 문서(목적·트레이스 구조·도구·베이스라인·이슈 카테고리)와 이슈 보드를 만든다.
  • 실전 사례: “금지된 filler 단어로 응답을 시작한다.” “great/here’s/let me/sure”를 쓰지 말라는 규칙이 AGENTS.md에 읽기용 메모리로만 있고 시스템 프롬프트엔 주입되지 않아, 작은 모델(Claude Haiku)이 우선순위를 낮춘 게 근본 원인. 서브에이전트 프롬프트도 규칙을 재진술하지 않아 위반이 전파됐다. Engine은 few-shot 예시를 AGENTS.md에 보강 + 서브에이전트 프롬프트 수정을 제안하고, “single pane of glass”에서 바로 적용한다.

장면별 상세 설명

[00:00] 1. 에이전트에는 메모리가 필요하다 — 로그가 아니라 메모리로서의 트레이스

장면 1 — 루프 없는 "Traces as logs" vs LangSmith의 "Traces as memory"

도입 슬라이드는 같은 트레이스를 두 가지로 대비시킨다. 왼쪽 Traces as logs는 “에이전트 실행 → 트레이스”에서 끝나고 점선이 X로 끊겨 메모리가 영영 갱신되지 않는다. 오른쪽 Traces as memory는 LangSmith를 가운데 둔 원형 루프로 매 실행이 다음 실행을 개선한다.

발표의 출발점은 단호하다 — “대부분의 에이전트는 학습하지 않는다, 그저 흔적(trace)만 남긴다.” 상호작용이 끝나면 트레이스는 저장되지만 행동은 똑같아서, 내일 같은 상황이 오면 같은 실수를 또 한다. 우리가 원하는 건 에이전트의 행동이 자기 메모리에 의해 빚어지는 지속 학습 루프다: 트레이스가 신호가 되고, 신호가 메모리가 되고, 그 메모리가 다음 실행을 안내한다. 이 영상은 그 루프를 직접 만든다.

[01:08] 2. 에이전트 메모리의 형태 — 작업 메모리와 장기 메모리

장면 2 — Agent · 작업 메모리(단기) · 장기 메모리(Semantic/Episodic/Procedural)와 retrieve/write 화살표

슬라이드는 메모리를 두 구역으로 가른다. 왼쪽 작업 메모리(short-term) 는 현재 실행의 살아 있는 컨텍스트 — 대화, 도구 결과, 스크래치패드 — 이고 실행이 끝나면 비워진다. 지금 과제를 푸는 동안 일관성을 유지해 주지만, 그 자체로는 시스템의 지속 메모리가 아니다.

오른쪽 장기 메모리(long-term, persistent · versioned · reviewed) 는 실행을 가로질러 남으며 세 갈래로 본다. Semantic = 아는 것(사실, 선호, 도메인 지식, 사용자·비즈니스에 대한 안정된 정보), Episodic = 겪은 것(과거 상호작용, 예시, 결과, 이전 실행의 패턴), Procedural = 행동 방식(지시, 워크플로, 도구 사용 규칙, 스킬, 의사결정 정책). 두 층 사이의 핵심은 read/write 루프다 — 실행 중엔 유용한 장기 메모리를 작업 메모리로 retrieve 하고, 실행 후 의미 있는 것이 학습됐다면 그 신호를 장기 메모리로 write 한다. 한 줄 요약은 “단기는 행동하고(acts), 장기는 학습한다(learns).”

[02:02] 3. 루프를 닫는 “지능적 프로세스”

장면 3 — Intelligent process: Spot patterns → Find root cause → Propose updates → Validate

원하는 시스템은 사용자가 에이전트와 상호작용하며 만들어 내는 신호를 포착 → 분석 → 백그라운드에서 도는 지능적 프로세스가 그것을 지속 가능한 장기 메모리 업데이트로 변환하는 구조다. 슬라이드의 Intelligent process 카드는 그 프로세스를 네 단계로 적는다: 01 Spot patterns → 02 Find root cause → 03 Propose updates → 04 Validate (“trace signal을 메모리 업데이트로 — 자동으로”). 결국 에이전트 메모리는 세 조각으로 이뤄진다 — 메모리 스토어, 트레이스, 그리고 트레이스에서 메모리 스토어로 가는 프로세스.

[02:47] 4. LangSmith Engine — 트레이스를 개선 신호로

장면 4 — LangSmith Engine: Detect → Diagnose → Fix → Evaluate

LangSmith에서 그 지능적 프로세스의 구체형이 Engine이다(같은 4단계가 Detect → Diagnose → Fix → Evaluate로 이름만 바뀐다 — “trace signal을 committed memory로, 자동으로”). 에이전트가 사용자와 대화하면 트레이스가 쌓이고, 거기엔 유용한 증거가 담긴다 — 실패한 도구 호출, 불일치, 교정, 나쁜 출력, 올바른 행동을 따르지 않은 지점들. 하지만 트레이스만으로는 에이전트가 나아지지 않는다. 무슨 일이 있었는지 보여 줄 뿐, 다음번에 무엇을 알지를 자동으로 바꾸지는 않기 때문이다. Engine은 트레이싱 프로젝트 전반에서 반복되는 이슈를 찾아 근본 원인을 진단하고, 수정을 제안하며, 같은 문제가 재발하면 잡히도록 평가(eval) 커버리지를 더한다.

[03:08] 5. Context Hub에 커밋하고, 다음 실행에서 다시 끌어오기

장면 5 — Agent(Model·Tools·Context·Context Hub)와 "commit · next run" 화살표

Engine은 진단·제안에 그치지 않고 Context Hub(에이전트의 메모리 스토어)에 직접 업데이트를 가한다 — 버전 관리되는 컨텍스트, 즉 에이전트 markdown 파일, 재사용 가능한 skill 파일, 그리고 staging에서 production으로 옮길 수 있는 환경별 버전. 다이어그램은 Engine이 만든 신호가 화살표(commit · next run)를 타고 에이전트의 Context Hub 슬롯(AGENTS.md · SKILL.md)으로 올라가는 모습을 보여 준다. 다음 실행에서 에이전트는 갱신된 컨텍스트를 그대로 끌어온다 — 같은 에이전트, 더 나은 메모리. 이렇게 “트레이스 → 신호 → 검토된 메모리 → 다음 실행의 더 나은 행동”이 Engine과 Context Hub로 닫힌다.

[03:35] 6. 데모 시작 — Context Hub에 NOVA 레포 만들기

장면 6 — LangSmith UI에서 nova Context Hub 레포 생성(AGENTS.md)

이제 실제 화면. LangSmith에서 새 Context Hub 레포를 만들고, 타입은 Agent 레포를 고른다 — 에이전트의 핵심 메모리 프로필과 사용할 스킬을 담는 최상위 레포이기 때문이다. 이름은 NOVA(사용자의 지출·저축을 돕는 금융 어시스턴트). 여기에 NOVA가 어떻게 행동해야 하는지를 정의하는 핵심 메모리 AGENTS.md를 추가하고, 세 개의 전문 스킬 파일도 넣는다 — 어휘(vocabulary), 차트 렌더링, 통화(currency) 포맷. Context Hub는 git 기반 버전 관리·환경 관리를 주는, 에이전트 메모리를 다루기에 좋은 자리이고 나머지 LangSmith와도 연결돼 있다.

[05:25] 7. 로컬에서 Deep Agent 만들기 — memory_path · skills_path · StateBackend

장면 7 — build_nova_agent 코드: SubAgent들, create_deep_agent, SkillsMiddleware, StateBackend

NOVA를 먼저 로컬에서 빌드한다. LangChain Deep Agents 프레임워크를 쓰며, 메인 함수가 핵심이다:

MODEL = os.getenv("MODEL", "anthropic:claude-haiku-4-5-20251001")
 
def build_nova_agent(
    backend,
    *,
    memory_path: str = "/AGENTS.md",
    skills_path: str = "/skills/",
):
    spending_analyst = SubAgent(...)
    savings_advisor  = SubAgent(...)
    account_manager  = SubAgent(...)
 
    return create_deep_agent(
        model=MODEL,
        backend=backend,
        memory=[memory_path],
        middleware=[
            SkillsMiddleware[None, Any](
                backend=backend,
                sources=[skills_path],
                system_prompt=SKILLS_PROMPT_TEMPLATE,
            )
        ],
        subagents=[spending_analyst, savings_advisor, account_manager],
        checkpointer=InMemorySaver(),
    )
 
state_backend = StateBackend()
state_agent   = build_nova_agent(state_backend)

두 경로가 중요하다. memory_path 는 NOVA의 AGENTS.md 위치 — 누구인지·어떻게 행동하고 어떤 규칙을 따라야 하는지를 담은 핵심 메모리 프로필. skills_path 는 앞서 만든 세 스킬 markdown 위치. 에이전트는 파일이 어디에 저장됐는지는 신경 쓰지 않고, 그 경로에서 파일을 읽어 줄 백엔드만 있으면 된다. 처음엔 가장 단순한 StateBackend를 쓴다 — 파일이 현재 스레드의 LangGraph state 안에 사는 방식이라 로컬에서 NOVA를 돌리기엔 충분하지만, 이건 어디까지나 스크래치패드일 뿐 우리가 원하는 지속 메모리 스토어는 아니다.

[07:28] 8. 백엔드 교체 — CompositeBackend로 “임시는 로컬, 장기는 Context Hub”

장면 8 — category-vocabulary 스킬과 CompositeBackend(default=StateBackend, /memories/=Context Hub) 코드

위쪽엔 어휘 스킬이 보인다 — 도구가 아는 정규(canonical) 이름으로 매핑하는 규칙표다(takeout, doordash, uber eats → delivery, gas, uber, lyft, parking → transportation, streaming, netflix, spotify → subscription …). 규칙은 “도구 인자에는 항상 정규 이름을 쓰고, 목록에 없는 카테고리는 추측하지 말고 사용자에게 물어라” 같은 식.

NOVA에게 스크래치패드는 남기되 모든 임시 파일이 장기 메모리가 되는 건 막고 싶다. 그래서 지속 백엔드로 CompositeBackend를 쓴다 — 여러 백엔드를 하나의 파일 인터페이스 뒤에 결합한다:

# Before: 모든 게 StateBackend state 안에 있었다
state_agent = build_nova_agent(StateBackend())
 
# Now: /memories/ 는 Context Hub, 그 밖은 StateBackend 스크래치패드
nova_backend = CompositeBackend(
    default=StateBackend(),
    routes={"/memories/": context_hub_backend},
)
 
context_agent = build_nova_agent(
    nova_backend,
    memory_path="/memories/AGENTS.md",
    skills_path="/memories/skills/",
)

기본 백엔드는 StateBackend라 평범한 파일은 임시 상태(스크래치패드)로 가고, /memories/ 아래에 Context Hub를 마운트해 그 밑은 전부 지속 메모리가 된다. 원하던 분리 — 작업 파일은 로컬에, 장기 메모리는 Context Hub에 — 가 완성된다. 마지막으로 트레이싱을 설정해, NOVA를 돌릴 때마다 트레이스가 LangSmith에 기록되도록 한다(여기에 곧 Engine을 붙인다).

[08:14] 9. NOVA 프런트엔드와 첫 트레이스

장면 9 — Nova 채팅 UI(좌)와 LangSmith Tracing 탭(우)

NOVA용 간단한 프런트엔드에서 대화하며 어떤 스킬을 참조하는지 시각화하고, 그 상호작용이 만드는 트레이스를 LangSmith에서 본다. “Show me my monthly spending breakdown” 같은 질문을 던지면 NOVA는 먼저 참조하는 스킬을 보여 주고, 여러 analyst 서브에이전트와 상호작용해 답한다. 동시에 오른쪽 LangSmith 트레이싱 화면에서 그 트레이스가 채워지는 걸 볼 수 있다. 요점은 단순하다 — NOVA를 호출하자마자 NOVA의 신호가 트레이스로 즉시 캡처된다는 것.

[08:56] 10. Engine 붙이기 — 레포 연결과 “무엇이 중요한가” 선택

장면 10 — Engine 설정: 코드 레포 + Context Hub 레포 연결, 관심 카테고리 선택

LangSmith의 Engine 탭(“Find and fix your agent’s issues”)에서 설정한다. ① 에이전트 코드 레포 연결(j-broekhuizen/nova-deep-agent) — 소스 코드를 참조해 문제를 진단하고 수정안을 생성한다. ② Context Hub 레포 연결 — 지시·문서·스킬에 대한 수정 제안에 쓰인다. ③ “What matters most to you?” 에서 우선 검토할 카테고리를 고른다(Coding Agents, Cost & Tokens, Latency, Reliability and Errors, Output Quality, Tool Call Failures, Hallucinations, Context and Memory, Safety and Guardrails). 발표자는 Context and Memory를 고르고, 추가로 “skill 파일의 정확성(correctness of skill files)“을 직접 적어 넣는다.

[10:05] 11. Engine 분석 — Agent Overview 문서와 이슈 카테고리

장면 11 — 분석 완료 후 생성된 Agent Overview Document(이슈 카테고리 목록)

분석을 시작하면 Engine은 NOVA의 트레이싱 프로젝트를 훑으며 우리가 고른 영역(컨텍스트·메모리, 스킬 파일 정확성, 출력 품질 드리프트 등) 주변에서 능동적으로 이슈를 찾고, NOVA가 부진할 수 있는 지점을 single pane of glass로 보여 준다. 분석이 끝나면 먼저 Agent Overview 문서(Engine의 agents.md)가 뜬다 — NOVA가 무엇이고 목적이 무엇인지, 표준 사용 방식, 트레이스 구조, NOVA가 호출하는 것으로 관측된 도구들, 베이스라인, 이슈 카테고리, 사용자 선호가 정리돼 있다. 문서의 Issue Categories(provisional) 에는 Banned-word openers, Hallucinated financial figures, Malformed chartdata JSON, Category vocabulary violation, ASCII/markdown table charts, Silent tool-data discard, Looping on no-data queries, HYSA rate hallucination 등이 잡힌다. 이를 accept 하고 진행한다.

[10:58] 12. 이슈 보드 — “금지된 filler 단어로 응답을 시작한다”

장면 12 — 이슈 보드(6건)와 선택된 이슈 상세·진단·연결된 트레이스

Engine 에이전트가 스캔하는 동안 이슈 보드에 검토용 이슈들이 채워진다(예: “분석 질문을 거절함”, “도구 데이터가 없을 때 달러 수치를 지어냄”, “차트 블록 누락” 등 6건). 그중 하나를 깊게 본다 — “에이전트가 톤 규칙에도 불구하고 금지된 filler 단어로 사용자 응답을 연다.” NOVA의 톤은 메모리의 일부이고, 우리는 great, here's, let me, sure 같은 단어를 피하라고 AGENTS.md에 명시했다. Engine의 진단은 이렇다 — 이 규칙이 AGENTS.md를 통해 읽기용 메모리(memory=["/AGENTS.md"])로만 로드될 뿐 시스템 프롬프트에 주입되지 않아, 작은 모델(Claude Haiku)이 우선순위를 낮춘다. 게다가 서브에이전트 시스템 프롬프트도 그 규칙을 재진술하지 않아서, 합성된 최종 답변이 위반을 그대로 상속한다. Engine은 위반이 일어난 연결 트레이스(“Final opens with banned word ‘Great’” 등)까지 짚어 줘서 바로 확인할 수 있다.

[11:45] 13. 제안된 수정 — few-shot 예시 + 서브에이전트 프롬프트, 그리고 바로 적용

장면 13 — AGENTS.md 변경 diff(TONE 규칙, CORRECT/BANNED 예시)와 View in Context Hub · Apply

수정 방향은 진단과 짝이 맞는다 — 톤 규칙이 AGENTS.md에만 살고 다른 시스템 프롬프트에서 재진술되지 않았으니, 명시적 예시(few-shot)를 AGENTS.md에 보강하고 서브에이전트들의 시스템 프롬프트도 함께 고친다. AGENTS.md diff에는 TONE: Lead with the answer. Never open with Perfect/Great/Sure/Absolutely/Here's/Let me… 같은 규칙과 함께 예시가 추가된다 — CORRECT openings(substance로 시작: “5,000 goal reached. Your balance is…”, “I’ll check your spending” → “(skip entirely; just call the tool)”). 변경은 Context Hub에서 보기거나 그 자리에서 Apply로 AGENTS.md에 직접 적용할 수 있다. 즉 Engine은 (1) 프로덕션 트레이스에서 이상 행동을 잡고, (2) Context Hub를 들여다봐 NOVA가 참조하는 컨텍스트·메모리를 이해하고, (3) single pane of glass에서 바로 적용 가능한 수정을 제안한 셈이다.

[12:28] 14. 검증 — 스킬을 다시 읽고, filler 없이 답하기

장면 14 — "Reading 3 skills from Context Hub"(currency-formatting/category-vocabulary/chart-data-emission)와 Spending Analyst 호출

수정을 적용한 뒤 다른 질문(“What is my monthly spending breakdown?”)으로 확인한다. NOVA는 Context Hub에서 세 스킬을 읽고(currency-formatting, category-vocabulary, chart-data-emission) Spending Analyst 서브에이전트를 호출하며, 응답에서 filler 단어가 보이지 않고 톤이 개선됐다. 이것은 LangSmith Engine과 Context Hub로 에이전트 메모리가 신호를 만들며 지속적으로 학습·갱신하게 만드는 한 예일 뿐이다 — Engine이 에이전트의 신호를 훑어 이상해 보이는 것을 포착하고, 메모리 스토어에 대한 변경을 제안해 사용자 상호작용으로부터 계속 배우게 한다.


부록 — 직접 해 볼 때 체크리스트

  • 메모리 3분류로 정리부터. 무엇을 Semantic(사실·선호), Episodic(과거 예시·결과), Procedural(규칙·스킬·워크플로)에 넣을지 구분해 두면 장기 메모리 설계가 단순해진다.
  • AGENTS.md = 핵심 메모리 프로필, 스킬 = 별도 파일. Deep Agent에 memory_pathskills_path로 위치만 알려 주고, 저장 위치는 백엔드에 위임한다.
  • 백엔드로 임시/지속을 분리하라. CompositeBackend(default=StateBackend(), routes={"/memories/": context_hub_backend})/memories/ 아래만 Context Hub(지속), 나머지는 스크래치패드.
  • 트레이싱을 켜 둬야 Engine이 일한다. 실행마다 트레이스가 LangSmith로 가야 신호가 쌓인다.
  • “읽기용 메모리”와 “시스템 프롬프트 주입”은 다르다. 작은 모델일수록 AGENTS.md에만 있는 규칙을 deprioritize하므로, 중요한 규칙은 few-shot 예시 + 서브에이전트 프롬프트 재진술로 강화한다.
  • Engine 설정 시 “중요한 카테고리”를 명시하라. Context and Memory, 스킬 파일 정확성, 출력 품질 등 — Engine은 고른 영역을 우선해서 스캔한다.
  • 수정은 검토 후 적용. Engine 제안은 연결 트레이스로 근거를 보여 주니, Context Hub에서 확인하고 Apply 한다(버전 관리되므로 staging→production 이동도 가능).

원문 인용 모음

  • [00:00] “Most agents don’t learn, they just leave traces. An interaction ends, the trace gets stored, and the agent’s behavior stays exactly the same.”
  • [00:19] “Traces become signal, signal becomes memory, and the memory guides the next run.”
  • [01:45] “Short-term memory helps the agent act in the moment, long-term memory helps the agent improve across runs.”
  • [02:39] “Traces alone do not make the agent better. They show you what happened, but they do not automatically change what the agent knows next time.”
  • [02:44] “LangSmith Engine is the background process that turns those traces into improvement signal.”
  • [03:19] “Same agent, better memory.”
  • [05:57] “To start, I use the simplest backend, a state backend… With the state backend, files live in the agent’s LangGraph state within the current thread.”
  • [07:40] “Then I mount the Context Hub under the memories file path. So anything under memories is durable memory from the Context Hub. Anything outside of memories is a temporary scratchpad backend.”
  • [10:46] “Engine has flagged that this rule is only loaded as readable memory via our agents.md file rather than injected into the system prompt, so the smaller model, Claude, deprioritizes it.”
  • [11:27] “What we should do is reinforce the rule by adding some explicit examples, some few-shot prompting, and we’ll add that in Context Hub to our agents.md file.”
  • [12:44] “Engine will scan your agent’s signal, capture things that look anomalous, and propose changes to your agent’s memory store so that it is continuously learning from your user interactions.”

관련 노트

  • 2026-07-11-trace-claude-code-langsmith — 같은 LangSmith 생태계, Claude Code 세션을 트레이싱으로 남기는 셋업 가이드(이 노트가 다루는 “트레이스→메모리” 파이프라인의 앞 단계에 해당)