실무 Multi-Agent 오케스트레이션 6장 · 데이터 조회 도구 구현 4 / 7 ← 이전목차다음 → TechLead Cro

6장. 데이터 조회 도구 구현

자동 함수 호출 — SDK가 왕복을 대신한다

한 줄 요약

파이썬 함수를 tools=[...]에 그대로 넘기면, SDK가 함수의 이름·타입힌트·독스트링으로 도구 선언을 만들고, 모델의 function call을 받아 함수를 실행하고 결과를 돌려주는 왕복까지 대신합니다. 5장에서 손으로 한 일 그대로입니다.


1. 5장과 무엇이 달라지는가

5장 (손으로) 6장 (자동으로)
도구 선언 FunctionDeclaration을 직접 썼다 SDK가 함수에서 만든다
함수 실행 get_order_status(**fc.args)를 직접 불렀다 SDK가 부른다
결과 반환 contents에 세 덩어리를 담아 다시 호출했다 SDK가 한다
generate_content 호출 우리 코드에 두 번 우리 코드에 한 번
돌아오는 것 첫 번째는 function call, 두 번째는 답변 바로 답변

호출 코드는 이렇게 줄어듭니다.

response = client.models.generate_content(
    model=MODEL,
    contents=question,
    config=types.GenerateContentConfig(
        system_instruction=SYSTEM,
        temperature=1.0,
        tools=[get_order_status, track_shipping],   # 파이썬 함수를 그대로 전달
        automatic_function_calling=types.AutomaticFunctionCallingConfig(
            maximum_remote_calls=4
        ),
    ),
)
print(response.text)

모델을 부르는 횟수가 줄어든 것은 아닙니다. SDK 안에서 여전히 두 번 이상 호출됩니다. 우리 눈에 보이지 않을 뿐입니다.


2. 독스트링이 도구 선언이 된다

독스트링(docstring) 은 함수 바로 아래 """...""" 안에 적는 설명글이고, 타입힌트(type hint) 는 order_id: str처럼 인자의 타입을 적어 둔 표시입니다. 보통은 사람을 위한 것이어서 없어도 코드는 돕니다.

자동 방식에서는 이 둘이 모델에게 가는 안내문의 재료가 됩니다.

def track_shipping(order_id: str) -> dict:
    """주문번호로 택배사·송장번호·출고일·배송완료일을 조회한다. 배송 위치 문의에 사용한다.

    Args:
        order_id: 하루마켓 주문번호. 'HR'로 시작한다.
    """

SDK가 이 함수로 만드는 선언을 출력해 보면 이렇습니다(「실습문제와 해답」 문제 3에서 직접 출력합니다).

{
  "description": "주문번호로 택배사·송장번호·출고일·배송완료일을 조회한다. 배송 위치 문의에 사용한다.\n\nArgs:\n    order_id: 하루마켓 주문번호. 'HR'로 시작한다.",
  "name": "track_shipping",
  "parameters": {
    "properties": {
      "order_id": {
        "type": "STRING"
      }
    },
    "required": [
      "order_id"
    ],
    "type": "OBJECT"
  }
}
함수의 이것이 선언의 이것이 된다
함수 이름 track_shipping name
독스트링 전체 (Args: 부분 포함) description
타입힌트 order_id: str parameters의 인자 이름과 타입
기본값이 없는 인자 required

눈여겨볼 점이 있습니다. Args: 아래에 쓴 인자 설명은 5장처럼 인자 칸에 따로 들어가지 않고, 도구 설명 글 안에 함께 실려 갑니다. 모델에게 전달되기는 하므로 "'HR'로 시작한다" 같은 단서는 여전히 쓸모가 있습니다.

자동 방식에서 독스트링은 문서가 아니라 기능입니다. 지우면 모델은 이 도구가 무엇인지 모르게 되고, 모호하게 쓰면 엉뚱하게 불립니다.

track_shipping의 독스트링에 있는 "배송 위치 문의에 사용한다" 를 봅니다. 도구가 둘이 되면 모델은 골라야 하고, 고르는 근거는 이 글뿐입니다. 무엇을 하는 도구인지에 더해 언제 쓰는 도구인지를 적어 주었습니다.


3. 횟수 상한 — maximum_remote_calls

모델은 도구 결과를 보고 다른 도구를 또 부를 수 있습니다. 자동 방식에서는 SDK가 이 반복을 계속 이어 갑니다.

automatic_function_calling=types.AutomaticFunctionCallingConfig(
    maximum_remote_calls=4
)

maximum_remote_calls는 SDK가 자동으로 이어 갈 수 있는 호출 횟수의 상한입니다. 정하지 않으면 SDK의 기본값 10이 쓰입니다(이 과정에서 설치한 google-genai 2.8 기준).

상한이 필요한 이유는 비용입니다. 도구를 한 번 부를 때마다 모델을 한 번 더 호출하고, 그때마다 지금까지의 대화 전체가 다시 입력 토큰으로 들어갑니다. 주문 조회 한 건에 호출이 열 번씩 필요할 일은 없으므로 4로 낮춰 두었습니다. 이런 상한을 왜, 어떻게 거는지는 10장에서 자세히 봅니다.


4. 숨은 왕복을 들여다보는 창 — history

왕복이 SDK 안으로 숨었으므로, 모델이 어떤 도구를 어떤 값으로 불렀는지 따로 확인해야 합니다. 응답의 automatic_function_calling_history 에 왕복 과정의 대화가 차례로 담겨 있습니다.

if response.automatic_function_calling_history:
    for content in response.automatic_function_calling_history:
        for part in content.parts or []:
            if part.function_call:
                print(f"  [도구 호출] {part.function_call.name}"
                      f"({dict(part.function_call.args)})")

이 안에는 5장에서 contents에 손으로 담았던 것과 같은 덩어리들(질문, 모델의 function call, 실행 결과)이 들어 있습니다. 그중 function call만 골라 한 줄씩 출력하는 코드입니다.

답만 보면 "맞는 것 같다"에서 끝납니다. 이 출력이 있어야 어떤 도구가 어떤 인자로 불려서 그 답이 나왔는지를 말할 수 있습니다. 도구를 쓰는 코드에서는 이 출력을 늘 켜 둡니다.


5. 시스템 프롬프트로 사실의 경계를 긋는다

도구가 사실을 가져와도, 모델은 도구가 주지 않은 빈자리를 짐작으로 채울 수 있습니다. orders.csv에는 도착 예정일이 없는데, 고객은 "언제 와요?"라고 묻습니다.

SYSTEM = """당신은 하루마켓 고객지원 상담원 '하루'입니다.
주문 관련 문의는 반드시 도구로 조회한 실제 데이터로만 답합니다.
조회 결과에 없는 내용(도착 예정 시간 등)은 추측하지 않습니다.
존댓말로 3~5문장 이내로 답하고, 마지막에 다음 행동을 안내합니다."""

둘째, 셋째 줄이 이번 장에서 더한 규칙입니다. 도구는 사실을 가져오고, 프롬프트는 그 사실 밖으로 나가지 못하게 묶습니다. 넷째 줄은 3장에서 배운 대로 길이를 숫자로 정한 것입니다.


6. 자동 방식의 값

편해진 만큼 손에서 떠난 것이 있습니다.

손으로 할 때 있던 것 자동 방식에서
실행 직전에 검사를 넣을 자리 우리 코드 밖에 있습니다. 검사는 도구 함수 안에 넣어야 합니다
모델이 요청한 이름을 확인할 자리 SDK가 요청받은 함수를 바로 실행합니다. 이름을 직접 확인하고 싶으면 왕복을 손으로 돌립니다
한 단계씩 보는 출력 automatic_function_calling_history로 나중에 봅니다

그래서 왕복을 더 세밀하게 다뤄야 할 때는 다시 손으로 돌립니다(9장).


핵심 정리

  • 파이썬 함수를 tools=[...]에 넘기면 SDK가 선언을 만들고 왕복을 대신합니다.
  • 함수 이름, 독스트링, 타입힌트가 도구 선언이 됩니다. 독스트링은 문서가 아니라 기능입니다.
  • 독스트링에는 무엇을 하는지와 함께 언제 쓰는지를 적습니다.
  • maximum_remote_calls 로 자동 왕복의 횟수에 상한을 겁니다.
  • automatic_function_calling_history 로 어떤 도구가 불렸는지 확인합니다.
  • 시스템 프롬프트로 답변을 조회 결과 안에 묶습니다.
← 이전 절반환값은 모델이 읽는다 — 실패도 사실로 돌려준다다음 절 →따라하기 — 주문 조회 도구 만들기
오명운 · macro@prag-ai.com