
이번 포스팅에서는 LangChain Agent의 '기본적인 템플릿과 모듈의 구체적인 사용 방법'에 대해서 소개합니다.
특히, 모델, 시스템 프롬프트, 출력 format, 메세지 타입, 스트리밍 총 5가지에 대해서,
LangChain Academy 강의에서 다루지 않은 옵션 종류와 설정 방법을 위주로 소개합니다.
LangChain Agent는 상황에 따라 모델, 프롬프트 등을 Dynamic하게 교체해 사용할 수 있는데,
이러한 내용은 이후 포스팅(4. Dynamic Agent편)에서 정리하도록 하겠습니다.
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.tools import tool
from langchain.chat_models import init_chat_model
from langchain.messages import SystemMessage, HumanMessage
from pydantic import BaseModel
load_dotenv()
# 1) 모델 설정 (chat 모델)
model_id = "openai:gpt-4.1" # provider:model 형식으로 지정
chat_model = init_chat_model(model_id, temperature=0)
# 2) system prompt
system_prompt = "You are a helpful assistant. Answer precisely."
# 3) structured output schema (optional)
class AnswerOutput(BaseModel):
place: str
reason: str
# 4) 에이전트 생성
agent = create_agent(
model=chat_model,
system_prompt=system_prompt,
response_format=AnswerOutput
)
# --- 5.1) 비-streaming 버전 실행 ---
result = agent.invoke(
{"messages": [
HumanMessage(content="What is the most beautiful place in South Korea?")
]}
)
print("Final Response:", result)
# --- 5.2) Streaming version 실행 ---
# streaming_mode: "messages" (토큰 단위), "updates" (agent progress)
for token, metadata in agent.stream(
{"messages": [
HumanMessage(content="What is the most beautiful place in South Korea?")
]},
stream_mode="messages"
):
if token.content: # Check if there's actual content
print(token.content, end="", flush=True) # Print token
LangChain Agent는 OpenAI, Anthropic, Grok 등 다양한 provider와 모델을 선택할 수 있습니다.
호환되는 모델을 model_id에 "provider:model" 형식으로 입력하면 됩니다.
호환되는 모델 종류는 Chat Models 에서 확인할 수 있습니다.
System prompt는 “모델이 어떤 역할과 규칙으로 행동해야 하는지”를 정의하는 최상위 지시문입니다.
LangChain Agent에서 system prompt는:
하는 역할을 합니다.
Structured output은 LLM의 출력을 자연어 문자열이 아니라, 명확한 스키마(JSON / Pydantic 등) 로 강제하는 기능입니다.
사실, 출력 형식은 system prompt에
"반드시 json 형식으로 출력하고, 절대 다른 부연설명을 하지 마세요.\n{...}"
등의 내용을 넣는 방식으로도 제어할 수 있습니다.
하지만, 코드 수정과 리뷰가 훨씬 편리하기 때문에, 예시처럼 Class로 관리하는 방식을 권장합니다.
# response_format을 설정했을 때 모델 output
# print(response["messages"][1]["content"]
{
"place": "Jeju Island",
"reason": "Jeju Island is often considered the most beautiful place in South Korea due to its stunning natural landscapes, including volcanic craters, waterfalls, lush forests, and picturesque beaches. Its unique scenery and mild climate make it a popular destination for both locals and tourists seeking natural beauty."
}
# response_format이 없을 때 모델 output
# print(response["messages"][1]["content"]
The "most beautiful" place in South Korea is subjective and depends on personal preferences, but **Jeju Island** is often considered the most beautiful destination in the country. Known for its stunning volcanic landscapes, lush forests, waterfalls, pristine beaches, and unique culture, Jeju is a UNESCO World Heritage Site and a favorite among both locals and international travelers. Other contenders for beauty include the cherry blossom-lined streets of **Gyeongju**, the dramatic mountains of **Seoraksan National Park**, and the tranquil palaces and gardens of **Seoul**. However, Jeju Island is most frequently cited as the crown jewel of South Korea’s natural beauty.
LangChain Messages는 모델과 소통하는 기본 단위입니다. LLM API(OpenAI, Anthropic 등)마다 메시지 포맷이 조금씩 다른데, LangChain은 이를 표준화된 클래스로 추상화하여 제공합니다.
SystemMessage: 대화의 맥락, 설정, 페르소나, 지시사항 등을 정의HumanMessage: 사용자가 입력하는 질의AIMessage: AI 모델의 답변role이 각각 system, user, assistant로 설정되어 전달되기 때문에, content(message 내용)만 입력하여 사용합니다.
messages = [
SystemMessage(content="You are a math tutor."),
HumanMessage(content="What is 1+1?"),
AIMessage(content="It is 2.")
]
ToolMessage: Tool 실행 결과반드시 Tool call을 요청하는 AIMessage 이후에 사용되어야 하며, role이 각각 tool로 설정됩니다.
content 이외에도 어떤 요청에 대한 결과인지 식별하기 위한 tool_call_id가 필수입니다.
messages = [
# ... (이전 대화 생략) ...
# 1. 모델이 도구 사용을 요청했던 상황 (AIMessage에 tool_calls가 포함됨)
# AIMessage(content="", tool_calls=[{'name': 'get_weather', 'args': {'city': 'Seoul'}, 'id': 'call_12345'}]),
# 2. 실제 함수 실행 후, 결과를 모델에게 돌려주는 ToolMessage
ToolMessage(
content="Current weather in Seoul is Sunny, 25°C.", # 도구 실행 결과
tool_call_id="call_12345" # 위 AIMessage의 요청 ID와 일치해야 함
)
]
ChatMessage: role을 직접 설정할 수 있는 커스텀 메세지role이 미리 정해지지 않은 가장 기본적인 메세지 형태입니다. role, content를 모두 입력해서 사용해야 합니다.
messages = [
# 표준 역할을 수동으로 지정할 수도 있음 (HumanMessage와 동일 효과)
ChatMessage(role="user", content="Hello, who are you?"),
# 모델이 지원하는 경우, 임의의 커스텀 역할을 부여할 때 사용
ChatMessage(role="reviewer", content="The code looks good, but needs optimization.")
]
Q.
role은 왜 설정해주는거에요?A: LangChain Messages의 작동 원리 포스팅 참고
현재 stream_mode는 "messages", "updates" 중 하나를 선택할 수 있습니다.
messages: LLM이 생성하는 메세지 단위를 실시간으로 스트리밍하는 기능. ChatGPT처럼 토큰 단위로 타이핑되는 느낌updates: Agent의 내부 상태 변화를 스트리밍하는 기능. 주로 디버깅, 시스템 로그 등 내부 플로우에 대해 파악하는 용도LangChain Academy 강의에서는 MCP Tool을 Agent 코드 내부에 정의하여 함수로 사용했습니다.
하지만, 실제 프로덕션 레벨에서는 내외부 MCP 서버를 유동적으로 연결하여 사용할 수 있어야 합니다.
따라서 다음 포스팅(2. MCP & Sub-Agent편)에서는 MCP 서버를 stdio 혹은 sse 방식으로 띄워두고 우리의 LangChain Agent에 연결하는 방법 에 대해서 자세히 다뤄보도록 하겠습니다.
추가로, LangChain Agent는 Sub Agent도 MCP Tools와 동일한 방식으로 연결하기 때문에, Sub Agent까지 묶어서 다뤄보도록 하겠습니다.