
Agent Builder의 메모리를 구축한 방법 | 에이전트에 메모리 구축하기
요약
LangSmith Agent Builder는 특정 작업을 반복 수행하는 노코드 에이전트 구축 도구로, 사용자 경험을 극대화하기 위해 메모리 시스템을 핵심 요소로 설계했습니다. 메모리는 절차적, 의미적, 일화적 범주로 정의되며, 모델이 파일 시스템을 잘 다룬다는 점을 활용해 파일 세트 형태로 구현되었습니다.
핵심 포인트
- LangSmith Agent Builder는 특정 워크플로 자동화를 위한 노코드 에이전트 빌더임
- 범용 에이전트와 달리 반복적인 작업을 수행하므로 세션 간 지식 전달을 위한 메모리가 필수적임
- 메모리는 COALA 논문의 정의에 따라 절차적, 의미적, 일화적 메모리로 구분됨
- 에이전트가 메모리를 쉽게 읽고 수정할 수 있도록 파일 시스템 기반의 파일 세트 방식을 채택함
핵심 요약 (Key Takeaways)
Agent Builder의 핵심 요소는 메모리 시스템입니다. 이 글에서는 메모리 시스템을 우선순위에 둔 이유, 이를 구축한 기술적 세부 사항, 메모리 시스템을 구축하며 얻은 교훈, 메모리 시스템이 가능하게 하는 것들에 대해 다루고 향후 작업에 대해 논의합니다.
우리는 이번 주에 에이전트를 구축할 수 있는 노코드 (no-code) 방식인 LangSmith Agent Builder를 출시했습니다. Agent Builder의 핵심 부분은 메모리 시스템입니다. 이 글에서는 메모리 시스템을 우선순위에 둔 이유, 이를 구축한 기술적 세부 사항, 메모리 시스템을 구축하며 얻은 교훈, 메모리 시스템이 가능하게 하는 것들에 대해 다루고 향후 작업에 대해 논의합니다.
LangSmith Agent Builder란 무엇인가
LangSmith Agent Builder는 노코드 (no-code) 에이전트 빌더입니다. 이는 Deep Agents 하네스 (harness)를 기반으로 구축되었습니다. 기술적 지식이 적은 시민 개발자 (citizen developers)를 대상으로 하는 호스팅 웹 솔루션입니다. LangSmith Agent Builder에서 빌더들은 특정 워크플로 (workflow) 또는 일과의 일부를 자동화하기 위한 에이전트를 생성하게 됩니다. 예시로는 이메일 어시스턴트, 문서 도우미 등이 있습니다.
초기에 우리는 플랫폼의 일부로서 메모리를 우선시하기로 의식적인 선택을 했습니다. 이는 당연한 선택은 아니었습니다. 대부분의 AI 제품은 초기에는 어떤 형태의 메모리도 없이 출시되며, 메모리를 추가하더라도 일부가 기대하는 것처럼 제품을 완전히 변화시키지는 못했습니다. 우리가 이를 우선시한 이유는 사용자들의 사용 패턴 때문이었습니다.
ChatGPT나 Claude, 또는 Cursor와 달리, LangSmith Agent Builder는 범용 에이전트(general purpose agent)가 아닙니다. 오히려 빌더들이 특정 작업(particular tasks)을 위해 에이전트를 맞춤 설정할 수 있도록 특별히 설계되었습니다. 범용 에이전트의 경우, 서로 완전히 무관할 수 있는 매우 다양한 작업들을 수행하기 때문에, 에이전트와의 한 세션에서 얻은 학습 내용이 다음 세션에는 관련이 없을 수도 있습니다. 반면 LangSmith 에이전트가 작업을 수행할 때는 동일한 작업을 반복해서 수행합니다. 따라서 한 세션에서의 교훈이 다음 세션으로 전달되는 비율이 훨씬 높습니다. 사실, 메모리(memory)가 존재하지 않는다면 그것은 나쁜 사용자 경험(user experience)이 될 것입니다. 이는 서로 다른 세션에서 에이전트에게 같은 말을 계속해서 반복해야 함을 의미하기 때문입니다.
LangSmith 에이전트에게 메모리가 정확히 무엇을 의미하는지 고민할 때, 우리는 메모리에 대한 제3자의 정의를 참고했습니다. COALA 논문은 에이전트의 메모리를 세 가지 범주로 정의합니다:
절차적 메모리 (Procedural): 에이전트의 행동을 결정하기 위해 작업 메모리(working memory)에 적용될 수 있는 규칙 세트
의미적 메모리 (Semantic): 세상에 대한 사실들
일화적 메모리 (Episodic): 에이전트의 과거 행동 시퀀스
메모리 시스템을 구축한 방법
우리는 Agent Builder에서 메모리를 파일 세트로 표현합니다. 이는 모델들이 파일 시스템(filesystem)을 사용하는 데 능숙하다는 사실을 활용하기 위한 의도적인 선택입니다. 이러한 방식을 통해, 우리는 에이전트에게 특화된 도구(specialized tools)를 제공할 필요 없이, 단순히 파일 시스템에 대한 접근 권한을 부여함으로써 에이전트가 자신의 메모리를 쉽게 읽고 수정할 수 있도록 할 수 있었습니다!
가능한 경우, 우리는 업계 표준을 사용하려고 노력합니다. 우리는 에이전트의 핵심 지침 세트(core instruction set)를 정의하기 위해 AGENTS.md를 사용합니다. 또한 에이전트 스킬(agent skills)을 사용하여 특정 작업에 대한 에이전트의 특별한 전문 지침을 제공합니다. 서브 에이전트(subagent)에 대한 표준은 없지만, 우리는 Claude Code와 유사한 형식을 사용합니다. MCP 접근을 위해 우리는 커스텀 tools.json 파일을 사용합니다. 우리가 표준 mcp.json이 아닌 커스텀 tools.json 파일을 사용하는 이유는, 컨텍스트 오버플로(context overflow)를 방지하기 위해 사용자가 MCP 서버에 있는 도구 중 일부만 에이전트에게 제공할 수 있도록 하기 위함입니다.
우리는 실제로 이 파일들을 저장하기 위해 실제 파일 시스템 (filesystem)을 사용하지 않습니다. 대신, 파일들을 Postgres에 저장하고 에이전트에게 파일 시스템의 형태로 노출합니다. 이렇게 하는 이유는 LLM (Large Language Models)이 파일 시스템을 다루는 데 매우 뛰어나지만, 인프라 관점에서는 데이터베이스를 사용하는 것이 더 쉽고 효율적이기 때문입니다. 이 "가상 파일 시스템 (virtual filesystem)"은 DeepAgents에서 기본적으로 지원하며, 완전히 플러그인 방식으로 교체 가능하므로 원하는 어떤 저장 계층 (S3, MySQL 등)이라도 가져올 수 있습니다.
또한 사용자와 에이전트 스스로가 에이전트의 메모리 폴더에 다른 파일들을 작성할 수 있도록 허용합니다. 이 파일들은 에이전트가 실행되는 동안 참조할 수 있는 임의의 지식 (arbitrary knowledge)을 포함할 수 있습니다. 에이전트는 작업하는 동안, 즉 "핫 패스 (hot path)" 내에서 이러한 파일들을 편집하게 됩니다.
코드나 도메인 특화 언어 (DSL, Domain Specific Language) 없이도 복잡한 에이전트를 구축할 수 있는 이유는 내부적으로 DeepAgents와 같은 범용 에이전트 하네스 (agent harness)를 사용하기 때문입니다. DeepAgents는 많은 복잡한 컨텍스트 엔지니어링 (context engineering, 예: 요약, 도구 호출 오프로딩, 계획 등)을 추상화하여, 사용자가 비교적 간단한 설정만으로 에이전트를 제어할 수 있게 해줍니다.
이 파일들은 COALA 논문에서 정의된 메모리 유형과 잘 매칭됩니다. 핵심 에이전트 지침 (agent directive)을 구동하는 절차적 메모리 (Procedural memory)는 AGENTS.md와 tools.json입니다. 의미론적 메모리 (Semantic memory)는 에이전트 기술 및 기타 지식 파일들입니다. 유일하게 누락된 메모리 유형은 일화적 메모리 (episodic memory)인데, 우리는 이러한 유형의 에이전트에게는 일화적 메모리가 다른 두 가지만큼 중요하지 않다고 판단했습니다.
파일 시스템 내 에이전트 메모리의 모습
우리가 내부적으로 사용해 온 실제 에이전트인 LangSmith Agent Builder 기반의 LinkedIn 리크루터(recruiter) 사례를 살펴볼 수 있습니다.
- AGENTS.md: 핵심 에이전트 지침을 정의합니다.
subagents/: 단 하나의 서브 에이전트(subagent)인linkedin_search_worker를 정의합니다.linkedin_search_worker: 메인 에이전트가 검색에 대해 보정(calibrated)된 후, 약 50명의 후보자를 소싱하기 위해 이 에이전트를 실행합니다.tools.json
: LinkedIn 검색 도구에 접근할 수 있는 MCP 서버를 정의합니다. 현재 메모리에는 서로 다른 후보자들을 위한 JD(Job Descriptions, 직무 기술서)를 나타내는 3개의 다른 파일이 더 있습니다. 우리가 이러한 검색 작업을 위해 에이전트와 함께 작업함에 따라, 에이전트는 해당 JD들을 업데이트하고 유지 관리해 왔습니다.
메모리 편집이 작동하는 방식: 구체적인 예시
메모리가 어떻게 작동하는지 더 구체적으로 이해하기 위해, 설명적인 예시를 살펴보겠습니다.
시작:
당신은 다음과 같은 간단한 AGENTS.md로 시작합니다:
회의록을 요약하세요.
1주 차:
에이전트가 문단 형태의 요약을 생성합니다. 당신은 이를 수정합니다: "문단 대신 불렛 포인트(bullet points)를 사용하세요." 에이전트는 AGENTS.md를 다음과 같이 편집합니다:
# Formatting Preferences (서식 선호도)
사용자는 문단이 아닌 불렛 포인트를 사용하여 요약하는 것을 선호함.
2주 차:
당신은 에이전트에게 다른 회의를 요약해 달라고 요청합니다. 에이전트는 자신의 메모리를 읽고 자동으로 불렛 포인트를 사용합니다. 별도의 리마인더(reminder)가 필요 없습니다. 이 세션 중에 당신은 다음과 같이 요청합니다: "마지막에 실행 항목(action items)을 별도로 추출하세요." 메모리가 업데이트됩니다:
# Formatting Preferences (서식 선호도)
사용자는 문단이 아닌 불렛 포인트를 사용하여 요약하는 것을 선호함.
마지막에 별도의 섹션으로 실행 항목(action items)을 추출할 것.
4주 차:
두 가지 패턴이 모두 자동으로 적용됩니다. 당신은 새로운 예외 케이스(edge cases)가 나타남에 따라 개선 사항을 계속해서 추가합니다.
3개월 차:
에이전트의 메모리에는 다음 내용이 포함됩니다:
- 다양한 문서 유형에 대한 서식 선호도
- 도메인 특화 용어 (Domain-specific terminology)
- "실행 항목 (action items)", "결정 사항 (decisions)", "논의 사항 (discussion points)" 간의 구분
- 빈번한 회의 참석자의 이름과 역할
- 회의 유형 처리 (엔지니어링 vs. 기획 vs. 고객)
- 사용을 통해 축적된 예외 케이스 수정 사항
메모리 파일은 다음과 같은 모습일 수 있습니다:
# Meeting Summary Preferences (회의 요약 선호도)
Format (서식)
- 문단 대신 불렛 포인트 사용
- 마지막에 별도의 섹션으로 실행 항목(action items) 추출
- 결정 사항에는 과거 시제 사용
- 상단에 타임스탬프(timestamp) 포함
Meeting Types (회의 유형)
-
엔지니어링 회의: 기술적 결정 및 근거 강조
-
기획 회의: 우선순위 및 타임라인 강조
-
고객 회의: 민감한 정보 삭제(redact)
-
짧은 회의 (<10분): 핵심 사항만 기록
인원 (People)
-
Sarah Chen (Engineering Lead) - 기술적 세부 사항에 집중
-
Mike Rodriguez (PM) - 비즈니스 영향에 집중
...
AGENTS.md는 사전 문서화가 아닌, 수정을 통해 스스로 구축되었습니다. 사용자가 AGENTS.md를 수동으로 변경하는 일 없이, 우리는 반복적인 과정을 통해 적절하게 상세한 에이전트 명세(agent specification)에 도달했습니다.
이 메모리 시스템을 구축하며 얻은 교훈 (Learnings from building this memory system)
우리는 이 과정에서 몇 가지 교훈을 얻었습니다.
가장 어려운 부분은 프롬프팅 (Prompting) 입니다
무언가를 기억할 수 있는 에이전트를 구축하는 데 있어 가장 어려운 부분은 프롬프팅 (Prompting)입니다. 에이전트가 제대로 작동하지 않았던 거의 모든 사례에서 해결책은 프롬프트 (prompt)를 개선하는 것이었습니다. 이 방식으로 해결된 문제의 예시는 다음과 같습니다:
- 에이전트가 기억해야 할 때 기억하지 못함
- 에이전트가 기억하지 말아야 할 때 기억함
- 에이전트가 스킬 (skills) 대신 AGENTS.md에 너무 많은 내용을 작성함
- 에이전트가 스킬 파일의 올바른 형식을 알지 못함
- … 그 외 훨씬 더 많은 사례
우리는 팀의 상당 부분에 해당하는 인력을 메모리를 위한 프롬프팅 (prompting) 작업에 전담 배치했습니다.
파일 유형 검증 (Validate file types)
여러 파일은 준수해야 하는 특정 스키마 (schema)를 가지고 있습니다 (tools.json은 유효한 MCP 서버를 포함해야 하고, skills는 적절한 프론트매터 (frontmatter)를 가져야 하는 등). 우리는 Agent Builder가 때때로 이를 잊어버려 결과적으로 유효하지 않은 파일을 생성하는 것을 목격했습니다. 우리는 이러한 커스텀 형태 (custom shapes)를 명시적으로 검증하는 단계를 추가했으며, 검증에 실패할 경우 파일을 커밋 (commit)하는 대신 모든 에러를 LLM에 다시 전달하도록 했습니다.
에이전트는 파일에 내용을 추가하는 데는 능숙했지만, 압축 (compact)하지는 못했습니다
에이전트들은 작업하면서 자신의 메모리를 편집했습니다. 파일에 특정 내용을 추가하는 데는 꽤 능숙했습니다. 하지만 한 가지 잘하지 못했던 점은 학습 내용을 언제 압축 (compact)해야 하는지 깨닫는 것이었습니다. 예를 들어, 제 이메일 어시스턴트는 모든 콜드 아웃리치 (cold outreach)를 무시하도록 스스로를 업데이트하는 대신, 특정 벤더(vendor)들을 무시해야 한다는 목록을 나열하기 시작했습니다.
최종 사용자로서 명시적 프롬프팅 (Explicit prompting)은 여전히 때때로 유용합니다
에이전트가 작업하면서 자신의 메모리를 업데이트할 수 있음에도 불구하고, (최종 사용자로서) 에이전트에게 메모리를 관리하도록 명시적으로 프롬프트를 주는 것이 유용하다고 판단되는 몇 가지 사례가 여전히 있었습니다. 그러한 사례 중 하나는 작업이 끝날 때 대화를 되돌아보고(reflect) 놓쳤을지도 모르는 사항들을 위해 메모리를 업데이트하도록 하는 것이었습니다. 또 다른 사례는 에이전트가 특정 사례들은 기억하지만 일반화(generalizing)하지 못하는 경우를 해결하기 위해, 메모리를 압축(compact)하도록 프롬프트를 주는 것이었습니다.
인간 참여형 (Human-in-the-loop)
우리는 메모리에 대한 모든 수정을 인간 참여형 (human-in-the-loop) 방식으로 진행했습니다. 즉, 업데이트하기 전에 명시적인 인간의 승인을 요구합니다. 이는 주로 프롬프트 인젝션 (prompt injection)의 잠재적인 공격 벡터 (attack vector)를 최소화하기 위해 수행되었습니다. 다만, 이러한 점을 크게 걱정하지 않는 경우를 위해 사용자가 이를 끌 수 있는 방법 ("yolo mode")을 제공하고 있습니다.
이것이 가능하게 하는 것
더 나은 제품 경험 외에도, 메모리를 이런 방식으로 표현하는 것은 여러 가지를 가능하게 합니다.
노코드 (No-code) 경험
노코드 빌더의 문제점 중 하나는 복잡성이 증가함에 따라 확장이 잘 되지 않는 생소한 DSL (Domain Specific Language)을 배워야 한다는 점입니다. 에이전트를 마크다운 (markdown) 및 JSON 파일로 표현함으로써, 에이전트는 이제 (a) 기술적 지식이 적은 대부분의 사람들에게 친숙하고, (b) 더 확장 가능한 형식을 갖추게 되었습니다.
더 나은 에이전트 구축
메모리는 실제로 더 나은 에이전트 구축 경험을 가능하게 합니다. 에이전트 구축은 매우 반복적 (iterative)입니다. 그 주된 이유는 직접 시도해 보기 전까지는 에이전트가 무엇을 할지 알 수 없기 때문입니다. 메모리는 반복 작업을 더 쉽게 만듭니다. 매번 에이전트 설정을 수동으로 업데이트하는 대신, 자연어 (natural language)로 피드백을 주기만 하면 에이전트가 스스로 업데이트하기 때문입니다.
이식 가능한 에이전트 (Portable agents)
파일은 매우 이식성이 높습니다! 덕분에 Agent Builder에서 구축한 에이전트를 (동일한 파일 컨벤션(file conventions)을 사용하는 한) 다른 하네스(harnesses)로 쉽게 이식할 수 있습니다. 저희는 바로 이러한 이유로 가능한 한 많은 표준 컨벤션을 사용하려고 노력했습니다. 예를 들어, Agent Builder에서 구축한 에이전트를 Deep Agents CLI에서 쉽게 사용할 수 있도록 만들고 싶습니다. 또는 Claude Code나 OpenCode와 같은 완전히 다른 에이전트 하네스에서도 사용할 수 있기를 바랍니다.
향후 방향 (Future directions)
출시 전까지 시간이나 충분한 확신이 부족하여 구현하지 못했던, 개선하고 싶은 많은 메모리 기능들이 있습니다.
에피소드 메모리 (Episodic memory)
Agent Builder에 누락된 단 하나의 COALA 메모리 유형은 에피소드 메모리(episodic memory), 즉 에이전트의 과거 행동 시퀀스입니다. 저희는 이전 대화들을 에이전트가 상호작용할 수 있는 파일 시스템의 파일로 노출함으로써 이를 구현할 계획입니다.
백그라운드 메모리 프로세스 (Background memory processes)
현재 모든 메모리는 "핫 패스(hot path)", 즉 에이전트가 실행되는 동안 업데이트됩니다. 저희는 모든 대화를 되돌아보고 메모리를 업데이트하기 위해 백그라운드에서 실행되는 프로세스(아마도 하루에 한 번 정도 실행되는 cron job 형태)를 추가하고 싶습니다. 이를 통해 에이전트가 그 순간에 인식하지 못한 항목들을 포착할 수 있을 것이며, 특히 특정 학습 내용을 일반화하는 데 유용할 것이라고 생각합니다.
/remember
에이전트에게 대화를 되돌아보고 메모리를 업데이트하도록 프롬프트를 줄 수 있도록 명시적인 /remember 명령어를 노출하고 싶습니다. 저희는 가끔 이 작업을 수행했을 때 큰 이점을 얻는 것을 발견했으며, 따라서 이를 더 쉽고 권장되는 방식으로 만들고자 합니다.
시맨틱 검색 (Semantic search)
glob과 grep을 사용하여 메모리를 검색할 수 있는 것은 훌륭한 시작점이지만, 에이전트가 자신의 메모리에 대해 시맨틱 검색(semantic search)을 수행할 수 있게 함으로써 이점을 얻을 수 있는 상황들이 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 LangChain Blog의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기