에이전트는 실패한 것이 아닙니다. 너무 많은 것을 너무 빨리 전달받았을 뿐입니다.
요약
에이전트의 실패 원인이 모델의 성능 부족이 아닌, 부적절한 정보 제공 타이밍에 있음을 지적합니다. UI 디자인의 '점진적 공개' 개념을 에이전트 설계에 도입하여 컨텍스트 과부하를 방지해야 한다고 제안합니다.
핵심 포인트
- 에이전트 실패의 주된 원인은 모델의 환각이 아닌 컨텍스트 과부하임
- UI의 '점진적 공개(Progressive disclosure)' 원칙을 에이전트 설계에 적용 필요
- 한꺼번에 쏟아지는 시스템 프롬프트와 정보는 모델의 주의력을 분산시킴
- 정보 노출 타이밍을 조절하여 컨텍스트 윈도우 내 신호(signal)를 강화해야 함
실패한 에이전트 배포의 사후 분석(post-mortems)에서 제가 계속해서 발견하는 패턴이 하나 있습니다. 누군가 실행 추적(trace)을 공유합니다. 에이전트가 잘못된 길로 들어섰거나, 잘못된 결정을 내렸거나, 혹은 더 나쁘게는 되돌릴 수 없는 행동을 저질렀습니다. 그리고 본능적으로 항상 모델을 탓하게 됩니다.
“아, LLM이 환각(hallucination)을 일으켰군.”
“지시사항을 따르지 않았어.”
하지만 추적 기록을 거슬러 올라가며 에이전트가 그 결정을 내린 순간 실제로 무엇을 알고 있었는지 살펴보면, 거의 항상 똑같은 사실을 발견하게 됩니다.
모든 정보가 처음에 거대한 덩어리로 한꺼번에 쏟아졌고, 그 특정 결정을 안내했을 컨텍스트(context) 조각은 아직 관련이 없는 정보 더미 아래 14,000 토큰(tokens) 전으로 파묻혀 있었다는 사실 말입니다.
모델이 실패한 것이 아닙니다. 정보 공개의 타이밍이 실패한 것입니다.
몇 년 전에 에이전트에게 적용되었어야 할 UI 개념
점진적 공개(Progressive disclosure)는 인터페이스 디자인에서 가장 오래된 아이디어 중 하나입니다. 원칙은 간단합니다. 사용자를 한꺼번에 모든 것으로 압도하지 마십시오. 사용자가 현재 하고 있는 일과 관련이 생기는 바로 그 시점에만 정보를 노출하는 것입니다.
- 설정 페이지는 “고급(Advanced)”을 클릭하기 전까지 고급 옵션을 보여주지 않습니다.
- 결제 흐름(checkout flow)은 장바구니를 확인하기 전까지 배송 주소를 묻지 않습니다.
이 통찰은 당연해 보이지만, 엔지니어링 측면에서의 함의는 실질적입니다. 정보에는 적절한 시점이 있으며, 그 시점이 오기 전에 정보를 전달하는 것은 중립적이지 않습니다. 그것은 주의력(attention)을 두고 경쟁합니다. 그것은 사용자를 더 이상 적용되지 않는 버전의 세계에 고정(anchor)시킵니다. 결국 적절한 신호(signal)가 나타났을 때 그것을 찾기 더 어렵게 만듭니다.
이제 우리가 에이전트를 구축하는 방식을 생각해 보십시오. 거의 예외 없이 우리는 정반대로 하고 있습니다. 전체 시스템 프롬프트(system prompt)가 처음에 한꺼번에 들어갑니다.
보안 정책, 도구 설명(tool descriptions), 도메인 규칙, 자격 증명(credentials), 운영 제약 조건, 역사적 컨텍스트(historical context) 등 이 모든 것이 에이전트가 단 한 가지 일도 하기 전에, 즉 에이전트가 문제의 어느 갈래를 따라갈지 전혀 알 수 없는 상태에서 단 한 번의 실행으로 쏟아집니다.
이는 신입 사원이 출근한 첫날, 회사 전체 핸드북, 모든 내부 정책, 접촉할 수 있는 모든 시스템의 로그인 자격 증명, 그리고 지금까지 발생한 모든 사건의 기록이 담긴 바인더를 건네주며, 그 직원이 자리에 앉기도 전에 "자, 이제 이 고객 불만을 처리해 보세요"라고 말하는 것과 같습니다.
우리는 사람에게 그렇게 하지 않습니다. 하지만 에이전트에게는 끊임없이 그렇게 하고 있습니다.
이것이 실제로 문제를 일으키는 두 가지 방식
컨텍스트 타이밍 (Context timing) 실패는 두 가지 뚜렷한 형태로 나타나는 경향이 있으며, 실행 추적(traces)에서 서로 다르게 보이기 때문에 두 가지 모두 명명할 가치가 있습니다.
-
첫 번째는 컨텍스트 과부하 (Context overload)입니다. 에이전트에게 너무 많은 정보가 너무 일찍 주어집니다. 상충하는 신호들이 노이즈 (noise)를 생성합니다. 모델은 지금 당장 중요한 것과, 설령 7단계가 진행된다 하더라도 7단계에서 중요해질 것들을 아우르는 컨텍스트 윈도우 (context window) 전체에서 관련성을 우선순위화해야 합니다. 토큰 예산 (Token budgets)은 상투적인 문구 (boilerplate)에 의해 소모됩니다. 어텐션 (Attention)은 희석됩니다. 에이전트가 아직 관련이 없는, 상황이 잘못되었을 때 어떻게 해야 하는지에 대한 정보 속에 빠져 있기 때문에 단순한 검색 (retrieval) 작업조차 어긋나게 됩니다.
-
두 번째는 더 미묘하고 실제로 더 위험한 방식인 오래된 컨텍스트 (Stale context)입니다. 에이전트에게 시작 시점에는 정확한 정보가 주어졌지만, 에이전트가 실행되는 동안 세상이 변해버린 경우입니다. 의사결정의 근거가 되는 컨텍스트가 이전의 상태를 반영하고 있습니다. 에이전트는 더 이상 사실이 아닌 믿음을 바탕으로 자신 있게 진행합니다. 이는 리서치 루프 (research loops), 다중 파일 편집 (multi-file edits), 또는 시간이 초 단위가 아닌 분 단위로 흐르는 작업 등을 수행하는 장기 실행 에이전트 (long-running agents)에서 특히 고통스럽습니다. 두 경우 모두 해결책은 더 나은 모델이 아닙니다. 각 컨텍스트 조각이 언제 속해야 하는지에 대한 더 나은 이해입니다.
훅 (Hooks)의 실제 정체 (그리고 왜 대부분의 사람들이 오독하는가)
오랫동안 시간 기반의 컨텍스트 전달 (timed context delivery)을 구현할 깔끔한 방법이 없었습니다. 멀티 에이전트 핸드오프 (multi-agent handoffs), 세심한 턴 관리 (turn management), 또는 동적 프롬프트 구성 (dynamic prompt construction) 등을 통해 복잡한 기교를 부릴 수는 있었지만, 그 무엇도 적절하다고 느껴지지 않았습니다. 인과적 트리거 (causal trigger)가 없었기 때문입니다. 당신은 언제 적절한 타이밍인지 항상 추측해야만 했습니다.
훅 (Hooks)이 이 상황을 바꿉니다.
Claude Code와 대부분의 현대적인 에이전트 하네스 (agentic harnesses)에서, 훅은 에이전트 생명주기 (agent lifecycle)의 특정 이벤트에 연결된 인터셉트 지점 (intercept points)입니다: PreToolUse, PostToolUse, PreCompact, Stop.
이들은 타이머에 의해 작동하거나 휴리스틱 (heuristic)에 의해 작동하지 않습니다. 에이전트 자체가 어떤 행동을 취했기 때문에 실행되는 것입니다.
에이전트가 도구 (tool)를 호출하는 것은 에이전트가 문제의 어느 지점에 있는지, 현재 무엇을 하려고 하는지, 그리고 따라서 어떤 컨텍스트가 현재 유효한지에 대한 그라운드 트루스 (ground-truth) 신호입니다. 에이전트가 query_database를 호출할 때, 이는 방금 당신에게 스키마 (schema)가 필요하다고 말한 것과 같습니다. 에이전트가 금융 데이터 엔드포인트 (endpoint)에 접근할 때, 이는 방금 컴플라이언스 규칙 (compliance rules)이 적용되어야 한다고 말한 것입니다. 시스템 프롬프트 (system prompt)에 자격 증명 (credentials)을 쏟아붓고 에이전트가 적절한 시점에 사용하기를 바라는 방식이 아닙니다. 에이전트가 그것을 필요로 하는 도구를 호출하면, 바로 그 순간에 주입 (inject)하는 것입니다.
멘탈 모델 (mental model)의 변화는 컨텍스트를 방송 (broadcasting)하는 것에서 전달 (delivering)하는 것으로 이동합니다. 전자가 소방 호스라면, 후자는 에이전트 자신의 행동에 의해 타이밍이 맞춰진 정밀한 핸드오프 (handoff)입니다.
대부분의 팀은 훅을 안전을 위한 기본 요소 (safety primitive)로 읽습니다. 즉, 에이전트가 하지 말아야 할 일을 하는 것을 막는 방법으로 보는 것입니다. 그러한 프레임워크 (framing)는 정확하지만 불완전하며, 이로 인해 많은 사람들이 훅을 운영적 도구 (operational tool)가 아닌 순수하게 방어적인 도구로 취급하게 만들었습니다. 더 깊은 프레임워크는 훅이 컨텍스트 오케스트레이션 기본 요소 (context orchestration primitive)라는 점입니다. 네, 차단하는 용도로 사용할 수 있습니다. 하지만 주입 (inject), 풍부화 (enrich), 그리고 타이밍 조절 (time)을 위해서도 사용할 수 있습니다. 훅은 에이전트가 아는 것과 에이전트가 하는 것 사이의 인과적 교차점에 위치하며, 이는 정보 공개 타이밍 (disclosure timing)을 중요하게 생각한다면 개입하기에 정확히 적절한 위치입니다.
실제 적용 사례
훅을 정보 공개 메커니즘 (disclosure mechanism)으로 생각하기 시작하면 자연스럽게 떠오르는 네 가지 패턴입니다.
요청 시 제공되는 비밀 정보 및 자격 증명 (Secrets and credentials on demand). 모든 API 키를 사전에 환경 변수에 로드하는 대신, 해당 키가 필요한 특정 도구(tool)를 위해 PreToolUse 훅이 실행될 때 이를 주입합니다. 에이전트는 곧 사용할 예정이 아닌 자격 증명을 보유하지 않습니다. 이를 통해 프롬프트 인젝션 (prompt injection)이나 유출 버그의 피해 범위 (blast radius)를 크게 줄일 수 있습니다.
규제 대상 영역에서의 컴플라이언스 컨텍스트 (Compliance context at regulated surfaces). 에이전트가 금융 서비스, 의료, 법률과 같이 정책 제약이 있는 도메인에서 작동하는 경우, 모든 규칙을 미리 로드하지 않습니다. 에이전트가 규제 대상 영역에 접촉할 때 관련 정책의 하위 집합 (subset)을 노출합니다. 규칙은 최신 상태를 유지하며, 범위가 제한되어 있고, 관리하고자 하는 정확한 동작과 인과적으로 연결됩니다.
재시도 시 제공되는 실패 이력 (Failure history on retry). 에이전트가 어떤 작업을 두 번째 또는 세 번째로 시도하려는 순간이 바로 이전에 무엇이 일어났고 왜 실패했는지를 노출해야 할 시점입니다. 첫 번째 시도 전에는 해당 정보가 그저 노이즈에 불과합니다. 실패한 호출로부터 얻은 PostToolUse 결과가 트리거가 됩니다. 재시도 시에는 초기 시도에는 필요하지 않았던 컨텍스트를 전달받게 됩니다.
요청 게이트 뒤에 숨겨진 고비용 컨텍스트 (Expensive context behind demand gates). 긴 문서, 전체 데이터베이스 스키마 (database schemas), 풍부한 도메인 지식 등은 포함하는 데 비용이 많이 들며, 에이전트가 관련 영역에 접촉하지 않는다면 대부분 낭비됩니다. 이를 필요한 특정 도구를 위한 PreToolUse 뒤에 배치함으로써, 실행 시간의 90% 동안은 작업 컨텍스트를 가볍게 유지하고, 정확히 필요한 순간에만 풍부하게 유지할 수 있습니다.
각 패턴은 동일한 기본 구조를 가집니다. 에이전트의 동작이 신호(signal)가 되고, 훅(hook)은 그 신호를 적절한 컨텍스트 전달로 변환하는 메커니즘이 됩니다.
이것이 여전히 과소평가되는 이유
문제의 일부는 훅(hook)이 도입된 방식에 있습니다. 에이전트 실패에 대한 기본 해결책은 더 크고 상세한 시스템 프롬프트 (system prompt)를 사용하는 것입니다.
더 많은 규칙.
더 많은 예시.
더 많은 커버리지.
솔직히 말해서, 이는 단기적으로는 종종 도움이 됩니다. 하지만 이는 증상만을 치료하는 것입니다. 잘못된 시점에 전달되는 더 큰 프롬프트는 여전히 잘못된 시점에 전달되는 것입니다. 당신은 에이전트가 아직 대부분의 정보가 관련 없는 상태에서 처리해야 할 더 많은 정보를 추가한 셈입니다.
다른 부분은 제가 앞서 언급한 프레이밍 문제 (framing problem)입니다. 훅 (Hooks)은 가드레일 (guardrails)로서 출시되었고, 그것이 채택된 방식입니다. 팀들은 파괴적인 작업 전에 "정말 확실합니까?"와 같은 확인 절차를 추가하기 위해 훅을 사용하는데, 이는 유용하지만 범위가 좁습니다. 컨텍스트 전달 인프라 (context delivery infrastructure)로서의 훅이라는 더 넓은 영역은 아직 많이 탐구되지 않았습니다. 부분적으로는 이것이 새로운 패턴이기 때문이며, 부분적으로는 이를 잘 수행하기 위한 도구들, 즉 Claude Code의 훅이나 에이전트 프레임워크 (agent frameworks)의 구조화된 라이프사이클 이벤트 (structured lifecycle events) 자체가 비교적 최신이기 때문입니다.
신뢰성과의 연결 (The Reliability Connection)
비결정론적 (non-deterministic)이고, 재현하기 어려우며, 디버깅하기 짜증 나는 에이전트 실패의 범주인 일시적 실패 (transient failures)를 살펴보면, 그중 상당수는 근본적으로 정보 공개 타이밍 버그 (disclosure timing bugs)입니다. 에이전트가 근본적인 의미에서 틀린 것이 아니었습니다. 단지 특정 결정에 필요한 것과 비교했을 때, 정보가 불충분하거나 (underspecified), 과부하되었거나 (overloaded), 혹은 오래된 (stale) 컨텍스트 내에서 결정을 내렸을 뿐입니다.
적절한 순간에 적절한 컨텍스트가 제공되면 환각 (hallucinations)이 줄어듭니다. 모델이 노이즈로부터 정보를 재구성하는 대신, 명확하고 최신이며 인과적으로 관련 있는 신호 (signal)를 바탕으로 작업하기 때문입니다. 또한 되돌릴 수 없는 작업 (irreversible actions)도 줄어듭니다. 해당 작업을 고려하는 시점에 작업을 제어하는 제약 조건들이 존재하며, 이전 지시 사항 아래에 묻혀 있지 않기 때문입니다. 작업 컨텍스트가 가볍게 유지되므로 토큰 (tokens) 소모도 줄어듭니다.
이것은 프롬프트 수준의 사고 (prompt-level thinking)가 아니라 인프라 수준의 사고 (infrastructure-level thinking)입니다. 더 나은 프롬프트를 작성하는 것에 관한 것이 아닙니다. 에이전트의 라이프사이클 (lifecycle)을 이해하고 그 라이프사이클에 맞춰 정보를 전달하는 시스템을 구축하는 것에 관한 것입니다.
이것이 나아갈 방향 (Where This Goes)
우리는 아직 초기 단계에 있습니다. 대부분의 프로덕션 에이전트 프레임워크는 여전히 컨텍스트 관리 (Context Management)를 시스템 문제라기보다 프롬프트 엔지니어링 (Prompt Engineering) 문제로 취급합니다. 하지만 에이전트가 더 오래 실행되고, 더 많은 시스템을 접하며, 더 큰 자율성을 가지고 작동할수록, 부적절한 정보 공개 타이밍 (Disclosure Timing)으로 인한 비용은 상승합니다. 에이전트가 할 수 있는 일과 실제로 신뢰성 있게 수행하는 일 사이의 격차는 모델의 능력 (Model Capability)이 아니라 런타임 컨텍스트 아키텍처 (Runtime Context Architecture)에 의해 점점 더 설명될 것입니다.
최전선에서의 흥미로운 미결 과제는 에이전트가 정보를 기다리는 대신, 정보를 요청하는 법을 결국 배울 수 있느냐 하는 것입니다. 자신이 더 확신을 가지고 행동하기 위해 무엇을 알아야 하는지를 하네스 (Harness)에 신호로 보내고, 시스템이 그 정보를 노출할지 여부와 시점을 결정하게 하는 것입니다. 이는 정적인 훅 규칙 (Static Hook Rules)으로는 불가능한 방식으로 루프를 완성할 것입니다.
하지만 그 단계에 도달하기 전이라도, "모든 것을 사전에 쏟아붓는 방식"에서 "훅 (Hooks)을 통해 인과적으로 컨텍스트를 전달하는 방식"으로의 전환은 프로덕션 에이전트를 구축하는 대부분의 팀이 아직 실행하지 못한 실질적인 도약입니다. 그리고 이것은 한 번 깨닫고 나면, 읽는 모든 트레이스 (Trace)에서 보이지 않을 수 없는 종류의 것입니다.
오늘 바로 훅 (Hooks) 시작하기
훅 파이프라인 (Hook Plumbing)을 처음부터 직접 작성하지 않고 Claude Code에서 이를 시작하고 싶다면, 저희는 이를 더 쉽게 만들기 위해 Failproof AI를 구축했습니다.
이는 글로벌 CLI로 설치되며, 단 하나의 명령어로 Claude Code의 훅 시스템에 연결됩니다. 그 시점부터 모든 도구 호출 (Tool Call)은 실행 전후에 Failproof를 거치게 됩니다. 파괴적인 명령 차단, 컨텍스트로의 비밀 정보 유출 방지, 에이전트를 프로젝트 경계 내에 유지, main 브랜치로의 실수로 인한 푸시 방지 등 가장 흔한 실패 모드 (Failure Modes)를 다루는 30가지 내장 정책을 즉시 사용할 수 있습니다. 이는 대부분의 팀이 무언가 잘못된 후에야 비로소 발견하게 되는 것들입니다.
위의 모든 내용과 더 관련이 깊은 부분은 커스텀 정책 (custom policies)입니다. 여러분은 세 가지 기본 요소(primitives)인 allow, deny, instruct를 사용하여 일반 JavaScript로 직접 정책을 작성할 수 있습니다. 여기서 instruct 기본 요소가 컨텍스트 전달 (context delivery)을 수행하는 역할을 합니다. 이는 작업을 차단하는 것이 아니라, 도구 (tool)가 실행되는 바로 그 순간 Claude의 컨텍스트 (context)에 메시지를 주입합니다. 예를 들어, 에이전트가 쿼리 명령을 실행할 때만 데이터베이스 스키마 (database schema)가 나타나게 하고 싶다면, 해당 특정 도구 호출 (tool call)을 매칭하고 instruct를 사용하여 그 즉시 스키마를 주입하는 정책을 작성하면 됩니다. 스키마는 시스템 프롬프트 (system prompt)에 계속 머물러 있지 않습니다. 스키마는 그것이 필요한 정확한 시점에, 해당 정보가 필요했던 동작과 인과적으로 연결되어 도착합니다.
또한 프로젝트 리포지토리 (repo)의 .failproofai/policies/ 폴더에 정책 파일을 넣어두면 설정 변경 없이 자동으로 로드됩니다. 이 폴더를 커밋하면, 팀의 모든 구성원이 다음 풀 (pull)을 받을 때 동일한 정책을 갖게 됩니다. 이는 팀 수준에서 적용되는 동일한 점진적 공개 (progressive disclosure) 개념으로, 코드베이스 (codebase)와 함께 이동하는 공유된 컨텍스트 표준을 의미합니다.
세션을 탐색하고, 어떤 도구 호출에서 정확히 어떤 정책이 실행되었는지 확인하며, 전체 트레이스 (trace)를 검토할 수 있는 로컬 대시보드 (local dashboard)도 제공됩니다. 이는 사후에 정보 공개 타이밍 문제를 디버깅 (debugging)할 때 유용합니다. 모든 것은 로컬에서 실행되며, 어떤 데이터도 사용자의 기기를 벗어나지 않습니다.
리포지토리는 https://github.com/FailproofAI/failproofai에 있습니다. 만약 이러한 프레임워크 (framing)가 에이전트 신뢰성 (agent reliability)에 대해 여러분이 생각하는 방식과 공명한다면, 스타 (star)를 눌러주시는 것이 큰 힘이 됩니다. 또한 저희가 아직 생각하지 못한 훅 패턴 (hook patterns)을 구축하셨다면, PR (pull request)을 보내주시거나 단순히 대화를 나누는 것도 진심으로 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기