Tools API
@tool
def tool(
fn: Callable | None = None,
*,
name: str | None = None,
description: str | None = None,
parallel_safe: bool = True,
) -> Tool | Callable: ...Decorate an async function to turn it into a Tool.
Arguments
fn— the async function being decorated. Filled in automatically when used as@toolwith no arguments.name— override the tool name (defaults to the function name).description— override the tool description (defaults to the docstring's first paragraph).parallel_safe—Falseif this tool shouldn't run concurrently with other tools. DefaultTrue.
Usage
@tool
async def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"{city}: 67°F"
@tool(name="my_renamed", parallel_safe=False)
async def get_weather_v2(city: str) -> str:
"""Get the current weather for a city."""
return ...Tool (dataclass)
The object the decorator returns:
@dataclass
class Tool:
name: str
description: str
input_schema: dict # JSON schema derived from the signature
handler: Callable # the async function
parallel_safe: bool = TrueYou can construct one manually if you don't want the decorator:
from mantis_agent import Tool
my_tool = Tool(
name="lookup_user",
description="Look up a user by id",
input_schema={
"type": "object",
"properties": {"user_id": {"type": "string"}},
"required": ["user_id"],
},
handler=lookup_user_impl,
)ToolRegistry
The runtime stores tools in a ToolRegistry. You rarely touch it
directly — pass tools via options.tools instead — but it's useful if
you're composing dynamic tool sets:
from mantis_agent import ToolRegistry
reg = ToolRegistry()
reg.add(get_weather)
reg.add_many([get_forecast, list_cities])
options = {"tools": reg.list()}Built-in tools
WebSearch
class WebSearch:
def __init__(self, num_results: int = 5, api_key: str | None = None): ...Backed by Exa. Reads EXA_API_KEY from env if api_key isn't passed.
Returns top-N URLs with titles and snippets.
from mantis_agent import WebSearch
options = {"tools": [WebSearch(num_results=10)]}WebFetch
class WebFetch:
def __init__(self, max_chars: int = 50_000): ...Fetches a URL and converts to clean markdown. Truncates at
max_chars to fit in context.
from mantis_agent import WebFetch
options = {"tools": [WebFetch()]}Functional forms
If you prefer functions over classes:
from mantis_agent import web_fetch, web_search
options = {"tools": [web_search, web_fetch]}These are pre-instantiated default versions of the classes above.
Tool errors
from mantis_agent import ToolExecutionError
@tool
async def query_db(sql: str) -> str:
if not _has_auth():
raise ToolExecutionError("Database auth missing", fatal=True)fatal=True raises out of the agent loop. fatal=False (default) is
caught and threaded back to the model as a tool result with
is_error=True.