Tool Input Validation and Error Handling

Validate Before You Trust

Do not assume the LLM will pass correct parameters to your tools. Always validate.

Step 1: Validate Parameter Types

Check that parameters are the right type (string, integer, etc.).

def search_web(query, num_results=5):
  # Validate query is a string
  if not isinstance(query, str):
    return {"error": "Parameter 'query' must be a string. You provided: " + str(type(query))}
  
  # Validate num_results is an integer
  if not isinstance(num_results, int):
    return {"error": "Parameter 'num_results' must be an integer. You provided: " + str(num_results)}
  
  # Validate num_results is in range
  if num_results < 1 or num_results > 10:
    return {"error": "Parameter 'num_results' must be between 1 and 10. You provided: " + str(num_results)}
  
  # Now proceed
  return do_search(query, num_results)

Step 2: Validate Parameter Values

Check that parameters make sense.

def fetch_page(url):
  # Validate URL format
  if not url.startswith("http"):
    return {"error": "Parameter 'url' must start with http:// or https://. You provided: " + url}
  
  # Validate URL length
  if len(url) > 2048:
    return {"error": "Parameter 'url' is too long (max 2048 characters)"}
  
  # Now proceed
  return do_fetch(url)

Step 3: Return Helpful Error Messages

When validation fails, tell the LLM what went wrong and how to fix it.

Bad error message:

return {"error": "Invalid input"}

Good error message:

return {
  "error": "Parameter 'num_results' must be an integer between 1 and 10. You provided: 25. Please retry with a value like 5 or 10."
}

The good message tells the LLM:

  • What parameter is wrong
  • What the valid range is
  • What you provided
  • An example of a correct value

Step 4: Handle Tool Failures

If the underlying operation fails (API down, network error, etc.), handle it gracefully.

def search_web(query):
  try:
    result = call_search_api(query)
    return result
  except ConnectionError as e:
    return {"error": "Could not connect to search service. The service may be down. Please try again in a few seconds."}
  except TimeoutError as e:
    return {"error": "Search request timed out. Try a simpler query with fewer words."}
  except Exception as e:
    return {"error": f"Unexpected error: {str(e)}"}

Step 5: Return Structured Results

Always return results in a predictable format. The LLM expects this.

Bad result format:

"Result: Some text that looks different every time"

Good result format:

{
  "status": "success",
  "query": "what I searched for",
  "results": [
    {"title": "...", "snippet": "...", "url": "..."}
  ],
  "total_results": 42
}

Structured results are easier for the LLM to parse and understand.

Example: Complete Tool with Validation

def fetch_webpage(url, max_length=5000):
  """Fetch the full text of a webpage.
  
  Args:
    url: The URL to fetch (required)
    max_length: Maximum characters to return (optional, default: 5000)
  
  Returns:
    Dict with 'status', 'title', 'text', 'length'
    Or dict with 'error' if something goes wrong
  """
  
  # Validate url
  if not isinstance(url, str):
    return {"error": f"Parameter 'url' must be a string, not {type(url).__name__}"}
  
  if not url.startswith(("http://", "https://")):
    return {"error": f"Parameter 'url' must start with http:// or https://. You provided: {url}"}
  
  # Validate max_length
  if not isinstance(max_length, int):
    return {"error": f"Parameter 'max_length' must be an integer, not {type(max_length).__name__}"}
  
  if max_length < 100 or max_length > 50000:
    return {"error": f"Parameter 'max_length' must be between 100 and 50000. You provided: {max_length}"}
  
  # Try to fetch
  try:
    page_text = call_fetch_api(url)
    
    if page_text is None:
      return {"error": f"Could not fetch {url}. The page may not exist or may be blocked."}
    
    # Truncate if too long
    if len(page_text) > max_length:
      page_text = page_text[:max_length] + "...[truncated]"
    
    return {
      "status": "success",
      "url": url,
      "text": page_text,
      "length": len(page_text)
    }
  
  except Exception as e:
    return {"error": f"Error fetching {url}: {str(e)}"}

Validation Checklist

  • Check parameter types (string, int, etc.)
  • Check parameter values (length, range, format)
  • Return helpful error messages
  • Handle API failures gracefully
  • Return results in a consistent format
  • Test with invalid inputs
  • Document what parameters are required

Key Principle

Do not trust the LLM to get parameters right. Validate everything. Return clear error messages. The LLM will use these errors to recover and retry.

Discussion

  • Loading…

← Back to Tutorials