[LangGraph
-
서브 에이전트를 @tool로 감싸는 멀티 에이전트 패턴IT 2026. 6. 30. 22:00
에이전트에게 역할을 너무 많이 주면 어떻게 될까. "리서치도 하고, 데이터 분석도 하고, 코드도 작성하고, 최종 보고서도 써라" — 이렇게 하나의 에이전트에 모든 역할을 몰아넣으면 각 역할의 품질이 떨어진다. 컨텍스트 창이 무거워지고, 단계 간 집중력이 분산되고, 한 단계의 실패가 전체를 망친다. 멀티 에이전트 패턴은 이 문제를 역할 분리로 해결한다. 그리고 LangGraph에서는 그 분리를 서브 에이전트를 @tool로 감싸는 방법으로 구현한다.단일 에이전트의 한계단일 에이전트 구조에서는 모든 것이 하나의 루프 안에 들어간다. 도구 목록이 길어지고, 시스템 프롬프트가 복잡해지고, 응답마다 불필요한 맥락이 누적된다. 무엇보다 각 역할에 맞는 "전문성"을 하나의 에이전트가 동시에 유지하기 어렵다.구조는 단순..
-
@tool이 내부에서 하는 일 — Pydantic BaseModel이 LLM의 호출 인터페이스가 되는 과정IT 2026. 6. 30. 21:00
LangGraph로 AI 에이전트를 만들다 보면 도구(tool) 함수를 정의하는 방식이 눈에 들어온다. 함수 위에 @tool 하나 붙이면 LLM이 그 함수를 알아서 호출한다. 마치 마법처럼 보이지만, 내부에서는 Pydantic BaseModel이 핵심 역할을 한다. 이 글은 그 메커니즘을 분해한다 — @tool이 Python 함수에서 무엇을 만들어내는지, 왜 굳이 BaseModel인지, 그리고 실제로 어떤 문제들이 있었는지.LLM이 함수를 호출하려면 무엇이 필요한가LLM은 텍스트를 입력받아 텍스트를 출력하는 모델이다. "search_movie 함수를 query='크리스토퍼 놀란 영화'로 호출해"라고 지시하려면 LLM에게 두 가지를 알려줘야 한다. 첫째, 그 함수가 어떤 인자를 받는지. 둘째, 각 인자의 ..
-
LangGraph가 Annotated를 쓰는 이유 — 덮어쓰기 문제와 리듀서의 등장IT 2026. 6. 29. 22:00
LangGraph 코드를 처음 보면 눈에 걸리는 문법이 있다.class AgentState(TypedDict): messages: Annotated[list[BaseMessage], add_messages]list[BaseMessage]만 써도 될 것 같은데, 왜 Annotated를 끼워 넣고 add_messages를 붙이는 걸까. 이 글은 그 "왜"를 배경부터 따라간다. 이 문법이 등장할 수밖에 없었던 이유, 없었을 때 생기는 문제, 그리고 리듀서라는 개념이 어떻게 그것을 깔끔하게 해결했는지를 순서대로 본다.1. 배경 — 여러 노드가 하나의 상태를 공유한다LangGraph 에이전트는 여러 노드(Python 함수)가 차례로 또는 조건에 따라 실행된다. 이 노드들이 데이터를 주고받는 방식은 함수 인자..
-
생성과 검증의 분리 — generator 노드와 validator 노드 설계IT 2026. 6. 28. 21:00
LangGraph로 자기수정 파이프라인을 구현할 때 가장 흔히 저지르는 실수는 "하나의 노드가 초안을 쓰고 스스로 검토하게" 만드는 것이다. 이 글은 왜 그게 문제인지, 그리고 generator와 validator를 별도 노드로 분리했을 때 무엇이 달라지는지를 코드와 함께 설명한다.왜 생성과 검증을 분리해야 하는가LLM에게 "글을 쓰고 스스로 검토해"라고 요청하면 자기 평가에 관대해진다. 사람도 자기가 쓴 글을 교정할 때 오탈자를 잘 못 잡는 것과 같은 이치다. 동일한 컨텍스트 안에서 생성 직후에 평가가 이어지면, LLM은 이미 작성한 내용을 합리화하는 방향으로 판단을 내린다.위 구조의 핵심 문제는 단 한 번의 LLM 호출이 생성과 평가를 모두 담당한다는 점이다. 초안 작성 단계에서 만들어진 내용이 자기..
-
LangGraph 자기 수정 패턴의 State 설계 — 루프를 위한 5가지 필드IT 2026. 6. 27. 23:00
LLM 기반 코드를 짜다 보면 어느 순간 "한 번 생성해서 끝내는 게 아니라, 결과물을 검토하고 부족하면 다시 고치는 루프"가 필요해진다. 글쓰기라면 초고를 쓰고 → 편집자가 피드백을 주고 → 그 피드백을 반영해 고쳐 쓰는 과정이다. LangGraph에서 이 구조를 자기 수정 패턴(self-correction loop)이라 부른다.문제는 이 루프를 코드로 옮길 때다. 단순히 while을 돌리면 되는 게 아닌가 싶지만, LangGraph는 그래프 기반 실행 엔진이라 루프의 상태를 State라는 공유 객체에 담아서 노드 간에 넘겨야 한다. 그래서 "어떤 필드를 State에 두어야 루프가 제대로 작동하는가"가 설계의 핵심이 된다. 이 글은 그 5가지 필드를 역할별로 정리한다.자기 수정 패턴이 무엇인가먼저 패턴..
-
LangGraph 조건부 라우팅 — 상태 값으로 다음 노드를 결정하는 방법IT 2026. 6. 27. 22:00
LangGraph로 멀티스텝 AI 파이프라인을 만들다 보면 반드시 마주치는 패턴이 있다. 입력이 어떤 종류인지에 따라 다른 처리 경로로 보내는 것 — 이른바 조건부 라우팅(conditional routing)이다. 단순해 보이지만 실제로 구현하다 보면 "라우팅 함수가 정확히 무엇을 해야 하는가", "add_conditional_edges의 세 번째 인자는 언제 필요한가" 같은 질문에서 한 번씩 막힌다. 이 글은 그 지점을 정확히 짚는다.라우팅 함수의 역할: 오직 "어디로 갈지"만 결정LangGraph에서 라우팅 함수를 처음 만들 때 가장 흔한 실수는 이 함수 안에서 무언가를 "생성"하려는 것이다. 라우팅 함수의 역할은 단 하나다 — state를 보고 다음에 실행할 노드의 이름을 문자열로 반환하는 것. 응..
-
LLM을 분류기로 쓰기 — SystemMessage와 HumanMessage로 Classifier Node 만들기IT 2026. 6. 27. 21:00
LLM을 쓸 때 우리는 보통 "질문을 던지면 자유롭게 답해주는 것"으로 생각한다. 그런데 LLM은 전혀 다른 방식으로도 동작할 수 있다. "이 입력이 영화 추천 요청인가, 영화 정보 질문인가, 일반 대화인가"를 판단하는 분류기(Classifier)로 쓰는 것이다. LangGraph에서 라우팅을 구현할 때 이 패턴이 결정적인 역할을 한다.왜 LLM을 분류기로 쓰는가규칙 기반 분류를 먼저 떠올리기 쉽다. "추천"이라는 단어가 있으면 recommend, "정보"가 있으면 info. 하지만 사용자 입력은 예측 불가능하다. "요즘 볼만한 거 없을까?" 같은 표현은 어떤 규칙으로 잡을 것인가. LLM은 자연어를 이해하기 때문에 이런 모호한 표현도 정확히 분류할 수 있다.분류기 노드의 목적은 단 하나다. 입력을 받아..
-
LangGraph 상태에 메시지 외 필드 추가하기 — RouterState 설계IT 2026. 6. 26. 23:00
LangGraph의 상태(State)를 처음 배울 때는 messages 필드 하나만 있는 AgentState를 본다. LLM과 주고받는 메시지를 누적하는 용도다. 그런데 실제 워크플로우를 만들다 보면 금세 한계에 부딪힌다. "이 요청이 어느 카테고리인지", "지금 몇 번째 시도인지", "사용자가 인증됐는지" 같은 데이터도 노드 간에 공유해야 하기 때문이다. messages 하나만으로는 이 데이터를 담을 곳이 없다.이 글은 RouterState라는 구체적인 예시를 통해, 상태(State) 클래스에 필드를 추가할 때 어떤 규칙이 적용되는지, 리듀서가 있는 필드와 없는 필드가 어떻게 다르게 동작하는지, 그리고 노드들이 상태의 어느 부분을 읽고 쓰는지를 설명한다.1. 복습: 상태는 노드들의 공유 칠판이전 글에서..