context가 차면 전략적으로 줄이는 법
"The agent can forget strategically and keep working forever." 전략적 망각 = 엔지니어링 능력.
왜 compact가 필요한가?
agent가 오래 실행되면 messages[]가 팽창합니다: read_file은 수천 token을 반환하고, bash는 수백을 반환하며, 매 라운드 모델의 추론 텍스트도 추가됩니다. 50라운드 실행하면 context가 100K+가 될 수 있습니다. 두 가지 결과:
- 모델 한도에 도달: 윈도우 크기에 달하면 실패하거나 API 호출당 비용이 선형으로 증가합니다.
- 주의 분산: 현재 작업이 30라운드 전의 관련 없는 tool_result에 묻혀버리고 모델이 헤매기 시작합니다.
s06의 접근법: agent가 중요하지 않은 내용을 능동적으로 잊되 핵심 상태는 유지합니다. 가벼운 것부터 무거운 것까지 3계층 메커니즘이 있습니다.
Layer 1 · micro_compact (매 라운드 조용히 실행)
가장 저렴한 계층입니다. 매 LLM 호출 전에 실행하여 3개 이상 오래된 tool_result를 플레이스홀더로 교체합니다:
# 10라운드 이전은 대부분 tool_result가 이렇게 됩니다: { "type": "tool_result", "tool_use_id": "toolu_01A", "content": "[Previous: used bash]" # 수천 자에서 수십 자로 }
예외가 있습니다: read_file 결과는 압축하지 않습니다. 왜냐하면 read 출력은 참고 자료이기 때문에—압축하면 모델이 다시 읽어야 하고 오히려 더 비쌉니다.
PRESERVE_RESULT_TOOLS = {"read_file"} # 절대 압축하지 않습니다
micro_compact가 turn마다 오래된 결과를 삭제하는 것 보기
아래에서 10라운드 상호작용을 단계별로 시뮬레이션하며 매 라운드 전에 micro_compact를 실행합니다. messages[]의 오래된 tool_result가 어떻게 [Previous: ...]로 변하는지, 하지만 최근 3개는 원본을 유지하는지 확인하세요.
Layer 2 · auto_compact (임계값 초과 시 트리거)
micro가 계속 실행되더라도 규모가 누적되면 결국 한도를 초과합니다. s06에는 임계값이 설정되어 있습니다(기본값 50000 token):
- token 수 추정
len(str(messages)) // 4(대략적이지만 충분합니다). - 임계값 초과 → 완전한 transcript를
.transcripts/transcript_TIMESTAMP.jsonl에 디스크에 기록 (보관용). - LLM에게 전체 대화에 대한 summary를 작성하게 합니다.
messages전체를 하나의"[compressed] SUMMARY..."로 교체합니다.
대가는 명확합니다—구체적인 도구 출력, 대화 톤이 사라지고 개요만 남습니다. 하지만 agent는 계속 일할 수 있으며, 이것이 핵심 이점입니다.
Layer 3 · 모델이 직접 compact 도구 호출
auto_compact는 harness가 자동으로 트리거하고 모델은 모릅니다. Layer 3은 반대입니다: 모델에게 compact 도구를 줘서 능동적으로 압축을 요청하게 합니다—예를 들어 이전 탐색이 이미 필요 없고 새 단계를 시작하려 할 때.
모델이 호출합니다:
tool_use("compact", focus="keep the API design decisions")
auto와 동일하게 트리거되지만, 요약 시 무엇을 중점적으로 보존할지 알리는 focus 파라미터를 함께 전달할 수 있습니다. 실전에서 매우 유용합니다—모델은 어떤 것이 "완료된 소작업"인지 harness의 휴리스틱보다 더 잘 압니다.
어느 계층이 적합한가? 판별 문제
다음 시나리오들에서 micro / auto / manual 중 어느 것이 트리거되는 것이 더 합리적인지 결정하세요.