Use this file to discover all available pages before exploring further.
The @function_tool decorator is the quickest path from a plain Python function to a QitOS tool. It inspects your function’s signature, type hints, and docstring, then builds a complete FunctionTool instance with an enriched ToolSpec — no subclassing required.
Step 4: Registering function tools in ToolRegistry
Once you have a FunctionTool, register it with a ToolRegistry so agents can discover and call it:
from qitos import ToolRegistry, function_tool@function_tool(read_only=True)def lookup_user(user_id: str) -> dict: """Look up a user by ID.""" return {"id": user_id, "name": "Alice"}registry = ToolRegistry()registry.register(lookup_user)# The tool is now available by namedescriptions = registry.get_tool_descriptions()
You can also register multiple tools at once and override names:
@function_tooldef create_user(name: str) -> dict: """Create a new user.""" return {"name": name}@function_tooldef delete_user(user_id: str) -> dict: """Delete a user by ID.""" return {"deleted": user_id}registry.register(create_user)registry.register(delete_user, name="remove_user")
Step 5: Comparing @function_tool with class-based BaseTool
QitOS offers two ways to define tools. Use the one that fits your needs:@function_tool — best for simple, stateless operations:
from qitos import function_tool@function_tool(read_only=True)def get_time() -> str: """Return the current time.""" from datetime import datetime return datetime.now().isoformat()
BaseTool subclass — best for stateful tools or complex initialization:
from qitos import BaseTool, ToolSpec, ToolMetaclass GetTimeTool(BaseTool): def __init__(self): meta = ToolMeta(name="get_time", read_only=True) spec = ToolSpec( name="get_time", description="Return the current time.", parameters={}, required=[], ) super().__init__(spec) def execute(self, **kwargs) -> str: from datetime import datetime return datetime.now().isoformat()
When to choose which:
Concern
@function_tool
BaseTool subclass
Simple functions
Best fit
Overkill
State or config in __init__
Not supported
Supported
Custom execute logic
N/A
Full control
Auto schema from signature
Automatic
Manual
Boilerplate
Minimal
More
Most tools are simple functions. Start with @function_tool and reach for BaseTool only when you need constructor state or custom execution behavior.