Skip to main content
에이전트는 언어 모델과 도구를 결합하여 작업에 대해 추론하고, 사용할 도구를 결정하며, 반복적으로 솔루션을 향해 작업하는 시스템을 만듭니다. create_agent는 프로덕션에 바로 사용할 수 있는 에이전트 구현을 제공합니다. LLM 에이전트는 목표를 달성하기 위해 루프 내에서 도구를 실행합니다. 에이전트는 중지 조건이 충족될 때까지 실행됩니다. 즉, 모델이 최종 출력을 내보내거나 반복 제한에 도달할 때까지 실행됩니다.
create_agentLangGraph를 사용하여 그래프 기반 에이전트 런타임을 구축합니다. 그래프는 에이전트가 정보를 처리하는 방법을 정의하는 노드(단계)와 엣지(연결)로 구성됩니다. 에이전트는 이 그래프를 통해 이동하며, 모델 노드(모델을 호출), 도구 노드(도구를 실행) 또는 미들웨어와 같은 노드를 실행합니다.Graph API에 대해 자세히 알아보세요.

핵심 구성 요소

모델

모델은 에이전트의 추론 엔진입니다. 정적 및 동적 모델 선택을 모두 지원하며 여러 방법으로 지정할 수 있습니다.

정적 모델

정적 모델은 에이전트를 생성할 때 한 번 구성되며 실행 전체에서 변경되지 않습니다. 이것이 가장 일반적이고 간단한 접근 방식입니다. 에서 정적 모델을 초기화하려면:
from langchain.agents import create_agent

agent = create_agent(
    "openai:gpt-5",
    tools=tools
)
모델 식별자 문자열은 자동 추론을 지원합니다(예: "gpt-5""openai:gpt-5"로 추론됩니다). 모델 식별자 문자열 매핑의 전체 목록을 보려면 참조를 참조하세요.
모델 구성을 더 세밀하게 제어하려면 공급자 패키지를 사용하여 모델 인스턴스를 직접 초기화하세요. 이 예제에서는 ChatOpenAI를 사용합니다. 사용 가능한 다른 채팅 모델 클래스는 채팅 모델을 참조하세요.
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="gpt-5",
    temperature=0.1,
    max_tokens=1000,
    timeout=30
    # ... (other params)
)
agent = create_agent(model, tools=tools)
모델 인스턴스를 사용하면 구성을 완전히 제어할 수 있습니다. temperature, max_tokens, timeouts, base_url과 같은 특정 매개변수 및 기타 공급자별 설정을 지정해야 할 때 사용하세요. 모델에서 사용 가능한 매개변수와 메서드를 보려면 참조를 참조하세요.

동적 모델

동적 모델은 현재 와 컨텍스트를 기반으로 에 선택됩니다. 이를 통해 정교한 라우팅 로직과 비용 최적화가 가능합니다. 동적 모델을 사용하려면 요청에서 모델을 수정하는 @wrap_model_call 데코레이터를 사용하여 미들웨어를 생성하세요:
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse


basic_model = ChatOpenAI(model="gpt-4o-mini")
advanced_model = ChatOpenAI(model="gpt-4o")

@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
    """대화 복잡도에 따라 모델을 선택합니다."""
    message_count = len(request.state["messages"])

    if message_count > 10:
        # 긴 대화에는 고급 모델을 사용
        model = advanced_model
    else:
        model = basic_model

    request.model = model
    return handler(request)

agent = create_agent(
    model=basic_model,  # 기본 모델
    tools=tools,
    middleware=[dynamic_model_selection]
)
사전 바인딩된 모델(이미 bind_tools가 호출된 모델)은 구조화된 출력을 사용할 때 지원되지 않습니다. 구조화된 출력과 함께 동적 모델 선택이 필요한 경우 미들웨어에 전달되는 모델이 사전 바인딩되지 않았는지 확인하세요.
모델 구성 세부 정보는 모델을 참조하세요. 동적 모델 선택 패턴은 미들웨어의 동적 모델을 참조하세요.

도구

도구는 에이전트에게 작업을 수행할 수 있는 능력을 제공합니다. 에이전트는 다음을 용이하게 함으로써 단순한 모델 전용 도구 바인딩을 넘어섭니다:
  • 순차적인 여러 도구 호출(단일 프롬프트에 의해 트리거됨)
  • 적절한 경우 병렬 도구 호출
  • 이전 결과를 기반으로 한 동적 도구 선택
  • 도구 재시도 로직 및 오류 처리
  • 도구 호출 간 상태 지속성
자세한 내용은 도구를 참조하세요.

도구 정의

에이전트에 도구 목록을 전달하세요.
from langchain.tools import tool
from langchain.agents import create_agent


@tool
def search(query: str) -> str:
    """정보를 검색합니다."""
    return f"Results for: {query}"

@tool
def get_weather(location: str) -> str:
    """위치의 날씨 정보를 가져옵니다."""
    return f"Weather in {location}: Sunny, 72°F"

agent = create_agent(model, tools=[search, get_weather])
빈 도구 목록이 제공되면 에이전트는 도구 호출 기능 없이 단일 LLM 노드로 구성됩니다.

도구 오류 처리

도구 오류 처리 방식을 사용자 정의하려면 @wrap_tool_call 데코레이터를 사용하여 미들웨어를 생성하세요:
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_tool_call
from langchain_core.messages import ToolMessage


@wrap_tool_call
def handle_tool_errors(request, handler):
    """사용자 정의 메시지로 도구 실행 오류를 처리합니다."""
    try:
        return handler(request)
    except Exception as e:
        # 모델에 사용자 정의 오류 메시지를 반환합니다
        return ToolMessage(
            content=f"Tool error: Please check your input and try again. ({str(e)})",
            tool_call_id=request.tool_call["id"]
        )

agent = create_agent(
    model="openai:gpt-4o",
    tools=[search, get_weather],
    middleware=[handle_tool_errors]
)
도구가 실패하면 에이전트는 사용자 정의 오류 메시지와 함께 ToolMessage를 반환합니다:
[
    ...
    ToolMessage(
        content="Tool error: Please check your input and try again. (division by zero)",
        tool_call_id="..."
    ),
    ...
]

ReAct 루프에서의 도구 사용

에이전트는 ReAct(“추론 + 행동”) 패턴을 따르며, 간단한 추론 단계와 목표 지향적인 도구 호출을 번갈아 수행하고, 결과 관찰을 후속 결정에 반영하여 최종 답변을 제공할 수 있을 때까지 반복합니다.
프롬프트: 현재 가장 인기 있는 무선 헤드폰을 식별하고 재고를 확인하세요.
================================ Human Message =================================

Find the most popular wireless headphones right now and check if they're in stock
  • 추론: “인기는 시간에 민감하므로 제공된 검색 도구를 사용해야 합니다.”
  • 행동: search_products("wireless headphones") 호출
================================== Ai Message ==================================
Tool Calls:
  search_products (call_abc123)
 Call ID: call_abc123
  Args:
    query: wireless headphones
================================= Tool Message =================================

Found 5 products matching "wireless headphones". Top 5 results: WH-1000XM5, ...
  • 추론: “답변하기 전에 상위 항목의 재고를 확인해야 합니다.”
  • 행동: check_inventory("WH-1000XM5") 호출
================================== Ai Message ==================================
Tool Calls:
  check_inventory (call_def456)
 Call ID: call_def456
  Args:
    product_id: WH-1000XM5
================================= Tool Message =================================

Product WH-1000XM5: 10 units in stock
  • 추론: “가장 인기 있는 모델과 재고 상태를 확인했습니다. 이제 사용자의 질문에 답변할 수 있습니다.”
  • 행동: 최종 답변 생성
================================== Ai Message ==================================

I found wireless headphones (model WH-1000XM5) with 10 units in stock...
도구에 대해 자세히 알아보려면 도구를 참조하세요.

시스템 프롬프트

프롬프트를 제공하여 에이전트가 작업에 접근하는 방식을 형성할 수 있습니다. system_prompt 매개변수는 문자열로 제공할 수 있습니다:
agent = create_agent(
    model,
    tools,
    system_prompt="You are a helpful assistant. Be concise and accurate."
)
system_prompt가 제공되지 않으면 에이전트는 메시지에서 직접 작업을 추론합니다.

동적 시스템 프롬프트

런타임 컨텍스트나 에이전트 상태에 따라 시스템 프롬프트를 수정해야 하는 고급 사용 사례의 경우 미들웨어를 사용할 수 있습니다. @dynamic_prompt 데코레이터는 모델 요청을 기반으로 시스템 프롬프트를 동적으로 생성하는 미들웨어를 생성합니다:
from typing import TypedDict

from langchain.agents import create_agent
from langchain.agents.middleware import dynamic_prompt, ModelRequest


class Context(TypedDict):
    user_role: str

@dynamic_prompt
def user_role_prompt(request: ModelRequest) -> str:
    """사용자 역할에 따라 시스템 프롬프트를 생성합니다."""
    user_role = request.runtime.context.get("user_role", "user")
    base_prompt = "You are a helpful assistant."

    if user_role == "expert":
        return f"{base_prompt} Provide detailed technical responses."
    elif user_role == "beginner":
        return f"{base_prompt} Explain concepts simply and avoid jargon."

    return base_prompt

agent = create_agent(
    model="openai:gpt-4o",
    tools=[web_search],
    middleware=[user_role_prompt],
    context_schema=Context
)

# 시스템 프롬프트는 컨텍스트에 따라 동적으로 설정됩니다
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Explain machine learning"}]},
    context={"user_role": "expert"}
)
메시지 유형 및 형식에 대한 자세한 내용은 메시지를 참조하세요. 포괄적인 미들웨어 문서는 미들웨어를 참조하세요.

호출

에이전트의 State에 업데이트를 전달하여 에이전트를 호출할 수 있습니다. 모든 에이전트는 상태에 메시지 시퀀스를 포함합니다. 에이전트를 호출하려면 새 메시지를 전달하세요:
result = agent.invoke(
    {"messages": [{"role": "user", "content": "What's the weather in San Francisco?"}]}
)
에이전트에서 단계 및/또는 토큰을 스트리밍하려면 스트리밍 가이드를 참조하세요. 그 외의 경우 에이전트는 LangGraph Graph API를 따르며 모든 관련 메서드를 지원합니다.

고급 개념

구조화된 출력

경우에 따라 에이전트가 특정 형식으로 출력을 반환하도록 할 수 있습니다. LangChain은 response_format 매개변수를 통해 구조화된 출력을 위한 전략을 제공합니다.

ToolStrategy

ToolStrategy는 인공 도구 호출을 사용하여 구조화된 출력을 생성합니다. 도구 호출을 지원하는 모든 모델에서 작동합니다:
from pydantic import BaseModel
from langchain.agents import create_agent
from langchain.agents.structured_output import ToolStrategy


class ContactInfo(BaseModel):
    name: str
    email: str
    phone: str

agent = create_agent(
    model="openai:gpt-4o-mini",
    tools=[search_tool],
    response_format=ToolStrategy(ContactInfo)
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "Extract contact info from: John Doe, [email protected], (555) 123-4567"}]
})

result["structured_response"]
# ContactInfo(name='John Doe', email='[email protected]', phone='(555) 123-4567')

ProviderStrategy

ProviderStrategy는 모델 공급자의 기본 구조화된 출력 생성을 사용합니다. 더 안정적이지만 기본 구조화된 출력을 지원하는 공급자(예: OpenAI)에서만 작동합니다:
from langchain.agents.structured_output import ProviderStrategy

agent = create_agent(
    model="openai:gpt-4o",
    response_format=ProviderStrategy(ContactInfo)
)
langchain 1.0부터 단순히 스키마를 전달하는 것(예: response_format=ContactInfo)은 더 이상 지원되지 않습니다. ToolStrategy 또는 ProviderStrategy를 명시적으로 사용해야 합니다.
구조화된 출력에 대해 자세히 알아보려면 구조화된 출력을 참조하세요.

메모리

에이전트는 메시지 상태를 통해 대화 기록을 자동으로 유지합니다. 대화 중에 추가 정보를 기억하도록 사용자 정의 상태 스키마를 사용하도록 에이전트를 구성할 수도 있습니다. 상태에 저장된 정보는 에이전트의 단기 메모리로 생각할 수 있습니다: 사용자 정의 상태 스키마는 TypedDictAgentState를 확장해야 합니다. 사용자 정의 상태를 정의하는 두 가지 방법이 있습니다:
  1. 미들웨어를 통해 (권장)
  2. create_agentstate_schema를 통해
미들웨어를 통해 사용자 정의 상태를 정의하는 것이 create_agentstate_schema를 통해 정의하는 것보다 선호됩니다. 이는 상태 확장을 관련 미들웨어 및 도구에 개념적으로 범위를 지정할 수 있기 때문입니다.state_schemacreate_agent에서 하위 호환성을 위해 여전히 지원됩니다.

미들웨어를 통한 상태 정의

특정 미들웨어 후크 및 해당 미들웨어에 연결된 도구에서 사용자 정의 상태에 액세스해야 할 때 미들웨어를 사용하여 사용자 정의 상태를 정의하세요.
from langchain.agents import AgentState
from langchain.agents.middleware import AgentMiddleware


class CustomState(AgentState):
    user_preferences: dict

class CustomMiddleware(AgentMiddleware):
    state_schema = CustomState
    tools = [tool1, tool2]

    def before_model(self, state: CustomState, runtime) -> dict[str, Any] | None:
        ...

agent = create_agent(
    model,
    tools=tools,
    middleware=[CustomMiddleware()]
)

# 에이전트는 이제 메시지 외에 추가 상태를 추적할 수 있습니다
result = agent.invoke({
    "messages": [{"role": "user", "content": "I prefer technical explanations"}],
    "user_preferences": {"style": "technical", "verbosity": "detailed"},
})

state_schema를 통한 상태 정의

도구에서만 사용되는 사용자 정의 상태를 정의하는 바로 가기로 state_schema 매개변수를 사용하세요.
from langchain.agents import AgentState


class CustomState(AgentState):
    user_preferences: dict

agent = create_agent(
    model,
    tools=[tool1, tool2],
    state_schema=CustomState
)
# 에이전트는 이제 메시지 외에 추가 상태를 추적할 수 있습니다
result = agent.invoke({
    "messages": [{"role": "user", "content": "I prefer technical explanations"}],
    "user_preferences": {"style": "technical", "verbosity": "detailed"},
})
langchain 1.0부터 사용자 정의 상태 스키마는 반드시 TypedDict 타입이어야 합니다. Pydantic 모델과 데이터 클래스는 더 이상 지원되지 않습니다. 자세한 내용은 v1 마이그레이션 가이드를 참조하세요.
메모리에 대해 자세히 알아보려면 메모리를 참조하세요. 세션 간에 지속되는 장기 메모리 구현에 대한 정보는 장기 메모리를 참조하세요.

스트리밍

invoke로 에이전트를 호출하여 최종 응답을 받는 방법을 살펴보았습니다. 에이전트가 여러 단계를 실행하는 경우 시간이 걸릴 수 있습니다. 중간 진행 상황을 표시하려면 메시지가 발생할 때 스트리밍할 수 있습니다.
for chunk in agent.stream({
    "messages": [{"role": "user", "content": "Search for AI news and summarize the findings"}]
}, stream_mode="values"):
    # 각 청크는 해당 시점의 전체 상태를 포함합니다
    latest_message = chunk["messages"][-1]
    if latest_message.content:
        print(f"Agent: {latest_message.content}")
    elif latest_message.tool_calls:
        print(f"Calling tools: {[tc['name'] for tc in latest_message.tool_calls]}")
스트리밍에 대한 자세한 내용은 스트리밍을 참조하세요.

미들웨어

미들웨어는 실행의 여러 단계에서 에이전트 동작을 사용자 정의하기 위한 강력한 확장성을 제공합니다. 미들웨어를 사용하여 다음을 수행할 수 있습니다:
  • 모델이 호출되기 전에 상태 처리(예: 메시지 자르기, 컨텍스트 주입)
  • 모델의 응답 수정 또는 검증(예: 가드레일, 콘텐츠 필터링)
  • 사용자 정의 로직으로 도구 실행 오류 처리
  • 상태 또는 컨텍스트에 따른 동적 모델 선택 구현
  • 사용자 정의 로깅, 모니터링 또는 분석 추가
미들웨어는 에이전트의 실행 그래프에 원활하게 통합되어 핵심 에이전트 로직을 변경하지 않고도 주요 지점에서 데이터 흐름을 가로채고 수정할 수 있습니다.
@before_model, @after_model@wrap_tool_call과 같은 데코레이터를 포함한 포괄적인 미들웨어 문서는 미들웨어를 참조하세요.

Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I