Tools

Tools let an agent act during a conversation: search the web, query your document libraries, call your workspace connectors, or run your own functions. Pass them to init(), or save them on an agent. Server-side tools run on Mistral's side. Client-side tools run your own handler in your code, and send the result back to the model.

Server-side tools

Server-side tools

Server-side tools are the built-in agent tools and your workspace connectors. Connectors that need authentication must already be authenticated in your workspace: the agent then uses them on your behalf.

ToolWhat it doesDictionary form
WebSearchToolSearches the web{"type": "web_search"}
DocumentLibraryToolQueries your document libraries{"type": "document_library", "library_ids": ["id1", ...]}
ConnectorToolCalls a workspace connector{"type": "connector", "connector_id": "my-connector"}
from mistralai.client.models import WebSearchTool

tools = [
    WebSearchTool(),
    {"type": "document_library", "library_ids": ["my-lib-id"]},
    {"type": "connector", "connector_id": "my_connector"},
]
Client-side tools

Client-side tools

Client-side tools expose your own functions to the agent. The SDK sends the declaration (name, description, and parameters) so the model knows the tool exists. When the model calls it, the SDK runs your handler in your code and returns the result to the model, which continues the conversation. Use them for data or actions that only your app has: the current state of the interface, the user's location, or an authenticated call to your backend.

In Python, the @function_tool decorator builds the parameter schema from the type hints and the description from the docstring. In TypeScript, functionTool takes a zod schema, and the handler's argument type comes from it.

from mistralai.extra.voice_agents import function_tool

@function_tool
def get_weather(city: str) -> dict:
    """Return the current weather for a city."""
    return {"city": city, "temp_c": 21}

session = await client.audio.sessions.init(
    llm={"model": "mistral-small-latest"},
    tts={"voice_id": "gb_oliver_excited"},
    tools=[get_weather],
)

In Python, pass name and description to override the defaults:

@function_tool(name="getWeather", description="Weather for a city.")
async def get_weather(city: str) -> dict: ...

The handler can be synchronous or asynchronous, and can return a value for the model to use.

Note

Handlers run on the same event loop that streams the audio. Make any handler that does I/O asynchronous, so the conversation doesn't stall. In the browser, client tools work slightly differently: see Client-side tools in the browser.

Save client tools on an agent

Save client tools on an agent

You can store client tools on a saved agent by passing the same tool object to audio.agents.create. Only the declaration is saved: the handler is code in your app and is never stored. When you start a session from that agent, pass the tool to init() again to attach the handler. The SDK matches it by name.

# Persist the declaration on the agent
agent = await client.audio.agents.create(
    name="Weather bot",
    configuration={
        "llm": {"model": "mistral-small-latest"},
        "tts": {"voice_id": "gb_oliver_excited"},
        "tools": [get_weather],
    },
)

# Re-attach the handler when connecting
session = await client.audio.sessions.init(agent_id=agent.id, tools=[get_weather])
Unhandled tools

Unhandled tools

A saved agent can declare a client tool that the current app doesn't implement. When the model calls it, the SDK emits an unhandled_tool event and reports the call as failed to the agent, so the conversation doesn't hang.

session.on("unhandled_tool", lambda e: print(f"no handler for {e.name}"))
Warning

Client tools only work where your code runs. If you launch the same agent from a surface that can't register handlers, such as a phone call or a test in the dashboard, its client tools fail when the model calls them. Use server-side tools for anything that must work everywhere.

Fillers

Fillers

A tool call can take a moment, and silence feels awkward in a conversation. Attach a filler to any tool, server-side or client-side: the agent plays a short clip when the call starts and stops it as soon as the result arrives. The clip is text, spoken in the agent's voice. The SDK prepares fillers when the session connects, so the first call isn't delayed. A tool without a filler stays silent. The user can talk over a filler, like any other speech from the agent. Fillers pair well with the tool_call_started and tool_call_ended session events.

from mistralai.client.models import WebSearchTool
from mistralai.extra.voice_agents import StaticToolFiller, function_tool

# Text filler on a server-side tool — synthesized in the agent's voice.
web_search = WebSearchTool(filler=StaticToolFiller(text="Searching the web…"))

# Text filler on a client-side tool.
@function_tool(filler=StaticToolFiller(text="Checking your order…"))
def check_order(order_id: str) -> dict:
    """Look up an order's delivery status."""
    return lookup(order_id)
Going further

Going further