핵심 요약
- "컨텍스트 부패(context rot)"는 오래 실행되는 에이전트가 모델이 담을 수 있는 것보다 더 많은 컨텍스트를 쌓이게 되면서 정확도가 떨어지는 현상입니다.
- LangChain의 오픈 소스 에이전트 하네스인 Deep Agents는 컨텍스트를 이동시키기 위해 다섯 가지 기법을 사용합니다 out 활성 창을 (삭제하지 않고) 닫아 컨텍스트 오염을 방지합니다.
- Deep Agents의 에이전트 메모리는 사용자가 제어하는 스토리지에 일반 파일로 저장되므로, 에이전트가 학습한 모든 내용을 유지한 채 모델이나 공급자를 전환할 수 있습니다.
시험 전날 밤 벼락치기를 해본 적이 있다면 그 느낌을 잘 알 것입니다: 공부를 할수록 앞부분 챕터들이 점점 머릿속에서 흘러나가는 것이죠.
에이전트도 같은 문제를 안고 있습니다. 더 긴 작업을 수행할수록 점점 더 많은 정보(지시사항, 도구 결과, 파일 등)를 다루게 되고, 결국에는 감당하기 어려울 정도로 정보가 너무 많아집니다. 문맥 모델의 컨텍스트 윈도우. 모델이 처리하는 대화 기록, 노이즈, 도구 출력이 많아질수록 정확도와 추론 능력은 대체로 저하된다.
에이전트 엔지니어링 세계에서 우리는 이것을 다음과 같이 부릅니다 컨텍스트 로트(context rot)“. 이 블로그는 에이전트의 컨텍스트 창을 관리하는 기법들과 Deep Agents 하네스가 미들웨어라는 개념을 사용하여 이를 에이전트 실행에 주입하는 방법을 다룹니다.”
컨텍스트 엔지니어링 기법 이해하기
간단히 말해, 에이전트란 모델을 둘러싼 하네스가 있는 것에 불과합니다.

컨텍스트 부패(context rot)를 해결하기 위해 에이전트가 활용할 수 있는 컨텍스트 엔지니어링 기법은 크게 두 가지 범주로 나뉩니다:
- 불필요한 정보를 차단하여 진입 컨텍스트 윈도우
- 무엇을 관리하고 필터링할지 이미 안에 컨텍스트 윈도우
이 하네스는 이러한 방법들을 전략적으로 적용하여 모델이 주어진 작업에 적시에 적절한 컨텍스트를
갖도록 합니다. 이제 이를 잘 수행하는 하네스를 구성하는 방법 말처럼 쉽지 않으며 많은 작업을 필요로 합니다(시험 전날 벼락치기를 하는 유형이라면 너무 많은 작업일 수도 있습니다).
Deep Agents 는 LangChain의 오픈 소스 하네스입니다. 선택한 모델을 감싸고, 컨텍스트를 활성 창 밖으로 옮기는(파일, 요약, 별도의 에이전트로) 기법들을 적용하여 메인 에이전트가 필요한 것만을 가지고 다니도록 합니다(나중에 필요하면 원본 데이터를 복구할 수 있습니다):
- 오프로딩(Offloading): 대용량 도구 결과와 사용자 메시지는 파일시스템에 저장되고, 모델에는 미리보기가 표시됩니다.
- 요약(Summarization): 대화가 컨텍스트 한도에 가까워지면 오래된 메시지들이 요약으로 압축됩니다.
- 스킬(Skills): 태스크 관련 노하우는 모델이 관련이 있다고 판단할 때만 로드됩니다.
- 서브에이전트(Subagents): 노이즈가 많은 작업은 별도의 컨텍스트 창에서 실행되고, 결과만 돌아옵니다.
- 장기 기억(Long-term memory): 에이전트가 학습한 내용은 파일에 저장되어 다음 대화로 이어집니다.
일반적인 사용 사례에 컨텍스트 엔지니어링 적용하기
위의 기법들을 실제 사용 사례인 경쟁사 분석 에이전트에 어떻게 적용할 수 있는지 살펴보겠습니다. 이 에이전트는 매주 월요일 5개 경쟁사를 조사하고 팀의 템플릿에 맞춰 보고서를 작성합니다. 한 번의 실행은 대략 다음과 같습니다:
- Company A의 시장 데이터 내보내기 가져오기(수만 행)
- 뉴스를 검색하고 기사 몇 개를 읽으며 메모하기
- Company B부터 E까지 반복하기
- 보고서 초안을 작성하고, 피드백을 반영해 수정하며, 서식을 지정하기
4단계에 이르면 에이전트는 5개의 원본 내보내기, 수십 개의 검색 결과, 두 개의 오래된 초안을 모든 모델 호출마다 가지고 다니게 됩니다. 그중 대부분은 최종 보고서 서식 지정에는 불필요한 것들입니다.
검색 방법(RAG또는 파일시스템 검색)은 에이전트가 필요한 것 만 가져오는 데 도움이 되지만, 그것으로 문제의 절반만 해결됩니다. 정교한 에이전트조차 불필요한 메시지, 도구 결과, 중간 작업을 축적하므로, 하네스는 컨텍스트 창 안팎에 이미 있는 것들도 관리해야 합니다.
이 기법들을 구현하는 방법: 미들웨어
에이전트는 루프로 실행됩니다: 모델이 무엇을 할지 결정하고, 도구를 호출하고, 결과를 읽고, 작업이 완료될 때까지 반복합니다. 미들웨어(Middleware) 는 그 루프의 특정 지점에 연결되는 코드입니다: 예를 들어 에이전트가 시작되기 전, 각 모델 호출 주변, 또는 각 도구 호출 주변입니다.
- 각 지점에서 다음 단계가 실행되기 전에 컨텍스트를 읽고 변경할 수 있습니다.
- 이 글의 모든 컨텍스트 엔지니어링 기법은 그 지점 중 하나에 연결된 미들웨어 조각입니다.
- 이 대부분은 기본으로 내장되어 있어, 이러한 기법을 사용하기 위해 미들웨어를 직접 작성할 필요가 없습니다(특정 부분을 사용자 정의하고 싶은 경우 제외).
오프로딩(Offloading): 컨텍스트 윈도우 밖으로 내보내기
우리의 에이전트는 항상 모든 도구 호출이나 사용자 메시지에서 반환되는 데이터를 볼 필요는 없습니다. 특히 그 양이 많은 경우에는 더욱 그렇습니다.
예를 들어, 각 pull_market_report 도구 호출은 전체 데이터 내보내기(수천 개의 행)를 반환하지만, 에이전트는 그중 몇 개의 숫자만 필요로 하므로 모델이 해당 행들만 보도록 제한할 수 있습니다.
FilesystemMiddleware는 도구가 호출될 때마다 실행됩니다:
- 도구 결과가 약 20,000 토큰을 초과하면, 전체 결과가 대화에 들어가기 전에 /large_tool_results/{tool_call_id}에 기록됩니다.
- 모델에는 짧은 미리보기(첫 몇 줄과 마지막 몇 줄)와 파일 경로만 표시됩니다.
- 에이전트가 나중에 B사의 분기 매출이 필요해지면, read_file로 해당 파일을 넘겨가며 읽습니다.
붙여넣은 통화 녹취록처럼 과도하게 큰 사용자/사람 메시지는 더 높은 기준(50,000 토큰)으로 동일한 처리를 받고 /conversation_history/에 저장됩니다.
요약(Summarization): 이미 있는 내용 압축하기
장황한 도구 호출을 아무리 오프로딩하려 해도, 긴 실행 동안에는 컨텍스트가 점차 쌓이기 시작합니다(예: 다섯 회사 분의 검색, 메모, 초안). 요약을 사용하면 에이전트의 전체 컨텍스트 윈도우를 지금까지 진행된 내용의 요약으로 압축하여, 연구 작업을 계속 진행할 수 있게 할 수 있습니다.

- 급증은 도착하는 큰 도구 결과/사람 메시지입니다. 오프로딩은 모델이 보기 전에 각각을 짧은 미리보기로 교체하므로, 컨텍스트는 아주 조금씩만 증가합니다.
- 요약은 완만한 상승을 처리합니다: 사용량이 85%에 도달하면, 오래된 메시지들이 요약으로 압축되고 컨텍스트는 다시 낮아집니다.
SummarizationMiddleware는 각 모델 호출 직전에 토큰 사용량을 확인합니다:
- 사용량이 기준(기본값은 모델의 컨텍스트 윈도우의 85%)을 넘으면, 별도의 LLM 호출이 오래된 메시지들을 하나의 요약으로 압축합니다.
- 오래된 메시지는 컨텍스트 윈도우에서 제거되고, 가장 최근 메시지들은 그대로 유지됩니다.
- 이제 모델은 요약을 먼저 본 다음, 최근 메시지를 봅니다(따라서 최근 내용은 의역되지 않습니다).
중요한 두 가지 세부 사항:
- 복구 가능합니다. 요약된 메시지들은 /conversation_history/{session_id}.md에 기록됩니다. 에이전트가 초안 작성 중 A사 연구의 세부 정보가 필요하면 다시 읽을 수 있습니다.
- 순환합니다. 실행이 계속되면 사용량이 다시 상승하고, 다음 요약에는 이전 요약이 포함됩니다.
주제가 바뀔 때도 요약할 수 있습니다, 특정 토큰 임계값에서만이 아니라. 요약 프롬프트를 커스터마이즈하는 것이 도움이 될 수 있습니다.

다음에 관한 저희 포스트 Deep Agents를 위한 컨텍스트 관리 에서 두 가지 모두 더 자세히 다룹니다.
Skills: 필요할 때만 정보 불러오기
영업팀이 분기별 사업 검토(quarterly business review)에 특정 형식을 사용한다고 가정해 보세요. 에이전트는 그 지침을 분기에 한 번만 필요로 하므로, 이를 시스템 프롬프트에 넣어두면 모든 호출마다 해당 내용에 대해(토큰과 응답 시간 측면에서) 비용을 지불하게 됩니다. 대신, 이 정보를 하나의 스킬로 패키징할 수 있습니다.
스킬은 전문화된 작업에 에이전트가 필요로 하는 것을 제공하는 지침(선택적으로 스크립트와 참조 문서 포함)의 폴더입니다.

에이전트는 먼저 짧은 설명을 보고 있다가, QBR이 다가올 때만 qbr-report의 전체 지침을 불러옵니다(다른 작업에는 이 지침이 전혀 포함되지 않습니다).
스킬은 레이어로 컨텍스트를 로드하기 때문에, 실제로 관련성이 있을 때까지는 컨텍스트 창이 작게 유지됩니다. 이를 점진적 공개(progressive disclosure)라고 합니다. 모델은 앞서 '메뉴'만 보고 있다가 필요할 때 전체 레시피를 불러오므로, 열 개의 스킬이 열 줄짜리 한 줄 요약 정도의 컨텍스트만 소모합니다.
에이전트가 여러분의 스킬을 가리키도록 하면, SkillsMiddleware는 두 개의 훅을 사용합니다:
- 에이전트가 시작되기 전에 skills 폴더를 스캔하고 각 SKILL.md의 헤더만 읽습니다.
- 모델 호출 시마다 해당 이름과 설명을 시스템 프롬프트에 추가합니다.
전체 지침은 모델이 해당 스킬이 관련이 있다고 판단할 때(read_file 도구로 읽을 때)에만 컨텍스트에 들어오므로, 우리 에이전트는 템플릿 없이 조사를 진행하다가 QBR을 작성할 시점이 되어서야 이를 불러옵니다.
서브에이전트: 시끄러운 작업 격리하기
오프로딩은 과도하게 큰 결과물에 효과적으로 대처하지만, 서브에이전트는 이미 ~한 작업에 대해서는 좋은 설계 선택입니다 알다 번잡할 것입니다(수십 번의 검색과 여러 페이지에 걸쳐 한 회사를 조사하는 것처럼요). 서브에이전트는 자체 컨텍스트 윈도우에서 그 작업을 수행하고 최종 결과만 반환하므로, 메인 에이전트는 그 "잡음"을 결시 보지 않습니다.

SubAgentMiddleware를 사용하면 서브에이전트에 제공되는 시스템 프롬프트와 도구를 사용자 지정할 수 있습니다.
market_researcher = {
"name": "market-researcher",
"description": "Researches a company and returns the 3 most notable developments.",
"system_prompt": "Use pull_market_report, then return 3 short bullet points. Do not return the raw report.",
"tools": [pull_market_report],
}
agent = create_deep_agent(model=model, subagents=[market_researcher])우리 사례에서는 메인 에이전트가 각 회사를 시장 조사(market-researcher) 서브에이전트에게 넘깁니다.
연구자 서브에이전트는 자체 컨텍스트에서 전체 보고서를 읽고 단 세 개의 불릿만 반환하므로, 메인 에이전트는 이 세 개의 불릿만 보게 됩니다(원본 보고서의 미리보기조차 보지 못합니다). 또한 서브에이전트 작업은 대체로 규모가 작고 범위가 명확하기 때문에 종종 더 저렴한 모델로 병렬로 실행할 수 있습니다.
장기 기억: 대화 간에 지속됨
결국에는 여러분의 에이전트가 많은 것을 학습하게 될 것입니다. 유용한 것도 있고, 유용하지 않은 것도 있습니다.
에이전트에게 "요약에는 문단 대신 글머리 기호를 사용해."라고 말한다고 해보세요. 메모리가 없다면 매주 똑같은 말을 반복해야 할 수도 있습니다. Deep Agents에서 장기 메모리는 마크다운 파일입니다. 인수 하나로 에이전트가 해당 파일을 가리키게 하면 MemoryMiddleware가 나머지를 처리합니다:
- 로드: 파일은 실행 시작 시 읽힙니다.
- 주입: 해당 내용은 매 모델 호출 시 시스템 프롬프트에 추가됩니다.
- 업데이트: 에이전트가 포맷 선호도처럼 보관할 가치가 있는 내용을 학습하면, 해당 파일을 업데이트합니다.
모델은 교체하되, 메모리는 유지하세요
Deep Agents는 제공자에 구애받지 않으며, 이는 메모리에도 그대로 적용됩니다. 메모리는 제공자가 보관하는 것이 아니라 여러분의 저장소에 있는 단순한 파일이므로, 동일한 백엔드를 다른 모델에 연결할 수 있습니다:
agent = create_deep_agent(
model="openai:gpt-6", # different provider, same memory
memory=["/memories/AGENTS.md"],
backend=backend,
store=store,
)다음 주에는 다른 모델이 동일한 파일을 읽고도 요약을 글머리 기호로 작성할 수 있을 것이다.
기억해 둘 만한 컨텍스트 엔지니어링 전략
Deep Agents를 사용해 구축하든, 다른 하네스를 사용하든, 직접 하나를 만들든, 다음과 같은 사항에 유의하세요:
- 대용량 입력은 잘라내는 것이 아니라 오프로드해야 합니다. 잘라내기(truncation)는 손실을 수반하지만, 오프로딩(offloading)은 나중에 다시 꺼내볼 수 있게 합니다.
- 컴팩션은 복구 가능해야 합니다. 요약 후에도 에이전트는 필요한 세부 정보를 다시 가져올 수 있습니다.
- 노하우는 온디맨드 방식으로 로드되어야 합니다. 시스템 프롬프트의 모든 작업 지침은 호출할 때마다 컨텍스트 비용을 발생시킵니다.
- 노이즈가 많은 작업은 분리해야 합니다. 자체 컨텍스트를 가진 서브에이전트가 메인 에이전트가 집중력을 유지하도록 돕습니다.
- 메모리는 직접 소유해야 합니다. 직접 제어하는 스토리지의 메모리는 모델이나 공급자를 전환해도 유지됩니다.
- 기본값은 사용자 지정 가능해야 합니다. 하나의 작업에 맞는 임계값이 모든 작업에 맞는 경우는 드뭅니다.
사용해 보기
uv add deepagents라이브 강사에게 더 배우고 싶으신가요? 저는 11월 3일에 이 내용을 다룰 예정입니다: 등록 여기!
컨텍스트 엔지니어링을 더 깊이 알아보려면 무료로 자기 주도 학습이 가능한 LangChain Academy의 Deep Agents 강좌를 확인해 보세요.
