
Scarwarden 구축하기: Alibaba Cloud에서 8일 만에 만든 AI 에이전트용 감사 가능한 메모리 엔진
요약
AI 에이전트의 블랙박스 메모리 문제를 해결하기 위해 감사 가능한 오픈 소스 메모리 엔진인 Scarwarden을 소개합니다. SQLite 기반의 에피소드 원장과 Qwen 모델을 활용한 플레이북 압축을 통해 에이전트의 결정 과정을 추적하고 재현할 수 있게 설계되었습니다.
핵심 포인트
- 에이전트의 결정 근거를 인용할 수 있는 감사 가능한 메모리 엔진 구축
- SQLite를 활용한 추가 전용(append-only) 에피소드 원장 설계
- Qwen 모델을 이용해 경험을 규칙으로 압축하는 플레이북 방식 도입
- 벡터 검색 대신 결정론적 회상 방식을 사용하여 설명 가능성 확보
저는 무언가를 출시할 때 한 가지 단순한 규칙을 따릅니다. 검증할 수 없는 것은 아무것도 믿지 마십시오. AI 에이전트들은 이 규칙을 끊임없이 어깁니다. 그들은 당신이 조사할 수 없는 "메모리 (memory)"를 바탕으로 행동하며, 왜 그런 결정을 내렸는지 물어도 답을 내놓지 못합니다.
그래서 Qwen Cloud와 함께하는 Global AI Hackathon Series에서 MemoryAgent 트랙이 열렸을 때, 저는 무엇을 만들고 싶은지 바로 알았습니다. 더 큰 메모리가 아니라, 감사 가능한 (auditable) 메모리를 만들고 싶었습니다.
영구 인턴 문제 (The permanent intern problem)
제가 배포한 모든 에이전트는 영구 인턴과 같습니다. 한 세션 동안은 매우 똑똑하지만, 자정이 되면 기억 상실증에 걸립니다. 당신은 매일 인턴 세금 (intern tax)을 지불합니다. 다시 설명해야 하는 컨텍스트 (context), 반복되는 실수, 그리고 증발해 버리는 수정 사항들 말입니다. 그리고 "메모리"를 약속하는 도구들은 종종 상황을 더 악화시키는데, 그들의 메모리가 블랙박스 (black box)이기 때문입니다. 벡터 저장소 (vector store)가 무언가를 검색하고 에이전트가 그것을 "기억한다"고 주장하지만, 왜 그런 결정을 내렸는지 물으면 보여줄 수 있는 것이 아무것도 없습니다. 출처가 없는 결과물뿐입니다.
Scarwarden은 에이전트가 따르는 모든 규칙이 그것을 가르쳐준 정확한 경험을 인용하는 오픈 소스 메모리 엔진입니다. 감사할 수 있는 메모리가 신뢰할 수 있는 메모리입니다.
저장소: https://github.com/azaniansky-design/scarwarden
글을 쓰기에 앞서 2분짜리 데모를 먼저 보여드립니다. 이 포스트의 나머지 내용은 이것이 어떻게 구축되었는지에 대한 것입니다.
설계 전략: 출처 (provenance)가 벡터 (vectors)를 이긴다
메모리 트랙에서 흔히 보이는 길은 명확합니다. 모든 것을 임베딩 (embed)하고, 코사인 유사도 (cosine-similarity)를 통해 데모를 구현하며, 검색 (retrieval)이 올바른 것을 가져오기를 바라는 것입니다. 저는 반대 방향에 베팅했습니다.
Scarwarden의 메모리는 세 가지 계층으로 구성됩니다:
- 에피소드 원장 (An episodic ledger). SQLite를 사용하며, 정신적으로는 추가 전용 (append-only) 방식입니다. 모든 에피소드는 하나의 경험입니다: 에이전트가 무엇을 했는지, 어떤 일이 일어났는지, 그리고 인간이 무엇을 수정했는지(있다면)를 기록합니다. 이 테이블은 그라운드 트루스 (ground truth)입니다. 메모리 내의 그 어떤 것도 이를 추적할 수 있는 기록 (paper trail) 없이는 존재할 수 없습니다.
- 정제된 플레이북 (A distilled playbook).
qwen3.6-flash가 에피소드들을 규칙으로 압축합니다. 모든 규칙은 해당 규칙을 가르쳐준 에피소드 ID를 반드시 인용해야 하며, 플레이북은 git에 저장되는 마크다운 (markdown) 형식으로 내보내집니다. 이를 통해 버전 간 에이전트의 사고방식을 diff (차이 비교) 할 수 있습니다. - 결정론적 회상 (Deterministic recall). 기본 경로에는 벡터 (vectors)를 전혀 사용하지 않습니다. 쿼리를 토큰화 (Tokenise) 하고, 어간 추출 (stem)을 수행하며, 불용어 (stopwords)를 제거한 뒤 규칙 태그와 매칭합니다. 모든 회상은 설명 가능하고, 로그를 남길 수 있으며, 재현 가능합니다.
회상은 또한 등급이 매겨지며, 결코 맹목적이지 않습니다. 신뢰도 라우터 (confidence router)는 다음 세 가지 판결 중 하나를 반환합니다:
if not top:
grade = ASK_HUMAN
elif top[0][1] >= 2 or top[0][0] >= 5: # 강력한 태그 또는 태그+텍스트 중첩
...
ACT는 규칙을 따르고 이를 인용하는 것을 의미합니다. ACT_AND_FLAG는 행동하되, 자신의 가정을 명시하는 것을 의미합니다. ASK_HUMAN은 관련 메모리가 존재하지 않으므로 추측하지 말고, 질문을 던지라는 의미입니다. 이때 인간의 답변은 새로운 에피소드가 됩니다. 저는 마지막 항목이 중요하다고 생각합니다. 날카로운 질문을 던지는 운영자는 허세를 부리는 열 명의 운영자보다 가치 있습니다. 질문하는 것은 메모리 쓰기 (memory write)이지, 실패가 아닙니다.
프로젝트 전체를 지탱하는 코드 한 줄
증류 (Distillation) 과정은 대부분의 메모리 시스템이 조용히 거짓말을 시작하는 지점입니다. 모델이 요약하고, 요약이 표류(drift)하면서, 곧
답변하는 측면에서도 동일한 규율이 적용됩니다. 메모리가 활성화되면, qwen3.7-plus는 인용 정보가 포함된 회상된 규칙들을 가져오며, 시스템 프롬프트(system prompt)는 적용되는 모든 규칙을 본문 내에 인용하도록 요구합니다:
당신은 감사 가능한 에피소드 메모리 (episodic memory)를 가진 에이전트인 Scarwarden입니다.
당신에게는 이 작업에 대해 회상된 플레이북 규칙들이 주어지며, 각 규칙에는 이를 학습시킨 에피소드 ID가 포함되어 있습니다. 규칙을 따르십시오. 답변 시, 인용하십시오...
작동한 순간
시드 원장(seed ledger)은 완전히 합성된 것입니다. Northstar Media라는 가상의 콘텐츠 팀을 설정하여, 실패한 게시물 16개 에피소드, 편집자의 수정 사항, 잘못 분류된 지원 티켓(support tickets) 등을 구성했습니다. 증류 (Distillation) 과정을 통해 이 데이터들은 인용된 10개의 규칙으로 변환되었습니다.
그 후, 저는 베타 출시를 알리는 LinkedIn 게시물을 초안으로 작성해 달라고 요청했습니다. 모델은 고충(pain-point)을 건드리는 후크(hook)로 시작하여, 끝에 해시태그를 달았고, 그 이유로 [PB-01, ep1과 ep14에서 학습됨]을 인용했습니다. 감사 UI(audit UI)에서 PB-01을 클릭하면 실제 상처(scar)에 도달하게 됩니다. 즉, 3주 전에 성과가 저조했던 게시물과 편집자의 수정 사항을 토씨 하나 틀리지 않고 그대로 확인할 수 있습니다.
저는 건망증(amnesia) 토글을 끄고 동일한 모델에 동일한 작업을 실행했습니다. 결과물은 [placeholder] 대괄호가 포함된 일반적인 이모지 템플릿이었습니다. 이 대조적인 모습을 나란히 놓고 보는 것만으로도, 제품의 가치가 한 화면에 모두 담깁니다.
하지만 테스트 중 제가 가장 좋아했던 트랜스크립트(transcript)는 이것입니다. 저는 트위터에 할인 코드를 게시하라고 명령했고, 모델은 다음과 같이 답했습니다:
작업 거부됨. PB-05는 공개 소셜 미디어에 할인 코드를 배포하는 것을 금지합니다 [PB-05, ep7에서 학습됨]. 따라서 트위터에 게시하지 않겠습니다.
에이전트는 제 지시를 거부했고, 거부하도록 가르쳐준 경험을 인용했습니다. 이것이 바로 핵심입니다. '아니오'라고 말할 수 있고, 그 이유를 보여줄 수 있는 메모리 말입니다.
솔직히 무엇을 덜어냈는가
저는 남아프리카 공화국 음푸말랑가에서, 무료 티어 크레딧을 사용하여 혼자서 8일 동안 작업했습니다 (Qwen 바우처 마감일을 며칠 놓치는 바람에 모든 토큰 비용을 제 사비로 지불해야 했기에, 의도적으로 소형 모델(small-model) 및 로컬 우선(local-first) 방식으로 설계했습니다). 원래 계획은 출시된 것보다 더 컸습니다. 기능 동결(feature freeze) 시점에 다음과 같은 것들을 덜어냈습니다:
- The Reviewer QC loop (검토자 QC 루프). 스크립트 감독(script supervisor)처럼 플레이북(playbook)을 기준으로 모든 초안을 확인하고 재작업을 요청하는 두 번째 모델. 설계는 되었으나 출시되지는 않았습니다.
- Qwen3-VL 시각적 감사 (visual audit). 학습된 시각적 규칙에 따라 캠페인 이미지를 확인하는 기능. 저는 불확실한 데모를 보여주느니 차라리 기능을 삭제하는 쪽을 택했습니다.
- MCP 서버. 어떤 에이전트에서도 마운트 가능한 도구로서의 Scarwarden. 이 부분은 아쉽습니다. 이전에도 MCP 서버를 출시한 적이 있지만, 마감 기한이라는 수학적 현실은 고려 대상이 아니었습니다.
- 재현된 벤치마크 곡선 (replayed benchmark curve). 실제 재현된 세션 전반에 걸친 측정된 개선 차트를 원했습니다. 이 기능이 없기 때문에, 이 포스트에는 어떠한 퍼센트(%) 수치 주장도 포함되어 있지 않다는 점을 눈치채셨을 것입니다. 이는 의도된 것입니다. 정직하게 측정한 후에 곡선을 공개할 것이며, 그 전에는 공개하지 않을 것입니다.
살아남은 것은 가장 먼저 제대로 갖춰져야 했던 부분들입니다: 원장(ledger), 인용된 플레이북(cited playbook), 결정론적 회상(deterministic recall), 라우터(router), 토글(toggle), 그리고 감사 UI(audit UI). 나머지는 로드맵(roadmap)입니다.
아키텍처 (The architecture)
모든 모델 호출은 DashScope 국제 엔드포인트의 Alibaba Cloud Model Studio를 통해 하나의 클라이언트 모듈(scarwarden/alibaba_cloud.py)을 거쳐 이루어지며, 역할에 따라 모델이 나뉩니다: qwen3.6-flash는 증류(distillation) 작업의 핵심 동력으로, qwen3.7-plus는 답변용으로 사용됩니다. 프로젝트 전체에서 Flask가 유일한 의존성(dependency)입니다.
직접 실행해보기, 네 가지 명령
git clone https://github.com/azaniansky-design/scarwarden.git
cd scarwarden && pip install -r requirements.txt
export DASHSCOPE_API_KEY=sk-... # Alibaba Cloud Model Studio에서 발급받은 무료 키
...
http://127.0.0.1:5054를 열고 작업을 부여한 다음, 메모리 토글(memory toggle)을 켜고 동일한 작업을 다시 부여해 보세요. 그 두 답변의 차이가 바로 제가 이것을 만든 이유입니다.
만약 여러분이 프로덕션(production) 환경을 위한 에이전트를 구축하고 있다면, 여러분이 어떻게 방어 가능한(defend) 메모리를 처리하고 있는지 진심으로 듣고 싶습니다. 그리고 만약 Scarwarden을 클론(clone)하여 그 메모리를 디프(diff)해 보신다면, 무엇을 발견했는지 저에게 알려주세요.
Qwen Cloud와 함께한 Global AI Hackathon Series의 MemoryAgent 트랙을 위해 구축되었습니다. MIT 라이선스가 적용됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기