CrewAI 에이전트가 중복 작업을 실행하지 않도록 하는 방법: 실용적인 중복 제거 가이드
CrewAI 에이전트가 작업을 반복하지 않도록 하려면 작업 소유권, 종속성, 위임, 재시도, Flow 트리거, 상태 지속성, 캐싱 및 멱등성을 수정하십시오.
LangChain 에이전트가 긴 대화 중에 세부 정보를 잊어버린다면, 모델 컨텍스트 윈도우를 늘리기 전에 아키텍처를 수정하십시오. 현재 LangChain v1 스타일 에이전트에서 대화 연속성은 두 개의 별도 레이어로 구성됩니다: 단기 스레드 범위 상태를 위한 체크포인터(checkpointer)와 스레드를 넘어 생존해야 하는 장기 정보를 위한 저장소(store)입니다. 긴 대화는 세 번째 고려 사항이 필요합니다: 일반적으로 모델이 압도당하기 전에 이전 메시지를 정리하거나 요약하는 컨텍스트 관리입니다.
이 가이드는 2026년 9월 11일에 확인된 LangChain 공식 문서를 따릅니다. 현재 문서는 새로운 에이전트에 대해 langchain.agents.create_agent를 권장하며, LangGraph 지속성을 근본적인 메모리 시스템으로 설명합니다. ConversationChain, ConversationBufferMemory 또는 initialize_agent를 기반으로 한 이전 예제는 레거시 자료에 여전히 나타날 수 있지만, LangChain의 v1 마이그레이션 가이드는 레거시 체인 및 기타 지원 중단된 기능을 langchain-classic으로 이동했습니다. 공식 LangChain v1 마이그레이션 가이드를 참조하십시오.

코드를 변경하기 전에, 사용자의 관점에서 종종 동일해 보이는 세 가지 문제를 구분하십시오.
| 증상 | 가능한 원인 | 수정해야 할 올바른 레이어 |
|---|---|---|
| 서버 재시작 후 에이전트가 잊어버림 | 상태가 프로세스 메모리에만 저장됨 | 영구 체크포인터 또는 저장소 |
| 동일한 채팅의 두 요청 사이에서 에이전트가 잊어버림 | 체크포인터가 없거나, 다른 thread_id가 사용됨 | 스레드 지속성 |
| 에이전트가 저장소에서는 초기 턴을 기억하지만 매우 긴 채팅에서는 사용을 중단함 | 모델 컨텍스트가 너무 크거나 노이즈가 많음 | 요약, 정리, 검색 |
| 에이전트가 한 채팅에서는 선호도를 기억하지만 새 채팅에서는 기억하지 못함 | 사실이 스레드 상태에만 존재함 | 장기 저장소 |
LangChain의 단기 메모리 문서는 단기 메모리를 단일 스레드 내의 상태로 정의합니다. 장기 메모리 문서는 장기 메모리를 서로 다른 대화 및 세션을 넘어 지속되는 정보로 정의합니다.

현재 LangChain/LangGraph 애플리케이션, 모델 통합 및 상태를 지속할 장소가 필요합니다. 로컬 실험의 경우 InMemorySaver로 충분합니다. 프로덕션의 경우 데이터베이스 기반 체크포인터를 사용하십시오. LangChain 공식 문서는 별도의 langgraph-checkpoint-postgres 패키지를 통해 PostgreSQL을 보여줍니다.
네 가지 식별자를 명확히 유지하십시오:
thread_id: 하나의 스레드 상태를 재개하는 데 사용되는 LangGraph 지속성 키입니다.이들은 자동으로 동일한 값이 되어서는 안 됩니다. 한 사용자는 여러 스레드를 가질 수 있으며, 하나의 스레드에는 여러 사실이 포함될 수 있습니다.
가능한 가장 작은 테스트로 시작하십시오. 에이전트에게 고유한 세부 정보를 기억하도록 요청한 다음, 다시 호출하여 그 세부 정보를 물어보십시오. 지속성이 깨진 경우에도 모델은 단일 요청 내에서 모든 것을 볼 수 있으므로 단일 invoke() 호출로 메모리를 테스트하지 마십시오.
config = {"configurable": {"thread_id": "debug-thread-001"}}
agent.invoke(
{"messages": [{"role": "user", "content": "Remember that my project codename is Juniper."}]},
config,
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is my project codename?"}]},
config,
)
두 번째 요청이 “Juniper”를 잊어버린다면, 프롬프트를 변경하기 전에 체크포인터 구성과 실제 thread_id를 검사하십시오.
체크포인터(checkpointer)는 에이전트 그래프 상태의 스냅샷을 지속합니다. LangGraph는 단기 메모리, 중단 복구, 인간 개입(Human-in-the-loop) 흐름 및 장애 허용을 위해 이를 사용합니다. 현재 지속성 가이드는 체크포인터가 스레드 범위이며 애플리케이션이 thread_id를 전달하여 상태에 접근한다고 설명합니다. 공식 LangGraph 지속성 가이드를 참조하십시오.
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
)
config = {"configurable": {"thread_id": "customer-42:case-7"}}
InMemorySaver는 스레드 연결이 작동하는지 확인하는 데 탁월하지만, 체크포인트를 RAM에 저장합니다. LangGraph는 MemorySaver/InMemorySaver가 프로세스 재시작을 넘어 지속되지 않는다고 명시적으로 경고합니다.
가장 일반적인 애플리케이션 수준 버그는 모든 HTTP 요청마다 새로운 thread_id를 생성하는 것입니다. 데이터베이스가 완벽하게 작동하더라도 모든 요청이 다른 LangGraph 스레드를 시작할 수 있습니다.
예를 들어, 프런트엔드에 채팅 ID chat_8bf4가 있다고 가정해 보십시오. 해당 값을 LangGraph 스레드에 결정적으로 매핑하고 해당 채팅의 모든 턴에서 재사용하십시오. 새 채팅은 새로운 스레드 ID를 받아야 합니다.

동일한 사용자에게 속한 모든 채팅에 대해 하나의 영구적인 thread_id를 사용하지 마십시오. 이는 관련 없는 대화들을 하나의 상태 스트림으로 병합합니다. PostgreSQL을 사용하는 경우, LangGraph의 현재 문제 해결 지침은 thread_id가 255자 미만이어야 한다고도 명시합니다. UUID나 결정적 해시가 거대한 직렬화된 객체보다 더 안전합니다.
두 요청 테스트가 통과되면 프로세스 재시작을 테스트하십시오. 사실을 저장하고, 애플리케이션을 중지하고, 다시 시작한 다음, 동일한 스레드 ID로 사실을 요청하십시오. 여전히 InMemorySaver를 사용 중이라면 잊어버리는 것은 예상된 동작입니다.
공식 단기 메모리 문서는 PostgresSaver를 사용한 PostgreSQL 기반 프로덕션 설정을 보여줍니다:
from langchain.agents import create_agent
from langgraph.checkpoint.postgres import PostgresSaver
DB_URI = "postgresql://user:password@db-host/app"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
checkpointer.setup()
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
)
LangChain이 현재 문서화한 패키지 설정은 단기 메모리를 참조하십시오. 실제 데이터베이스 자격 증명을 소스 코드에 직접 넣지 마십시오. 일반적인 시크릿 관리 시스템을 사용하십시오.

컨텍스트 윈도우(context window)는 모델이 한 번의 모델 호출에서 처리할 수 있는 입력 및 출력 컨텍스트의 양입니다. 체크포인팅은 저장소에 매우 긴 대화를 보존할 수 있지만, 모든 과거 메시지를 영원히 모델에게 다시 보내야 한다는 의미는 아닙니다.
LangChain의 단기 메모리 가이드는 긴 기록이 모델 컨텍스트 윈도우를 초과할 수 있으며, 전체 기록을 수용할 수 있는 모델조차도 오래되거나 주제와 무관한 콘텐츠로 인해 주의가 분산되어 지연 시간과 비용이 증가할 수 있다고 말합니다. 문서화된 전략은 정리, 삭제, 요약 또는 사용자 정의 정책 적용입니다.
SummarizationMiddleware는 최근 메시지를 유지하면서 이전 기록을 컴팩트한 요약으로 대체하기 위한 현재 내장 옵션입니다. 트리거는 토큰 수, 메시지 수 또는 모델 컨텍스트의 비율에 따라 결정될 수 있습니다.
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
middleware=[
SummarizationMiddleware(
model="your-provider:summary-model",
trigger=("fraction", 0.8),
keep=("fraction", 0.3),
)
],
)
위의 숫자는 예시 정책일 뿐 보편적인 설정이 아닙니다. 자체 프롬프트, 도구 출력, 모델 컨텍스트 제한, 지연 시간 및 요약 품질을 측정한 후 임계값을 선택하십시오. 현재 지원되는 트리거 및 유지 옵션은 LangChain의 내장 미들웨어 문서를 참조하십시오.

사용자 정의 삭제 또는 정리를 구현하는 경우, 유효한 메시지 시퀀스를 유지하십시오. LangChain은 많은 제공업체가 도구 호출을 포함하는 어시스턴트 메시지가 해당 도구 결과 메시지로 따라야 한다고 경고합니다. 해당 쌍의 한쪽을 제거하면 제공업체 오류나 혼란스러운 모델 동작이 발생할 수 있습니다.
저장소(store)는 하나의 스레드 그래프 상태 외부에 있는 애플리케이션 정의 데이터를 위한 LangGraph의 지속성 레이어입니다. 현재 LangChain 문서는 사용자 선호도, 사실 또는 공유 애플리케이션 지식과 같이 대화 간에 사용 가능해야 하는 정보를 위해 저장소를 사용합니다.
장기 저장소 항목은 네임스페이스(namespace)와 키(key)로 구성된 JSON 문서입니다. 실용적인 네임스페이스에는 종종 사용자 또는 조직 식별자가 포함됩니다:
namespace = ("users", user_id, "preferences")
store.put(
namespace,
"response_style",
{"value": "concise", "source": "explicit_user_request"},
)
이는 전체 대화 기록을 저장하는 것과는 다릅니다. 제품이 의도적으로 영구적인 것으로 취급하는 정보를 저장하십시오. 사실이 비공개이거나 규제 대상인 경우, “에이전트 메모리”가 해당 정책에서 면제된다고 가정하지 말고 일반적인 보존, 권한 부여, 암호화 및 삭제 정책을 적용하십시오.

공식 장기 메모리 가이드는 InMemoryStore와 PostgresStore를 모두 보여주며, 프로덕션을 위해 인메모리 구현을 데이터베이스 기반 저장소로 교체해야 한다고 명시적으로 언급합니다. 또한 PostgreSQL을 제외한 저장소 통합도 나열합니다. “메모리”라는 단어가 관련되어 있다는 이유만으로 벡터 데이터베이스를 선택하지 말고, 배포 및 운영 요구 사항에 맞는 백엔드를 사용하십시오.
LangGraph 저장소는 store.search()가 시맨틱 유사성으로 항목을 검색할 수 있도록 인덱스로 구성할 수 있습니다. 이는 많은 메모리가 있고 정확한 키를 모르는 경우에 유용합니다. 소규모의 구조화된 선호도 집합의 경우, 직접적인 네임스페이스/키 조회가 종종 더 단순하고 결정적입니다.
장기 항목을 지속한다고 해서 에이전트가 이를 사용할 것이라고 보장되지 않습니다. 애플리케이션에는 여전히 검색 경로가 필요합니다. 현재 LangChain 에이전트는 도구가 ToolRuntime을 통해 제공된 저장소에 접근할 수 있도록 합니다.
from dataclasses import dataclass
from langchain.tools import tool, ToolRuntime
@dataclass
class Context:
user_id: str
@tool
def get_response_style(runtime: ToolRuntime[Context]) -> str:
store = runtime.store
if store is None:
return "No memory store configured"
namespace = ("users", runtime.context.user_id, "preferences")
item = store.get(namespace, "response_style")
return item.value["value"] if item else "default"
모델 호출 전에 상태와 영구 메모리를 읽는 동적 프롬프트나 미들웨어를 구축할 수도 있습니다. 중요한 설계 규칙은 검색 경로가 관찰 가능하고 테스트 가능해야 한다는 것입니다. “정보가 어딘가 데이터베이스에 존재한다”는 충분하지 않습니다.

신뢰할 수 있는 메모리 테스트 스위트는 “모델이 내 이름을 한 번 기억했다”는 것보다 더 많은 것을 다루어야 합니다. 최소한 다음 네 가지 경우를 사용하십시오:
| 테스트 | 예상 결과 |
|---|---|
| 두 호출, 동일한 스레드 ID | 스레드 범위 정보 사용 가능 |
| 두 호출, 다른 스레드 ID | 단기 스레드 기록이 누출되지 않음 |
| 영구 체크포인터를 사용한 애플리케이션 재시작, 동일한 스레드 ID | 스레드 상태 재개 가능 |
| 장기 저장소를 사용한 새 스레드, 동일한 사용자 | 의도적으로 저장된 영구적인 사실만 회상 가능 |
그런 다음 요약 임계값을 초과하는 긴 대화 테스트를 추가하십시오. 중요한 영구적인 사실이 생존하고, 최근 도구 호출 시퀀스가 유효하게 유지되며, 프롬프트 크기가 목표 예산 내에 있는지 확인하십시오.

많은 에이전트 애플리케이션의 경우, 견고한 설계는 다음과 같습니다:
user_id, conversation_id 및 새 사용자 메시지를 수신합니다.conversation_id를 안정적인 LangGraph thread_id에 매핑합니다.LangGraph Agent Server를 통해 배포하는 경우, 현재 지속성 가이드는 서버가 지속성 인프라를 자동으로 처리한다고 설명하므로, 배포 모델을 확인하지 않고 해당 레이어를 중복하지 마십시오.
이것은 매 턴마다 새로운 대화 상태를 생성합니다. 애플리케이션 채팅 ID 옆에 스레드 ID를 기록하고 재사용을 확인하십시오.
RAM 로컬 상태는 프로세스와 함께 사라지며 워커 간에 공유되지 않을 수 있습니다. 프로덕션 연속성을 위해 영구 백엔드를 사용하십시오.
체크포인터는 상태를 보존하지만, 계속 증가하는 기록이 모델에게 유용하다는 것을 보장하지는 않습니다. 명시적인 컨텍스트 관리 정책을 추가하십시오.
더 많은 컨텍스트가 자동으로 더 나은 컨텍스트는 아닙니다. 현재 턴과 관련된 정보를 검색하고 최근 대화 연속성은 별도로 유지하십시오.
요약은 압축된 모델 생성 표현입니다. 사실이 정확해야 하는 경우(계정 식별자, 계약상 제약 조건, 사용자 승인된 선호도 또는 워크플로우 상태) 반복적인 요약을 통해 생존하기를 바라는 대신 구조화된 데이터로 저장하십시오.
스레드 기록이 조용히 전역 사용자 프로필이 되어서는 안 됩니다. 반대로, 채팅 간에 사용자를 따라다녀야 하는 사용자 선호도는 하나의 스레드에만 존재해서는 안 됩니다.
예제가 레거시 체인이나 오래된 메모리 클래스에서 시작하는 경우, 새로운 애플리케이션에 사용하기 전에 현재 v1 마이그레이션 및 메모리 문서와 비교하십시오.
thread_id를 기록하고 비교하십시오.InMemorySaver를 영구 체크포인터로 교체하십시오.LangChain 에이전트 메모리 손실은 더 큰 컨텍스트 윈도우 하나로 해결되는 경우가 거의 없습니다. 먼저 체크포인터와 안정적인 thread_id를 사용하여 스레드 상태를 영구적으로 만드십시오. 그런 다음 정리 또는 SummarizationMiddleware를 사용하여 긴 기록을 제어하십시오. 마지막으로, 대화 간에 생존해야 하는 사실을 네임스페이스가 지정된 장기 저장소에 배치하고 의도적으로 검색하십시오.
해당 분리는 “메모리”보다 훨씬 유용한 것을 제공합니다: 사용자가 “에이전트가 왜 잊어버렸나요?”라고 물었을 때 재시작, 확장, 테스트, 감사 및 추론할 수 있는 시스템입니다.
CrewAI 에이전트가 작업을 반복하지 않도록 하려면 작업 소유권, 종속성, 위임, 재시도, Flow 트리거, 상태 지속성, 캐싱 및 멱등성을 수정하십시오.
미국 프리랜서 업무를 위한 독립 계약자 경비 추적기를 구축하세요. IRS 기준 카테고리, 영수증 기록, 2026년 마일리지 요율, 세무 검토 플래그를 포함합니다.
시간 계산기, 야간 근무 수식, 주간 합계, 품질 점검 및 명확한 한계를 갖춘 무료 직원 근무 일정표를 엑셀로 만들어 보세요.
테이블, 드롭다운, 후속 조치 알림, 간단한 파이프라인 요약 기능을 갖춘 실용적인 엑셀 리드 트래커를 구축하고, CRM으로 전환해야 할 시기를 판단하는 명확한 신호를 확인하세요.
서비스 이력, 마감일, 가동 중단 시간, 비용, 점검 기록 및 명확한 안전 경계를 포함하여 작업장 자산용 실용적인 엑셀 장비 유지보수 로그를 구축하세요.
개인 부동산 중개인을 위한 HubSpot 무료 CRM과 Zoho CRM 무료를 연락처 제한, 파이프라인, 이메일, 자동화, 모바일 도구 및 업그레이드 장단점 등을 기준으로 비교해 보세요.
LM Studio를 통해 Windows 11에서 DeepSeek을 로컬로 실행하세요. 일반 PC에 적합한 모델 선택법, 다운로드 및 로드 방법, 오프라인 사용 확인 및 일반적인 문제 해결 방법을 알아보세요.
4가지 실용적인 프롬프트 압축 기법, 캐시 친화적 레이아웃, 구조화된 출력, 품질 보존 평가 계획을 통해 LLM API 비용을 절감하세요.
셀프 호스팅 n8n과 Claude를 사용하여 무료 호스팅이 가능한 AI 콘텐츠 재활용 파이프라인을 구축하세요. 구조화된 출력, 검토 게이트 및 현실적인 API 비용 가이드를 포함합니다.
타임라인, 벤더 추적, 예상 비용 대 실제 비용, 결제 및 당일 작업을 포함한 Word용 실용적인 인쇄 가능한 이벤트 기획 체크리스트 및 예산 템플릿을 사용하세요.