목차
단순한 툴 호출 데모에서 진짜 에이전트로 넘어가는 결정적 차이는 오류 처리 방식이다. 이 튜토리얼은 Gemma 4와 Ollama를 사용해 도구 실패를 모델이 스스로 복구하는 반복 에이전트 루프를 Python으로 구현한다.
전제 조건
- Ollama 설치 및 Gemma 4 모델 다운로드
- Ollama Python SDK:
pip install ollama - 이전 단계: 단일 턴 툴 호출 구현
핵심 아이디어: 오류를 메시지로 변환
기존 방식은 오류가 나면 스크립트가 멈추거나 try/except로 에러 메시지를 출력하고 끝낸다. 이 튜토리얼은 다른 접근을 취한다:
오류 발생
→ 오류를 모델이 읽을 수 있는 메시지로 변환
→ 컨텍스트에 추가해 모델에 전달
→ 모델이 재시도·우회·설명 중 선택이 패턴이 “툴 호출 데모”를 “에이전트”로 만드는 핵심이다.
에이전트가 처리하는 오류 유형
- 존재하지 않는 함수명 호출 (할루시네이션)
- 잘못된 인자 타입 전달 (문자열 vs. 숫자)
- 알 수 없는 데이터 요청 (예: 존재하지 않는 도시)
- 업스트림 API 타임아웃
- 필수 인자 누락
구현
1단계: 도구 정의
import ollama
import json
TOOLS = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "도시의 현재 날씨 반환",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "도시명"}
},
"required": ["city"],
},
},
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "수식 계산",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "계산할 수식"}
},
"required": ["expression"],
},
},
},
]2단계: 툴 실행 래퍼 (오류 처리 포함)
TOOL_REGISTRY = {
"get_weather": get_weather,
"calculate": calculate,
}
def execute_tool(tool_call):
name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
if name not in TOOL_REGISTRY:
raise ValueError(f"Unknown tool: {name}")
return TOOL_REGISTRY[name](**args)3단계: 반복 에이전트 루프
MAX_ITERATIONS = 10
def run_agent(user_message):
messages = [{"role": "user", "content": user_message}]
for i in range(MAX_ITERATIONS):
response = ollama.chat(
model="gemma4",
messages=messages,
tools=TOOLS,
)
messages.append(response.message)
if not response.message.tool_calls:
# 툴 호출 없음 = 최종 응답
return response.message.content
for tool_call in response.message.tool_calls:
try:
result = execute_tool(tool_call)
content = str(result)
except Exception as e:
# 오류도 일반 툴 결과와 동일한 형식으로 전달
content = f"Error executing {tool_call.function.name}: {str(e)}"
messages.append({
"role": "tool",
"content": content,
})
return "최대 반복 횟수 초과"핵심 포인트: 오류도 일반 툴 결과와 동일한 형식으로 컨텍스트에 추가한다. 모델은 오류 메시지를 읽고 다음 행동(재시도·다른 툴 사용·설명)을 스스로 결정한다.
4단계: 실행
result = run_agent("서울 날씨 알려줘, 그리고 (15 * 4) + 7 계산해줘")
print(result)동작 원리
사용자: "서울 날씨 알려줘"
→ 에이전트: get_weather("서울") 호출
→ 오류: "Seoul not found"
→ 에이전트: 오류 메시지를 컨텍스트에 추가
→ 에이전트: get_weather("Seoul") 재시도 또는 대안 설명
→ 최종 응답전체 코드
GitHub: mmmayo13/gemma_4_tool_calling
마무리
이 패턴의 핵심은 단순하다: 오류도 데이터다. 오류를 숨기거나 포기하는 대신, 모델의 컨텍스트 창에 넣어 주면 모델이 스스로 전략을 바꾼다. 반복 횟수 상한(MAX_ITERATIONS)은 무한 루프를 방지하는 최소한의 안전망이다.
참고 자료
- Building a Multi-Tool Gemma 4 Agent with Error Recovery — MachineLearningMastery.com (2026-05-22)