backend/core/utils/TOOL_AUTO_GENERATION.md
The tool discovery system automatically generates human-readable metadata when decorators are not provided. This ensures tools work out-of-the-box without requiring manual configuration.
Logic:
Examples:
| Class Name | Generated Display Name |
|---|---|
SandboxFilesTool | Sandbox Files |
sb_shell_tool | Sb Shell |
MessageTool | Message |
BrowserTool | Browser |
sb_image_edit_tool | Sb Image Edit |
Code Location: tool_discovery.py:_generate_display_name()
def _generate_display_name(self, name: str) -> str:
# Remove "Tool" suffix
if name.endswith('_tool'): name = name[:-5]
if name.endswith('Tool'): name = name[:-4]
# CamelCase: "SandboxFiles" -> "Sandbox Files"
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1 \2', name)
s2 = re.sub('([a-z0-9])([A-Z])', r'\1 \2', s1)
# snake_case: "sandbox_files" -> "sandbox files"
s3 = s2.replace('_', ' ')
# Title case: "sandbox files" -> "Sandbox Files"
return s3.title()
@tool_metadata(description=...) decorator (if provided)"{ClassName} functionality"Examples:
# Option 1: Using decorator (RECOMMENDED)
@tool_metadata(
display_name="File Operations",
description="Create, read, edit, and manage files in the workspace"
)
class SandboxFilesTool(Tool):
pass
# Option 2: Using class docstring (AUTOMATIC)
class SandboxFilesTool(Tool):
"""Create, read, edit, and manage files in the workspace"""
pass
# Option 3: No decorator, no docstring (FALLBACK)
class SandboxFilesTool(Tool):
pass
# Auto-generates: "SandboxFilesTool functionality"
Code Location: tool_discovery.py:_extract_tool_metadata()
if tool_metadata:
# Use decorator
metadata["description"] = tool_metadata.description
else:
# Use docstring or fallback
metadata["description"] = (
tool_class.__doc__.strip()
if tool_class.__doc__
else f"{tool_class.__name__} functionality"
)
Logic: Same as tool names (snake_case → Title Case)
Examples:
| Method Name | Generated Display Name |
|---|---|
create_file | Create File |
str_replace | Str Replace |
execute_command | Execute Command |
browser_navigate_to | Browser Navigate To |
web_search | Web Search |
@method_metadata(description=...) decorator (if provided)@openapi_schema description (from function.description field)"{method_name} function"Examples:
# Option 1: Using method_metadata decorator (RECOMMENDED)
@method_metadata(
display_name="Create File",
description="Create new files with content"
)
@openapi_schema({...})
def create_file(self, path: str, content: str):
pass
# Option 2: Using openapi_schema description (AUTOMATIC)
@openapi_schema({
"type": "function",
"function": {
"name": "create_file",
"description": "Create a new file at the specified path", # <-- Used here
"parameters": {...}
}
})
def create_file(self, path: str, content: str):
pass
# Option 3: No decorators (FALLBACK)
@openapi_schema({...})
def create_file(self, path: str, content: str):
pass
# Auto-generates: "create_file function"
Code Location: tool_discovery.py:_extract_tool_metadata()
if method_name in method_metadata:
# Use @method_metadata decorator
method_info["description"] = method_metadata[method_name].description
else:
# Try to extract from @openapi_schema
if schemas[method_name]:
schema = schemas[method_name][0].schema
if 'function' in schema and 'description' in schema['function']:
method_info["description"] = schema['function']['description']
else:
method_info["description"] = f"{method_name} function"
Default Behavior: Not auto-generated (optional fields)
If not provided via @tool_metadata, these fields are None:
icon: Default icon used in UI (e.g., Wrench)color: Default styling appliedTo specify:
@tool_metadata(
display_name="File Operations",
description="Manage files",
icon="FolderOpen", # Lucide icon name
color="bg-blue-100 dark:bg-blue-800/50" # Tailwind classes
)
Default: 100 (if not specified)
Lower weight = Higher priority in UI sorting
Recommended Ranges:
10-2030-5060-8090-100+Example:
@tool_metadata(
display_name="File Operations",
description="Manage files",
weight=20 # High priority - shows near top
)
class SandboxFilesTool(Tool):
pass
@tool_metadata(
display_name="Advanced Analytics",
description="Complex data analysis",
weight=95 # Lower priority - shows near bottom
)
class AdvancedAnalyticsTool(Tool):
pass
Frontend Sorting:
import { sortToolsByWeight } from './tool-groups';
const sortedTools = sortToolsByWeight(toolsData);
// Returns tools ordered by weight (ascending)
Default: is_core = False
Core tools cannot be disabled in the UI.
To mark as core:
@tool_metadata(
display_name="Message Tool",
description="User communication",
is_core=True # Cannot be disabled
)
class MessageTool(Tool):
pass
Core Methods:
@method_metadata(
display_name="Ask Question",
description="Ask user questions",
is_core=True # This method is always enabled
)
def ask(self, question: str):
pass
Default:
visible = False (tools hidden by default)visible = True (methods visible by default)Controls whether a tool/method is shown in the frontend UI.
Use Cases:
False for internal/system toolsFalse for deprecated featuresFalse for tools that should only be used programmaticallyFalse for beta features not ready for general useTool Level:
@tool_metadata(
display_name="Internal System Tool",
description="Internal functionality not shown to users",
visible=False # Hidden from UI
)
class InternalTool(Tool):
pass
@tool_metadata(
display_name="File Operations",
description="Standard file operations",
visible=True # Visible in UI (this is the default)
)
class SandboxFilesTool(Tool):
pass
Method Level:
class SandboxFilesTool(Tool):
@method_metadata(
display_name="Create File",
description="Create new files",
visible=True # Visible in UI (default)
)
def create_file(self, path: str):
pass
@method_metadata(
display_name="Internal Helper",
description="Internal method not shown in UI",
visible=False # Hidden from UI
)
def internal_helper(self, path: str):
pass
Difference from is_core:
is_core=True: Always visible AND cannot be disabledvisible=False: Hidden from UI entirely (users never see it)from core.agentpress.tool import Tool, tool_metadata, method_metadata, openapi_schema
# Full manual control (BEST for production)
@tool_metadata(
display_name="File Operations",
description="Create, read, edit, and manage files in your workspace",
icon="FolderOpen",
color="bg-blue-100 dark:bg-blue-800/50",
is_core=False,
weight=20, # Show near top
visible=True # Visible in UI (default)
)
class SandboxFilesTool(Tool):
@method_metadata(
display_name="Create File",
description="Create a new file with specified content",
is_core=False,
visible=True # Visible in UI (default)
)
@openapi_schema({
"type": "function",
"function": {
"name": "create_file",
"description": "Create a new file at the given path",
"parameters": {...}
}
})
def create_file(self, path: str, content: str):
return self.success_response("File created!")
# This method auto-generates display name & description from schema
@openapi_schema({
"type": "function",
"function": {
"name": "delete_file",
"description": "Delete a file from the workspace", # <-- Auto-used
"parameters": {...}
}
})
def delete_file(self, path: str):
return self.success_response("File deleted!")
# Internal helper method - hidden from UI
@method_metadata(
display_name="Internal Validation",
description="Internal validation logic not shown to users",
visible=False # Hidden from UI
)
@openapi_schema({...})
def _internal_validate(self, path: str):
return self.success_response("Validated!")
Generated Metadata:
{
"name": "sb_files_tool",
"display_name": "File Operations",
"description": "Create, read, edit, and manage files in your workspace",
"icon": "FolderOpen",
"color": "bg-blue-100 dark:bg-blue-800/50",
"is_core": false,
"weight": 20,
"visible": true,
"methods": [
{
"name": "create_file",
"display_name": "Create File",
"description": "Create a new file with specified content",
"is_core": false,
"visible": true
},
{
"name": "delete_file",
"display_name": "Delete File", // Auto-generated from method name
"description": "Delete a file from the workspace", // From schema
"is_core": false,
"visible": true // Auto-default
},
{
"name": "_internal_validate",
"display_name": "Internal Validation",
"description": "Internal validation logic not shown to users",
"is_core": false,
"visible": false // Hidden from UI
}
]
}
Use @tool_metadata for all public tools
@tool_metadata(display_name="...", description="...", weight=20)
Use @method_metadata for important methods
@method_metadata(display_name="...", description="...")
Put good descriptions in @openapi_schema
@openapi_schema({
"function": {"description": "Clear, helpful description"}
})
Use class docstrings as fallback
class MyTool(Tool):
"""This is a good description"""
| Field | Source 1 (Best) | Source 2 (Good) | Source 3 (Fallback) |
|---|---|---|---|
| Tool Name | @tool_metadata(display_name=...) | - | Auto from class name |
| Tool Description | @tool_metadata(description=...) | Class docstring | "{ClassName} functionality" |
| Tool Icon | @tool_metadata(icon=...) | - | None (UI default) |
| Tool Color | @tool_metadata(color=...) | - | None (UI default) |
| Tool Weight | @tool_metadata(weight=...) | - | 100 |
| Tool Visible | @tool_metadata(visible=...) | - | True |
| Tool is_core | @tool_metadata(is_core=True) | - | False |
| Method Name | @method_metadata(display_name=...) | - | Auto from method name |
| Method Description | @method_metadata(description=...) | @openapi_schema description | "{method_name} function" |
| Method Visible | @method_metadata(visible=...) | - | True |
| Method is_core | @method_metadata(is_core=True) | - | False |
The system gracefully degrades - even without ANY decorators, tools still work with auto-generated names! 🎉