Agentic AI 구축/LangChain & LangGraph

[LangChain 함수 2] Agent의 Model과 Message 이해하기

gksyb4235 2026. 1. 10. 19:58

ReAct 구조에서 Model의 역할


 

ReAct(Reason + Act) 패턴에서 모델은 단순히 텍스트를 생성하는 역할을 넘어서,
추론(reasoning)행동(action, tool calling) 을 결정하는 핵심 요소다.

LangChain은 이러한 구조를 전제로, 다양한 Vendor와 Model을 동일한 Interface로 사용할 수 있도록 설계되었다.

 

 

현재 LangChain은 100개 이상의 모델 Vendor를 지원하며, OpenAI, Anthropic, Cohere, Azure 등 다양한 Chat Model을 동일한 방식으로 다룰 수 있다.

어떤 모델이 지원되는지는 LangChain의 공식 Docs에서 확인할 수 있다.

 

 

 

Message란 무엇인가?


 

 

Agent 시스템에서 Message는 모든 정보 교환의 기본 단위다.
LangChain에서 Message는 단순한 문자열이 아니라, 역할(role), 콘텐츠(content), 그리고 다양한 메타데이터를 포함하는 구조화된 객체다. Agent는 다음과 같은 Message 유형을 중심으로 동작한다.

  • SystemMessage : Agent의 기본 역할과 행동 원칙을 정의한다.
    예: “You are a helpful assistant”
  • HumanMessage : 사용자의 입력을 나타낸다.
    초기 요청이거나, 중간에 개입하는 피드백일 수 있다.
  • ToolMessage : Tool 실행 결과를 담는 메시지다.
    Tool 호출 이후 반드시 ToolMessage로 응답이 반환된다.
  • AIMessage : 모델이 생성한 모든 메시지를 의미한다.
    여기에는 reasoning 결과, tool 호출 요청, 최종 응답이 모두 포함된다.

Agent의 실행은 결국 이 Message들이 순서대로 누적되는 과정이라고 볼 수 있다.

 

 

Scratch_Pad의 의미


 

LangChain Agent에서는 Message가 노드 간에 전달되는 구조가 아니다.
대신, 모든 노드가 공유하는 지속적인 scratch pad(messages 리스트) 에 저장된다.

 

Agent가 실행될 때마다,

  1. 새로운 Message가 생성되고
  2. scratch pad에 추가되며
  3. 모델은 항상 지금까지의 전체 Message 히스토리를 참조한다

이 덕분에 모델은 다음 정보를 동시에 활용할 수 있다.

  • 원래의 사용자 질문
  • 이전 모델 응답
  • Tool 호출 및 Tool 결과
  • 중간 reasoning 흔적

최종 결과에는 마지막 AIMessage뿐만 아니라, Agent의 전체 활동 기록이 함께 포함된다.

 

 

 

System Prompt의 중요성


 

모든 Message 중에서 가장 중요한 것은 Agent의 System Prompt(SystemMessage) 다.
System Prompt는 Agent의 성격, 말투, 행동 범위를 결정한다.

Agent가 단순할수록 System Prompt는 짧아도 되지만,
Agent가 복잡해질수록 System Prompt는 커지고, 더 정교한 설계가 필요해진다.

실제 서비스 환경에서는 다음이 중요해진다.

  • Prompt 변경이 성능에 미치는 영향 평가
  • 시간에 따른 Prompt 품질 변화 추적
  • Monitoring과 Evaluation을 통한 관리

 

 

 

ToolMessage를 포함하는 Agent의 흐름


Agent가 Tool을 호출한는 구조를 살펴보자.

Agent는 haiku를 생성하는 역할을 하고, Tool은 AI가 생성한 haiku가 3줄이 맞는지를 확인하는 간단한 함수이다.

agent = create_agent(
    model="openai:gpt-5",
    tools=[check_haiku_lines],
    system_prompt="You are a sports poet who only writes Haiku. You always check your work."
)
from langchain_core.tools import tool

@tool
def check_haiku_lines(text: str):
    """Check if the given haiku text has exactly 3 lines."""
    lines = [line.strip() for line in text.strip().splitlines() if line.strip()]
    if len(lines) != 3:
        return f"Incorrect! This haiku has {len(lines)} lines."
    return "Correct, this haiku has 3 lines."

 

이제 Agent를 invoke하면 아래와 같다.

result = agent.invoke({"messages": "Please write me a poem"})

---

checking haiku, it has 3 lines:
 Whistle splits cool air
Stadium hearts drum in time
Footsteps chase the dawn

 

이제 최종 AIMessage가 출력되기까지의 생성된 모든 Messsage들의 과정을 살펴보자.

for i, msg in enumerate(result["messages"]):
    msg.pretty_print()
    
---

================================ Human Message =================================

Please write me a poem
================================== Ai Message ==================================
Tool Calls:
  check_haiku_lines (call_uOLf0ZxcBTNBT2a77IZJi1jO)
 Call ID: call_uOLf0ZxcBTNBT2a77IZJi1jO
  Args:
    text: Whistle splits cool air
Stadium hearts drum in time
Footsteps chase the dawn
================================= Tool Message =================================
Name: check_haiku_lines

Correct, this haiku has 3 lines.
================================== Ai Message ==================================

Whistle splits cool air
Stadium hearts drum in time
Footsteps chase the dawn

 

Agent 실행 시 흐름은 다음과 같다.

  1. HumanMessage 입력
  2. AIMessage에서 haiku 생성
  3. Tool 호출 요청
  4. ToolMessage로 결과 반환 (Correct)
  5. 최종 AIMessage 생성

이 모든 과정이 messages 리스트에 순차적으로 기록된다.

 

Message 객체에는 content 외에도 다양한 정보가 들어 있다.

result

---

{'messages': [HumanMessage(content='Please write me a poem', additional_kwargs={}, response_metadata={}, id='13b18ae4-f92e-4582-925a-39d7984806a8'),
  AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 555, 'prompt_tokens': 170, 'total_tokens': 725, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 512, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'gpt-5-2025-08-07', 'system_fingerprint': None, 'id': 'chatcmpl-CQbI0V3W0uPCDlcnD4GYTydYxCsAJ', 'service_tier': 'default', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--0055426a-ee06-4daa-a36c-4074fa9c1ceb-0', tool_calls=[{'name': 'check_haiku_lines', 'args': {'text': 'Whistle splits cool air\nStadium hearts drum in time\nFootsteps chase the dawn'}, 'id': 'call_uOLf0ZxcBTNBT2a77IZJi1jO', 'type': 'tool_call'}], usage_metadata={'input_tokens': 170, 'output_tokens': 555, 'total_tokens': 725, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 512}}),
  ToolMessage(content='Correct, this haiku has 3 lines.', name='check_haiku_lines', id='5aff8da9-c8c0-4bed-b8d4-7bf884a8c097', tool_call_id='call_uOLf0ZxcBTNBT2a77IZJi1jO'),
  AIMessage(content='Whistle splits cool air\nStadium hearts drum in time\nFootsteps chase the dawn', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 231, 'total_tokens': 252, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_provider': 'openai', 'model_name': 'gpt-5-2025-08-07', 'system_fingerprint': None, 'id': 'chatcmpl-CQbIATueaDYKiqYDNX5xKHjKGWCr5', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--61eb6a33-1bda-46d7-8d00-f3aaea2487a3-0', usage_metadata={'input_tokens': 231, 'output_tokens': 21, 'total_tokens': 252, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}

 

여기에는 다음 정보가 포함될 수 있다.

  • 입력 / 출력 토큰 수
  • 캐시 사용 여부
  • 모델 응답 관련 세부 메타데이터

이 정보는 비용 분석, 성능 최적화, 디버깅에 매우 유용하다.