이 가이드는 LangChain v1과 이전 버전 간의 주요 변경 사항을 설명합니다.

간소화된 패키지

langchain 패키지 네임스페이스는 v1에서 에이전트의 핵심 빌딩 블록에 집중하도록 크게 축소되었습니다. 간소화된 패키지는 코어 기능을 더 쉽게 발견하고 사용할 수 있도록 합니다.

Namespace

ModuleWhat’s availableNotes
langchain.agentscreate_agent, AgentState핵심 에이전트 생성 기능
langchain.messagesMessage 타입, content blocks, trim_messageslangchain-core에서 재-export됨
langchain.tools@tool, BaseTool, 주입 헬퍼langchain-core에서 재-export됨
langchain.chat_modelsinit_chat_model, BaseChatModel통합된 모델 초기화
langchain.embeddingsinit_embeddings, EmbeddingsEmbedding 모델

langchain-classic

langchain 패키지에서 아래 항목들을 사용 중이었다면 langchain-classic을 설치하고 import를 업데이트해야 합니다:
  • 레거시 체인 (LLMChain, ConversationChain 등)
  • Retriever (예: MultiQueryRetriever 또는 기존 langchain.retrievers 모듈의 모든 것)
  • Indexing API
  • Hub 모듈(프롬프트를 프로그래밍 방식으로 관리)
  • Embeddings 모듈(예: CacheBackedEmbeddings 및 community embeddings)
  • langchain-community 재-export
  • 기타 deprecated 기능
# Chains
from langchain_classic.chains import LLMChain

# Retrievers
from langchain_classic.retrievers import ...

# Indexing
from langchain_classic.indexes import ...

# Hub
from langchain_classic import hub
설치:
pip install langchain-classic

create_agent로 마이그레이션

v1.0 이전에는 에이전트를 만들 때 langgraph.prebuilt.create_react_agent 사용을 권장했습니다. 이제는 에이전트를 만들 때 langchain.agents.create_agent 사용을 권장합니다. 아래 표는 create_react_agent에서 create_agent로 변경된 기능을 요약합니다:
SectionTL;DR - What’s changed
Import path패키지가 langgraph.prebuilt에서 langchain.agents로 이동
Prompts파라미터가 system_prompt로 변경, 동적 prompts는 middleware 사용
Pre-model hookbefore_model 메서드를 가진 middleware로 대체
Post-model hookafter_model 메서드를 가진 middleware로 대체
Custom stateTypedDict만 지원, state_schema 또는 middleware로 정의 가능
Modelmiddleware를 통한 동적 선택, 사전 바인딩된 모델은 미지원
ToolsTool 에러 처리 로직이 wrap_tool_call이 있는 middleware로 이동
Structured outputprompted output 제거, ToolStrategy/ProviderStrategy 사용
Streaming node name노드 이름이 "agent"에서 "model"로 변경
Runtime contextconfig["configurable"] 대신 context 인자를 통한 의존성 주입
Namespace에이전트 빌딩 블록에 집중하도록 간소화, 레거시 코드는 langchain-classic로 이동

Import path

에이전트 prebuilt의 import 경로가 langgraph.prebuilt에서 langchain.agents로 변경되었습니다. 함수 이름도 create_react_agent에서 create_agent로 변경되었습니다:
from langgraph.prebuilt import create_react_agent 
from langchain.agents import create_agent 
자세한 내용은 Agents를 참조하세요.

Prompts

정적 프롬프트 이름 변경

prompt 파라미터가 system_prompt로 변경되었습니다:
from langchain.agents import create_agent


agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[check_weather],
    system_prompt="You are a helpful assistant"
)

SystemMessage를 문자열로

시스템 프롬프트에서 SystemMessage 객체를 사용 중이라면 문자열 content를 추출하세요:
from langchain.agents import create_agent


agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[check_weather],
    system_prompt="You are a helpful assistant"
)

동적 프롬프트

동적 프롬프트는 핵심 컨텍스트 엔지니어링 패턴으로, 현재 대화 state에 따라 모델에 전달하는 내용을 적응시킵니다. 이를 위해 @dynamic_prompt 데코레이터를 사용하세요:
from dataclasses import dataclass

from langchain.agents import create_agent
from langchain.agents.middleware import dynamic_prompt, ModelRequest
from langgraph.runtime import Runtime


@dataclass
class Context:  
    user_role: str = "user"

@dynamic_prompt
def dynamic_prompt(request: ModelRequest) -> str:  
    user_role = request.runtime.context.user_role
    base_prompt = "You are a helpful assistant."

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

    return prompt  

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

# Use with context
agent.invoke(
    {"messages": [{"role": "user", "content": "Explain async programming"}]},
    context=Context(user_role="expert")
)

Pre-model hook

Pre-model hook은 이제 before_model 메서드를 가진 middleware로 구현됩니다. 이 새로운 패턴은 확장성이 높아 모델 호출 전에 실행할 여러 middleware를 정의할 수 있으며, 여러 에이전트에서 공통 패턴을 재사용할 수 있습니다. 일반적인 사용 사례:
  • 대화 이력 요약
  • 메시지 트리밍
  • PII 마스킹 같은 입력 가드레일
v1에는 요약 middleware가 기본 옵션으로 제공됩니다:
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware


agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=tools,
    middleware=[
        SummarizationMiddleware(  
            model="anthropic:claude-sonnet-4-5",  
            max_tokens_before_summary=1000
        )  
    ]  
)

Post-model hook

Post-model hook은 이제 after_model 메서드를 가진 middleware로 구현됩니다. 이 새로운 패턴은 확장성이 높아 모델 호출 후에 실행할 여러 middleware를 정의할 수 있으며, 여러 에이전트에서 공통 패턴을 재사용할 수 있습니다. 일반적인 사용 사례: v1에는 도구 호출에 대한 human in the loop 승인용 기본 제공 middleware가 있습니다:
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware


agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[read_email, send_email],
    middleware=[HumanInTheLoopMiddleware(
        interrupt_on={
            "send_email": True,
            "description": "Please review this email before sending"
        },
    )]
)

Custom state

Custom state는 기본 에이전트 state에 추가 필드를 확장합니다. 커스텀 state를 정의하는 방법은 두 가지입니다:
  1. create_agentstate_schema - 도구에서 사용하는 state에 최적
  2. middleware로 - 특정 middleware hooks와 해당 middleware에 연결된 도구가 관리하는 state에 최적
middleware로 custom state를 정의하면 관련 middleware와 도구에 개념적으로 범위가 맞춰져 유지되므로, create_agentstate_schema로 정의하는 것보다 선호됩니다.state_schema는 여전히 create_agent에서 하위 호환을 위해 지원됩니다.

state_schema로 state 정의

커스텀 state를 도구에서 접근해야 할 때 state_schema 파라미터를 사용하세요:
from langchain.tools import tool, ToolRuntime
from langchain.agents import create_agent, AgentState  


# Define custom state extending AgentState
class CustomState(AgentState):
    user_name: str

@tool
def greet(
    runtime: ToolRuntime[CustomState]
) -> str:
    """Use this to greet the user by name."""
    user_name = runtime.state.get("user_name", "Unknown")  
    return f"Hello {user_name}!"

agent = create_agent(  
    model="anthropic:claude-sonnet-4-5",
    tools=[greet],
    state_schema=CustomState  
)

middleware로 state 정의

Middleware는 state_schema 속성을 설정하여 custom state를 정의할 수도 있습니다. 이는 state 확장을 관련 middleware와 도구에 개념적으로 범위를 맞출 수 있도록 돕습니다.
from langchain.agents.middleware import AgentState, AgentMiddleware
from typing_extensions import NotRequired
from typing import Any

class CustomState(AgentState):
    model_call_count: NotRequired[int]

class CallCounterMiddleware(AgentMiddleware[CustomState]):
    state_schema = CustomState  

    def before_model(self, state: CustomState, runtime) -> dict[str, Any] | None:
        count = state.get("model_call_count", 0)
        if count > 10:
            return {"jump_to": "end"}
        return None

    def after_model(self, state: CustomState, runtime) -> dict[str, Any] | None:
        return {"model_call_count": state.get("model_call_count", 0) + 1}

agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[...],
    middleware=[CallCounterMiddleware()]  
)
middleware를 통한 custom state 정의에 대한 자세한 내용은 middleware 문서를 참조하세요.

State 타입 제한

create_agent는 state 스키마로 TypedDict만 지원합니다. Pydantic 모델과 dataclass는 더 이상 지원되지 않습니다.
from langchain.agents import AgentState, create_agent

# AgentState is a TypedDict
class CustomAgentState(AgentState):  
    user_id: str

agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=tools,
    state_schema=CustomAgentState  
)
BaseModel 상속이나 dataclass 데코레이터 대신 langchain.agents.AgentState를 상속하세요. 검증이 필요하다면 middleware hooks에서 처리하세요.

Model

동적 모델 선택을 사용하면 런타임 context(예: 작업 복잡도, 비용 제약, 사용자 선호)에 따라 다른 모델을 선택할 수 있습니다. langgraph-prebuilt의 v0.6에서 릴리스된 create_react_agentmodel 파라미터에 전달한 callable을 통해 동적 모델/도구 선택을 지원했습니다. 이 기능은 v1에서 middleware 인터페이스로 이식되었습니다.

동적 모델 선택

from langchain.agents import create_agent
from langchain.agents.middleware import (
    AgentMiddleware, ModelRequest, ModelRequestHandler
)
from langchain.messages import AIMessage
from langchain_openai import ChatOpenAI


basic_model = ChatOpenAI(model="gpt-5-nano")
advanced_model = ChatOpenAI(model="gpt-5")

class DynamicModelMiddleware(AgentMiddleware):

    def wrap_model_call(self, request: ModelRequest, handler: ModelRequestHandler) -> AIMessage:
        if len(request.state.messages) > self.messages_threshold:
            model = advanced_model
        else:
            model = basic_model

        return handler(request.replace(model=model))

    def __init__(self, messages_threshold: int) -> None:
        self.messages_threshold = messages_threshold

agent = create_agent(
    model=basic_model,
    tools=tools,
    middleware=[DynamicModelMiddleware(messages_threshold=10)]
)

사전 바인딩된 모델

구조화된 출력 지원을 강화하기 위해, create_agent는 도구나 설정이 사전 바인딩된 모델을 더 이상 허용하지 않습니다:
# No longer supported
model_with_tools = ChatOpenAI().bind_tools([some_tool])
agent = create_agent(model_with_tools, tools=[])

# Use instead
agent = create_agent("openai:gpt-4o-mini", tools=[some_tool])
동적 모델 함수는 구조화된 출력을 사용하지 않는 경우 사전 바인딩된 모델을 반환할 수 있습니다.

Tools

create_agenttools 인자는 다음의 리스트를 받을 수 있습니다:
  • LangChain BaseTool 인스턴스(@tool로 데코레이트된 함수)
  • 적절한 타입 힌트와 docstring을 갖춘 callable 객체(함수)
  • 내장 provider 도구를 나타내는 dict
이 인자는 더 이상 ToolNode 인스턴스를 허용하지 않습니다.
from langchain.agents import create_agent


agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[check_weather, search_web]
)

도구 에러 처리

이제 wrap_tool_call 메서드를 구현한 middleware로 도구 에러 처리 방식을 구성할 수 있습니다.
# Example coming soon

Structured output

노드 변경

이전에는 구조화된 출력이 메인 에이전트와 분리된 노드에서 생성되었습니다. 이제는 그렇지 않습니다. 메인 루프에서 구조화된 출력을 생성하여 비용과 지연을 줄입니다.

도구/프로바이더 전략

v1에서는 두 가지 새로운 구조화된 출력 전략이 도입되었습니다:
  • ToolStrategy는 인공적인 도구 호출을 사용하여 구조화된 출력을 생성
  • ProviderStrategy는 provider 고유의 구조화된 출력 생성을 사용
from langchain.agents import create_agent
from langchain.agents.structured_output import ToolStrategy, ProviderStrategy
from pydantic import BaseModel


class OutputSchema(BaseModel):
    summary: str
    sentiment: str

# Using ToolStrategy
agent = create_agent(
    model="openai:gpt-4o-mini",
    tools=tools,
    # explicitly using tool strategy
    response_format=ToolStrategy(OutputSchema)  
)

Prompted output 제거

response_format 인자를 통한 prompted output은 더 이상 지원되지 않습니다. 인공 도구 호출이나 provider 고유의 구조화된 출력과 같은 전략에 비해, prompted output은 특히 신뢰성이 높지 않은 것으로 나타났습니다.

Streaming node name 변경

에이전트에서 이벤트를 스트리밍할 때, 노드 이름이 노드의 목적을 더 잘 반영하도록 "agent"에서 "model"로 변경되었습니다.

Runtime context

에이전트를 호출할 때, 보통 두 가지 유형의 데이터를 전달해야 할 수 있습니다:
  • 대화 내에서 지속적으로 변하는 동적 state(예: 메시지 이력)
  • 대화 중 변하지 않는 정적 context(예: 사용자 메타데이터)
v1에서는 invokestreamcontext 파라미터를 설정하여 정적 context를 지원합니다.
from dataclasses import dataclass

from langchain.agents import create_agent


@dataclass
class Context:
    user_id: str
    session_id: str

agent = create_agent(
    model=model,
    tools=tools,
    context_schema=ContextSchema  
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "Hello"}]},
    context=Context(user_id="123", session_id="abc")  
)
기존 config["configurable"] 패턴은 하위 호환을 위해 계속 동작하지만, 새로운 애플리케이션 또는 v1로 마이그레이션하는 애플리케이션에서는 새로운 context 파라미터 사용을 권장합니다.

표준 콘텐츠

v1에서는 메시지가 provider-agnostic 표준 content blocks를 지원합니다. provider 간 일관되고 타입이 지정된 보기를 위해 @[message.content_blocks][content_blocks]를 통해 접근하세요. 기존 message.content 필드는 문자열 또는 provider 고유의 구조에 대해 변경되지 않습니다.

변경 사항

  • 정규화된 content에 대한 새로운 content_blocks 메시지 속성 추가
  • Messages에 문서화된 표준화된 블록 형태
  • LC_OUTPUT_VERSION=v1 또는 output_version="v1"을 통해 표준 블록을 content로 직렬화하는 옵션

표준화된 콘텐츠 읽기

from langchain.chat_models import init_chat_model

model = init_chat_model("openai:gpt-5-nano")
response = model.invoke("Explain AI")

for block in response.content_blocks:
    if block["type"] == "reasoning":
        print(block.get("reasoning"))
    elif block["type"] == "text":
        print(block.get("text"))

멀티모달 메시지 만들기

from langchain.messages import HumanMessage

message = HumanMessage(content_blocks=[
    {"type": "text", "text": "Describe this image."},
    {"type": "image", "url": "https://example.com/image.jpg"},
])
res = model.invoke([message])

블록 형태 예시

# Text block
text_block = {
    "type": "text",
    "text": "Hello world",
}

# Image block
image_block = {
    "type": "image",
    "url": "https://example.com/image.png",
    "mime_type": "image/png",
}
자세한 내용은 content blocks 레퍼런스를 참조하세요.

표준 콘텐츠 직렬화

표준 content blocks는 기본적으로 content 속성에 직렬화되지 않습니다. content 속성에서 표준 content blocks에 접근해야 하는 경우(예: 클라이언트로 메시지를 보낼 때), 이를 content로 직렬화하도록 옵트인할 수 있습니다.
export LC_OUTPUT_VERSION=v1

간소화된 패키지

langchain 패키지 네임스페이스는 v1에서 에이전트의 핵심 빌딩 블록에 집중하도록 크게 축소되었습니다. 간소화된 패키지는 코어 기능을 더 쉽게 발견하고 사용할 수 있도록 합니다.

Namespace

ModuleWhat’s availableNotes
langchain.agentscreate_agent, AgentState핵심 에이전트 생성 기능
langchain.messagesMessage 타입, content blocks, trim_messageslangchain-core에서 재-export됨
langchain.tools@tool, BaseTool, 주입 헬퍼langchain-core에서 재-export됨
langchain.chat_modelsinit_chat_model, BaseChatModel통합된 모델 초기화
langchain.embeddingsinit_embeddings, EmbeddingsEmbedding 모델

langchain-classic

langchain 패키지에서 아래 항목들을 사용 중이었다면 langchain-classic을 설치하고 import를 업데이트해야 합니다:
  • 레거시 체인 (LLMChain, ConversationChain 등)
  • Retriever (예: MultiQueryRetriever 또는 기존 langchain.retrievers 모듈의 모든 것)
  • Indexing API
  • Hub 모듈(프롬프트를 프로그래밍 방식으로 관리)
  • Embeddings 모듈(예: CacheBackedEmbeddings 및 community embeddings)
  • langchain-community 재-export
  • 기타 deprecated 기능
# Chains
from langchain_classic.chains import LLMChain

# Retrievers
from langchain_classic.retrievers import ...

# Indexing
from langchain_classic.indexes import ...

# Hub
from langchain_classic import hub
설치:
uv pip install langchain-classic

변경 사항(호환성 파괴)

Python 3.9 지원 중단

모든 LangChain 패키지는 이제 Python 3.10 이상이 필요합니다. Python 3.9는 2025년 10월에 수명 종료(EOL)에 도달합니다.

Chat 모델 반환 타입 업데이트

Chat 모델 호출의 반환 타입 시그니처가 BaseMessage에서 AIMessage로 수정되었습니다. bind_tools를 구현하는 커스텀 chat 모델은 반환 시그니처를 업데이트해야 합니다:
def bind_tools(
        ...
    ) -> Runnable[LanguageModelInput, AIMessage]:

OpenAI Responses API의 기본 메시지 형식

Responses API와 상호작용할 때, langchain-openai는 이제 응답 항목을 메시지 content에 저장하는 것이 기본입니다. 이전 동작을 복원하려면 LC_OUTPUT_VERSION 환경 변수를 v0로 설정하거나, ChatOpenAI 인스턴스화 시 output_version="v0"를 지정하세요.
# Enforce previous behavior with output_version flag
model = ChatOpenAI(model="gpt-4o-mini", output_version="v0")

langchain-anthropic의 기본 max_tokens

langchain-anthropicmax_tokens 파라미터는 이제 선택한 모델에 따라 더 높은 값으로 기본 설정됩니다(이전 기본값 1024 대신). 이전 기본값에 의존하던 경우, 명시적으로 max_tokens=1024로 설정하세요.

레거시 코드의 langchain-classic 이동

표준 인터페이스와 에이전트의 초점을 벗어나는 기존 기능은 langchain-classic 패키지로 이동했습니다. 코어 langchain 패키지에서 제공되는 항목과 langchain-classic으로 이동한 항목에 대한 자세한 내용은 간소화된 네임스페이스 섹션을 참조하세요.

Deprecated API 제거

이미 deprecated 되었고 1.0에서 제거 예정이었던 메서드, 함수 및 기타 객체가 삭제되었습니다. 대체 API는 이전 버전의 deprecation 공지를 확인하세요.

.text()는 이제 프로퍼티

메시지 객체에서 .text() 메서드를 사용할 때 괄호를 제거해야 합니다:
# Property access
text = response.text

# Deprecated method call
text = response.text()
기존 사용 방식(즉, .text())은 계속 동작하지만 이제 경고를 발생시킵니다.
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I