research

Tool 구현 — 근본적인 구조

Tool 구현 — 근본적인 구조

Tool의 세 가지 구성 요소

1. 인터페이스  — LLM이 이해하는 명세 (입출력 정의)
2. 실행 코드   — 실제로 작업하는 함수
3. 에러 처리   — 실패했을 때 LLM에게 뭘 전달할지

기반 클래스

# tools/base.py
class Tool:
    def __init__(self, name, description, params, returns, when_to_use):
        self.name = name
        self.description = description
        self.params = params
        self.returns = returns
        self.when_to_use = when_to_use
    
    def run(self, **kwargs) -> dict:
        raise NotImplementedError
    
    def to_prompt(self) -> str:
        return f"""
## Tool: {self.name}
설명: {self.description}
입력: {self.params}
출력: {self.returns}
사용 시점: {self.when_to_use}
"""

모든 Tool이 이 클래스를 상속해서 run()만 구현.

에러 처리 원칙

에러를 exception으로 터뜨리면 LLM이 뭘 해야 할지 모른다. 에러를 LLM이 읽을 수 있는 구조화된 응답으로 반환해야 한다.

# 나쁨: exception 터짐 → LLM이 할 수 있는 것 없음
# 좋음: 구조화된 에러 반환 → LLM이 재시도 or 사용자 알림 결정

return {"success": False, "error": "timeout",
        "message": "다운로드 시간 초과. 나중에 다시 시도해라."}

핵심 원칙

1. 모든 Tool은 항상 dict를 반환한다
   {"success": True/False, ...}

2. 에러는 exception이 아니라 응답으로
   LLM이 다음 행동을 결정할 수 있게

3. Side effect는 명확하게 반환
   파일 생성 → local_path 반환
   세션 생성 → session_id 반환

파일 구조

tools/
├── base.py           ← Tool 기반 클래스
├── file_tools.py     ← download_file, convert_to_md
├── browser_tools.py  ← login, navigate, search
├── db_tools.py       ← query_db, insert_db
└── rag_tools.py      ← index_to_rag, search_rag

tool_registry.py      ← 등록 + System prompt 자동 생성
agent.py              ← Tool 실행 루프

브라우저 Tool (Playwright)

class LoginTool(Tool):
    def __init__(self):
        super().__init__(name="login", ...)
        self._sessions = {}
    
    def run(self, url, credentials_key):
        try:
            creds = get_credentials(credentials_key)
            pw = sync_playwright().start()
            context = pw.chromium.launch().new_context()
            # 로그인 처리...
            session_id = generate_id()
            self._sessions[session_id] = context
            return {"success": True, "session_id": session_id}
        except Exception as e:
            return {"success": False, "error": "auth_failed",
                    "message": str(e)}

관련 개념