도구 (Tools) 심화
도구 (Tools) 심화
여기서는 도구의 고급 사용법을 살펴볼게요.
[!TIP] 에이전트 만들기가 처음이라면 에이전트 소개와 smolagents 가이드 투어를 먼저 읽어보세요.
도구란 무엇이고, 어떻게 만들까
도구는 대체로 에이전트 시스템에서 LLM이 사용할 수 있는 함수예요. 하지만 LLM이 쓰려면 API가 필요해요. 이름, 도구 설명, 입력 타입·설명, 출력 타입 말이죠. 그래서 도구는 그냥 함수일 수 없고 클래스여야 해요.
핵심적으로 도구는 LLM이 어떻게 써야 할지 이해하도록 돕는 메타데이터로 함수를 감싼 클래스예요. 이렇게 생겼어요.
from smolagents import Tool
class HFModelDownloadsTool(Tool):
name = "model_download_counter"
description = """
This is a tool that returns the most downloaded model of a given task on the Hugging Face Hub.
It returns the name of the checkpoint."""
inputs = {
"task": {
"type": "string",
"description": "the task category (such as text-classification, depth-estimation, etc)",
}
}
output_type = "string"
def forward(self, task: str):
from huggingface_hub import list_models
model = next(iter(list_models(filter=task, sort="downloads", direction=-1)))
return model.id
model_downloads_tool = HFModelDownloadsTool()
커스텀 도구는 Tool을 서브클래스로 만들어 유용한 메서드를 상속받아요. 자식 클래스는 아래 속성들을 정의해요.
name— 도구 자체의 이름에 해당해요. 보통 도구가 무엇을 하는지 설명해요. 코드가 특정 작업에서 가장 많이 다운로드된 모델을 반환하니model_download_counter라고 이름 붙여볼게요.description— 에이전트의 시스템 프롬프트를 채우는 데 쓰여요.inputs—"type"과"description"키를 가진 딕셔너리예요. 파이썬 인터프리터가 입력에 대해 현명한 결정을 내리도록 돕는 정보를 담아요.output_type— 출력 타입을 지정해요.inputs와output_type의 타입은 Pydantic 형식이어야 해요.["string", "boolean","integer", "number", "image", "audio", "array", "object", "any", "null"]중 하나예요.forward— 실행될 추론 코드를 담는 메서드.
이것만 있으면 에이전트에서 쓸 수 있어요! 도구를 만드는 또 다른 방법도 있어요. 가이드 투어에서 @tool 데코레이터로 도구를 구현했는데, tool 데코레이터는 단순한 도구를 정의하는 권장 방법이에요. 하지만 더 필요한 때가 있어요. 명확성을 위해 클래스에 여러 메서드를 쓰거나, 추가 클래스 속성을 쓸 때요. 그럴 때는 위에서 설명한 대로 Tool을 서브클래스로 해서 도구를 만들면 돼요.
도구를 허브에 공유하기
커스텀 도구는 도구의 ~Tool.push_to_hub를 호출해 허브에 Space 레포지토리로 공유할 수 있어요. 허브에 레포지토리를 만들었고 읽기 접근 권한이 있는 토큰을 쓰고 있는지 확인하세요.
model_downloads_tool.push_to_hub("{your_username}/hf-model-downloads", token="<YOUR_HUGGINGFACEHUB_API_TOKEN>")
허브로 푸시가 동작하려면 도구가 몇 가지 규칙을 지켜야 해요.
- 모든 메서드는 자족적(self-contained)이어야 해요. 즉 인자에서 오는 변수만 써야 해요.
- 위 사항에 따라 모든 import는 도구 함수 안에 직접 정의되어야 해요. 그렇지 않으면 커스텀 도구로
~Tool.save나~Tool.push_to_hub를 호출할 때 오류가 나요. __init__메서드를 서브클래스로 만들면self외에 다른 인자를 줄 수 없어요. 특정 도구 인스턴스 초기화 중 설정된 인자는 추적하기 어려워서 허브에 제대로 공유하지 못하기 때문이에요. 그리고 어차피 특정 클래스를 만드는 이유는 하드코딩할 것이 있으면class YourTool(Tool):줄 바로 아래에your_variable=(...)로 클래스 속성을 설정할 수 있기 때문이에요. 물론 코드 어디에서든self.your_variable에 할당해 클래스 속성을 만들 수도 있어요.
도구가 허브에 푸시되면 시각화할 수 있어요. 여기가 제가 푸시한 model_downloads_tool인데, 멋진 gradio 인터페이스를 가져요. 도구 파일을 들여다보면 모든 도구 로직이 tool.py 아래에 있는 걸 발견할 수 있어요. 다른 사람이 공유한 도구를 검사할 수 있는 곳이죠.
그다음 load_tool로 도구를 불러오거나 ~Tool.from_hub로 만들고 에이전트의 tools 파라미터에 넘기면 돼요. 도구를 실행하는 건 커스텀 코드를 실행하는 것이므로, 레포지토리를 신뢰하는지 확인해야 해요. 그래서 허브에서 도구를 불러올 때 trust_remote_code=True를 넘겨야 해요.
from smolagents import load_tool, CodeAgent
model_download_tool = load_tool(
"{your_username}/hf-model-downloads",
trust_remote_code=True
)
MCP 서버에서 도구 사용하기
MCPClient를 쓰면 MCP 서버에서 도구를 불러오고, 연결과 도구 관리에 대한 완전한 제어권을 얻을 수 있어요.
stdio 기반 MCP 서버의 경우:
from smolagents import MCPClient, CodeAgent
from mcp import StdioServerParameters
import os
server_parameters = StdioServerParameters(
command="uvx", # uvx를 쓰면 의존성 확보 가능
args=["--quiet", "[email protected]"],
env={"UV_PYTHON": "3.12", **os.environ},
)
with MCPClient(server_parameters) as tools:
agent = CodeAgent(tools=tools, model=model, add_base_tools=True)
agent.run("Please find the latest research on COVID-19 treatment.")
Streamable HTTP 기반 MCP 서버의 경우:
from smolagents import MCPClient, CodeAgent
with MCPClient({"url": "http://127.0.0.1:8000/mcp", "transport": "streamable-http"}) as tools:
agent = CodeAgent(tools=tools, model=model, add_base_tools=True)
agent.run("Please find a remedy for hangover.")
연결 수명주기를 try...finally 패턴으로 직접 관리할 수도 있어요.
from smolagents import MCPClient, CodeAgent
from mcp import StdioServerParameters
import os
# 서버 파라미터 초기화
server_parameters = StdioServerParameters(
command="uvx",
args=["--quiet", "[email protected]"],
env={"UV_PYTHON": "3.12", **os.environ},
)
# 연결 수동 관리
try:
mcp_client = MCPClient(server_parameters)
tools = mcp_client.get_tools()
# 에이전트와 함께 도구 사용
agent = CodeAgent(tools=tools, model=model, add_base_tools=True)
result = agent.run("What are the recent therapeutic approaches for Alzheimer's disease?")
# 필요에 따라 결과 처리
print(f"Agent response: {result}")
finally:
# 연결이 항상 올바르게 닫히도록 보장
mcp_client.disconnect()
여러 MCP 서버에 한 번에 연결하려면 서버 파라미터 리스트를 넘기면 돼요.
from smolagents import MCPClient, CodeAgent
from mcp import StdioServerParameters
import os
server_params1 = StdioServerParameters(
command="uvx",
args=["--quiet", "[email protected]"],
env={"UV_PYTHON": "3.12", **os.environ},
)
server_params2 = {"url": "http://127.0.0.1:8000/sse"}
with MCPClient([server_params1, server_params2]) as tools:
agent = CodeAgent(tools=tools, model=model, add_base_tools=True)
agent.run("Please analyze the latest research and suggest remedies for headaches.")
[!WARNING] 보안 경고: 특히 프로덕션 환경에서는 어떤 MCP 서버에 연결하기 전에 항상 소스와 무결성을 검증하세요. MCP 서버 사용에는 보안 위험이 따릅니다.
- 신뢰가 필수: 신뢰할 수 있는 소스의 MCP 서버만 사용하세요. 악성 서버가 내 머신에서 해로운 코드를 실행할 수 있어요.
- stdio 기반 MCP 서버는 항상 내 머신에서 코드를 실행해요(그게 의도된 기능이에요).
- Streamable HTTP 기반 MCP 서버: 원격 MCP 서버는 내 머신에서 코드를 실행하지 않지만, 그래도 주의를 기울이세요.
구조화된 출력과 출력 스키마 지원
최신 MCP 사양(2025-06-18+)은 outputSchema를 지원해, 도구가 정의된 스키마를 가진 구조화된 데이터를 반환할 수 있게 해요. smolagents는 이 구조화된 출력 기능을 활용해서, 에이전트가 복잡한 데이터 구조, JSON 객체, 기타 구조화된 형식을 반환하는 도구와 작업할 수 있게 해줘요. 이 기능이 있으면 에이전트의 LLM이 도구를 호출하기 전에 도구 출력의 구조를 "볼" 수 있어 더 지능적이고 맥락을 아는 상호작용이 가능해져요.
구조화된 출력 지원을 활성화하려면 MCPClient 초기화 시 structured_output=True를 넘기세요.
from smolagents import MCPClient, CodeAgent
# 구조화된 출력 지원 활성화
with MCPClient(server_parameters, structured_output=True) as tools:
agent = CodeAgent(tools=tools, model=model, add_base_tools=True)
agent.run("Get weather information for Paris")
structured_output=True면 다음 기능이 활성화돼요.
- 출력 스키마 지원 — 도구가 출력에 대한 JSON 스키마를 정의할 수 있음.
- 구조화된 콘텐츠 처리 — MCP 응답의
structuredContent지원. - JSON 파싱 — 도구 응답에서 구조화된 데이터를 자동 파싱.
구조화된 출력을 쓰는 날씨 MCP 서버 예시예요.
# demo/weather.py - 구조화된 출력을 쓰는 MCP 서버 예시
from pydantic import BaseModel, Field
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Weather Service")
class WeatherInfo(BaseModel):
location: str = Field(description="The location name")
temperature: float = Field(description="Temperature in Celsius")
conditions: str = Field(description="Weather conditions")
humidity: int = Field(description="Humidity percentage", ge=0, le=100)
@mcp.tool(
name="get_weather_info",
description="Get weather information for a location as structured data.",
# structured_output=True is enabled by default in FastMCP
)
def get_weather_info(city: str) -> WeatherInfo:
"""Get weather information for a city."""
return WeatherInfo(
location=city,
temperature=22.5,
conditions="partly cloudy",
humidity=65
)
출력 스키마와 구조화된 출력을 쓰는 에이전트:
from smolagents import MCPClient, CodeAgent
# 구조화된 출력으로 날씨 서버 사용
from mcp import StdioServerParameters
server_parameters = StdioServerParameters(
command="python",
args=["demo/weather.py"]
)
with MCPClient(server_parameters, structured_output=True) as tools:
agent = CodeAgent(tools=tools, model=model)
result = agent.run("What is the temperature in Tokyo in Fahrenheit?")
print(result)
구조화된 출력이 활성화되면 CodeAgent 시스템 프롬프트에 도구의 JSON 스키마 정보가 추가돼, 에이전트가 도구 출력의 예상 구조를 이해하고 데이터를 적절히 접근하는 데 도움을 줘요.
하위 호환성: structured_output 파라미터는 하위 호환성을 유지하기 위해 현재 기본값이 False예요. 기존 코드는 변경 없이 계속 동작하고, 이전처럼 단순 텍스트 출력을 받아요.
향후 변경: 향후 릴리스에서 structured_output의 기본값은 False에서 True로 바뀔 거예요. 향상된 기능(더 나은 도구 출력 처리와 개선된 에이전트 성능)을 선택하려면 structured_output=True를 명시적으로 설정하는 걸 권장해요. 현재 텍스트 전용 동작을 유지해야 하는 특별한 경우에만 structured_output=False를 쓰세요.
Space를 도구로 가져오기
Tool.from_space 메서드로 허브의 Gradio Space를 바로 도구로 가져올 수 있어요! 허브의 Space id, 이름, 그리고 에이전트가 도구가 무엇을 하는지 이해하도록 돕는 설명만 제공하면 돼요. 내부적으로는 gradio-client 라이브러리를 사용해 Space를 호출해요.
예를 들어 허브의 FLUX.1-dev Space를 가져와 이미지를 생성해볼게요.
image_generation_tool = Tool.from_space(
"black-forest-labs/FLUX.1-schnell",
name="image_generator",
description="Generate an image from a prompt"
)
image_generation_tool("A sunny beach")
그리고 짠, 여기 당신의 이미지가 있어요! 🏖️
그다음 이 도구를 다른 도구처럼 쓰면 돼요. 예를 들어 a rabbit wearing a space suit 프롬프트를 개선해 이미지를 생성해볼게요. 이 예시는 에이전트에 추가 인자를 전달하는 방법도 보여줘요.
from smolagents import CodeAgent, InferenceClientModel
model = InferenceClientModel(model_id="Qwen/Qwen3-Next-80B-A3B-Thinking")
agent = CodeAgent(tools=[image_generation_tool], model=model)
agent.run(
"Improve this prompt, then generate an image of it.", additional_args={'user_prompt': 'A rabbit wearing a space suit'}
)
=== Agent thoughts:
improved_prompt could be "A bright blue space suit wearing rabbit, on the surface of the moon, under a bright orange sunset, with the Earth visible in the background"
Now that I have improved the prompt, I can use the image generator tool to generate an image based on this prompt.
>>> Agent is executing the code below:
image = image_generator(prompt="A bright blue space suit wearing rabbit, on the surface of the moon, under a bright orange sunset, with the Earth visible in the background")
final_answer(image)
정말 멋지죠? 🤩
LangChain 도구 사용하기
우리는 LangChain을 좋아하고 그 도구 모음이 매우 훌륭하다고 생각해요. LangChain에서 도구를 가져오려면 from_langchain() 메서드를 쓰세요.
시작 부분의 검색 결과를 LangChain 웹 검색 도구로 재현해볼게요. 이 도구는 pip install langchain google-search-results -q가 필요해요.
from langchain.agents import load_tools
search_tool = Tool.from_langchain(load_tools(["serpapi"])[0])
agent = CodeAgent(tools=[search_tool], model=model)
agent.run("How many more blocks (also denoted as layers) are in BERT base encoder compared to the encoder from the architecture proposed in Attention is All You Need?")
에이전트의 툴박스 관리하기
agent.tools는 표준 딕셔너리이므로, 여기에 도구를 추가하거나 교체해 에이전트의 툴박스를 관리할 수 있어요. 기본 툴박스만으로 초기화된 기존 에이전트에 model_download_tool을 추가해볼게요.
from smolagents import InferenceClientModel
model = InferenceClientModel(model_id="Qwen/Qwen3-Next-80B-A3B-Thinking")
agent = CodeAgent(tools=[], model=model, add_base_tools=True)
agent.tools[model_download_tool.name] = model_download_tool
이제 새 도구를 활용할 수 있어요.
agent.run(
"Can you give me the name of the model that has the most downloads in the 'text-to-video' task on the Hugging Face Hub but reverse the letters?"
)
[!TIP] 에이전트에 도구를 너무 많이 추가하지 않도록 주의하세요. 약한 LLM 엔진을 압도할 수 있어요.
도구 컬렉션 사용하기
ToolCollection로 도구 컬렉션을 활용할 수 있어요. 허브의 컬렉션 또는 MCP 서버 도구를 불러오는 걸 지원해요.
어떤 MCP 서버에서든 도구 컬렉션 가져오기
glama.ai나 smithery.ai에서 제공하는 수백 개의 MCP 서버 도구를 활용할 수 있어요. MCP 서버 도구는 ToolCollection.from_mcp로 불러올 수 있어요.
[!WARNING] 보안 경고: 특히 프로덕션 환경에서는 어떤 MCP 서버에 연결하기 전에 항상 소스와 무결성을 검증하세요. MCP 서버 사용에는 보안 위험이 따릅니다.
- 신뢰가 필수: 신뢰할 수 있는 소스의 MCP 서버만 사용하세요. 악성 서버가 내 머신에서 해로운 코드를 실행할 수 있어요.
- stdio 기반 MCP 서버는 항상 내 머신에서 코드를 실행해요(그게 의도된 기능이에요).
- Streamable HTTP 기반 MCP 서버: 원격 MCP 서버는 내 머신에서 코드를 실행하지 않지만, 그래도 주의를 기울이세요.
stdio 기반 MCP 서버의 경우 서버 파라미터를 mcp.StdioServerParameters 인스턴스로 넘기세요.
from smolagents import ToolCollection, CodeAgent
from mcp import StdioServerParameters
server_parameters = StdioServerParameters(
command="uvx",
args=["--quiet", "[email protected]"],
env={"UV_PYTHON": "3.12", **os.environ},
)
with ToolCollection.from_mcp(server_parameters, trust_remote_code=True) as tool_collection:
agent = CodeAgent(tools=[*tool_collection.tools], model=model, add_base_tools=True)
agent.run("Please find a remedy for hangover.")
ToolCollection으로 구조화된 출력 지원을 활성화하려면 structured_output=True 파라미터를 추가하세요.
with ToolCollection.from_mcp(server_parameters, trust_remote_code=True, structured_output=True) as tool_collection:
agent = CodeAgent(tools=[*tool_collection.tools], model=model, add_base_tools=True)
agent.run("Please find a remedy for hangover.")
Streamable HTTP 기반 MCP 서버의 경우 파라미터 딕셔너리를 mcp.client.streamable_http.streamablehttp_client에 넘기고 transport 키에 "streamable-http" 값을 추가하면 돼요.
from smolagents import ToolCollection, CodeAgent
with ToolCollection.from_mcp({"url": "http://127.0.0.1:8000/mcp", "transport": "streamable-http"}, trust_remote_code=True) as tool_collection:
agent = CodeAgent(tools=[*tool_collection.tools], add_base_tools=True)
agent.run("Please find a remedy for hangover.")
허브 컬렉션에서 도구 컬렉션 가져오기
사용하려는 컬렉션의 slug로 활용할 수 있어요. 그다음 에이전트 초기화에 리스트로 넘기고 사용하기 시작하면 돼요.
from smolagents import ToolCollection, CodeAgent
image_tool_collection = ToolCollection.from_hub(
collection_slug="huggingface-tools/diffusion-tools-6630bb19a942c2306a2cdb6f",
token="<YOUR_HUGGINGFACEHUB_API_TOKEN>"
)
agent = CodeAgent(tools=[*image_tool_collection.tools], model=model, add_base_tools=True)
agent.run("Please draw me a picture of rivers and lakes.")
시작 속도를 높이기 위해 도구는 에이전트가 호출할 때만 불러와져요.
출처 인용
- 원문: smolagents - Tools, in-depth guide (Hugging Face Docs)
- 원본 파일: huggingface/smolagents - docs/source/en/tutorials/tools.md