에이전트 디버깅은 어렵다: AI Kernel을 위한 'Flight Recorder'를 구축한 방법

발행: (2026년 1월 20일 오전 06:54 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

Cover image for Debugging Agents is Tough: How I Built a

에이전트가 왜 환각했는지 추측을 멈추세요. 데이터베이스를 쿼리하세요.

지난 글에서 Agent Control Plane을 소개했습니다—에이전트가 rm -rf / 명령을 환각하는 것을 막기 위해 만든 “Kernel”입니다.
표준 소프트웨어 앱이 충돌하면 스택 트레이스를 받지만, AI 에이전트가 실패하면 보통 한숨을 쉬게 됩니다.

  • refund 도구를 $0와 함께 호출했을까요?
  • ABAC 정책이 차단했나요, 아니면 LLM이 그냥 호출을 잊었나요?
  • 컨텍스트 윈도우가 가득 찼나요?

“죄송합니다, LLM 때문이었습니다”는 엔지니어링 근본 원인이 아니라 변명입니다.
에이전트를 “디지털 직원”으로 다루고 싶다면, 그들의 실행 주기를 Audit Logs(감사 로그)로 다뤄야 합니다. 저는 Kernel에 Flight Recorder(비행 기록기)를 추가했습니다. 왜 이것이 필요한지, 그리고 print() 문만으로는 충분하지 않은 이유를 설명합니다.

“블랙 박스” 문제

Standard LLM observability tools (LangSmith, Arize, etc.) are great for prompt engineering: they tell you about tokens, latency, and costs.
They don’t tell you about Governance.

What I needed to know:

PieceQuestion
Intent에이전트가 사용하려고 시도한 도구는 무엇인가요?
Verdict내 커널이 허용했나요?
Reasoning차단되었다면, 어떤 정책 규칙이 트리거되었나요?

구현: SQLite만 있으면 충분합니다

복잡한 관측 스택을 띄우고 싶지 않았습니다. 저는 감소에 의한 확장을 믿습니다.
Flight Recorder는 커널 인터셉터 체인에 직접 연결된 가벼운 로컬 SQLite 엔진입니다. 결정 로직을 원자적으로 캡처합니다.

# src/agent_control_plane/flight_recorder.py
import sqlite3, json
from datetime import datetime

class FlightRecorder:
    def __init__(self, db_path="agent_blackbox.db"):
        self.conn = sqlite3.connect(db_path)
        self._init_schema()

    def _init_schema(self):
        self.conn.execute("""
            CREATE TABLE IF NOT EXISTS flight_events (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp TEXT,
                agent_id TEXT,
                tool_name TEXT,
                arguments TEXT,
                policy_verdict TEXT,
                violation_reason TEXT
            )
        """)
        self.conn.commit()

    def log_interception(self, agent_id, tool_name, args,
                         policy_verdict, violation_reason=None):
        """
        Records the 'Black Box' data of an interception event.
        """
        self.conn.execute("""
            INSERT INTO flight_events 
            (timestamp, agent_id, tool_name, arguments, policy_verdict, violation_reason)
            VALUES (?, ?, ?, ?, ?, ?)
        """, (
            datetime.now().isoformat(),
            agent_id,
            tool_name,
            json.dumps(args),
            policy_verdict,          # 'ALLOWED' or 'BLOCKED'
            violation_reason
        ))
        self.conn.commit()

그것은 지루한 기술입니다—바로 그 점이 핵심이죠. 견고하고, 쿼리 가능하며, 코드 바로 옆에 위치합니다.

크래시 사이트 쿼리

실제 힘은 데이터를 기록하는 것이 아니라 조사하는 데 있습니다. SQL일 뿐이므로 복잡한 거버넌스 질문에 밀리초 단위로 답할 수 있습니다.

예시 1 – 차단된 고가 환불 찾기

SELECT timestamp, arguments, violation_reason
FROM flight_events
WHERE agent_id = 'finance_agent'
  AND policy_verdict = 'BLOCKED'
  AND tool_name = 'process_refund'
ORDER BY timestamp DESC;

예시 2 – 프롬프트 변경 후 정책 위반 급증 감지

# kernel_v1_demo.py usage
stats = recorder.get_statistics()
print(f"Total Actions: {stats['total_actions']}")
print(f"Blocked Ratio: {stats['by_verdict'].get('blocked', 0) / stats['total_actions']:.2%}")

이것은 “AI 디버깅”을 분위기 점검에서 데이터‑과학 문제로 전환합니다.

과도한 부하 없는 거버넌스

우리는 종종 AI 인프라를 과도하게 복잡하게 만들며, 메모리를 위해 벡터 DB가 필요하고 감사를 위해 대규모 클라우드 로깅이 필요하다고 가정합니다. Flight Recorder는 로컬 파일과 고정 스키마가 종종 더 우수함을 보여줍니다.

  • Zero Latency: 커널과 함께 프로세스 내에서 실행됩니다.
  • Zero Cost: SQLite로 구동됩니다.
  • Total Clarity: 실패로 이어진 정확한 이벤트 순서를 재생합니다.

직접 해보기

Kernel v1.0은 Flight Recorder가 활성화된 상태로 제공됩니다. 저장소를 클론하고 demo_flight_recorder() 함수를 실행하면 데이터베이스 파일이 생성되는 것을 확인할 수 있습니다. 그런 다음 에이전트를 깨뜨려 보세요—보호된 경로(/etc/passwd)에 접근하도록 강제하고 레코더가 현장을 적발하는 모습을 지켜보세요.

🔗 GitHub Repo: imran‑siddique/agent‑control‑plane

거버넌스 없는 인텔리전스는 발생을 기다리는 버그에 불과합니다. Flight Recorder가 바로 그것을 잡는 방법입니다.

Back to Blog

관련 글

더 보기 »