본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 08. 16:04

에이전트 시리즈 (16): 도구 설계 — LLM이 도구를 올바르게 사용하도록 만드는 5가지 원칙

요약

LLM 에이전트가 도구를 정확하게 사용하도록 만드는 5가지 설계 원칙을 다룹니다. 설명 품질, 에러 핸들링, 세분성의 중요성을 실험 데이터를 통해 설명하며, 특히 다중 도구 환경에서의 문서화 전략을 강조합니다.

핵심 포인트

  • 도구 설명은 LLM이 여러 도구 중 최적의 것을 선택할 수 있도록 명확해야 함
  • 에러 발생 시 예외를 던지기보다 에러 메시지를 반환하여 에이전트의 연속성 유지
  • 황금 독스트링 형식을 사용하여 기능과 반환 값의 의미를 상세히 기술
  • 도구 설계의 핵심 3요소: 설명 품질, 에러 핸들링, 세분성

도구 문서화는 인간이 아니라 LLM을 위해 작성되어야 합니다

혹시 다음과 같이 도구를 작성해 본 적이 있나요?

@lc_tool
def get_data(query: str) -> str:
    """데이터를 가져옵니다."""
...

이는 인간에게도 나쁜 문서화입니다. LLM에게는 더 최악입니다. LLM은 이 도구가 무엇을 하는지, 언제 호출해야 하는지, 또는 파라미터(parameter)로 무엇을 전달해야 하는지 알 수 없습니다.

도구 설계에는 세 가지 핵심 차원이 있습니다: 설명 품질 (description quality) (LLM이 해당 도구를 선택할지 여부), 에러 핸들링 (error handling) (실패 시 에이전트가 충돌할지 여부), 그리고 세분성 (granularity) (파라미터를 추출하기 쉬운지 여부). 이 글은 실험 데이터를 사용합니다.

데모 1: 설명 품질 — 실제로 중요해지는 시점

동일한 날씨 도구의 두 가지 버전:

# 버전 A: 모호함
@lc_tool
def weather_vague(city: str) -> str:
...

두 에이전트를 대상으로 테스트한 다섯 가지 날씨 쿼리:

쿼리                                            모호함      정밀함
------------------------------------------------ ---------- ----------
오늘 베이징 날씨는 어때?                        ✓ 호출됨    ✓ 호출됨
...

두 버전 모두 5/5점을 기록했습니다.

이는 직관에 반하는 결과이며, 중요한 전제 조건이 있습니다: 에이전트가 단 하나의 도구만 가지고 있을 때, LLM은 설명과 상관없이 그 도구를 사용할 수밖에 없습니다. 설명 품질은 LLM이 여러 도구 중에서 선택해야 할 때 중요하며, 이것이 실제 프로덕션(production) 환경의 일반적인 모습입니다.

10개의 도구를 가진 에이전트에게 "베이징 날씨를 확인해줘"라는 요청이 들어옵니다. LLM은 최적의 일치 항목을 찾기 위해 10개의 독스트링(docstring)을 모두 읽습니다. 잘 문서화된 도구가 그 경쟁에서 승리하며, 모호한 도구는 목적이 더 명확하게 기술된 도구들에 밀려 간과됩니다.

황금 독스트링 형식:

"""<무엇을 하는지 설명하는 한 문장>

Returns: <반환 값의 형식과 의미>
...

데모 2: 에러 핸들링 — 예외를 발생시킬 것인가, 반환할 것인가?

로직은 동일하지만 실패 동작이 다른 두 가지 도구:

# 알 수 없는 도시일 때 예외 발생(Raise) ← 위험함
@lc_tool
def weather_raises(city: str) -> str:
...

세 가지 테스트 케이스:

알려진 도시 (Beijing): 두 방식 모두 동일하게 작동하며, 관찰 가능한 차이가 없습니다.

알려지지 않은 도시 (Atlantis):

raises : [CRASHED] ValueError: City 'Atlantis' not found in database.
returns: I'm sorry, but I couldn't find the weather information for Atlantis.
         Please make sure the city name is correct...

weather_raises는 에이전트 실행 전체를 중단(crash)시키지만, weather_returns_error는 LLM이 에러 문자열을 읽고 친절한 응답을 구성할 수 있게 합니다.

오타가 있는 도시 (Shanghia):

raises : The current weather in Shanghai is cloudy with a temperature of 22°C.
returns: The current weather in Shanghai is 22°C with a cloudy condition.

두 방식 모두 올바르게 답변했습니다. 이는 LLM이 도구를 호출하기 전에 "Shanghia"를 "Shanghai"로 수정했기 때문입니다. 도구는 올바른 도시 이름을 전달받았고, 에러 경로에 도달하지 않았습니다.

이는 LLM의 자가 치유 입력 (self-healing input) 능력을 보여주지만, 이를 전적으로 신뢰해서는 안 됩니다.

규칙: 도구는 오직 return해야 하며, 절대 raise해서는 안 됩니다. 예외(Exceptions)는 에이전트의 제어 흐름(control flow)을 벗어나기 때문에, LLM이 이를 처리할 기회를 갖지 못합니다. 반면 에러 문자열은 읽고, 이해하고, 조치를 취할 수 있습니다. LLM은 수정된 파라미터로 재시도하거나, 사용자에게 무엇이 잘못되었는지 알려주거나, 다른 접근 방식을 시도할 수 있습니다.

데모 3: 입도 (Granularity) — 비대한 도구 (Fat Tool) vs 세분화된 도구 (Fine-grained Tools)

비대한 도구 (Fat tool): 모든 것을 처리하며, 자유 텍스트 입력을 받습니다.

@lc_tool
def omnibus_lookup(query: str) -> str:
    """날씨, 제품 정보 조회 또는 수학 계산을 수행합니다. 사용자 질문 전체를 전달하세요."""
...

세분화된 도구 (Fine-grained tools): 타입이 지정된 파라미터를 가진 세 개의 별도 도구입니다.

네 가지 테스트 케이스:

단일 쿼리 (날씨, 제품): 두 방식 모두 작동하며, 유의미한 차이가 없습니다.

다단계 — 날씨 + 온도 차이:

Fat  tools=['omnibus_lookup', 'omnibus_lookup']
     → The temperature in Beijing is 25°C and Shanghai is 22°C. The difference is 3°C.

...

다단계 — 제품 가격 + 연간 계산:

Fat tools=['omnibus_lookup'] ← 단 한 번의 호출!
→ 월간 가격은 $299입니다. 연간 비용은 $3588입니다.

...

이 마지막 결과가 가장 흥미롭습니다: Fat 도구는 단 한 번만 호출되었고 정답을 얻었습니다. LLM은 omnibus_lookup의 응답 내에서 $299라는 가격을 찾아낸 뒤, 별도의 계산기 호출을 트리거하지 않고 암산(299×12=3588)을 수행했습니다.

Fat 도구가 항상 더 나쁜 것은 아닙 — 때로는 더 적은 호출로 작업을 완수하기도 합니다. 하지만 실행 경로가 불투명하고, 테스트가 불가능하며, 유지보수가 어렵습니다.

세분화된(Fine-grained) 도구를 사용해야 할 때와 병합(Merging)이 허용되는 때:

다음의 경우 세분화된 도구를 사용하세요:
  - 서로 다른 쿼리 유형에 따라 다른 도구가 트리거될 때
  - 매개변수(Parameter)가 명확한 의미론적 타입(semantic types)을 가질 때 (city: str, amount: float)
...

도구 설계를 위한 5가지 황금률 (Five Golden Rules for Tool Design)

원칙(Principle)        나쁜 예(Bad)                      좋은 예(Good)
──────────────────────────────────────────────────────────────────────
설명(Description)      "데이터 가져오기."               무엇을 + 언제 + 어떻게 + 매개변수 예시
...

황금률: 인간이 아닌 LLM을 위해 도구를 설계하세요.

LLM은 도구를 어떻게 호출할지 결정하기 위해 세 가지 정보를 사용합니다:

  1. Docstring (독스트링): 이 도구를 선택할지 여부를 결정합니다.
  2. Parameter types and names (매개변수 타입 및 이름): 어떤 값을 전달할지 결정합니다.
  3. Return value (반환 값): 다음에 무엇을 할지 결정합니다.

이 세 가지를 올바르게 설정하면, 추가적인 프롬프팅(prompting) 없이도 도구가 정확하게 사용될 것입니다.

설계 체크리스트 (Design Checklist)

Docstring (독스트링)

  • 첫 문장에 도구가 무엇을 하는지 명시 (동사로 시작)
  • 반환 값 형식 설명 (JSON / plain text / error string)
  • 사용 시점 명시 ("사용자가 ...에 대해 물을 때 이 도구를 사용하세요")
  • 매개변수 예시 제공 (e.g. 'Beijing', e.g. '299 * 12')

Error Handling (에러 처리)

  • 도구는 오직 return만 해야 하며, 절대 raise를 해서는 안 됩니다.
  • 에러 메시지에 실행 가능한 가이드 포함 ("찾을 수 없습니다. 사용 가능한 항목: [...]")
  • ["데이터가 존재하지 않음"과 "입력 형식이 잘못됨"을 구분하여 서로 다른 힌트 제공]

Granularity (세분성)

  • 파라미터 (Parameters)는 자유 형식의 텍스트가 아닌 구조화된 타입 (의미가 명확한 str, int, float)이어야 함
  • 하나의 도구는 한 가지 일만 수행해야 함 — 만약 설명에 "그리고 (and)" 또는 "또는 (or)"가 필요하다면 분리를 고려할 것
  • 도구들은 상호 배타적이어야 함: 서로 다른 쿼리가 서로 다른 도구를 트리거해야 함

반환 형식 (Return Format)

  • 성공 시: JSON 문자열 (LLM이 필드를 파싱하기 쉬움)
  • 실패 시: "Error: <이유>. <권장 조치>" 형식
  • None이나 빈 문자열을 절대 반환하지 말 것 — LLM은 그것들을 어떻게 처리해야 할지 알지 못함

요약 (Summary)

다섯 가지 핵심 요점:

  1. 다중 도구 경쟁에서는 설명의 품질이 중요함: 도구가 하나뿐일 때 LLM은 선택의 여지가 없지만, 도구가 많을 때는 잘 문서화된 도구가 선택을 받음
  2. 도구는 문자열을 반환해야 하며, 절대 예외(exception)를 발생시키지 말 것: 예외를 발생시키면 에이전트(agent)가 충돌(crash)하지만, 에러 문자열을 반환하면 LLM이 복구할 기회를 얻음
  3. LLM은 스스로 입력을 수정하는 능력이 있지만, 이에 의존하지 말 것: "Shanghia"가 "Shanghai"로 자동 수정되었으나, 이는 신뢰할 수 있는 방어 계층이 아님
  4. 비대한 도구(Fat tools)가 항상 나쁜 것은 아니지만, 불투명함: 실제 벤치마크 결과 비대한 도구가 두 단계의 작업을 한 번의 호출로 완료하는 것을 보여주었으나, 그 과정은 추적할 수 없고 테스트할 수 없음
  5. 파라미터 타입이 파라미터의 품질을 결정함: city: str (명확한 의미론)이 q: str (자유 형식 텍스트)보다 우수함 — 파라미터 타입이 명확할수록 LLM은 값을 더 정확하게 추출함

다음 단계: 고급 컨텍스트 엔지니어링 (Advanced Context Engineering) — 시스템 프롬프트 최적화, 퓨샷 (few-shot) 예시 선택, 동적 컨텍스트 주입을 통해 LLM에 전송되는 정보를 정밀하게 제어하는 방법을 다룹니다.

참고 문헌 (References)

PrimeSkills를 확인해 보세요 — 실제 기업급 워크플로 (enterprise-grade workflows)에서 검증된 AI 에이전트와 기술 (skills)을 엄선하여 제공하는 마켓플레이스입니다. 불필요한 내용은 빼고, 실제로 작동하는 것들만 담았습니다.

홈페이지에서 더 유용한 지식과 흥미로운 제품들을 찾아보세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0