AutoGen 도구
AutoGen 도구 (Tools)
에이전트가 액션을 수행하려면 코드가 필요한데, 그 "코드"를 AutoGen에서는 도구(tools)라고 불러요. 도구는 계산기처럼 단순한 함수일 수도 있고, 주식 가격 조회나 날씨 예보처럼 제3자 서비스에 대한 API 호출일 수도 있습니다. AI 에이전트의 맥락에서 도구는 모델이 생성한 함수 호출에 응답해 에이전트가 실행하도록 설계돼요.
AutoGen은 커스텀 도구를 만들고 실행하기 위한 내장 도구와 유틸리티 모음인 autogen_core.tools 모듈을 제공합니다.
Built-in Tools
내장 도구 중 하나는 에이전트가 Python 코드 조각을 실행할 수 있게 해 주는 PythonCodeExecutionTool이에요.
from autogen_ext.tools.code_execution import PythonCodeExecutionTool
from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor
# Docker 컨테이너에서 Python 코드를 실행하는 코드 실행기를 만든다.
code_executor = DockerCommandLineCodeExecutor(work_dir="workspace")
await code_executor.start()
# Python 코드를 실행하는 도구를 만든다.
code_execution_tool = PythonCodeExecutionTool(code_executor)
DockerCommandLineCodeExecutor 클래스는 Docker 컨테이너의 커맨드라인 환경의 서브프로세스에서 Python 코드 조각을 실행하는 내장 코드 실행기예요. PythonCodeExecutionTool 클래스는 그 코드 실행기를 감싸서 Python 코드 조각을 실행하는 간단한 인터페이스를 제공합니다.
다른 내장 도구의 예:
LocalSearchTool과GlobalSearchTool: GraphRAG 사용mcp_server_tools: Model Context Protocol (MCP) 서버를 도구로 사용HttpTool: REST API에 HTTP 요청LangChainToolAdapter: LangChain 도구 사용
Custom Function Tools
도구는 특정 동작을 수행하는 간단한 Python 함수일 수도 있어요. 커스텀 함수 도구를 만들려면 Python 함수를 만들고 FunctionTool 클래스로 감싸면 됩니다.
FunctionTool 클래스는 설명(description)과 타입 어노테이션을 사용해 LLM에게 함수를 언제 어떻게 쓸지 알려줍니다. 설명은 함수의 목적과 의도된 사용 사례에 대한 맥락을 제공하고, 타입 어노테이션은 예상 파라미터와 반환 타입을 LLM에 알려줘요.
예를 들어 회사 주가를 얻는 간단한 도구는 이렇게 생겼어요:
from autogen_core.tools import FunctionTool
from typing import Annotated, Literal
async def get_stock_price(ticker: str, currency: Literal["USD", "EUR"]) -> float:
"""Get the stock price of a company"""
# 실제 구현에서는 API 호출 등이 들어간다.
return 0.0
stock_price_tool = FunctionTool(
get_stock_price,
description="Get the stock price of a company",
schema_extra={"title": "Stock Price"},
)
Calling Tools with Model Clients
AutoGen에서 모든 도구는 BaseTool의 하위 클래스이고, 도구의 JSON 스키마를 자동으로 생성합니다. 예를 들어 stock_price_tool의 JSON 스키마를 얻으려면 schema 속성을 쓰면 돼요.
stock_price_tool.schema
모델 클라이언트는 도구의 JSON 스키마를 사용해 도구 호출을 생성해요.
FunctionTool 클래스를 OpenAIChatCompletionClient와 함께 쓰는 예시는 다음과 같습니다. 다른 모델 클라이언트 클래스도 비슷하게 쓸 수 있어요. 자세한 내용은 Model Clients를 참고하세요.
from autogen_ext.models.openai import OpenAIChatCompletionClient
model_client = OpenAIChatCompletionClient(model="gpt-4o")
# 함수 도구를 스키마로 모델에 전달한다.
result = await model_client.create(
messages=[
UserMessage(
content="What is the stock price of Apple?",
source="user",
)
],
tools=[stock_price_tool], # type: ignore[list-item]
)
BaseOpenAIChatCompletionClient.create 호출 내부에서 실제로 무슨 일이 일어날까요? 모델 클라이언트는 도구 목록을 받아 각 도구 파라미터의 JSON 스키마를 생성하고, 도구 JSON 스키마와 다른 메시지들을 모델 API에 보내 결과를 얻습니다.
OpenAI의 GPT-4o나 Llama-3.2 같은 많은 모델은 도구의 JSON 스키마를 따르는 구조화된 JSON 문자열 형태의 도구 호출을 생성하도록 학습돼요. AutoGen의 모델 클라이언트는 모델의 응답을 파싱해서 JSON 문자열에서 도구 호출을 추출합니다.
그 결과는 FunctionCall 객체 리스트이고, 이를 사용해 해당 도구를 실행할 수 있어요.
json.loads로 FunctionCall.arguments 필드의 JSON 문자열을 Python 딕셔너리로 파싱하고, BaseTool.run_json 메서드가 그 딕셔너리를 받아 제공된 인자로 도구를 실행합니다.
import json
function_call = result[0] # type: ignore
arguments = json.loads(function_call.arguments)
result = await stock_price_tool.run_json(arguments, cancellation_token)
이제 모델 클라이언트를 한 번 더 호출해서 도구 실행 결과에 대한 반성(reflection)을 생성하게 할 수 있어요.
도구 호출의 결과는 FunctionExecutionResult 객체로 감싸지는데, 여기에는 도구 실행 결과와 호출된 도구의 ID가 들어 있어요. 모델 클라이언트는 이 정보를 사용해 도구 실행 결과에 대한 반성을 생성할 수 있습니다.
Tool-Equipped Agent
모델 클라이언트와 도구를 합치면, 도구를 사용해 액션을 수행하고 그 결과를 반성할 수 있는 도구 장착 에이전트를 만들 수 있어요.
Core API는 최소한으로 설계되어서, 모델 클라이언트와 도구 주변에 자신만의 에이전트 로직을 직접 만들어야 해요.
도구를 쓸 수 있는 "프리빌트" 에이전트는 [AgentChat API](../../agentchat-user-guide/index.md)를 참고하세요.
from typing import List
from autogen_core import (
AgentId,
MessageContext,
RoutedAgent,
SingleThreadedAgentRuntime,
message_handler,
)
from autogen_core.models import UserMessage
from autogen_ext.models.openai import OpenAIChatCompletionClient
class ToolUseAgent(RoutedAgent):
def __init__(self, model_client: ChatCompletionClient, tool: FunctionTool) -> None:
super().__init__("Tool Use Agent")
self._model_client = model_client
self._tool = tool
self._system_message = SystemMessage(content="You are a helpful AI assistant.")
@message_handler
async def handle_user_message(self, message: UserMessage, ctx: MessageContext) -> None:
session = self.session_id
# 모델 클라이언트로 도구 호출 목록을 생성한다.
create_result = await self._model_client.create(
[self._system_message, message],
tools=[self._tool],
cancellation_token=ctx.cancellation_token,
)
# 도구 호출을 실행한다.
function_call = create_result.content[0]
arguments = json.loads(function_call.arguments) # type: ignore
result = await self._tool.run_json(arguments, ctx.cancellation_token)
# 도구 실행 결과에 대한 반성을 생성한다.
reflection = await self._model_client.create(
[
self._system_message,
message,
AssistantMessage(content=create_result.content, source="assistant"),
FunctionExecutionResultMessage(content=[result]),
],
cancellation_token=ctx.cancellation_token,
)
print(reflection.content[0].content) # type: ignore
사용자 메시지를 처리할 때 ToolUseAgent 클래스는 먼저 모델 클라이언트로 도구에 대한 함수 호출 목록을 생성하고, 도구를 실행한 뒤 도구 실행 결과에 대한 반성을 생성해요. 그 반성은 에이전트의 응답으로 사용자에게 돌아갑니다.
이 예제는 OpenAIChatCompletionClient를 쓰는데, Azure OpenAI와 다른 클라이언트는 Model Clients를 참고하세요. 주가에 대한 질문으로 에이전트를 테스트해 봅시다.