LangGraph에서 멀티 에이전트 상태 공유, supervisor vs swarm 어떤 패턴이 나은가요
사내 운영 자동화용으로 에이전트 여러 개를 묶고 있습니다. 리서치 담당, SQL 담당, 리포트 작성 담당 세 개를 두고 서로 결과를 넘기는 구조인데요.
처음엔 그냥 supervisor 노드 하나가 다음에 누구한테 보낼지 라우팅하게 짰습니다. 근데 supervisor가 매 턴마다 LLM 호출을 한 번 더 먹으니까 토큰이랑 레이턴시가 만만치 않더라고요. 4~5번 핸드오프하면 supervisor 호출만 그만큼 쌓입니다.
그래서 swarm 스타일(에이전트끼리 직접 handoff 툴로 넘기는)도 봤는데, 이건 라우팅 로직이 각 에이전트 프롬프트에 흩어져서 관리가 어려워 보입니다.
실무에서 어느 쪽을 쓰시나요? state는 어떻게 공유하는 게 깔끔한가요?
답변 3개
- 채택된 답변에디터 검증
둘 다 써봤는데 결론부터: 워크플로우가 정해져 있으면 supervisor도 LLM으로 라우팅하지 말고 그냥 코드로 엣지를 박으세요.
님 케이스(리서치 → SQL → 리포트)는 순서가 사실상 고정이잖아요. 그런데 supervisor한테 매번 "다음 누구?"를 LLM으로 물어보는 건 토큰·레이턴시 낭비입니다. LangGraph면
add_conditional_edges의 라우팅 함수를 그냥 파이썬 함수로 짜면 LLM 호출 0번으로 분기돼요. state에next_step같은 필드 두고 각 노드가 끝날 때 채워주는 식으로. LLM supervisor가 정당화되는 건 다음 단계가 진짜로 동적일 때(사용자 입력 따라 어떤 전문가 필요한지 매번 달라짐)뿐입니다.state 공유는
TypedDict+Annotated[list, add]리듀서로 메시지 누적하는 기본 패턴이 제일 무난하고요. 한 가지, 에이전트별 스크래치패드를 공유 state에 다 때려넣지 마세요. SQL 에이전트가 쿼리 디버깅하면서 남긴 찌꺼기까지 리포트 작성 에이전트 컨텍스트에 다 들어가면 토큰 터지고 품질 떨어집니다. 서브그래프 안에서만 살게 하고 바깥엔 "확정된 산출물"만 올리는 식으로 거르세요. swarm 라우팅이 프롬프트에 흩어지는 문제는, 핸드오프 툴을 한 곳에서 팩토리로 찍어내면 좀 완화됩니다. 각 에이전트한테
transfer_to_X툴을 코드로 생성해서 주입하면 프롬프트엔 "필요하면 적절한 동료에게 넘겨라" 정도만 남고 연결 그래프는 코드에 모여요.근데 솔직히 윗분 말대로 님 워크플로우가 선형에 가까우면 swarm은 오버킬입니다. swarm은 상담봇처럼 "청구 문의 → 환불 전문 → 다시 일반 상담" 식으로 왔다갔다 예측 불가능할 때 빛을 봐요. 운영 리포트 파이프라인이면 그냥 그래프 엣지 박는 게 디버깅도 쉽고 재현도 되고요. 제 경험엔 그게 밤에 발 뻗고 자는 길입니다.
supervisor를 LLM으로 유지하더라도 라우팅 결정에 큰 모델 쓸 필요는 없어요. 라우팅은 "다음은 SQL" 같은 분류 문제라 Haiku급이나 Gemini Flash급이면 충분하고, 무거운 추론만 큰 모델로 돌리면 됩니다. LangGraph는 노드별로 LLM 바인딩 따로 가는 게 자유로워서 이 분리가 쉬워요. 라우팅에 매번 풀사이즈 모델 박고 있으면 거기서 비용 새는 거 맞습니다.