KSCOLD LogoKSCOLD
Blog
Feed
Product
Admin Night
Vault
Guestbook
Info

Vault 목록

LLM Tool Selection

연결된 노트와 함께 읽기

LLM Tool Selection

2026년 7월 16일

LLM Tool Selection

정의

LLM Tool Selection은 LLM이 사용자 메시지와 도구 스키마를 보고 어떤 도구를 호출할지, 또는 도구 없이 바로 답할지 판단하는 단계이다.

도구를 코드에서 정의했다고 해서 자동으로 실행되는 것은 아니다. 도구를 LLM에게 알려준 뒤, 반드시 LLM 호출을 한 번 거쳐야 한다.

Mermaid스크롤로 확대 · 드래그로 이동

핵심 원칙

도구 선택은 Python 코드가 먼저 하는 것이 아니라, 도구를 쥔 LLM에게 질문을 넣었을 때 LLM이 결정한다.

즉 다음 코드만으로는 도구가 실행되지 않는다.

Python

이 코드는 LLM에게 "이런 도구들이 있다"고 알려주는 단계일 뿐이다.

실제 도구 선택은 아래 호출에서 일어난다.

Python

예시 코드

Python

이 함수는 도구로 등록될 수 있는 함수이다.

Python

이 단계에서는 도구가 실행되지 않는다. LLM 객체가 도구 스키마를 알고 있는 상태가 된다.

Python

여기서 비로소 LLM에게 현재 메시지가 전달된다.

LLM은 다음 정보를 함께 본다.

  • 사용자 질문
  • 이전 대화 메시지
  • food_tool의 이름, 인자, docstring
  • care_tool의 이름, 인자, docstring

여기서 중요한 점은 # 일반 주석이 아니라 docstring을 본다는 것이다.

Python

위 docstring은 LLM의 도구 선택 판단에 들어간다.

하지만 아래 같은 일반 주석은 보통 도구 스키마에 포함되지 않는다.

Python

따라서 도구의 목적은 반드시 docstring에 적는 것이 좋다.

그다음 다음 중 하나를 선택한다.

TEXT

LLM 호출 결과

llm_with_tools.invoke(...)의 결과는 크게 두 종류가 될 수 있다.

1. 도구 호출이 없는 응답

LLM이 도구가 필요 없다고 판단하면 일반 텍스트 응답을 만든다.

TEXT

이 경우 ToolNode로 갈 필요 없이 종료할 수 있다.

2. 도구 호출이 있는 응답

LLM이 도구가 필요하다고 판단하면 tool_calls가 포함된 응답을 만든다.

TEXT

이 응답은 "내가 care_tool을 직접 실행했다"는 뜻이 아니다.

뜻은 다음에 가깝다.

TEXT

이후 LangGraph ToolNode가 실제 Python 함수를 실행한다.

LangGraph에서의 흐름

Mermaid스크롤로 확대 · 드래그로 이동

chatbot 노드는 도구를 실행하는 노드가 아니다.

chatbot 노드는 LLM에게 현재 메시지를 넣고, LLM이 다음 행동을 결정하게 만드는 노드이다.

실제 도구 실행은 ToolNode가 담당한다.

왜 LLM에게 먼저 물어봐야 하는가

도구 선택은 자연어 의미 판단이 필요하기 때문이다.

예를 들어 두 도구가 있다고 하자.

Python

사용자 질문:

TEXT

이 질문은 food_tool에 가깝다.

사용자 질문:

TEXT

이 질문은 care_tool에 가깝다.

이런 의미 판단은 단순 if문으로도 만들 수 있지만, 다양한 자연어 표현을 다루려면 LLM이 도구 설명을 보고 판단하게 하는 것이 유연하다.

bind_tools와 invoke의 차이

코드역할도구 실행 여부
llm.bind_tools(mytools)LLM에게 도구 목록을 알려줌실행 안 됨
llm_with_tools.invoke(messages)LLM에게 메시지를 넣어 도구 호출 여부를 판단시킴아직 실행 안 됨
ToolNode(mytools)LLM이 요청한 tool call을 실제 함수 실행으로 바꿈실행됨

주의할 점

도구를 바인딩했다고 해서 LLM이 반드시 도구를 쓰는 것은 아니다.

도구 사용을 강제하지 않는 한, LLM은 다음 중 하나를 선택할 수 있다.

  • 도구 호출
  • 일반 답변
  • 잘못된 도구 선택
  • 필요한 도구를 호출하지 않음

따라서 도구 설명, 시스템 프롬프트, 조건부 라우팅을 명확히 설계해야 한다.

create_react_agent에서의 도구 선택

create_react_agent(llm, mytools)를 쓰면 직접 bind_tools, ToolNode, tools_condition을 조립하지 않아도 기본 도구 호출 루프가 만들어진다.

Python

이 경우에도 핵심은 같다.

TEXT

예를 들어 다음 도구들이 있다면:

Python

사용자 질문이 다음과 같을 때:

TEXT

상위 agent는 chinese_meal_expert의 이름과 docstring을 보고 이 도구가 적절하다고 판단할 수 있다.

이때 별도의 prompt를 넣지 않아도 동작할 수 있지만, 신뢰도는 도구 이름과 docstring 품질에 크게 의존한다.

관련: LangGraph create_react_agent

한 줄 정리

도구를 LLM에게 쥐어준 뒤 llm_with_tools.invoke()를 호출해야 LLM이 어떤 도구를 쓸지 판단하고, 그 다음 ToolNode가 실제 도구를 실행한다.

관련:

  • LangChain @tool
  • LangGraph ToolNode
  • Tool Calling
  • Workflow Node vs Tool

동적 도구 노출

도구 선택 정확도는 단지 description 품질만의 문제가 아니다. 모델은 이번 호출에 실제로 노출된 도구 집합 안에서만 선택할 수 있다. 사용자 권한, 현재 workflow 단계, feature flag, 비용 예산, 데이터 범위에 따라 도구 후보를 먼저 줄이는 동적 노출 정책이 필요하다.

  1. Capability Catalog에서 현재 요청에 가능한 도구 후보를 찾는다.
  2. 권한·위험도·테넌트 범위를 코드 정책으로 걸러 낸다.
  3. 남은 작은 도구 집합만 모델에 바인딩한다.
  4. ToolNode 또는 wrapper가 실행 전 인자와 권한을 다시 검증한다.

이 순서는 모델에게 더 많은 도구를 보여 주는 것보다 선택 오류와 토큰 사용을 줄인다. 단, 도구를 숨기는 정책도 감사 가능해야 하며, 모델이 보지 못한 도구를 호출할 수 없다는 사실을 UI와 fallback 정책에 반영한다.

관련: Capability Catalog, Tool Execution Policy, Agent Middleware

Synapse Map Insight

mytools = [food_tool, care_tool] llm_with_tools = llm.bind_tools(mytools)
response = llm_with_tools.invoke(current_messages)
@tool def care_tool(care: str): """감기에 걸렸을 때 해야 할 조치를 알려줄 때 사용한다.""" print("care_tool 노드") return "충분히 쉬고, 침대에 누워 전기 장판으로 땀을 흘려야합니다."
mytools = [food_tool, care_tool] llm_with_tools = llm.bind_tools(mytools)
def chatbot(state: State): current_messages = state["messages"] response = llm_with_tools.invoke(current_messages) return {"messages": [response]}
@tool def care_tool(care: str): """감기에 걸렸을 때 해야 할 조치를 알려줄 때 사용한다."""
# 감기에 걸렸을 때 해야 할 조치를 알려주는 함수 @tool def care_tool(care: str): ...
1. 도구 없이 바로 답변한다. 2. food_tool 호출을 요청한다. 3. care_tool 호출을 요청한다. 4. 여러 도구 호출을 요청한다.
AIMessage(content="감기에는 충분한 휴식이 중요합니다.")
AIMessage( content="", tool_calls=[ { "name": "care_tool", "args": {"care": "감기 조치"}, "id": "..." } ] )
LLM: care_tool을 이 인자로 호출해줘.
@tool def food_tool(food: str): """감기에 좋은 음식을 알려줄 때 사용한다.""" @tool def care_tool(care: str): """감기에 걸렸을 때 해야 할 조치를 알려줄 때 사용한다."""
감기에 걸렸는데 뭘 먹으면 좋아?
감기에 걸렸는데 어떻게 해야 해?
agent = create_react_agent(llm, mytools) result = agent.invoke({"messages": "나는 고혈압 환자인데 중식이 먹고싶어"})
상위 agent LLM이 사용자 질문과 도구 설명을 보고 어떤 도구를 호출할지 판단한다.
mytools = [chinese_meal_expert, japanese_meal_expert, western_meal_expert]
나는 고혈압 환자인데 중식이 먹고싶어