두뇌에 손발 달기 — 도구란 그냥 파이썬 함수
한 줄 요약
도구(tool) 는 특별한 무언가가 아니라 평범한 파이썬 함수입니다. 그 함수를 config 의 tools=[...] 에 넣어 주면 LLM이 필요할 때 스스로 쓰겠다고 요청합니다. 이 순간부터 그 프로그램을 에이전트라고 부릅니다.
1. 2장이 남긴 문제
2장의 상담원은 말은 잘합니다. 그런데 이렇습니다.
고객 : 주문 O001203은 지금 어떤 상태인가요?
상담원: 확인 후 안내드리겠습니다.
시스템 지시를 아무리 정교하게 써도 이 답은 안 바뀝니다. 주문 데이터가 입력 어디에도 없기 때문입니다.
정보가 없으면 두 갈래뿐입니다.
- 정직하게 모른다고 한다 → 쓸모가 없다
- 그럴듯하게 지어낸다 → 위험하다 (1장 반품 기간 사례)
세 번째 길이 필요합니다. 정보를 가져오는 통로를 뚫어 주는 것.
2. 도구는 그냥 함수입니다
이게 도구입니다.
아래는 4절에서 만들 code/ch03_order_agent.py 의 일부를 미리 보는 것입니다 — 지금 붙여 넣지 않아도 됩니다.
def get_order_status(order_id: str) -> str:
"""주문번호로 주문 상태를 조회한다. 예: 'O001203'"""
oid = order_id.strip().upper()
hit = orders[orders["order_id"] == oid]
if hit.empty:
return f"주문번호 {oid} 를 찾을 수 없습니다."
r = hit.iloc[0]
return f"주문 {r.order_id} | {r.product_name} | 상태 '{r.status}'"
특별한 절차가 하나도 없습니다. 어딘가에 등록할 필요도, 정해진 틀을 물려받을 필요도 없습니다. 그냥 파이썬 함수입니다. 따로 호출해도 잘 동작합니다.
지금 방식에서는 함수 위에 별도의 표시를 붙이지 않습니다. 우리가 쓰는 구글 SDK(
google-genai)는 함수를 그대로 받습니다. 5장에서 쓸 LangChain 은 함수 위에@tool이라는 표시 한 줄을 붙이게 하는데(파이썬에서 이런 걸 데코레이터라고 부릅니다), 함수 본문은 여기 있는 것과 똑같습니다. 라이브러리가 알아보게 꼬리표만 하나 더 다는 것이죠. 4장 마지막 절에서 그 모습을 미리 봅니다.함수 안의 pandas 세 줄이 낯설어도 괜찮습니다. 1장 1절에서 말한 그대로 — 이 과정이 가르치는 것은 pandas가 아니라 "AI가 짜 준 코드를 함수로 묶어 도구로 쥐여 주는 법" 입니다. 저 세 줄은
"orders 라는 표에서 order_id 가 이 값인 행을 찾아 줘"라고 AI에게 부탁하면 나오는 코드입니다. 도구 안이 pandas든 SQL이든 사내 API 호출이든, 바깥의 에이전트 구조는 한 글자도 안 바뀝니다.
아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.
>>> get_order_status("O001203")
"주문 O001203 | 승승 스마트워치 Fit 5 | 상태 '배송완료'"
도구로 만드는 방법도 한 줄입니다.
아래는 4절에서 만들 code/ch03_order_agent.py 의 일부를 미리 보는 것입니다 — 지금 붙여 넣지 않아도 됩니다.
config=types.GenerateContentConfig(
tools=[get_order_status], # ← 함수를 목록에 넣는다. 이게 전부.
system_instruction=SYSTEM,
)
2장의 config 에 tools=[...] 한 줄이 추가된 것뿐입니다. 그런데 이 한 줄로 프로그램의 성격이 바뀝니다.
3. 무엇이 달라지나
| 2장 (도구 없음) | 3장 (도구 있음) | |
|---|---|---|
| 입력 | 질문만 | 질문 + 쓸 수 있는 도구 목록 |
| 모델이 하는 일 | 답변 문장을 만든다 | 답하거나, "이 도구를 써 달라"고 요청한다 |
| 부르는 이름 | LLM 애플리케이션 | 에이전트 |
에이전트의 정의를 다시 봅시다. 1장에서 이렇게 적었습니다 — "LLM에게 도구를 쥐여 주고, 필요할 때 스스로 그 도구를 쓰게 만든 프로그램." 이제 그 "쥐여 준다"가
tools=[...]라는 걸 알게 됐습니다.
4. "스스로 쓴다"가 정확히 무슨 뜻인가
여기가 오해하기 쉬운 지점입니다. 모델이 함수를 직접 실행하는 게 아닙니다.
일어나는 일을 순서대로 보면 이렇습니다.
① 우리 → 모델 : "주문 O001203 상태 알려줘"
+ [쓸 수 있는 도구: get_order_status(order_id: str)]
② 모델 → 우리 : "get_order_status 를 order_id='O001203' 로 불러 주세요"
↑ 요청서일 뿐. 아직 아무것도 실행되지 않았다.
③ 우리 : 실제로 함수 실행 → "주문 O001203 | ... | 상태 '배송완료'"
④ 우리 → 모델 : "결과가 이렇습니다"
⑤ 모델 → 우리 : "주문 O001203은 배송완료 상태입니다."
②와 ③ 사이에 선이 하나 그어져 있습니다. 모델은 ②까지만 하고, ③은 우리 코드가 합니다.
이 선이 이 장에서 가장 중요합니다. 다음 절 전체를 여기에 씁니다.
왜 이 선이 중요한가 — ③이 우리 쪽 일이라는 건, 무엇을 실행할지 우리가 통제할 수 있다는 뜻입니다. 모델이 이상한 요청을 하면 거부할 수 있고, 위험한 함수는 애초에 목록에 안 넣으면 됩니다. 5장에서 코드를 실행하는 도구를 만들 때 이 통제권이 결정적으로 중요해집니다.
5. 도구로 만들 수 있는 것들
이 과정에서 만들 도구들을 미리 봅시다. 전부 평범한 파이썬 함수입니다.
| 장 | 도구 | 안에서 하는 일 |
|---|---|---|
| 3장 | get_order_status(order_id) |
CSV에서 한 행을 찾아 문장으로 |
| 4장 | get_product_info(product_name) |
CSV에서 상품 정보를 찾아 문장으로 |
| 4장 | search_web(query) |
DuckDuckGo 검색 결과를 문장으로 |
| 5장 | run_pandas(expr) |
pandas 식을 실행해 결과를 문장으로 |
| 6장 | policy_search(query) |
PDF에서 관련 조각을 찾아 문장으로 |
공통점 두 가지를 눈여겨보세요.
- 입력도 출력도 문자열입니다. 모델은 문자열로 소통합니다.
- 하는 일은 전부 평범한 프로그래밍입니다. AI가 들어간 부분은 없습니다.
도구 안에는 AI가 없습니다. 데이터베이스 조회, 파일 읽기, API 호출 — 여러분이 원래 짜던 코드 그대로입니다. AI가 하는 일은 "언제 어느 도구를 쓸지 고르는 것"뿐입니다. 이 경계를 분명히 해 두면, 나중에 에이전트가 이상하게 동작할 때 모델 문제인지 내 코드 문제인지 바로 구분할 수 있습니다.
6. 이번 장에서 만들 것
1장에서 못 풀었던 첫 번째 질문을 풉니다.
[1장]
Q: 승승장구몰 주문 O001203은 지금 어떤 상태인가요?
A: 죄송하지만 저는 승승장구몰의 내부 시스템에 접근할 수 없습니다...
[3장 — 이번 장이 끝나면]
고객 : 승승장구몰 주문 O001203은 지금 어떤 상태인가요?
상담원: 주문 O001203은 배송완료 상태입니다.
그리고 없는 주문번호를 물었을 때도 지어내지 않게 만듭니다.
고객 : 주문 O999999 어떻게 됐나요?
상담원: 주문번호 O999999를 찾을 수 없습니다. 번호를 다시 확인해 주세요.
핵심 정리
- 도구는 그냥 파이썬 함수입니다. 특별한 상속도, 등록 절차도 없습니다. 지금 쓰는 구글 SDK에서는 함수 위에 아무 표시도 붙이지 않습니다 — 5장 LangChain에서는
@tool한 줄을 붙이지만, 함수 본문은 그대로입니다. - 함수를
config의tools=[...]에 넣으면 도구가 됩니다. 2장 코드에 한 줄 추가입니다. - 이 한 줄이 붙는 순간 그 프로그램을 에이전트라고 부릅니다.
- 모델은 함수를 직접 실행하지 않습니다. "이 함수를 이 값으로 불러 달라"는 요청까지만 하고, 실행은 우리 코드가 합니다.
- 도구 안에는 AI가 없습니다. AI가 하는 일은 언제 어느 도구를 쓸지 고르는 것뿐입니다.
- 다음 절에서 이 경계선을 자세히 봅니다. 이 장에서 가장 중요한 개념입니다.