LangChain v1 마이그레이션 가이드
LangChain v1 마이그레이션 가이드 (LangChain v1 migration guide)
LangChain v1과 이전 버전 사이의 주요 변경 사항을 다루는 가이드예요. v1은 langchain 패키지의 네임스페이스를 크게 줄여 에이전트의 핵심 구성 요소에 집중했고, 기존 코드는 langchain-classic으로 옮겼어요. 마이그레이션에는 langchain>=1.0.0, langchain-core>=1.0.0, 그리고 Python 3.10 이상이 필요해요.
출처: 공식문서
핵심 변경 사항을 먼저 정리하면:
- 패키지 네임스페이스 축소:
langchain패키지는 에이전트, 메시지, 툴, chat 모델, 임베딩에 집중해요. 레거시 체인, retriever, index, hub,CacheBackedEmbeddings같은 임베딩 헬퍼, 커뮤니티 재수출은langchain-classic으로 옮겨졌어요.langchain-classic을 설치하고 해당 import를langchain_classic.*로 바꾸세요.langchain의 커뮤니티 통합 재수출 대신 프로바이더 패키지를 직접 설치해요(예:langchain-openai). create_react_agent→create_agent:from langgraph.prebuilt import create_react_agent를from langchain.agents import create_agent로 바꾸세요.prompt=는system_prompt=로 이름이 바뀌었어요.agent.invoke({"messages": [...]})/agent.stream(...)으로 호출해요. deprecated된langgraph.prebuilt에이전트 상태 헬퍼보다langchain.agents.AgentState를 선호해요.- 훅이 미들웨어가 됨:
pre_model_hook=,post_model_hook=,state_modifier=커스터마이징을create_agent미들웨어(before_model,after_model,@wrap_model_call,@wrap_tool_call)로 대체해요. 툴 승인용 human-in-the-loop은langchain.agents.middleware의HumanInTheLoopMiddleware(interrupt_on={...})를 사용해요. - 구조화 출력:
response_format=은 유지하되langchain.agents.structured_output의ToolStrategy/ProviderStrategy를 사용해요.response_format=("please generate ...", Schema)같은 프롬프트 기반 출력 형식은 제거됐어요. - 스트리밍 노드 이름: 스트리밍 이벤트를 노드 이름으로 필터링·매칭할 때
"agent"를"model"로 바꾸세요. - 런타임 컨텍스트:
config["configurable"]만 쓰는 대신invoke/stream의context=인자로 정적 컨텍스트를 전달해요(create_agent에선context_schema=). - 표준 콘텐츠 블록: 프로바이더 무관 콘텐츠에는
message.content_blocks를 선호해요. 기존message.content도 여전히 유효해요.
create_react_agent, pre_model_hook, post_model_hook, state_modifier, langgraph.prebuilt의 import, 그리고 langchain.chains, langchain.retrievers, langchain.indexes, langchain.hub 같은 레거시 langchain 모듈을 코드베이스에서 검색해 필요한 변경을 적용하세요.
단순화된 패키지 (Simplified package)
v1에서 langchain 패키지 네임스페이스는 에이전트의 필수 빌딩 블록에 집중하도록 크게 줄었어요. 이렇게 정리된 패키지는 핵심 기능을 더 쉽게 발견하고 사용하게 해줘요.
네임스페이스
| 모듈 | 제공 내용 | 비고 |
|---|---|---|
langchain.agents |
create_agent, AgentState |
핵심 에이전트 생성 기능 |
langchain.messages |
메시지 유형, content blocks, trim_messages |
langchain-core에서 재수출 |
langchain.tools |
@tool, BaseTool, 주입 헬퍼 |
langchain-core에서 재수출 |
langchain.chat_models |
init_chat_model, BaseChatModel |
통합 모델 초기화 |
langchain.embeddings |
init_embeddings, Embeddings |
임베딩 모델 |
langchain-classic
langchain 패키지에서 다음 중 하나라도 썼다면 langchain-classic을 설치하고 import를 업데이트해야 해요.
- 레거시 체인 (
LLMChain,ConversationChain등) - Retriever (예:
MultiQueryRetriever또는 이전langchain.retrievers모듈의 것) - Indexing API
- Hub 모듈 (프롬프트를 프로그래밍 방식으로 관리)
- 임베딩 모듈 (예:
CacheBackedEmbeddings, 커뮤니티 임베딩) langchain-community재수출- 기타 deprecated 기능
# v1 (new) — 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
# v0 (old) — Chains
from langchain_classic.chains import LLMChain
# Retrievers
from langchain.retrievers import ...
# Indexing
from langchain.indexes import ...
# Hub
from langchain import hub
설치:
pip install langchain-classic
uv add langchain-classic
create_agent로 마이그레이션 (Migrate to create_agent)
v1.0 이전에는 에이전트를 만들 때 langgraph.prebuilt.create_react_agent를 권장했어요. 이제는 langchain.agents.create_agent를 권장해요.
| 섹션 | TL;DR — 무엇이 바뀌었나 |
|---|---|
| Import 경로 | 패키지가 langgraph.prebuilt에서 langchain.agents로 이동 |
| 프롬프트 | 파라미터가 system_prompt로 이름 변경, 동적 프롬프트는 미들웨어 사용 |
| Pre-model hook | before_model 메서드를 가진 미들웨어로 대체 |
| Post-model hook | after_model 메서드를 가진 미들웨어로 대체 |
| 커스텀 상태 | TypedDict만 지원, state_schema 또는 미들웨어로 정의 |
| 모델 | 미들웨어를 통한 동적 선택, 사전 바인딩 모델 미지원 |
| 툴 | 툴 오류 처리가 wrap_tool_call 미들웨어로 이동 |
| 구조화 출력 | 프롬프트 기반 출력 제거, ToolStrategy/ProviderStrategy 사용 |
| 스트리밍 노드 이름 | 노드 이름이 "agent"에서 "model"로 변경 |
| 런타임 컨텍스트 | config["configurable"] 대신 context 인자로 의존성 주입 |
| 네임스페이스 | 에이전트 빌딩 블록에 집중하도록 정리, 레거시는 langchain-classic으로 이동 |
Import 경로 (Import path)
에이전트 prebuilt의 import 경로가 langgraph.prebuilt에서 langchain.agents로 바뀌었고, 함수 이름도 create_react_agent에서 create_agent로 바뀌었어요.
from langgraph.prebuilt import create_react_agent # [!code --]
from langchain.agents import create_agent # [!code ++]
자세한 내용은 Agents를 참고해요.
프롬프트 (Prompts)
정적 프롬프트 이름 변경
prompt 파라미터가 system_prompt으로 이름이 바뀌었어요.
# v1 (new)
from langchain.agents import create_agent
agent = create_agent(
model="claude-sonnet-4-6",
tools=[check_weather],
system_prompt="You are a helpful assistant" # [!code highlight]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=[check_weather],
prompt="You are a helpful assistant" # [!code highlight]
)
SystemMessage를 문자열로
시스템 프롬프트에 SystemMessage 객체를 썼다면 문자열 콘텐츠를 추출하세요.
# v1 (new)
from langchain.agents import create_agent
agent = create_agent(
model="claude-sonnet-4-6",
tools=[check_weather],
system_prompt="You are a helpful assistant" # [!code highlight]
)
# v0 (old)
from langchain.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=[check_weather],
prompt=SystemMessage(content="You are a helpful assistant") # [!code highlight]
)
동적 프롬프트
동적 프롬프트는 핵심 컨텍스트 엔지니어링 패턴이에요. 현재 대화 상태에 따라 모델에게 알려주는 내용을 바꾸는 거죠. 이를 위해 @dynamic_prompt 데코레이터를 사용해요.
# v1 (new)
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: # [!code highlight]
user_role: str = "user"
@dynamic_prompt # [!code highlight]
def dynamic_prompt(request: ModelRequest) -> str: # [!code highlight]
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 # [!code highlight]
agent = create_agent(
model="gpt-5.5",
tools=tools,
middleware=[dynamic_prompt], # [!code highlight]
context_schema=Context
)
# Use with context
agent.invoke(
{"messages": [{"role": "user", "content": "Explain async programming"}]},
context=Context(user_role="expert")
)
# v0 (old)
from dataclasses import dataclass
from langgraph.prebuilt import create_react_agent, AgentState
from langgraph.runtime import get_runtime
@dataclass
class Context:
user_role: str
def dynamic_prompt(state: AgentState) -> str:
runtime = get_runtime(Context) # [!code highlight]
user_role = runtime.context.user_role
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_react_agent(
model="gpt-5.5",
tools=tools,
prompt=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 메서드를 가진 미들웨어로 구현해요. 이 새 패턴은 더 확장 가능해요 — 모델 호출 전에 실행할 미들웨어를 여러 개 정의해 다양한 에이전트에서 공통 패턴을 재사용할 수 있죠.
흔한 사용 사례:
- 대화 히스토리 요약
- 메시지 정리(trimming)
- PII 삭제 같은 입력 가드레일
v1에는 요약 미들웨어가 내장 옵션으로 들어 있어요.
# v1 (new)
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
agent = create_agent(
model="claude-sonnet-4-6",
tools=tools,
middleware=[
SummarizationMiddleware( # [!code highlight]
model="claude-sonnet-4-6", # [!code highlight]
trigger={"tokens": 1000} # [!code highlight]
) # [!code highlight]
] # [!code highlight]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent, AgentState
def custom_summarization_function(state: AgentState):
"""Custom logic for message summarization."""
...
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=tools,
pre_model_hook=custom_summarization_function
)
Post-model hook
post-model hook은 이제 after_model 메서드를 가진 미들웨어로 구현해요. 모델 호출 후 실행할 미들웨어를 여러 개 정의해 공통 패턴을 재사용할 수 있어요.
흔한 사용 사례:
- Human in the loop
- 출력 가드레일
v1에는 툴 호출 인간 승인용 내장 미들웨어가 있어요.
# v1 (new)
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
agent = create_agent(
model="claude-sonnet-4-6",
tools=[read_email, send_email],
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={
"send_email": {
"description": "Please review this email before sending",
"allowed_decisions": ["approve", "reject"]
}
}
)
]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent
from langgraph.prebuilt import AgentState
def custom_human_in_the_loop_hook(state: AgentState):
"""Custom logic for human in the loop approval."""
...
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=[read_email, send_email],
post_model_hook=custom_human_in_the_loop_hook
)
커스텀 상태 (Custom state)
커스텀 상태는 기본 에이전트 상태에 추가 필드를 확장해요. 두 가지 방법으로 정의할 수 있어요.
create_agent의state_schema로 — 툴에서 사용하는 상태에 적합- 미들웨어로 — 특정 미들웨어 훅과 그 미들웨어에 붙은 툴이 관리하는 상태에 적합
미들웨어로 커스텀 상태를 정의하는 게
create_agent의state_schema로 정의하는 것보다 선호돼요. 상태 확장을 관련 미들웨어·툴에 개념적으로 범위를 한정할 수 있기 때문이죠.state_schema는create_agent에서 역호환을 위해 여전히 지원해요.
state_schema로 상태 정의
커스텀 상태를 툴이 접근해야 할 때 state_schema 파라미터를 사용해요.
# v1 (new)
from langchain.tools import tool, ToolRuntime
from langchain.agents import create_agent, AgentState # [!code highlight]
# Define custom state extending AgentState
class CustomState(AgentState):
user_name: str
@tool # [!code highlight]
def greet(
runtime: ToolRuntime[None, CustomState]
) -> str:
"""Use this to greet the user by name."""
user_name = runtime.state.get("user_name", "Unknown") # [!code highlight]
return f"Hello {user_name}!"
agent = create_agent( # [!code highlight]
model="claude-sonnet-4-6",
tools=[greet],
state_schema=CustomState # [!code highlight]
)
# v0 (old)
from typing import Annotated
from langgraph.prebuilt import InjectedState, create_react_agent
from langgraph.prebuilt.chat_agent_executor import AgentState
class CustomState(AgentState):
user_name: str
def greet(
state: Annotated[CustomState, InjectedState]
) -> str:
"""Use this to greet the user by name."""
user_name = state["user_name"]
return f"Hello {user_name}!"
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=[greet],
state_schema=CustomState
)
미들웨어로 상태 정의
미들웨어는 state_schema 속성을 설정해 커스텀 상태를 정의할 수도 있어요. 상태 확장을 관련 미들웨어·툴에 개념적으로 범위를 한정하는 데 도움돼요.
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 # [!code highlight]
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="claude-sonnet-4-6",
tools=[...],
middleware=[CallCounterMiddleware()] # [!code highlight]
)
미들웨어로 커스텀 상태를 정의하는 자세한 내용은 미들웨어 문서를 참고해요.
상태 타입 제한
create_agent는 상태 스키마에 TypedDict만 지원해요. Pydantic 모델과 dataclass는 더 이상 지원되지 않아요.
# v1 (new)
from langchain.agents import AgentState, create_agent
# AgentState is a TypedDict
class CustomAgentState(AgentState): # [!code highlight]
user_id: str
agent = create_agent(
model="claude-sonnet-4-6",
tools=tools,
state_schema=CustomAgentState # [!code highlight]
)
# v0 (old)
from typing_extensions import Annotated
from pydantic import BaseModel
from langgraph.graph import StateGraph
from langgraph.graph.messages import add_messages
from langchain.messages import AnyMessage
class AgentState(BaseModel): # [!code highlight]
messages: Annotated[list[AnyMessage], add_messages]
user_id: str
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=tools,
state_schema=AgentState
)
BaseModel 상속이나 dataclass 데코레이터 대신 langchain.agents.AgentState에서 상속하면 돼요. 검증이 필요하면 미들웨어 훅에서 처리하세요.
모델 (Model)
동적 모델 선택은 런타임 컨텍스트(작업 복잡도, 비용 제약, 사용자 선호 등)에 따라 다른 모델을 고를 수 있게 해줘요. langgraph-prebuilt의 v0.6에서 릴리스된 create_react_agent는 model 파라미터에 전달된 콜러블로 동적 모델·툴 선택을 지원했어요. 이 기능은 v1에서 미들웨어 인터페이스로 포팅됐어요.
동적 모델 선택
# v1 (new)
from langchain.agents import create_agent
from langchain.agents.middleware import (
AgentMiddleware, ModelRequest
)
from langchain.agents.middleware.types import ModelResponse
from langchain_openai import ChatOpenAI
from typing import Callable
basic_model = ChatOpenAI(model="gpt-5-nano")
advanced_model = ChatOpenAI(model="gpt-5.5")
class DynamicModelMiddleware(AgentMiddleware):
def wrap_model_call(self, request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse]) -> ModelResponse:
if len(request.state.messages) > self.messages_threshold:
model = advanced_model
else:
model = basic_model
return handler(request.override(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)]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent, AgentState
from langchain_openai import ChatOpenAI
basic_model = ChatOpenAI(model="gpt-5-nano")
advanced_model = ChatOpenAI(model="gpt-5.5")
def select_model(state: AgentState) -> BaseChatModel:
# use a more advanced model for longer conversations
if len(state.messages) > 10:
return advanced_model
return basic_model
agent = create_react_agent(
model=select_model,
tools=tools,
)
사전 바인딩 모델
구조화 출력을 더 잘 지원하기 위해 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("gpt-5.4-mini", tools=[some_tool])
구조화 출력을 사용하지 않으면 동적 모델 함수는 사전 바인딩 모델을 반환할 수 있어요.
툴 (Tools)
create_agent의 tools 인자는 다음 목록을 받아요.
- LangChain
BaseTool인스턴스 (@tool데코레이터를 쓴 함수) - 적절한 타입 힌트와 docstring을 가진 콜러블 객체(함수)
- 내장 프로바이더 툴을 나타내는
dict
이 인자는 더 이상 ToolNode 인스턴스를 받지 않아요.
# v1 (new)
from langchain.agents import create_agent
agent = create_agent(
model="claude-sonnet-4-6",
tools=[check_weather, search_web]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent, ToolNode
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=ToolNode([check_weather, search_web]) # [!code highlight]
)
툴 오류 처리
wrap_tool_call 메서드를 구현하는 미들웨어로 툴 오류 처리를 구성할 수 있어요.
# v1 (new)
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_tool_call
from langchain.messages import ToolMessage
@wrap_tool_call
def handle_tool_errors(request, handler):
"""Handle tool execution errors with custom messages."""
try:
return handler(request)
except Exception as e:
# Only handle errors that occur during tool execution due to invalid inputs
# that pass schema validation but fail at runtime (e.g., invalid SQL syntax).
# Do NOT handle:
# - Network failures (use tool retry middleware instead)
# - Incorrect tool implementation errors (should bubble up)
# - Schema mismatch errors (already auto-handled by the framework)
#
# Return a custom error message to the model
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="claude-sonnet-4-6",
tools=[check_weather, search_web],
middleware=[handle_tool_errors]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent, ToolNode
from langchain.messages import ToolMessage
def handle_tool_error(error: Exception) -> str:
"""Custom error handler function."""
return f"Tool error: Please check your input and try again. ({str(error)})"
agent = create_react_agent(
model="claude-sonnet-4-6",
tools=ToolNode(
[check_weather, search_web],
handle_tool_errors=handle_tool_error # [!code highlight]
)
)
구조화 출력 (Structured output)
노드 변경
구조화 출력은 이전에 메인 에이전트와 별도 노드에서 생성됐어요. 이제는 아닙니다. 구조화 출력을 메인 루프에서 생성해 비용과 지연시간을 줄여요.
툴·프로바이더 전략
v1에는 두 가지 새 구조화 출력 전략이 있어요.
ToolStrategy— 인공 툴 호출로 구조화 출력 생성ProviderStrategy— 프로바이더 네이티브 구조화 출력 생성
# v1 (new)
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="gpt-5.4-mini",
tools=tools,
# explicitly using tool strategy
response_format=ToolStrategy(OutputSchema) # [!code highlight]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent
from pydantic import BaseModel
class OutputSchema(BaseModel):
summary: str
sentiment: str
agent = create_react_agent(
model="gpt-5.4-mini",
tools=tools,
# using tool strategy by default with no option for provider strategy
response_format=OutputSchema # [!code highlight]
)
# OR
agent = create_react_agent(
model="gpt-5.4-mini",
tools=tools,
# using a custom prompt to instruct the model to generate the output schema
response_format=("please generate ...", OutputSchema) # [!code highlight]
)
프롬프트 기반 출력 제거
**프롬프트 기반 출력(Prompted output)**은 더 이상 response_format 인자를 통해 지원되지 않아요. 인공 툴 호출·프로바이더 네이티브 구조화 출력 같은 전략과 비교해, 프롬프트 기반 출력은 그다지 신뢰할 만하지 않다는 게 입증됐어요.
스트리밍 노드 이름 변경 (Streaming node name rename)
에이전트에서 이벤트를 스트리밍할 때 노드 이름이 node의 목적을 더 잘 반영하도록 "agent"에서 "model"로 바뀌었어요.
런타임 컨텍스트 (Runtime context)
에이전트를 호출할 때 두 종류의 데이터를 전달하고 싶은 경우가 많아요.
- 대화 중 변하는 동적 상태 (예: 메시지 히스토리)
- 대화 중 변하지 않는 정적 컨텍스트 (예: 사용자 메타데이터)
v1에서는 정적 컨텍스트를 invoke와 stream의 context 파라미터로 설정해 지원해요.
# v1 (new)
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=Context # [!code highlight]
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "Hello"}]},
context=Context(user_id="123", session_id="abc") # [!code highlight]
)
# v0 (old)
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(model, tools)
# Pass context via configurable
result = agent.invoke(
{"messages": [{"role": "user", "content": "Hello"}]},
config={ # [!code highlight]
"configurable": { # [!code highlight]
"user_id": "123", # [!code highlight]
"session_id": "abc" # [!code highlight]
} # [!code highlight]
} # [!code highlight]
)
예전
config["configurable"]패턴은 역호환을 위해 여전히 동작하지만, 새 애플리케이션이나 v1로 마이그레이션하는 애플리케이션에는 새context파라미터를 권장해요.
표준 콘텐츠 (Standard content)
v1에서 메시지는 프로바이더 무관 표준 콘텐츠 블록을 얻게 돼요. message.content_blocks로 접근해 프로바이더 전반에서 일관되고 타입이 지정된 뷰를 얻을 수 있어요. 기존 message.content 필드는 문자열이나 프로바이더 네이티브 구조에 그대로 유지돼요.
무엇이 바뀌었나
- 메시지에 새
content_blocks속성 추가 (정규화된 콘텐츠용) - Messages에 문서화된 표준화된 블록 형태
LC_OUTPUT_VERSION=v1또는output_version="v1"로 표준 블록을content로 선택적 직렬화
표준화된 콘텐츠 읽기
# v1 (new)
from langchain.chat_models import init_chat_model
model = init_chat_model("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"))
# v0 (old)
# Provider-native formats vary; you needed per-provider handling
response = model.invoke("Explain AI")
for item in response.content:
if item.get("type") == "reasoning":
... # OpenAI-style reasoning
elif item.get("type") == "thinking":
... # Anthropic-style thinking
elif item.get("type") == "text":
... # Text
멀티모달 메시지 만들기
# v1 (new)
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])
# v0 (old)
from langchain.messages import HumanMessage
message = HumanMessage(content=[
# Provider-native structure
{"type": "text", "text": "Describe this image."},
{"type": "image_url", "image_url": {"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 속성으로 직렬화되지 않아요. content 속성에서 표준 콘텐츠 블록에 접근해야 한다면(예: 메시지를 클라이언트에 보낼 때) content로 직렬화하도록 옵트인할 수 있어요.
export LC_OUTPUT_VERSION=v1
from langchain.chat_models import init_chat_model
model = init_chat_model(
"gpt-5-nano",
output_version="v1",
)
더 보기: Messages, Standard content blocks, Multimodal.
파괴적 변경 (Breaking changes)
Python 3.9 지원 중단
모든 LangChain 패키지는 이제 Python 3.10 이상이 필요해요. Python 3.9는 2025년 10월에 수명 종료됩니다.
chat 모델 반환 타입 업데이트
chat 모델 호출의 반환 타입 시그니처가 BaseMessage에서 AIMessage로 고쳐졌어요. bind_tools를 구현하는 커스텀 chat 모델은 반환 시그니처를 업데이트해야 해요.
# v1 (new)
def bind_tools(
...
) -> Runnable[LanguageModelInput, AIMessage]:
# v0 (old)
def bind_tools(
...
) -> Runnable[LanguageModelInput, BaseMessage]:
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-5.4-mini", output_version="v0")
langchain-anthropic의 기본 max_tokens
langchain-anthropic의 max_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())은 계속 동작하지만 경고를 내보내요. 메서드 형태는 v2에서 제거됩니다.
AIMessage에서 example 파라미터 제거
AIMessage 객체에서 example 파라미터가 제거됐어요. 필요한 경우 추가 메타데이터는 additional_kwargs로 전달하는 것을 권장해요.
사소한 변경 (Minor changes)
AIMessageChunk객체는 이제 스트림의 최종 청크를 나타내기 위해chunk_position속성('last'값)을 포함해요. 스트리밍 메시지 처리를 더 명확하게 해주죠. 청크가 최종이 아니면chunk_position은None이에요.LanguageModelOutputVar가BaseMessage대신AIMessage로 타입이 지정됐어요.- 메시지 청크 병합(
AIMessageChunk.add) 로직이 병합된 청크의 최종 id에 대한 더 정교한 선택 처리를 갖도록 업데이트됐어요. LangChain 생성 ID보다 프로바이더 지정 ID를 우선해요. - 이제 기본적으로
utf-8인코딩으로 파일을 열어요. - 표준 테스트는 이제 멀티모달 콘텐츠 블록을 사용해요.
보관된 문서 (Archived docs)
구식 문서는 참고용으로 보관돼 있어요.
더 알아보기 (Learn more)
- LangChain v1 릴리스 — v1 변경 사항 요약
- Agents —
create_agent사용법 - Messages — 표준 콘텐츠 블록과 멀티모달
- Middleware — 미들웨어 기반 확장