본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 28. 05:18

FailureDNA 구축하기: 스스로를 신뢰하지 말아야 할 때를 아는 에이전트 메모리

요약

사고 대응 에이전트가 과거의 유사한 실패 사례를 반복하지 않도록 돕는 'FailureDNA' 메모리 아키텍처를 소개합니다. 모델의 판단에만 의존하지 않고, 결정론적인 유효성 게이트를 통해 실패한 조치를 강제로 배제하는 구조를 제안합니다.

핵심 포인트

  • 유사성이 반드시 해결책의 유효성을 보장하지 않음
  • 실패한 과거 조치를 강제로 제거하는 결정론적 게이트 도입
  • 모델은 선택만 하고, 유효성 검증은 시스템이 수행
  • 사용(used), 검토(inspected), 회피(avoided) 기반의 메모리 관리

Global AI Hackathon Series with Qwen Cloud에 제출됨 — 트랙 1: MemoryAgent.

시작점이 된 버그

사고 대응 (incident-response) 에이전트에게 과거 사고 데이터가 담긴 벡터 데이터베이스 (vector database)를 제공하면, 똑똑해 보이지만 조용히 위험한 행동을 하게 됩니다. 새로운 장애가 과거의 것과 유사할 때, 가장 '유사한' 과거 사고를 검색하고 그곳에서 발견된 조치를 그대로 재사용하는 것입니다.

문제는 유사성이 적용 가능성을 의미하지는 않는다는 점입니다. 가장 유사한 과거 사고는 restart_service실패했던 사례일 수도 있습니다. 혹은 increase_connection_pool이 효과가 있었던 사례일 수도 있지만, 이는 당시 데이터베이스 드라이버가 psycopg2였고 토폴로지 (topology)가 단일 리전이었기 때문일 뿐, 그 이후로 두 가지 모두 변경되었을 수 있습니다. 코사인 유사도 (cosine score) 1.0은 증상이 비슷하다는 것을 알려줄 뿐, 그 해결책이 여전히 유효한지에 대해서는 아무것도 알려주지 않습니다.

사고 대응에서 이러한 격차는 막대한 비용을 초래합니다. 이미 실패한 복구 조치를 반복하는 것은 장애 상황에서 가장 비용이 많이 드는 시간을 허비하게 만들며, 전제 조건이 변해버린 해결책을 재사용하는 것은 사고를 악화시킬 수 있습니다. 그래서 저는 FailureDNA를 구축했습니다. 이는 모델이 행동하기 전에, 실제 결과들을 축적하고 과거의 경험을 사용할지 (used), 검토할지 (inspected), 아니면 **피해야 할지 (avoided)**를 추론하는 지속 가능한 메모리입니다.

핵심 아이디어: 결정론적 게이트 (deterministic gate) 위의 LLM

이 아키텍처에는 한 가지 확고한 규칙이 있습니다: 모델은 선택할 뿐, 무엇이 유효한지는 결코 결정하지 않습니다.

사고 (Incident)
  -> 증상 임베딩 (embed symptoms) (Qwen text-embedding-v3)
  -> Alibaba Cloud RDS 상의 pgvector 의미론적 검색 (semantic search)
...

유효성 게이트 (validity gate)는 의도적으로 지루하고 결정론적입니다:

이전 결과 (Prior outcome)환경 일치 여부 (Environment match)성향 (Disposition)
실패 (failure)무관 (any)회피 (avoid)
...

어떤 모델도 메모리가 신뢰할 수 있는지 여부를 결정하지 않습니다. 그리고 결정적으로, avoid는 권고 사항이 아니라 **강제 사항 (enforced, not advised)**입니다. 증상과 일치하는 이전 실패 사례가 있는 행동은 모델이 확인하기 전에 후보 목록에서 제거됩니다. 에이전트는 설령 원하더라도 이미 알려진 실패를 반복할 수 없습니다. 이는 매우 중요한데, 라이브 LLM에 동일한 메모리를 "힌트"로 제공할 경우 때때로 그 힌트를 무시하기 때문입니다. (증거가 주어졌을 때 어떤 행동을 할 것인가라는) 창의적인 부분은 Qwen이 담당하고, (이 메모리가 유효한가? 이 행동이 성공했는가?와 같이) 절대 환각 (hallucinate)을 일으켜서는 안 되는 부분은 결정론적 코드 (deterministic code)에 머뭅니다.

Qwen Cloud가 적합한 이유

저는 OpenAI 호환 DashScope 엔드포인트를 통해 Qwen Cloud를 사용했으며, 덕분에 다음 두 가지를 거의 무료로 구현할 수 있었습니다:

  1. 회상을 위한 임베딩 (Embeddings for recall). text-embedding-v3는 사고 증상을 pgvector 검색을 위한 1024차원 벡터로 변환합니다. 하이브리드 검색 (Hybrid retrieval)은 의미론적 유사성 (semantic similarity, 가중치 0.70)과 키워드 중첩 (keyword overlap, 0.30)을 결합하므로, 의역된 증상과 정확한 토큰 증상을 모두 포착합니다.
  2. 검증된 행동 선택 (Validated action selection). Qwen 채팅 모델은 증상, 환경 지문 (environment fingerprint), (게이트가 적용된) 후보 행동, 그리고 메모리를 전달받아 temperature=0 및 사고 기능(thinking)이 비활성화된 상태에서 단일 JSON 결정을 반환합니다. 이는 실행 전 제가 검증할 수 있는 빠르고 결정론적인(deterministic-ish) 출력입니다.

OpenAI와 호환되기 때문에, 전체 클라이언트는 명시적인 타임아웃과 단일 재시도 로직을 갖춘 얇고 타입이 잘 지정된 (well-typed) 래퍼(wrapper)일 뿐이며, 씨름해야 할 생소한 SDK도 없습니다.

도움이 된다는 것을 증명하기 (자기기만 없이)

새로운 방식이 승리하는 데모를 만드는 것은 조작하기 쉽습니다. 따라서 FailureDNA는 스스로에게 가혹하도록 설계된 벤치마크를 함께 제공합니다: 동일한 시드(seeded) 히스토리를 바탕으로 한 세 가지 모드(no_memory, naive, failuredna), 숨겨진 시뮬레이터 결과, 평가자 전용 (evaluator-only) 안전/불안전 라벨, 모드별로 격리된 메모리, 그리고 특정 행동이 보통 옳다는 사실을 단순히 재발견하는 것이 아닌지 확인하기 위한 정적 지름길 베이스라인(always_inspect_downstream, …)을 포함합니다.

FailureDNA는 첫 번째 행동 해결(first-action resolution) 능력을 단순한 에이전트보다 훨씬 높게 끌어올리고, 안전하지 않은 첫 행동을 급격히 줄이며, 더 적은 행동 수로 문제를 해결합니다. 또한 과거의 실패를 단 한 번도(zero) 반복하지 않으며, 오래된 성공 사례(stale successes) 또한 단 한 번도(zero) 반복하지 않습니다. 제가 공개적으로 남겨둔 솔직한 주의사항은 다음과 같습니다. 이 작은 시나리오 세트에서는 정적인 '항상 검사(always-inspect)' 정책 또한 높은 점수를 기록했다는 점인데, 바로 이 점 때문에 지름길 감사(shortcut audit)가 존재하는 것입니다. FailureDNA의 가치는 마법 같은 행동에 있는 것이 아닙니다. 그것은 알려진 실패를 절대 반복하지 않으며, 환경이 변함에 따라 오래된 해결책을 맹목적으로 재사용하지 않는다는 점에 있습니다. 이것이 바로 고정된 벤치마크를 넘어 일반화되는 동작입니다.

Alibaba Cloud에서 실행하기 (및 주의해야 할 날카로운 지점들)

백엔드는 Alibaba Cloud Function Compute (FastAPI, 포트 9000) 상의 커스텀 컨테이너로 실행되며, 메모리는 ApsaraDB RDS for PostgreSQL + pgvector (HNSW)에 영구 저장되고, 이미지는 ACR Personal Edition에 저장됩니다. 몇 가지 까다로운 점들이 있었으며, 다음 작업자를 위해 기록해 둘 가치가 있습니다:

  • ACR 티어(tier)가 중요합니다. Enterprise Economy 티어는 FC 커스텀 컨테이너 함수를 지원할 수 없습니다 (이미지 프로세싱 불가). Personal Edition (무료)은 작동합니다.
  • 기본 *.fcapp.run 도메인은 다운로드를 강제합니다. HTML 및 JSON 응답에 Content-Disposition: attachment를 추가하기 때문에, 브라우저가 대시보드나 상태(health) JSON을 렌더링하는 대신 다운로드하게 됩니다. 저는 UI를 GitHub Pages에서 서빙하고, /health/ready를 가져와 표시하는 작은 API 상태 페이지를 추가했습니다.
  • CORS는 앱이 아닌 게이트웨이의 역할입니다. FC 게이트웨이는 이미 Access-Control-* 헤더를 주입합니다 (요청의 Origin을 반영하기까지 합니다). 앱의 유일한 CORS 책임은 OPTIONS 요청에 대해 200 응답을 반환하는 것입니다. 만약 프리플라이트(preflight) 요청에 405 응답을 보내면 브라우저가 모든 POST 요청을 차단합니다. 앱 레벨에서 CORS 헤더를 추가로 붙이는 것은 브라우저가 거부하는 중복 헤더를 생성할 뿐입니다.
  • 오래된 이미지를 주의하세요. ACR에 태그를 푸시한다고 해서 실행 중인 함수가 업데이트되지는 않습니다. 반드시 함수를 다시 가리키도록(repoint) 설정해야 하며, FC는 캐시된 이미지를 제공할 수도 있습니다.

저는 /health/cors-debug 엔드포인트와 build 마커를 추가하여, "내 새로운 코드가 실제로 라이브 상태인가?"를 한눈에 확인할 수 있도록 했습니다.

다음 단계로 할 일

가장 흥미로운 미해결 과제는 inspect 처분(disposition)입니다. 현재 결정론적 게이트(deterministic gate)는 avoid 액션은 완전히 제거하지만, inspect 액션은 경고와 함께 사용 가능한 상태로 남겨둡니다. 다음으로 적절한 단계는 inspect 뒤에 실제 검증 도구를 배치하는 것입니다. 즉, 오래된 성공 사례가 단순히 플래그(flag) 처리되는 것에 그치지 않고, 현재 환경과 대조하여 _검증(checked)_되도록 하는 것입니다. 이렇게 함으로써 본래의 논지를 유지할 수 있습니다. 즉, 창의성이 도움이 되는 곳에서는 모델이 창의력을 발휘하게 두고, 오류의 비용이 큰 곳에서는 결정론적 코드(및 실제 검증)가 방어선을 유지하게 하는 것입니다.

체험하기: Live dashboard · API status · GitHub (MIT)

Qwen Cloud + Alibaba Cloud Function ComputeRDS pgvector를 사용하여 구축되었습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0