AI 에이전트의 메모리에 CI/CD 파이프라인을 구축했습니다
요약
AI 에이전트의 지식 그래프 메모리를 관리하기 위한 CI/CD 파이프라인인 SOBER를 소개합니다. 테스트, diff, bisect, 게이트 배포 기능을 통해 에이전트 메모리의 변이와 오염을 방지하고 안정적인 운영을 지원합니다.
핵심 포인트
- 에이전트 메모리 관리를 위한 DevOps 개념인 SOBER 구축
- 지식 그래프의 변경 사항을 확인하는 diff 및 bisect 기능 제공
- 비밀 정보 유출 방지를 위한 forget-regression 테스트 포함
- 평가 게이트 통과 시 자동으로 PR을 생성하는 개선 기능
🧠 AI 에이전트의 메모리에 CI/CD 파이프라인을 구축했습니다
Cognee × WeMakeDevs의 "Where's My Context?" 해커톤을 위해 지식 그래프 (Knowledge Graph)를 위한 테스트, diff, bisect, 그리고 게이트 배포 (gated deploys) 기능을 갖춘 SOBER를 구축했습니다.
요약 (TL;DR) — 에이전트의 메모리는 테스트도, diff도, 롤백 (rollback)도 없는 프로덕션 인프라입니다. SOBER는 Cognee 지식 그래프를 실제 CI/CD로 감싸는
brainCLI + GitHub Action입니다: 회수된 비밀 정보가 계속 남아있지 않음을 증명하는 forget-regression 테스트, 오염된 그래프를 위한git bisect, 그리고 통과된 평가 게이트 (eval gate) 뒤에서 스스로 Pull Request를 생성하는 야간improve()기능이 포함됩니다. 혼자서 AI의 도움을 받아 구축했으며, 재미있는 점은 제 코드에서 14개의 실제 버그를 찾아낸 에이전트 군단이 리뷰를 진행했다는 것입니다.
🍸 새벽 3시의 문제
모든 온콜 (on-call) 엔지니어는 이 해커톤의 이름이 유래된 그 기분을 알고 있습니다. 새벽 3시이고, 무언가 고장 났으며, 지난번에는 어떻게 고쳤는지 아무도 기억하지 못하는 상황 말입니다.
우리는 수십 년 전에 **코드 (code)**에 대해서는 이 문제를 해결했습니다 — 버전 관리 (version control), 테스트 (tests), 코드 리뷰 (code review), 롤백 (rollback), 카나리 배포 (canary deploys) 등을 통해서 말이죠. 하지만 에이전트가 무엇을 알고 무엇을 할지를 점점 더 결정하게 되는 AI 에이전트의 **메모리 (memory)**에는 이 중 어느 것도 적용되지 않은 채 배포됩니다. 메모리는 조용히 제자리에서 변이합니다. 다음과 같은 것들이 없습니다:
- ❌ 회수된 비밀 정보나 오래되고 위험한 사실이 계속 회상(recall)되지 않도록 막는 테스트 (test)
- ❌ 재수집 (re-ingest)이나
improve()실행이 그래프에서 무엇을 변경했는지 확인하는 diff - ❌ 어떤 수집 (ingestion)이 뇌를 오염시켰는지 찾아내는 bisect
- ❌ 메모리가 프로덕션으로 "배포"되기 전의 게이트 (gate)
그래서 저는 SOBER — 에이전트의 뇌를 위한 CI/CD를 만들었습니다. DevOps를 위한 메모리가 아니라, 메모리를 위한 DevOps입니다.
🎯 아이디어 선정 (솔직한 부분)
처음부터 SOBER를 떠올린 것은 아닙니다. 저의 초기 직관은 과거의 장애를 회상하는 온콜 어시스턴트인 인시던트-메모리 코파일럿 (incident-memory copilot) 이었습니다. 청중을 대상으로 압박 테스트를 하기 전까지는 꽤 괜찮은 아이디어처럼 느껴졌습니다:
WeMakeDevs는 **DevOps 커뮤니티 (DevOps community)**이므로, "새벽 3시의 장애 메모리 (3 a.m. incident memory)"는 그들을 위해 만들 수 있는 가장 예측 가능한 (predictable) 아이템입니다. 또한 Cognee의 엔지니어들에게는 명사만 바꾼 과거의 "Company Brain" 해커톤 우승작처럼 들리기도 합니다.
그대로 두었다면 유사한 프로젝트들에 파묻혔을 것입니다. 승리할 수 있었던 재정의(reframe)는 다른 질문에서 시작되었습니다: _"어떤 메모리 앱을 만들어야 할까?"_가 아니라 _"메모리라는 카테고리 자체에 여전히 부족한 것은 무엇인가?"_라는 질문이었습니다.
그 답은 바로 운영 계층 (operations layer) 전체였습니다. 다른 모든 참가작들은 무언가를 기억하기 위해 Cognee를 사용할 (use) 것이었습니다. 반면 SOBER는 기억하는 행위 그 자체를 관리합니다. 그렇게 함으로써 SOBER는 Cognee의 동사 중 아무도 데모에서 보여주지 않는 단 하나, 즉 **forget()**에 강력하게 의존합니다.
🏗️ 아키텍처: 뇌는 데이터셋의 _가족 (family)_이다
이 설계의 핵심이 되는 결정입니다. Cognee의 forget()은 전체 데이터셋 범위로 지정되지만, 저는 나머지 부분을 방해하지 않으면서 단 하나의 배치 (one batch) 지식만을 철회해야 했습니다. 따라서 논리적 (logical) 뇌는 물리적 데이터셋의 **가족 (family)**으로 모델링됩니다. 즉, 수집 배치 (node_set)당 하나씩 존재합니다:
flowchart TD
K["📄 knowledge/*.md"] -->|brain build| ING["ingest_batch()"]
ING --> C["brain__core"]
...
recall()과export()는 가족 전체를 아우릅니다 → 지식이 어떤 배치에 들어있든 상관없이 찾아낼 수 있습니다.forget(node_set)은 정확히 한 구성원만을 제거합니다 → 정밀한 철회(surgical retraction) 및 단일 배치 롤백(one-batch rollback)이 가능합니다.- 구성원 정보는
snapshots/.family.json에서 결정론적으로 추적됩니다.
이러한 단 한 번의 간접 참조(indirection)가 철회와 이분 탐색 기반 복구(bisect-revert)를 정밀하게 만듭니다.
🔒 기능 1 — 망각 회귀 테스트 (Forget-regression tests)
프로덕션 출시 코드가 수집된 후 철회됩니다. 메모리-CI(memory-CI) 스위트는 해당 정보가 사라졌음을 증명합니다. 단순히 명시적인 쿼리뿐만 아니라, 의역 탐색 (paraphrase probes) 및 내보낸 그래프의 잔여물 (residue in the exported graph) 전체에 걸쳐 확인합니다.
다음은 실제 Cognee 1.2.2 + Gemini에서 실행한 결과입니다:
$ brain test # secret still present
🔴 FAIL — brain failed memory CI
6/11 passed, 5 failed
...
철회된 사실이 계속해서 철회된 상태로 유지됨을 모든 변경 사항에서 증명합니다. 그 어떤 다른 메모리 도구도 이러한 보장을 제공하지 않습니다. 제가 단 하나의 기능(feature)을 작성하기 전에 가장 먼저 검증한 것은,
cognee.forget()이 단순히 사실을 숨기는 것이 아니라 벡터 회상(vector recall)에서 실제로 사실을 제거하는지(recallable → [])였습니다. 그 하나의 초록색 체크 표시가 나머지 모든 것을 구축할 가치가 있게 만들었습니다.
🪓 기능 2 — 오염된 뇌를 위한 git bisect
평가(eval)가 빨간색(FAIL)으로 변하면, 어떤 인제스션(ingestion) 배치(batch)가 원인입니다. SOBER는 배치 이력을 이진 탐색(binary-search)하여 O(log n) 번의 조사(probe)만으로 범인을 찾아냅니다:
$ brain bisect --failing-eval no-cache-flush-advice
probe 1: prefix_len=8 full-set sanity red=True
probe 2: prefix_len=5 bisectbrain__b05 red=False
...
제가 깨닫게 된 미묘하지만 중요한 정확성 포인트는, bisect가 본질적으로 forbidden (금지된)-평가 개념이라는 점입니다. bisect는 누출(leak)이나 오염(poison)을 도입한 배치를 찾아내며, 이는 더 큰 모든 접두사(prefix)에 지속적으로 남아 있습니다(단조성, monotonic). 누락된 must_know 사실은 그런 방식으로 작동하지 않습니다. 따라서 SOBER는 잘못된 답을 조용히 반환하는 대신, bisect를 forbidden 평가로 제한합니다.
🌙 기능 3 — 스스로를 배포하는 뇌
cognee.improve()는 채팅 세션을 그래프로 증류(distill)합니다. 이는 메모리를 퇴보(regress)시킬 수 있는 조용한 변이(mutation)입니다. SOBER는 오직 초록색 게이트(green gate) 뒤에서만 이를 실행합니다:
sequenceDiagram
participant N as 🌙 nightly job
participant CI as memory CI (evals)
...
| 이전 | 이후 | 결과 |
|---|---|---|
| 🟢 green | 🟢 green | accepted — exit 0 |
| ... |
이것이 에이전트 뇌를 위한 CI/CD의 CD 측면입니다. 즉, 초록색 게이트와 인간의 승인 뒤에서 스스로 업그레이드를 제안하는 메모리입니다.
🧩 Cognee와의 매핑
드물게 사용되는 명령어를 포함하여 모든 메모리 동사(verb)는 핵심적인 역할을 수행합니다:
| SOBER 기능 | Cognee API |
|---|---|
| 소스로부터 뇌 구축 (Build the brain from source) | cognee.add() + cognee.cognify() |
| ... |
🔥 가장 어려웠던 것은 코드가 아니었습니다 — 하루 20개의 요청이었습니다
결제 정보가 등록되지 않은 키를 사용한 Gemini의 무료 티어(free tier)는 하루 20회 요청으로 제한되어 있었습니다. 핵심 루프(core loop)를 실시간으로 증명하는 과정에서 할당량을 모두 소진했고, 새 키를 발급받아도 똑같이 하루 20회라는 아주 적은 양만 제공된다는 사실을 알게 되었습니다 — 마치 두더지 잡기 게임 같았습니다.
그래서 저는 방식을 변경했습니다. 핵심인 '금지된 지식(forbidden-knowledge) → 망각(forget)' 루프는 실시간으로 증명하였고, 더 까다로운 이분법적 탐색(bisect) 및 개선 게이트(improve-gate) **로직(logic)**은 결정론적 오프라인 하네스(deterministic offline harnesses)(스텁된 판정, API 호출 제로)를 통해 검증했습니다. 흥미로운 엔지니어링은 종종 제약 사항을 뚫고 지나가는 것이 아니라, 제약 사항을 우회하여(working around) 해결하는 데 있다는 점을 상기시켜 주는 좋은 사례였습니다. 또한, 20번밖에 실행할 수 없는 실시간 테스트보다 1,000번 실행할 수 있는 키리스(keyless) 테스트가 훨씬 더 가치 있다는 사실도 깨달았습니다.
🤖 에이전트 군단을 활용한 구축 — 그리고 리뷰
저는 이를 Claude Code를 페어 프로그래머(pair programmer)로 활용하여 구축했으며, 적극적으로 의존했습니다. 몇 가지 검증 게이트를 통해 실제 Cognee API를 확정한 후, **고정된 인터페이스 계약(frozen interface contract)**을 작성하고 7개의 에이전트를 병렬로 배치했습니다. 각 에이전트는 모듈별로 하나씩(cognee 래퍼, 스냅샷/diff, 평가 스위트(eval suite), 이분법적 탐색(bisect), CLI, 코퍼스(corpus), 워크플로) 담당했으며, 여기에 조립 과정의 통합 및 임포트 체크를 수행할 여덟 번째 에이전트를 추가했습니다. 이 에이전트는 스스로 배선 버그(wiring bugs)를 잡아냈습니다.
그다음 제가 가장 자랑스럽게 생각하는 부분은 에이전트들을 제 자신의 코드에 투입한 것입니다. **6인의 리뷰어로 구성된 적대적 리뷰(adversarial review)**를 진행했습니다. 각 리뷰어가 발견한 오류는 실제 코드를 다시 읽어보는 회의론자에 의해 재검증된 후에야 인정되었습니다. 그 결과 14개의 확정된 버그를 발견했으며, 오탐(false positives)은 제로였고, 중복을 제거하면 5개의 실제 근본 원인(root issues)으로 압축되었습니다. 가장 골치 아팠던 두 가지는 다음과 같습니다:
- brain.improve(dataset="brain") # 항상 비어 있는(EMPTY) 기본 데이터셋을 대상으로 함
+ for member in list_family(dataset): # brain__core, brain__runbooks, … 등을 아우름
+ await cognee.improve(dataset=member) # 셀프 개선(self-improve) 기능이 실제로는 아무 동작도 하지 않는(no-op) 상태였음!
- glob("snapshots/brain__*") # 절대 생성되지 않는 배치별 스냅샷 파일들
+ read(".family.json") # 배치를 실제로 기록하는 레지스트리
# → `brain bisect`가 매번 실패했던 원인
두 가지 모두 제가 오프라인(offline) 상태에서만 검증했던 경로에 있었기에, 스텁(stub)들이 이를 가리고 있었습니다. 저는 다섯 가지 문제를 모두 수정하고, 키리스(keyless) 검증을 재확인한 뒤 푸시(push)했습니다. 자신의 작업물을 적대적(adversarially)으로 검토할 수 있고, 그것이 실제 버그를 찾아내게 만드는 능력은 진정한 초능력입니다.
(해커톤 공개 규칙에 따라: 과정 전반에 AI 지원이 사용되었습니다. 제가 "검증되었다"고 언급한 모든 결과는 생성된 것이 아니라 실제 Cognee + Gemini를 대상으로 실행되었습니다.)
🗺️ 다음 단계
- Cognee Cloud 카나리 배포 (canary deploys) —
brain ci가 통과(green)되면, 브레인을 Cognee Cloud로push()하고 트래픽의 일부에serve()하여, 실시간 피드백에 따라 승격(promoting)하거나 롤백(rolling back)합니다. - 프로세스 내 스냅샷 복구 (In-process snapshot restore) — 성능이 저하된
improve()가 단순히 차단되는 것에 그치지 않고 자동으로 롤백되도록 합니다. - 더 다양한 평가 (eval) 종류 — 의미론적 모순 탐지 (semantic contradiction detection), 최신성/TTL 체크, 노드 세트별 커버리지 게이트 (per-node-set coverage gates).
하지만 논지는 이미 확립되었습니다: 당신의 에이전트 메모리는 프로덕션 인프라(production infrastructure)이며, 이제 다른 빌드 아티팩트(build artifact)와 마찬가지로 테스트, 차이 비교(diffed), 이분법적 탐색(bisected), 게이트 적용 및 배포가 가능합니다.
이제 당신의 브레인은 더 이상 회귀(regression)를 머지(merge)할 수 없습니다.
⭐ Repo: https://github.com/wiz-abhi/SOBER · The Hangover Part AI를 위해 Cognee를 기반으로 구축되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기