Tool Search Tool: BM25 + Regex Dual-Engine Dynamic Loading for 10,000-Tool Libraries
Chapter 19: Tool Design Patterns: Parameter Schema, Description Optimization, and Type Constraints
19.1 Why Tool Design Matters
The quality of tool definitions directly determines how accurately Claude uses them. A vaguely described tool causes Claude to invoke it in inappropriate scenarios or pass incorrectly formatted parameters. Conversely, a carefully designed tool Schema enables Claude to make correct judgments in complex situations.
Tool design has three core objectives:
- Semantic clarity: Claude must accurately understand the tool's purpose and limitations from its name and description
- Complete parameter constraints: JSON Schema constraints maximize the reduction of invalid parameter inputs
- Error tolerance: Even if Claude passes slightly off-target parameters, the tool handles them gracefully
19.2 Best Practices for Tool Naming
Naming Conventions
Tool names should follow these rules:
# Good names: verb_noun format, semantically clear
good_names = [
"search_products",
"create_invoice",
"get_user_profile",
"update_order_status",
"send_notification",
"calculate_shipping",
]
# Poor names: vague or overly broad
bad_names = [
"process", # Process what?
"data", # Data operation?
"helper", # Help with what?
"do_thing", # Do what?
"api_call", # Which API?
]
Avoiding Name Conflicts
When multiple tools have similar functionality, names must reflect key differences:
tools_with_clear_scope = [
{
"name": "search_internal_knowledge_base",
"description": "Search the company's internal knowledge base for documents and FAQs. Contains only approved internal documents."
},
{
"name": "search_web",
"description": "Search publicly available information on the internet via a search engine. Results may include unverified content."
},
{
"name": "search_product_catalog",
"description": "Search the product catalog for merchandise information including prices, inventory, and specifications."
}
]
19.3 Optimization Strategies for the description Field
The description is the most overlooked yet most important part of tool design. It is not just human-readable documentation โ it is the primary basis Claude uses to decide whether to call a tool.
Five Elements of a Good Description
A good tool description should include:
- Core function: What the tool does
- Usage scenarios: When it should be used
- Output format: What data it returns
- Limitations: When it should NOT be used
- Differentiation from similar tools: If multiple related tools exist
tool_with_optimized_description = {
"name": "search_customer_database",
"description": """Search customer records in the CRM system.
[When to use]
- Need to find a specific customer's contact info, purchase history, or account status
- Need to filter customer groups by criteria (region, spend, registration date)
[Return data]
Returns a list of matching customer records. Each record contains:
customer_id, name, email, phone, registration_date, total_purchases, status
[Important limitations]
- Returns at most 100 records; use the limit parameter to control output size
- Does not include deleted accounts; use the search_deleted_customers tool for those
- Results are queried in real time, not cached
[Difference from search_orders]
This tool searches customer information; search_orders searches order information.
If both are needed, first use this tool to get customer_id, then pass it to search_orders.""",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"limit": {"type": "integer", "default": 20}
},
"required": ["query"]
}
}
Using Examples to Strengthen Descriptions
Including concrete examples in descriptions helps Claude understand parameter formats more precisely:
{
"name": "parse_date_range",
"description": """Parse a user-described date range and return start/end dates in standard format.
[Examples for date_expression parameter]
- "last week" โ {"start": "2026-04-21", "end": "2026-04-28"}
- "previous month" โ {"start": "2026-03-01", "end": "2026-03-31"}
- "Q1 2026" โ {"start": "2026-01-01", "end": "2026-03-31"}
- "this quarter" โ {"start": "2026-04-01", "end": "2026-06-30"}""",
"input_schema": {
"type": "object",
"properties": {
"date_expression": {
"type": "string",
"description": "Natural language date description from the user"
},
"reference_date": {
"type": "string",
"description": "Reference date in ISO 8601 format, used to resolve relative dates like 'yesterday'. Defaults to today."
}
},
"required": ["date_expression"]
}
}
19.4 Advanced Constraint Patterns in Parameter Schemas
Basic Type and Format Constraints
advanced_schema_examples = {
"type": "object",
"properties": {
# String format constraints
"email": {
"type": "string",
"format": "email",
"description": "User email address"
},
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Date in YYYY-MM-DD format"
},
"phone": {
"type": "string",
"pattern": "^\\+?[1-9]\\d{6,14}$",
"description": "Phone number in international format"
},
# Numeric range constraints
"page_size": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20,
"description": "Pagination size"
},
"discount_rate": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Discount rate: 0.1 means 10% off"
},
# Enum constraints
"order_status": {
"type": "string",
"enum": ["pending", "processing", "shipped", "delivered", "cancelled"],
"description": "Order status"
},
# Array constraints
"tags": {
"type": "array",
"items": {"type": "string"},
"minItems": 1,
"maxItems": 10,
"uniqueItems": True,
"description": "Tag list: 1-10 unique tags"
},
# String length constraints
"title": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Title, no more than 200 characters"
}
}
}
Nested Object Schemas
nested_schema = {
"name": "create_shipping_order",
"description": "Create a shipping order",
"input_schema": {
"type": "object",
"properties": {
"sender": {
"type": "object",
"description": "Sender information",
"properties": {
"name": {"type": "string"},
"phone": {"type": "string"},
"address": {
"type": "object",
"properties": {
"city": {"type": "string"},
"state": {"type": "string"},
"street": {"type": "string"},
"postal_code": {"type": "string", "pattern": "^\\d{5}(-\\d{4})?$"}
},
"required": ["city", "state", "street"]
}
},
"required": ["name", "phone", "address"]
},
"recipient": {
"type": "object",
"description": "Recipient information (same structure as sender)",
"properties": {
"name": {"type": "string"},
"phone": {"type": "string"},
"address": {
"type": "object",
"properties": {
"city": {"type": "string"},
"state": {"type": "string"},
"street": {"type": "string"},
"postal_code": {"type": "string"}
},
"required": ["city", "state", "street"]
}
},
"required": ["name", "phone", "address"]
},
"package": {
"type": "object",
"properties": {
"weight_kg": {"type": "number", "minimum": 0.1, "maximum": 50},
"dimensions": {
"type": "object",
"properties": {
"length_cm": {"type": "number"},
"width_cm": {"type": "number"},
"height_cm": {"type": "number"}
}
},
"declared_value": {"type": "number", "minimum": 0}
},
"required": ["weight_kg"]
}
},
"required": ["sender", "recipient", "package"]
}
}
Conditional Schemas with if/then
For complex scenarios where parameter format depends on other parameters:
conditional_schema = {
"name": "send_message",
"description": "Send a message through different channels",
"input_schema": {
"type": "object",
"properties": {
"channel": {
"type": "string",
"enum": ["email", "sms", "push"],
"description": "Delivery channel"
},
"recipient": {
"type": "string",
"description": "Recipient: email address for email, phone number for SMS, user ID for push"
},
"content": {
"type": "string",
"description": "Message content. SMS max 160 chars; email supports HTML."
},
"subject": {
"type": "string",
"description": "Email subject (required only when channel=email)"
}
},
"required": ["channel", "recipient", "content"],
"if": {
"properties": {"channel": {"const": "email"}}
},
"then": {
"required": ["subject"]
}
}
}
19.5 Tips for Optimizing Parameter Descriptions
Common Mistakes in Parameter Descriptions
# Poor: description too simple
bad_parameter = {
"query": {
"type": "string",
"description": "Query string" # Too vague; Claude doesn't know format requirements
}
}
# Good: specific and complete description
good_parameter = {
"query": {
"type": "string",
"description": """Search keywords. Supports the following syntax:
- Plain keywords: enter directly, e.g. "iPhone 14"
- Exact match: wrap in quotes, e.g. '"apple phone"'
- Exclude terms: use minus prefix, e.g. "phone -used"
- Field search: use colon separator, e.g. "brand:apple"
Maximum 500 characters.""",
"maxLength": 500
}
}
Using Descriptions to Guide Parameter Selection
smart_defaults_tool = {
"name": "export_report",
"description": "Export a data report",
"input_schema": {
"type": "object",
"properties": {
"format": {
"type": "string",
"enum": ["pdf", "excel", "csv", "json"],
"description": "Export format. Default to pdf (best for viewing) when unspecified. Choose csv or excel if the user says they want to 'process data' or 'import into a system'.",
"default": "pdf"
},
"date_range": {
"type": "string",
"enum": ["today", "week", "month", "quarter", "year", "custom"],
"description": "Time range. Default to month (last 30 days) when unspecified.",
"default": "month"
}
},
"required": ["format"]
}
}
19.6 Tool Group Design Patterns
Pattern 1: CRUD Tool Group
CRUD operations on the same resource should maintain consistent naming and parameter styles:
user_crud_tools = [
{
"name": "get_user",
"description": "Get full information for a single user by ID",
"input_schema": {
"type": "object",
"properties": {
"user_id": {"type": "string", "description": "User ID"}
},
"required": ["user_id"]
}
},
{
"name": "list_users",
"description": "List users with pagination and filtering support",
"input_schema": {
"type": "object",
"properties": {
"page": {"type": "integer", "minimum": 1, "default": 1},
"page_size": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20},
"status": {"type": "string", "enum": ["active", "inactive", "all"], "default": "active"},
"search": {"type": "string", "description": "Search by name or email"}
}
}
},
{
"name": "create_user",
"description": "Create a new user account",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1, "maxLength": 100},
"email": {"type": "string", "format": "email"},
"role": {"type": "string", "enum": ["admin", "editor", "viewer"], "default": "viewer"},
"send_welcome_email": {"type": "boolean", "default": True}
},
"required": ["name", "email"]
}
},
{
"name": "update_user",
"description": "Update user information. Only pass the fields that need to be changed.",
"input_schema": {
"type": "object",
"properties": {
"user_id": {"type": "string", "description": "ID of the user to update"},
"name": {"type": "string", "minLength": 1, "maxLength": 100},
"email": {"type": "string", "format": "email"},
"role": {"type": "string", "enum": ["admin", "editor", "viewer"]},
"status": {"type": "string", "enum": ["active", "inactive"]}
},
"required": ["user_id"]
}
}
]
Pattern 2: Pipeline Tool Group
Tools with a clear dependency ordering:
pipeline_tools = [
{
"name": "upload_file",
"description": "Upload a file; returns a file ID. This is the first step in file processing.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {"type": "string", "description": "Local file path"},
"file_type": {"type": "string", "enum": ["csv", "excel", "json", "xml"]}
},
"required": ["file_path", "file_type"]
}
},
{
"name": "validate_file",
"description": "Validate the format and data integrity of an uploaded file. Requires a file_id from upload_file.",
"input_schema": {
"type": "object",
"properties": {
"file_id": {"type": "string", "description": "File ID returned by upload_file"},
"schema_id": {"type": "string", "description": "Schema ID for validation (optional)"}
},
"required": ["file_id"]
}
},
{
"name": "import_file",
"description": "Import a validated file into the database. Must pass validate_file first.",
"input_schema": {
"type": "object",
"properties": {
"file_id": {"type": "string"},
"target_table": {"type": "string"},
"conflict_strategy": {
"type": "string",
"enum": ["skip", "overwrite", "append"],
"default": "skip"
}
},
"required": ["file_id", "target_table"]
}
}
]
19.7 Using Tools for Structured Output
An important use case of Tool Use is forcing Claude to produce structured data rather than free-form text:
extraction_tool = {
"name": "extract_invoice_data",
"description": "Extract structured data from invoice text",
"input_schema": {
"type": "object",
"properties": {
"invoice_number": {"type": "string"},
"invoice_date": {"type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$"},
"vendor_name": {"type": "string"},
"total_amount": {"type": "number"},
"tax_amount": {"type": "number"},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {"type": "string"},
"quantity": {"type": "number"},
"unit_price": {"type": "number"},
"total": {"type": "number"}
},
"required": ["description", "quantity", "unit_price", "total"]
}
}
},
"required": ["invoice_number", "invoice_date", "vendor_name", "total_amount"]
}
}
def extract_invoice(invoice_text: str) -> dict:
"""Extract structured data from invoice text"""
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
tools=[extraction_tool],
tool_choice={"type": "tool", "name": "extract_invoice_data"},
messages=[{
"role": "user",
"content": f"Please extract data from this invoice:\n\n{invoice_text}"
}]
)
for block in response.content:
if block.type == "tool_use":
return block.input
raise ValueError("Failed to extract invoice data")
19.8 Tool Versioning and Backward Compatibility
As systems evolve, tool Schemas need to be updated. Here is a strategy for maintaining backward compatibility:
# Version 1: only query parameter
tool_v1 = {
"name": "search_products",
"description": "Search products (v1)",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"}
},
"required": ["query"]
}
}
# Version 2: add new parameters; query remains required, new params have defaults
tool_v2 = {
"name": "search_products",
"description": "Search products with category filtering and price range (v2)",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"category": {
"type": "string",
"description": "Product category (optional; omit to search all categories)"
},
"min_price": {
"type": "number",
"description": "Minimum price filter (optional)"
},
"max_price": {
"type": "number",
"description": "Maximum price filter (optional)"
}
},
"required": ["query"] # Only original required parameters
}
}
Summary
High-quality tool design is the foundation of a successful Tool Use system. The core principles are:
- Naming conveys the tool's action and target object without ambiguity
- Description includes usage scenarios, output format, limitations, and differentiation from similar tools
- Schema uses type constraints, enums, and range limits to maximize the reduction of invalid parameter inputs
- Tool groups maintain consistent parameter naming conventions and structural styles
- Structured output scenarios should prefer the
tool_choice: toolpattern
The next chapter explores how to have Claude call multiple tools simultaneously, achieving an efficient parallel processing architecture.