mantis
reference

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 @tool with 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_safeFalse if this tool shouldn't run concurrently with other tools. Default True.

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 = True

You 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.