Documentation Index
Fetch the complete documentation index at: https://docs.upsonic.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Combine different types of tools in a single task.
Usage
from upsonic import Agent, Task
from upsonic.tools import tool, ToolKit
# Function tool
@tool
def fetch_data(source: str) -> str:
"""Fetch data from source."""
return f"Data from {source}"
# ToolKit
class DataProcessor(ToolKit):
@tool
def transform(self, data: str) -> str:
"""Transform data."""
return data.upper()
@tool
def validate(self, data: str) -> bool:
"""Validate data."""
return len(data) > 0
# Specialized agent
analyzer_agent = Agent(
name="Data Analyzer",
model="anthropic/claude-sonnet-4-5",
system_prompt="Analyze data patterns"
)
# Combine all tools
task = Task(
description="Fetch, process, validate, and analyze data",
tools=[
fetch_data,
DataProcessor(),
analyzer_agent
]
)
agent = Agent(model="anthropic/claude-sonnet-4-5", name="Main Agent")
result = agent.print_do(task)
print("Result:", result)
The tools list accepts any combination of:
| Type | Example | Registered As |
|---|
| Function tool | @tool decorated function | Function name |
| ToolKit instance | DataProcessor() | All @tool methods |
| Class instance | Calculator() | All public methods |
| Agent instance | analyzer_agent | ask_{agent_name} |
| MCP Handler | MCPHandler(...) | All MCP-provided tools |
| KnowledgeBase | KnowledgeBase(...) | search_{kb_name} |
| Builtin tools | WebSearchTool() | Provider-specific |
Deduplication
When combining tools, duplicate registrations are automatically ignored:
from upsonic.tools import tool
@tool
def shared_tool(x: int) -> int:
"""A tool used by multiple tasks."""
return x * 2
# Adding the same tool multiple times is safe
task = Task(
description="Process data",
tools=[shared_tool, shared_tool, DataProcessor()] # shared_tool registered once
)
If multiple tools have the same name, the last one registered wins:
class Kit1(ToolKit):
@tool
def process(self, x: str) -> str:
"""Process from Kit1."""
return f"kit1: {x}"
class Kit2(ToolKit):
@tool
def process(self, x: str) -> str:
"""Process from Kit2."""
return f"kit2: {x}"
# Warning: Both have 'process' - Kit2's version overwrites Kit1's
task = Task(tools=[Kit1(), Kit2()]) # Only Kit2.process is available
Solution: Use unique method names or separate tasks.
Best Practices
- Group related tools: Combine tools that work together for a task
- Avoid name conflicts: Use unique, descriptive tool names
- Consider performance: More tools = more tokens in the prompt
- Remove unused tools: Keep the tool set focused for better agent performance
# Good: Focused tool set for a specific task
task = Task(
description="Analyze sales data and create a report",
tools=[database_tools, chart_generator, report_writer]
)
# Avoid: Too many unrelated tools
task = Task(
description="Analyze sales data",
tools=[database_tools, email_tools, calendar_tools,
chart_generator, weather_api, translation_tools] # Unfocused
)