AGENTS.md에서 AGENTS.db로 전환하여 환각(Hallucinations) 문제를 해결한 방법
요약
에이전트 워크플로우에서 발생하는 환각과 데이터 마이그레이션 오류를 해결하기 위해, 텍스트 기반 메모리(AGENTS.md)를 SQLite 데이터베이스(AGENTS.db)로 전환한 사례를 다룹니다. 에이전트가 CLI 도구를 활용하고 단계별 수정 방식을 통해 안정성을 높이는 아키텍처를 설명합니다.
핵심 포인트
- 텍스트 파일 기반 메모리를 SQLite DB로 전환하여 데이터 무결성 확보
- 에이전트의 오류 대응을 위한 3단계 수정 방식(자동-스크립트-Human-in-the-loop) 도입
- LangGraph의 복잡한 워크플로우 대신 CLI 도구 중심의 에이전트 하네스 구축
- 계획 단계(plan step) 추가를 통한 에이전트 실행 안정성 강화
본격적으로 시작하기 전에, 심층 분석 및 노트 생성을 위한 Exam Intelligence의 에이전트 워크플로우(agentic workflow)가 어떻게 작동하는지에 대한 배경 지식을 조금 말씀드리겠습니다...
처음에는 완전한 엔드 투 엔드(end-to-end) LangGraph 워크플로우를 구축하려고 시도했습니다. 하지만 PDF 누락, 논문 검색 불가, 파싱 실패, 또는 에이전트가 503 에러나 깨진 JSON을 반환하는 것과 같은 외부 요인으로 인해 항상 예상치 못한 버그가 발생했습니다.
그 시점에서, 저는 이러한 예외 상황(edge cases)을 처리하기 위해서만 별도의 코딩 에이전트(coding agent)를 구축해야 할 것처럼 보였습니다.
해결책
마스터 워크플로우 대신, 코딩 에이전트가 사용할 수 있는 CLI 도구들을 만드는 방식으로 전환했습니다.
- 설정 (The Setup): Docker 샌드박스(sandbox) 내에서 실행되는 PI 코딩 에이전트 하네스(harness) 안에서 Ollama를 통해 qwen3.6:35b를 실행합니다.
- 흐름 (The Flow): 기본적으로 각 파일이 하나의 노드(특정 결과를 달성하기 위한 단계 또는 전체 워크플로우)이며, 에이전트는 이를 하나씩 실행합니다.
무언가 고장 날 경우, 저는 3단계의 수정 방식을 결정했습니다:
- 1단계 (자동): 에이전트가 수동으로 작업을 수행합니다 (예: 누락된 URL 찾기).
- 2단계 (자동): 에이전트가 단기적으로 반복되는 패턴을 식별하고 이를 위한 스크립트를 작성합니다.
- 3단계 (Human-in-the-loop): 에이전트가 제 CLI 도구에서 버그를 식별하면, 이를 표시하고 수정안을 제안한 뒤, 코드베이스를 깨끗하게 유지하기 위해 중단합니다. 즉, 코드를 수정하기 전에 제 승인을 기다립니다.
메모리 아키텍처 (The Memory Architecture)
표준적인 AGENTS.md 명명 규칙을 알지 못했던 저는 처음에 다음과 같은 설정을 선택했습니다:
instructions.md: 에이전트에게 전체 워크플로우, 아키텍처, 그리고 이를 어떻게 실행해야 하는지에 대해 알려줍니다.memory.md: 에이전트를 위한 세션 간 지속적인 메모리(persistent cross-session memory)로, 주로 어떤 버그/문제에 직면했는지와 이를 어떻게 해결했는지를 저장합니다.workflow_checkpoints.db: 워크플로우를 위한 임시 저장소로 사용되는 SQLite3 데이터베이스이며, 품질 검사 후 운영 환경과의 격리(production isolation)를 보장하기 위해 나중에 PostgreSQL(저희 Django 앱에서 사용)로 푸시됩니다.
문제점 (The Problem)
에이전트가 시작은 제대로 했지만, 노트 데이터와 기타 항목들을 Django 데이터베이스로 마이그레이션(migration)해야 할 때가 되자 완전히 망가져 버렸습니다.
제 워크플로우에는 작업을 쉽게 수행하기 위해 호출할 수 있는 migrate.py CLI 도구가 있었지만(instructions.md에 언급됨), 에이전트는 인라인 Python(inline Python)을 사용하기 시작했고, 항상 구문 오류(syntax errors)를 발생시켰으며, 깨진 포맷으로 데이터를 마이그레이션하거나 때로는 특정 테이블의 마이그레이션을 완전히 건너뛰기도 했습니다.
따라서 여러 번의 실패를 목격한 후, 저는 다음과 같은 변경 사항을 적용했습니다:
- 계획 단계 (plan step) 추가.
- 메모리 레이어(memory layer)를 완전히 **
agents.db**로 전환.
스키마 레이아웃은 다음과 같습니다:
sqlite> .schema
CREATE TABLE instructions (
id INTEGER PRIMARY KEY,
...
새로운 엔진 설정 (The New Engine Setup)
instructions테이블:instructions.md를 완전히 대체했습니다. 이 테이블은 에이전트에게 엄격한 목표, 수행해야 할 구체적인 작업, 접근 가능한 CLI 도구, 그리고 성공의 정의가 명확히 규정된 격리된 단계별 지침을 제공합니다.memories테이블: 과거 실행 과정에서 무엇이 잘못되었고 어떻게 수정했는지에 대한 경험을 담고 있습니다.
저는 **합성 메모리 (synthetic memories)**를 사용하여 이전 실행에서 잘못되었던 모든 사항과 에이전트가 해당 상황에서 수행했어야 할 작업들을 memories 테이블에 미리 채워 넣었습니다 (pre-seeded).
실행 흐름 (The Execution Flow)
에이전트는 instructions 테이블을 따라 단계별로 진행하도록 지시받았습니다. 각 단계마다 에이전트는 무엇을 해야 하는지, 어떻게 해야 하는지, 그리고 무엇이 잘못될 수 있는지에 대한 요약(tldr)을 가져오기 위해 memories 테이블을 쿼리(query)합니다. 새로운 문제에 직면하면, 에이전트는 단순히 그 내용을 메모리에 추가합니다.
이러한 변경을 통해 저는 에이전트가 의도하는 작업(계획)을 감사(audit)하고, 필요한 경우 수정 사항을 삽입할 수 있게 되었습니다. 또한 지침과 버그에 대한 계층적 쿼리(hierarchical querying)가 가능해졌으며, 이전의 문제들을 완전히 해결했습니다.
추가 권장 사항 (Additional Recommendations)
제가 에이전트에게 데이터베이스를 읽으라고 지시하는 방식(언제 수행할지 알려주는 방식)을 임시방편(quick fix)으로 프롬프트에 포함시켰지만, 더 신뢰할 수 있는 방법은 하네스(harness)를 직접 수정하여 적절한 지침(instructions)과 메모리(memories)를 삽입하는 것입니다. 이렇게 하면 단계별 SQL 쿼리에 소모되는 토큰을 더 많이 절약할 수 있습니다.
유연성의 대가 (The Flexibility Tax)
PI 코딩 에이전트 하네스(PI coding agents harness)를 오케스트레이터(orchestrator)로 사용하면 유연성은 높아지지만, 상황을 너무 예측 불가능하게 만듭니다. 흐름이 대부분 계층적(hierarchical)임에도 불구하고, 이제 저는 에이전트에게 전체 실행(full run)을 요청하고, 환각(hallucinations)을 잡아내고, 메모리를 업데이트하는 과정에 갇혀버렸습니다...
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기