07. SDK로 도구와 메모리 다루기

🎯 이 장의 목표
  • @function_tool 데코레이터로 파이썬 함수를 도구로 만든다
  • 빌트인 도구(웹 검색 등)와 직접 만든 도구의 차이를 안다
  • Sessions로 대화 메모리를 자동 관리하는 법을 익힌다
  • 구조화된 출력(structured output)으로 결과를 안정적으로 받는 법을 본다

비유로 시작하기: 라벨만 붙이면 끝

1부에서 도구를 만들 때는 함수와 별도로 JSON 스키마를 손으로 적어야 했습니다. 이름, 설명, 인자 타입을 일일이 명시했죠. SDK에서는 함수 위에 데코레이터 한 줄만 붙이면, 함수 시그니처와 독스트링(docstring)을 읽어 스키마를 자동 생성합니다. 데코레이터는 함수 위에 @이름 형태로 붙여 그 함수에 기능을 더해 주는 파이썬 문법이고, 독스트링은 함수 바로 아래 """..."""로 적는 함수 설명문입니다. 마치 상자에 내용물 라벨을 자동으로 붙여주는 것과 같습니다.

함수를 도구로: @function_tool

PYTHON
from agents import Agent, Runner, function_tool

@function_tool
def get_weather(city: str) -> str:
    """도시 이름을 받아 현재 날씨를 반환한다.

    Args:
        city: 날씨를 조회할 도시 이름 (예: 서울)
    """
    fake = {"서울": "맑음, 24도", "부산": "흐림, 22도"}
    return fake.get(city, "정보 없음")

agent = Agent(
    name="WeatherBot",
    instructions="사용자의 날씨 질문에 도구를 사용해 답한다.",
    tools=[get_weather],
)

result = Runner.run_sync(agent, "서울 날씨 어때?")
print(result.final_output)

비교해 보면 차이가 분명합니다. 1부에서는 함수 + 수동 JSON 스키마 + 수동 실행 루프가 모두 필요했지만, SDK에서는 @function_tool + tools=[...]만으로 끝납니다. 타입 힌트(city: str처럼 인자·반환값의 자료형을 표시하는 파이썬 문법)와 독스트링이 곧 스키마가 됩니다.

📌 핵심: 타입 힌트와 독스트링이 도구의 품질을 좌우합니다. 1부에서 강조한 "명확한 description" 원칙은 여기서 독스트링으로 이어집니다. 모델은 이 독스트링을 읽고 "언제 이 도구를 쓸지" 판단합니다.

flowchart LR
    classDef code fill:#90CAF9,stroke:#1565C0,color:#000
    classDef agent fill:#80DEEA,stroke:#00838F,color:#000

    F["@function_tool<br/>def get_weather(city: str)"]:::code
    F -->|타입 힌트+독스트링<br/>자동 파싱| S[도구 스키마 생성]:::code
    S --> A[Agent tools=...]:::agent

빌트인 도구

매번 도구를 만들 필요는 없습니다. SDK는 자주 쓰는 기능을 호스티드 도구(hosted tools)로 제공합니다. 웹 검색(WebSearchTool), 파일 검색(FileSearchTool), 코드 실행(CodeInterpreterTool), 이미지 생성(ImageGenerationTool) 등이 있습니다.

PYTHON
from agents import Agent, Runner, WebSearchTool

agent = Agent(
    name="Researcher",
    instructions="최신 정보가 필요하면 웹을 검색해 답한다.",
    tools=[WebSearchTool()],
)

result = Runner.run_sync(agent, "오늘 기준 최신 AI 뉴스 하나만 알려줘.")
print(result.final_output)
도구 종류예시특징
함수 도구@function_tool로 만든 내 함수내 로직·내부 API 연결
호스티드 도구WebSearchTool, FileSearchToolOpenAI가 실행, 설정만 하면 됨
MCP 도구외부 MCP 서버의 도구표준 프로토콜로 연결 (7부)
📌 핵심
최신 정보: 강의는 Tavily 같은 외부 검색 API를 함수 도구로 붙이는 방식을 보여줍니다. 그 방식도 여전히 유효하지만, 단순 웹 검색이라면 빌트인 WebSearchTool이 더 간편합니다. 둘 다 알아두면 상황에 맞게 고를 수 있습니다.

메모리: Sessions

1부에서 대화 기록 리스트를 손으로 누적했던 것을 기억하시나요? SDK는 Sessions로 이를 자동화합니다. 세션을 넘기면 turn 간 맥락이 알아서 유지됩니다.

PYTHON
from agents import Agent, Runner, SQLiteSession

agent = Agent(name="Assistant", instructions="친절하게 답한다.")
session = SQLiteSession("user_123")  # 사용자별 세션

# 첫 턴
Runner.run_sync(agent, "내 이름은 민수야.", session=session)
# 둘째 턴 — 이전 맥락을 기억
result = Runner.run_sync(agent, "내 이름이 뭐라고 했지?", session=session)
print(result.final_output)  # "민수"라고 답한다

SQLiteSession은 대화를 SQLite에 저장해, 프로그램을 재시작해도 맥락이 유지됩니다. SQLite는 별도 서버 없이 파일 하나로 동작하는 가벼운 데이터베이스로, 설치가 필요 없어 로컬 개발에 흔히 쓰입니다. 1부에서 만든 MemoryAgent의 화이트보드를, SDK가 영속 저장소까지 붙여 자동화해 준 셈입니다.

⚠️ 흔한 실수: 세션을 쓰면서 동시에 서버 관리 상태(conversation_id, previous_response_id)를 같은 호출에 섞는 것. 맥락이 중복될 수 있습니다. 한 대화에는 한 가지 영속 전략만 쓰세요.

구조화된 출력

에이전트가 자유 텍스트가 아니라 정해진 구조로 답하게 하고 싶을 때가 있습니다(예: 분류 결과를 JSON으로). output_type에 Pydantic 모델을 주면 됩니다. Pydantic은 파이썬에서 데이터의 구조와 자료형을 클래스로 선언하고 자동 검증해 주는 라이브러리로, 에이전트 출력을 정해진 형식으로 강제할 때 자주 쓰입니다.

PYTHON
from pydantic import BaseModel
from agents import Agent, Runner

class Sentiment(BaseModel):
    label: str       # "긍정" / "부정" / "중립"
    confidence: float

agent = Agent(
    name="SentimentClassifier",
    instructions="입력 문장의 감성을 분류한다.",
    output_type=Sentiment,
)

result = Runner.run_sync(agent, "이 제품 정말 최고예요!")
print(result.final_output.label)        # "긍정"
print(result.final_output.confidence)   # 예: 0.95

📌 핵심: output_type을 쓰면 결과가 검증된 객체로 돌아옵니다. 후속 코드에서 .label처럼 안전하게 다룰 수 있어, 멀티 에이전트 파이프라인에서 특히 유용합니다.

💡 실습 아이디어(강의의 Tweet/검색 도구 대응): @function_tool로 검색 함수를 만들고, output_type으로 "트윗 본문 + 해시태그 리스트" 구조를 정의해 보세요. 검색으로 최신 정보를 얻고, 구조화된 트윗을 생성하는 에이전트가 됩니다.

이 장에서 배운 것

  • @function_tool 데코레이터가 타입 힌트와 독스트링을 읽어 도구 스키마를 자동 생성한다.
  • 빌트인 호스티드 도구(웹 검색·파일 검색 등)로 직접 만들지 않고도 기능을 붙일 수 있다.
  • Sessions(예: SQLiteSession)가 대화 메모리를 자동·영속 관리한다.
  • output_type(Pydantic)으로 구조화된 출력을 안정적으로 받을 수 있다.

✍️ 확인 문제

  1. @function_tool을 붙인 함수에서 타입 힌트와 독스트링을 생략하면 어떤 문제가 생기는가?
  2. 단순 웹 검색을 붙일 때 외부 검색 API를 함수 도구로 만드는 방법과 빌트인 도구를 쓰는 방법의 장단점을 각각 한 가지씩 들어라.
  3. 감성 분류 결과를 후속 코드에서 안전하게 다루려면 Agent에 무엇을 설정해야 하는가?
이전 장: 06. OpenAI Agents SDK 입문
다음 장: 08. 멀티 에이전트 팀 만들기