에이전트 아키텍처 감사은(는) 무엇을 하나요?
래퍼 계층, 오래된 메모리, 재시도 루프, 혹은 전송/렌더링 변이 뒤에 실패를 숨기는 에이전트 시스템을 위한 진단 워크플로입니다.
활성화 시기
필수 사용:
- 모든 에이전트 또는 LLM 기반 애플리케이션을 프로덕션에 출시할 때
- 도구 호출, 메모리 또는 다단계 워크플로가 포함된 기능을 출시할 때
- 래퍼 계층을 추가한 후 에이전트 동작이 저하될 때
- 사용자가 "에이전트가 점점 나빠지고 있어요" 또는 "도구가 불안정해요"라고 보고할 때
- 동일한 모델이 플레이그라운드에서는 잘 작동하지만 사용자 래퍼 내에서는 깨질 때
- 15분 이상 에이전트 동작을 디버깅했지만 근본 원인을 찾지 못했을 때
특히 중요한 경우:
- 새 프롬프트 계층, 도구 정의 또는 메모리 시스템을 추가한 경우
- 시스템 내의 서로 다른 에이전트가 일관되지 않게 동작하는 경우
- 어제까지 괜찮았던 모델이 오늘 환각을 일으키는 경우
- 숨은 복구/재시도 루프가 조용히 응답을 변형하고 있다고 의심되는 경우
사용하지 말아야 할 경우:
- 일반 코드 디버깅 —
agent-introspection-debugging사용 - 코드 리뷰 — 언어별 리뷰어 에이전트 사용
- 보안 스캐닝 —
security-review또는security-review/scan사용 - 에이전트 성능 벤치마킹 —
agent-eval사용 - 새 기능 작성 — 적절한 워크플로 스킬 사용
12계층 스택
모든 에이전트 시스템에는 이러한 계층이 있습니다. 이 중 어느 것이라도 응답을 손상시킬 수 있습니다:
| # | 계층 | 문제점 |
|---|---|---|
| 1 | 시스템 프롬프트 | 충돌하는 지침, 지침 비대화 |
| 2 | 세션 기록 | 이전 턴에서 잘못된 컨텍스트 주입 |
| 3 | 장기 메모리 | 세션 간 오염, 새 대화에 이전 주제 등장 |
| 4 | 증류 | 압축된 아티팩트가 의사 사실로 재유입 |
| 5 | 능동 회상 | 중복 요약 계층이 컨텍스트 낭비 유발 |
| 6 | 도구 선택 | 잘못된 도구 라우팅, 모델이 필수 도구 건너뜀 |
| 7 | 도구 실행 | 환각 실행 — 호출을 주장하지만 실제로는 수행하지 않음 |
| 8 | 도구 해석 | 도구 출력을 오해하거나 무시 |
| 9 | 응답 형성 | 최종 응답의 형식 손상 |
| 10 | 플랫폼 렌더링 | 전송 계층 변이 (UI, API, CLI가 유효한 응답 변형) |
| 11 | 숨은 복구 루프 | 두 번째 LLM 패스를 실행하는 자동 폴백/재시도 에이전트 |
| 12 | 지속성 | 만료된 상태 또는 캐시된 아티팩트를 최신 증거로 재사용 |
일반적인 실패 패턴
1. 래퍼 회귀
기본 모델은 정확한 답변을 생성하지만 래퍼 계층이 오히려 성능을 저하시킵니다.
증상:
- 모델이 플레이그라운드나 직접 API 호출에서는 잘 작동하지만 사용자 에이전트에서는 깨짐
- 새 프롬프트 계층을 추가했더니 기존 동작이 저하됨
- 에이전트가 확신에 차 있지만 확신에 찬 잘못된 답을 제공
- "마지막 업데이트 전까지는 잘 작동했어요"
2. 메모리 오염
이전 주제가 히스토리, 메모리 검색 또는 증류를 통해 새 대화로 유출됩니다.
증상:
- 에이전트가 관련 없는 과거 주제를 꺼냄
- 사용자 수정이 적용되지 않음 (이전 메모리가 새 정보를 덮어씀)
- 동일 세션 아티팩트가 의사 사실로 재유입
- 메모리가 지속적으로 증가하며 시간이 지남에 따라 응답 품질 저하
3. 도구 규율 실패
도구가 프롬프트에 선언되었지만 코드에서 강제되지 않습니다. 모델이 도구를 건너뛰거나 실행을 환각합니다.
증상:
- 프롬프트에 "도구 X를 반드시 사용해야 함"이라고 명시되어 있지만 모델이 호출 없이 응답
- 도구 결과가 올바른 것처럼 보이지만 실제로는 실행된 적이 없음
- 서로 다른 도구가 동일한 책임을 두고 경쟁
- 모델이 필요하지 않을 때 도구를 사용하거나 반드시 사용해야 할 때 건너뜀
4. 렌더링/전송 손상
에이전트의 내부 응답은 정확하지만 플랫폼 계층이 전달 중에 변이시킵니다.
증상:
- 로그에는 올바른 응답이 표시되지만 사용자는 깨진 출력을 봄
- 마크다운 렌더링, JSON 파싱 또는 스트리밍 조각이 유효한 응답을 손상
- 숨은 폴백 에이전트가 전달 전에 조용히 응답을 대체
- 터미널과 UI 간 출력 차이
5. 숨은 에이전트 계층
명시적인 계약 없이 자동 복구, 재시도, 요약 또는 회상 에이전트가 실행됩니다.
증상:
- 내부 생성과 사용자 전달 간 출력이 변경됨
- 사용자가 모르는 사이에 두 번째 LLM 패스를 실행하는 "자동 수정" 루프
- 여러 에이전트가 조정 없이 동일한 출력을 수정
- 보이지 않는 계층에 의해 응답이 "부드럽게" 되거나 "수정"됨
감사 워크플로
1단계: 범위 설정
감사할 대상을 정의합니다:
- 대상 시스템 — 어떤 에이전트 애플리케이션인가?
- 진입점 — 사용자가 어떻게 상호 작용하는가?
- 모델 스택 — 어떤 LLM과 공급자인가?
- 증상 — 사용자가 무엇을 보고하는가?
- 시간대 — 언제부터 시작되었는가?
- 감사할 계층 — 12개 계층 중 어떤 것이 적용되는가?
2단계: 증거 수집
코드베이스에서 증거를 수집합니다:
- 소스 코드 — 에이전트 루프, 도구 라우터, 메모리 수용, 프롬프트 조립
- 로그 — 과거 세션 추적, 도구 호출 기록
- 설정 — 프롬프트 템플릿, 도구 스키마, 공급자 설정
- 메모리 파일 — SOP, 지식 베이스, 세션 아카이브
rg를 사용하여 안티 패턴을 검색합니다:
# 프롬프트 텍스트에만 표현된 도구 요구사항 (코드에는 없음)
rg "must.*tool|必须.*工具|required.*call" --type md
# 검증 없는 도구 실행
rg "tool_call|toolCall|tool_use" --type py --type ts
# 주 에이전트 루프 외부의 숨은 LLM 호출
rg "completion|chat\.create|messages\.create|llm\.invoke"
# 사용자 수정 우선순위 없는 메모리 수용
rg "memory.*admit|long.*term.*update|persist.*memory" --type py --type ts
# 추가 LLM 호출을 실행하는 폴백 루프
rg "fallback|retry.*llm|repair.*prompt|re-?prompt" --type py --type ts
# 조용한 출력 변이
rg "mutate|rewrite.*response|transform.*output|shap" --type py --type ts
3단계: 실패 매핑
각 결과에 대해 다음을 문서화합니다:
- 증상 — 사용자가 보는 것
- 메커니즘 — 래퍼가 이를 어떻게 유발하는지
- 소스 계층 — 12개 계층 중 어느 것인지
- 근본 원인 — 가장 깊은 원인
- 증거 — 파일:줄 또는 로그:행 참조
- 신뢰도 — 0.0에서 1.0 사이
4단계: 수정 전략
기본 수정 순서 (프롬프트 우선이 아닌 코드 우선):
- 도구 요구사항을 코드로 게이트 — 프롬프트 텍스트가 아닌 코드로 강제
- 숨은 복구 에이전트 제거 또는 축소 — 명시적인 계약으로 폴백 공개
- 컨텍스트 중복 감소 — 동일 정보가 프롬프트 + 히스토리 + 메모리 + 증류를 통해 전달되지 않도록 함
- 메모리 수용 강화 — 에이전트 주장보다 사용자 수정 우선
- 증류 트리거 강화 — 압축해서는 안 될 것을 압축하지 않음
- 렌더링 변이 감소 — 변형하지 말고 통과시키기
- 타입이 지정된 JSON 봉투로 변환 — 자유 형식 산문이 아닌 구조화된 내부 흐름
심각도 모델
| 수준 | 의미 | 조치 |
|---|---|---|
critical | 에이전트가 잘못된 운영 동작을 확신하여 생성할 수 있음 | 다음 릴리스 전에 수정 |
high | 에이전트가 정확성 또는 안정성을 자주 저하시킴 | 이번 스프린트에 수정 |
medium | 정확성은 대개 유지되지만 출력이 취약하거나 낭비적임 | 다음 사이클에 계획 |
low | 주로 미용 또는 유지보수 문제 | 백로그에 추가 |
출력 형식
다음 순서로 사용자에게 결과를 제시합니다:
- 심각도 순위별 결과 (가장 심각한 것부터)
- 아키텍처 진단 (어느 계층이 무엇을 어떻게 손상시켰는지)
- 정렬된 수정 계획 (코드 우선, 프롬프트 우선 아님)
칭찬이나 요약으로 시작하지 마십시오. 시스템이 손상된 경우, 그렇게 직접적으로 말하십시오.
빠른 진단 질문
에이전트 시스템을 감사할 때 다음 질문에 답하십시오:
| # | 질문 | 예 → |
|---|---|---|
| 1 | 모델이 필수 도구를 건너뛰고도 응답할 수 있습니까? | 도구가 코드로 게이트되지 않음 |
| 2 | 낡은 대화 내용이 새 턴에 나타납니까? | 메모리 오염 |
| 3 | 동일한 정보가 시스템 프롬프트, 메모리, 히스토리에 모두 있습니까? | 컨텍스트 중복 |
| 4 | 플랫폼이 전달 전에 두 번째 LLM 패스를 실행합니까? | 숨은 복구 루프 |
| 5 | 내부 생성과 사용자 전달 간 출력이 다릅니까? | 렌더링 손상 |
| 6 | "도구 X를 반드시 사용해야 함" 규칙이 프롬프트 텍스트에만 있습니까? | 도구 규율 실패 |
| 7 | 에이전트 자신의 독백이 영구 메모리가 될 수 있습니까? | 메모리 중독 |
피해야 할 안티 패턴
- 래퍼 계층 회귀를 반증하기 전에 모델을 비난하지 마십시오.
- 오염 경로를 보여주지 않고 메모리를 비난하지 마십시오.
- 깨끗한 현재 상태가 더러운 과거 사건을 지우도록 허용하지 마십시오.
- 마크다운 산문을 신뢰할 수 있는 내부 프로토콜로 취급하지 마십시오.
- 프롬프트 텍스트에 "반드시 사용"이라고 쓰여 있어도 코드에서 강제하지 않는다면 받아들이지 마십시오.
- 결과는 직접적이고, 증거에 기반하며, 심각도 순위를 매기십시오.
보고서 스키마
감사는 다음 형식을 따르는 구조화된 보고서를 생성해야 합니다:
{
"schema_version": "ecc.agent-architecture-audit.report.v1",
"executive_verdict": {
"overall_health": "high_risk",
"primary_failure_mode": "string",
"most_urgent_fix": "string"
},
"scope": {
"target_name": "string",
"model_stack": ["string"],
"layers_to_audit": ["string"]
},
"findings": [
{
"severity": "critical|high|medium|low",
"title": "string",
"mechanism": "string",
"source_layer": "string",
"root_cause": "string",
"evidence_refs": ["file:line"],
"confidence": 0.0,
"recommended_fix": "string"
}
],
"ordered_fix_plan": [
{ "order": 1, "goal": "string", "why_now": "string", "expected_effect": "string" }
]
}
관련 스킬
agent-introspection-debugging— 에이전트 런타임 실패 (루프, 타임아웃, 상태 오류) 디버깅agent-eval— 에이전트 성능을 직접 비교 벤치마킹security-review— 코드 및 설정에 대한 보안 감사autonomous-agent-harness— 자율 에이전트 운영 설정agent-harness-construction— 처음부터 에이전트 하네스 구축