상위: 05_00_MOC
한 줄 정의
에이전트 시스템에서 컨텍스트 부패는 단발성 문제가 아니라 누적(accumulative) 문제다. 멀티턴 대화, 툴 호출 루프, 서브에이전트 오케스트레이션이 진행될수록 컨텍스트는 저절로 불어나고, 부패는 조용히 그리고 위치마다 다르게 심해진다. 에이전트 설계의 핵심은 결국 컨텍스트를 얼마나 능동적으로 관리하느냐에 달려 있다.
왜 중요한가
에이전트는 한 번 호출하고 끝나는 구조가 아니라 같은 컨텍스트를 계속 물려받으며 루프를 도는 구조다. 그래서 단발 호출에서는 잘 드러나지 않던 부패가 턴이 쌓일수록 누적되고, 어느 순간 검색 실패나 잘못된 거부로 표면화된다. 부패를 관리할 줄 모르면 긴 작업을 수행하는 에이전트일수록 더 빨리 무너진다.
1. 왜 에이전트가 특히 취약한가
1.1 단발 호출 vs. 에이전트 루프의 구조 차이
단발 LLM 호출과 에이전트 시스템은 컨텍스트가 자라는 양상부터 다르다.
graph LR subgraph 단발호출 A1["입력<br/>(고정 길이)"] --> B1["LLM 호출"] --> C1["출력"] end subgraph 에이전트루프 A2["초기 지시"] --> B2["Turn 1<br/>LLM 호출"] B2 --> C2["툴 호출<br/>결과 반환"] C2 --> D2["Turn 2<br/>컨텍스트 누적"] D2 --> E2["툴 호출<br/>결과 반환"] E2 --> F2["Turn N<br/>컨텍스트 급증"] end
에이전트 루프에서는 매 턴마다 컨텍스트가 저절로 늘어난다.
- 이전 대화 이력 (Human+Assistant turns)
- 툴 호출 요청 + 툴 응답 (tool_use + tool_result 블록)
- 중간 추론 과정 (thinking blocks, 확장 추론 사용 시)
- 에러 메시지 및 재시도 이력
1.2 컨텍스트 부패의 누적 메커니즘
Chroma Research(2025)의 LongMemEval 실험은 한 가지를 분명히 보여준다. 긴 컨텍스트는 모델에게 “무엇이 관련 있는지 찾기”라는 검색 과제를 떠안기고, 이 부담이 정작 풀어야 할 “어떻게 답할지”라는 추론의 성능을 갉아먹는다.
에이전트 루프에서는 이 문제가 매 턴 되풀이된다.
| 턴 수 | 컨텍스트 토큰 (개념도) | 부패 수준 |
|---|---|---|
| Turn 1 | ~2K | 낮음 |
| Turn 5 | ~10K | 시작 |
| Turn 10 | ~25K | 중간 |
| Turn 20 | ~60K | 높음 — 검색 실패 빈번 |
| Turn 30+ | ~100K+ | 심각 — Claude의 경우 abstention 급증 |
작업이 복잡할수록 이 누적은 더 빠르게 진행된다. 코드 실행 결과나 웹 검색 결과, 파일 내용 같은 툴 응답은 보통 수백에서 수천 토큰을 차지하기 때문이다.
2. 에이전트 컨텍스트 부패의 4가지 실패 패턴
패턴 A: 초기 지시 망각 (Instruction Forgetting)
긴 대화가 이어지면 모델이 시스템 프롬프트나 초기 사용자 지시를 “잊은” 듯 행동한다. 기억이 지워진 것이 아니라, 컨텍스트 중간에 놓인 초기 지시가 U자형 위치 편향 탓에 어텐션을 받지 못하는 것이다(Liu et al., 2023 “Lost in the Middle”).
예컨대 “항상 한국어로 답하라”던 시스템 프롬프트가 10턴쯤 지나면 슬그머니 영어 응답으로 바뀐다.
패턴 B: 툴 결과 오활용 (Tool Result Misuse)
툴 호출 결과를 이전 결과와 헷갈리거나, 여러 결과 중 오래된 것을 참조하는 오류다. 같은 구조의 tool_result 블록이 컨텍스트에 여럿 쌓이면 induction head 기반 어텐션이 엉뚱한 블록을 이어 붙일 수 있다.
패턴 C: 누적 오류 전파 (Error Accumulation)
중간 단계의 오류(툴 오류나 잘못된 추론)가 컨텍스트에 쌓이면 이후 단계의 모델이 이를 “이미 확립된 사실”로 받아들인다. 오래된 오류가 컨텍스트 중간부에 자리 잡으면 위치 편향 때문에 새 정보로 바로잡기도 어려워진다.
패턴 D: 과제 표류 (Task Drift)
긴 멀티턴 루프에서 원래 목표를 놓치고 가장 최근 정보(recency bias)에 지나치게 쏠리는 현상이다. 에이전트가 “지금 무엇을 하던 중이었는지”보다 “마지막에 무슨 일이 있었는지”에 반응하기 시작한다.
3. Claude Code·Codex 스타일 에이전트의 실제 취약점
에이전트 툴 루프에서 컨텍스트 부패가 구체적으로 드러나는 시나리오를 보자.
3.1 코드 수정 루프
[파일 읽기] → [분석] → [수정] → [오류 발생] → [재시도]
→ [파일 재읽기] → [재분석] → ...
이 루프가 열 번 넘게 돌면 이런 일이 벌어진다.
- 처음 읽은 파일 내용이 컨텍스트 중간으로 밀려나 위치 편향으로 접근이 떨어진다
- 여러 tool_result 블록(파일 내용) 중 오래된 버전을 참조할 위험이 커진다
- 오류 메시지가 쌓이면서 “이 파일은 손댈 수 없는 문제가 있다”는 잘못된 패턴을 학습한다
3.2 리서치 에이전트
[검색1] → [결과1 저장] → [검색2] → [결과2 저장] → ...
→ [종합 분석]
검색 결과가 컨텍스트 중간부에 쌓이면 이렇게 된다.
- 초기 검색 결과가 Lost in the Middle 효과로 최종 분석에서 누락된다
- 의미가 비슷한 검색 결과들이 서로 디스트랙터로 작용한다 (NoLiMa의 distractor 효과와 같다)
3.3 멀티에이전트 오케스트레이션
오케스트레이터가 여러 서브에이전트의 결과를 모을 때는 이런 위험이 있다.
- 서브에이전트 결과가 오케스트레이터 컨텍스트에 차례로 덧붙는다
- 먼저 끝난 서브에이전트 결과가 중간에 묻혀 최종 종합에서 빠질 수 있다
4. 에이전트 컨텍스트 관리 전략
전략 1: 컨텍스트 윈도우 예산 설계 (Budget Design)
에이전트 루프 시작 전에 컨텍스트 예산을 명시적으로 설계한다.
[권장 구조]
시스템 프롬프트: ~2K 토큰 (앞부분 고정)
현재 과제 상태: ~1K 토큰 (앞부분, 매 턴 업데이트)
최근 N턴 이력: ~5K 토큰 (슬라이딩 윈도우)
현재 툴 결과: ~3K 토큰 (끝부분)
사용자 질문: ~500 토큰 (끝부분 직전)
───────────────────────────
총: ~12K 토큰 (안정 구간 유지)
핵심 원칙은 컨텍스트 총량이 모델의 NoLiMa effective length 안에 머물도록 설계하는 것이다.
전략 2: 컨텍스트 압축 / 요약 (Context Summarization)
긴 대화 이력을 그대로 쌓아 두지 말고 주기적으로 요약본으로 갈아 끼운다.
graph LR A["Turn 1~10<br/>전체 이력 유지"] --> B{"이력 길이<br/>임계값 초과?"} B -- "YES" --> C["이력 요약 호출<br/>(별도 LLM 호출)"] C --> D["요약본으로 교체<br/>상세 이력 삭제"] D --> E["Turn 11~<br/>요약본 + 신규 이력"] B -- "NO" --> E
이 방식의 장점은 이렇다.
- 컨텍스트 길이를 능동적으로 통제한다
- 이력에서 핵심 정보만 남긴다
대신 다음을 유의해야 한다.
- 요약 과정에서 정보가 손실될 수 있다 (요약 품질에 좌우된다)
- 요약 자체가 추가 LLM 호출이라 비용이 늘어난다
전략 3: 검색-추론 분리 (Focused Context per Turn)
에이전트 턴마다 전체 이력을 넘기지 말고, 현재 서브태스크에 관련된 정보만 추려 focused context를 구성한다.
[비효율적 패턴]
오케스트레이터 → 서브에이전트 전달:
전체 대화 이력 (100K 토큰) + 서브태스크 지시
[효율적 패턴]
오케스트레이터 → 서브에이전트 전달:
해당 서브태스크에 관련된 컨텍스트만 (1~3K 토큰) + 서브태스크 지시
Chroma(2025)의 Focused Input 실험 결과를 에이전트 시스템에 그대로 옮긴 패턴이다.
전략 4: 상태 외부화 (State Externalization)
에이전트가 기억해야 할 상태(state)를 컨텍스트에 쌓아 두지 말고 외부 저장소에 보관했다가 필요할 때만 꺼내 온다.
graph TD A[에이전트 루프] --> B{"현재 작업 상태<br/>컨텍스트에 유지?"} B -- "전통적 방식" --> C["컨텍스트에 축적<br/>→ 부패 위험"] B -- "외부화 방식" --> D["외부 DB/메모리에 저장"] D --> E["필요 시 Focused Query<br/>관련 항목만 조회"] E --> F["짧은 컨텍스트로<br/>추론 수행"]
외부 상태 저장소 유형:
- 단기: 인메모리 딕셔너리 (같은 세션 내)
- 중기: 세션 파일 / SQLite
- 장기: 벡터 DB (의미 기반 검색)
5. Claude의 Abstention 패턴: 에이전트 시스템에서의 의미
Chroma Research(2025)의 LongMemEval 실험에서 Claude Opus 4와 Sonnet 4는 Full 컨텍스트 조건에서 abstention(답변 거부)이 급증했다. 불확실할 때 모른다고 답하도록 학습된 RLHF 훈련 방향의 결과다.
에이전트 시스템에서 이 패턴은 양면적이다.
| 상황 | Abstention의 영향 |
|---|---|
| 정보가 실제로 없을 때 | 올바른 거부 — 환각 방지 |
| 정보가 컨텍스트에 있지만 찾지 못할 때 | 컨텍스트 부패의 증상 — 잘못된 거부 |
실제 사례를 보자(Chroma 2025, Claude Sonnet 4, Full 조건).
- 질문: “How many days passed between the gardening workshop and planting the tomatoes?”
- 정답: 6일 (컨텍스트 내 명시된 날짜에서 계산 가능)
- 모델 응답: “the specific dates for these events are not provided in the chat history”
에이전트 루프에서 이런 잘못된 거부가 일어나면 악순환이 생긴다. 에이전트가 “정보가 없다”고 판단해 불필요한 툴을 더 호출하고, 그만큼 컨텍스트가 늘어나 부패가 심해지는 양성 피드백 루프다.
대응 원칙은 이렇다. Claude 기반 에이전트에서 abstention이 늘어나는 시점을 컨텍스트 부패의 조기 경보 신호로 보고 모니터링하라.
6. 에이전트 설계 원칙 — 컨텍스트 부패 관점
graph TD P1["원칙 1<br/>컨텍스트 예산 명시적 설계<br/>(NoLiMa effective length 이내 목표)"] P2["원칙 2<br/>슬라이딩 윈도우 + 요약<br/>(전체 이력 무한 축적 금지)"] P3["원칙 3<br/>툴 결과 선택적 유지<br/>(최신 관련 결과만 보존)"] P4["원칙 4<br/>상태 외부화<br/>(컨텍스트 = 추론용, DB = 기억용)"] P5["원칙 5<br/> Abstention 모니터링<br/>(증가 시 컨텍스트 정리 트리거)"] P6["원칙 6<br/>서브에이전트 Focused Context<br/>(오케스트레이터 이력 전체 전달 금지)"] P1 --> CORE["컨텍스트 부패<br/>완화 에이전트"] P2 --> CORE P3 --> CORE P4 --> CORE P5 --> CORE P6 --> CORE
원칙별 실행 지침
원칙 1 — 컨텍스트 예산 설계
- 목표: 총 컨텍스트를 GPT-4.1 기준 16K, Claude 기준 32K 이하로 유지 (NoLiMa effective length 기준)
- 초과하면 자동 압축을 트리거한다
원칙 2 — 슬라이딩 윈도우 + 요약
- 최근 N턴만 원문으로 두고 그 이전은 요약본으로 교체한다
- N 기본값은 3~5를 권하되 도메인에 맞게 조정한다
원칙 3 — 툴 결과 선택적 유지
- 툴 결과를 죄다 컨텍스트에 쌓지 않는다
- 현재 과제에 바로 필요한 최신 결과만 남긴다
- 이전 툴 결과는 외부 저장소로 옮긴다
원칙 4 — 상태 외부화
- “에이전트가 기억해야 할 것”과 “LLM이 지금 생각해야 할 것”을 나눈다
- 작업 상태(task state), 완료된 서브태스크, 발견한 사실 따위는 외부 DB에 저장한다
원칙 5 — Abstention 모니터링
- Claude 기반 에이전트에서 abstention rate를 자동으로 추적한다
- 일정 임계값을 넘으면 컨텍스트 정리 루틴을 자동 실행한다
원칙 6 — 서브에이전트 Focused Context
- 오케스트레이터가 서브에이전트를 호출할 때 전체 이력을 넘기지 않는다
- 해당 서브태스크에 필요한 최소 컨텍스트만 구성해 전달한다
7. 에이전트 프레임워크별 컨텍스트 관리 패턴
Claude Code / Anthropic Agent SDK
- context window 모니터링: 매 턴
usage.input_tokens를 추적하는 것이 좋다 - 중간 요약 패턴: 시스템 프롬프트에 “50K 토큰 초과 시 이전 이력을 요약하라”는 지시를 넣는다
- subagent 호출 시:
system프롬프트에 서브태스크 관련 컨텍스트만 담은 별도 메시지를 구성한다
일반 멀티에이전트 패턴
- 검색 에이전트와 추론 에이전트 분리: Chroma 2025 Focused Input 실험을 에이전트에 적용한 것이다
- 메모리 에이전트 분리: 장기 상태 관리를 전담하는 에이전트를 따로 두어 주 추론 에이전트의 컨텍스트 부담을 던다
8. 미해결 논쟁점
-
컨텍스트 요약의 적절한 타이밍 — 언제 요약을 트리거할 것인가? 토큰 수 기준인가, 성능 저하 감지 기준인가? 성능 저하를 실시간으로 감지하는 표준 방법은 아직 없다.
-
슬라이딩 윈도우 크기의 최적값 — N=3이 나은가, N=10이 나은가? 도메인과 과제, 모델마다 달라 일반적 기준이 없다.
-
외부 메모리냐, 컨텍스트 내 이력이냐 — 외부 DB 검색으로 만든 Focused Context가 순수 컨텍스트 이력보다 늘 나은가? 검색이 어긋나면 외부화가 오히려 성능을 떨어뜨릴 수 있다.
-
Thinking Mode와 컨텍스트 부패의 상호작용 — 확장 추론을 켠 에이전트는 thinking block이 컨텍스트를 추가로 잡아먹는다. Thinking이 부패를 줄이는 효과가 thinking block이 부르는 추가 부패를 상쇄할 만큼인가?
-
에이전트 루프에서의 비균질성 패턴 — 단발 호출에서 나타나는 비균질적 성능 저하(어느 위치에서, 어떤 과제에서 실패하는지)가 에이전트 루프에서도 똑같이 나타나는지에 관한 실증 연구가 부족하다.
관련 노트
- 05_00_MOC — 챕터 05 전체 맵
- 05_03-메커니즘-왜-발생하는가 — 이중 과제 부하 메커니즘 (에이전트 취약성의 이론적 근거)
- 05_07-처방-완화-체크리스트 — 컨텍스트 최소화·분리 처방의 상세 실행 지침
- 05_04-paper-context-rot-chroma — LongMemEval Focused vs. Full 실험 (핵심 근거)
- 06 해결전략 — 검색-추론 분리 기반 멀티에이전트 전략 전체
참고문헌
- Context Rot: How Increasing Input Tokens Impacts LLM Performance — Kelly Hong, Anton Troynikov, Jeff Huber, Chroma Research, 2025
- LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory — Di Wu et al., ICLR 2025
- Lost in the Middle: How Language Models Use Long Contexts — Nelson F. Liu et al., TACL 2024
- Context Length Alone Hurts LLM Performance Despite Perfect Retrieval — Du et al., Findings of EMNLP 2025
- NoLiMa: Long-Context Evaluation Beyond Literal Matching — Modarressi et al., ICML 2025
- AbsenceBench: Can LLMs Reason About What Is Not There? — Harvey Yiyun Fu et al., 2025
- In-context Learning and Induction Heads — Olsson et al., 2022