research

Tool Registry — 포괄적 Agent 구현 구조

Tool Registry — 포괄적 Agent 구현 구조

핵심 구조

사용자 채팅
    ↓
LLM (Tool Registry 참조, CoT)
    ↓
Tool call 생성
    ↓
execute_tool() → 실제 코드 실행
    ↓
결과 → 다시 LLM → 자연어 응답
    ↓
사용자

Tool Registry

사용 가능한 Tool들의 카탈로그. 새 Tool 추가 → 등록 → 자동 반영.

TOOLS = {
    "download_file": {
        "description": "파일을 다운로드한다",
        "params": {"url": "str", "save_path": "str"},
        "returns": "local_path: str",
        "when_to_use": "사용자가 파일 저장을 요청할 때"
    },
    "query_db": {
        "description": "DBMS에서 데이터를 조회한다",
        "params": {"query": "str", "db_name": "str"},
        "returns": "results: list",
        "when_to_use": "데이터 조회가 필요할 때"
    },
}

System prompt 자동 생성

Tool을 손으로 쓰지 않고 Registry에서 자동 생성:

def build_system_prompt(user_config):
    tools_text = ""
    for name, spec in TOOLS.items():
        tools_text += f"""
## Tool: {name}
설명: {spec['description']}
입력: {spec['params']}
출력: {spec['returns']}
사용 시점: {spec['when_to_use']}
"""
    return f"너는 사용자의 AI agent다.\n{tools_text}\n{user_config}"

대화 실행 흐름

def chat(user_message, history):
    system = build_system_prompt(user_config)
    response = llm.chat(system=system, messages=history + [user_message])
    
    while response.has_tool_call():
        result = execute_tool(response.tool_call.name, response.tool_call.params)
        history.append({"role": "tool", "content": result})
        response = llm.chat(system=system, messages=history)
    
    return response.text

포괄성 확보 방법

1. Tool을 원자적으로 쪼개면 조합으로 대부분 커버

download_file + convert_to_md + index_to_rag
→ "파일 다운받아서 RAG에 넣어줘"

2. 없는 Tool은 명시적으로 알려주게 강제

System prompt 추가:
"요청한 작업을 수행할 Tool이 없으면
 '현재 이 작업은 지원되지 않습니다: [이유]'라고 말해라.
 없는 Tool을 만들어내지 말 것."

Skill의 위치

Skill = 자주 쓰는 Tool 조합을 미리 묶어둔 것. 없어도 작동하지만, 있으면 LLM이 더 빠르고 일관되게 선택.

Tool Registry  → "무엇을 할 수 있는가"
Skill 정의     → "자주 쓰는 조합을 미리 정의"
대화           → LLM이 Registry + Skill 보고 판단

관련 개념