Tool Call
Tool Call 방식은 Agent가 유기적으로 상황에 필요한 Tool을 호출하고 그거에 대한 답변을 반환하는 방식이다
그렇기 때문에 당연히 LLM을 로드하는 것부터가 시작이다
class My_Agent:
def __init__(self):
self.name = 'My_Agent'
self.my_llm = ChatOpenAI(
openai_api_base=base_url,
openai_api_key=api_key,
model="gpt-5.2",
temperature=0
)
대부분 Tool을 사용한다는 것은 일정한 대답을 원하는 경우가 많기 때문에
LLM의 temperature는 0으로 설정하였다
Tool 정의하기
그러면 이제 Tool을 정의해줄 차례인데
Tool은 Class 밖에 먼저 선언되어야 한다
@Tool 데코레이터를 사용하면 되는데 자주쓰는 양식은 다음과 같다
# Type 1
@tool("First_tool", return_direct=True, description="이것은 나의 첫번째 tool 입니다")
def First_tool(param1: str, param2: int) -> str:
logger.info(f"MY First Tool")
# Type 2
@tool("Second_tool", return_direct=False)
def Second_tool(param1: str, param2: int) -> str:
'''
이것은 나의 두번째 tool 입니다
'''
logger.info(f"MY First Tool")
지금은 별 기능이 없기 때문에 첫번째, 두번째 tool 입니다로 description과 doc-string 을 간단히 적었는데
여기에 tool에 대한 자세한 설명을 정의하면 좋다
추가적은 return_direct란 결과를 AI가 한번 더 가공할 것인지 아니면 그대로 뱉어낼 것인지를 결정하는 것이다
> return_direct
return_direct=False이면 도구의 결과가 모델 내부로 다시 들어가서 후처리나 추가 설명을 거친 뒤 사용자에게 전달.
return_direct=True이면 모델이 그 결과를 가공하지 않고 도구의 반환값을 그대로 사용자에게 보여줌
Tool 연결하기
이렇게 LLM과 Tool을 만들었으면 이 둘을 Bind (연결)시켜주면 된다
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage, ToolMessage
# tool은 class 밖에 있어야 한다
@tool("First_tool", return_direct=True, description=prompts["My_Agent"]["First_tool"])
def First_tool(param1: str, param2: int) -> str:
logger.info(f"MY First Tool")
@tool("Second_tool", return_direct=False)
def Second_tool(param1: str, param2: int) -> str:
'''
이것은 나의 두번째 tool 입니다
'''
logger.info(f"MY First Tool")
class My_Agent:
def __init__(self):
self.name = 'My_Agent'
self.my_llm = ChatOpenAI(
openai_api_base=base_url,
openai_api_key=api_key,
model="gpt-5.2",
temperature=0
)
# run 메서드의 docstring을 동적으로 주입
# ✅ 클래스 함수 객체의 docstring 수정
My_Agent.run.__doc__ = self.description
#self.run.__doc__ = self.description
def __str__(self):
return f"[{self.name}] {self.description}"
def run(self,state: State):
"""tool을 사용하는 Agent 입니다"""
logger.info(f"[{self.name}]가 실행됩니다")
messages = HumanMessage(content=state["user_prompt"]),
# 도구를 tools 리스트에 추가
self.tools = [First_tool,Second_tool]
self.my_agent = self.my_llm.bind_tools(self.tools)
# 도구를 모델에 바인딩: 모델에 도구를 바인딩하면, 도구를 사용하여 llm 답변을 생성할 수 있음
response = self.my_agent.invoke(messages)
이렇게 넣어서 답변을 생성해보면
response 객체에 tool_calls 속성이 있게 된다
Tool Call 에 따른 Control 해보기
이를 이용해서 조건문을 만들어보면
if isinstance(response, AIMessage):
tool_calls = getattr(response, "tool_calls", None) or response.additional_kwargs.get("tool_calls")
이렇게 만들 수 있다
isinstance(response, AIMessage)
→ response가 AI 모델의 메시지 객체인지 확인. LangChain이나 LangGraph에서는 모델의 출력이 AIMessage 형태로 반환
getattr(response, "tool_calls", None)
→ response 객체에 tool_calls 속성이 있으면 그 값을 가져오고, 없으면 None을 반환.
response.additional_kwargs.get("tool_calls")
→ 일부 모델 응답은 tool_calls가 additional_kwargs 딕셔너리 안에 들어 있을 수 있기 때문에 첫 번째 방법으로 못 찾았을 때, 이 경로로 한 번 더 확인.
이제 이걸 연결하여서 조건을 만들어 본다면
def Tool_Control(self,response):
tool_call_names = []
# 5) tool_calls가 있으면 실제 실행하고 ToolMessage로 결과를 이어붙임
if isinstance(response, AIMessage):
tool_calls = getattr(response, "tool_calls", None) or response.additional_kwargs.get("tool_calls")
#if isinstance(response, AIMessage) and response.tool_calls:
tool_msgs = []
for call in response.tool_calls:
name = call["name"] # "First_Tool"
args = call["args"] # {"param1": "test", "param2": 3} 등
tool_call_names.append(name)
return tool_call_names
이렇게 쪼개서 각각 Tool에 대한 시나리오를 설정할 수 있다
이제 이거를 run 함수에 연결해서 Agent가 자연스럽게 Tool_Control까지 할 수 있게 하면 끝
(Tool Control은 필요시에만 사용한다)
def Tool_Control(self,response):
tool_call_names = []
# 5) tool_calls가 있으면 실제 실행하고 ToolMessage로 결과를 이어붙임
if isinstance(response, AIMessage):
tool_calls = getattr(response, "tool_calls", None) or response.additional_kwargs.get("tool_calls")
#if isinstance(response, AIMessage) and response.tool_calls:
tool_msgs = []
for call in response.tool_calls:
name = call["name"] # "First_Tool"
args = call["args"] # {"param1": "test", "param2": 3} 등
tool_call_names.append(name)
return tool_call_names
def run(self,state: State):
"""tool을 사용하는 Agent 입니다"""
logger.info(f"[{self.name}]가 실행됩니다")
messages = HumanMessage(content=state["user_prompt"]),
# 도구를 tools 리스트에 추가
self.tools = [First_tool,Second_tool]
self.my_agent = self.my_llm.bind_tools(self.tools)
# 도구를 모델에 바인딩: 모델에 도구를 바인딩하면, 도구를 사용하여 llm 답변을 생성할 수 있음
response = self.my_agent.invoke(messages)
tool_control_result ,tool_call_names =self.Tool_Control(response)'AI Study > AI Agent' 카테고리의 다른 글
| LangGraph, Agent의 Description, Doc-string Yaml로 관리법 (0) | 2026.02.03 |
|---|---|
| [AI Agent] ollama 외부 연결 Setting(Container + local) (0) | 2025.10.30 |
| [AI Agent] ollama 모델 Open Web ui 연동(Docker) (0) | 2025.10.29 |
| Ollama를 이용한 환경 세팅 (0) | 2025.10.27 |
| [AI Agent] Langchain의 기초 (0) | 2025.10.23 |