Tools
Tools let the model call your Python functions during a voice session. Register an async (or sync) function with @tools.action(...), pass the Tools instance to RealtimeAgent, and the model will invoke it when appropriate.
Basic registration
from typing import Annotated
from rtvoice import Tools
tools = Tools()
@tools.action("Get the current weather for a given city")
async def get_weather(city: Annotated[str, "The city name"]) -> str:
return f"It is sunny and 22°C in {city}."
Pass the description as the first argument — write it as a natural-language instruction so the model knows when to call the tool.
Parameter descriptions are read from Annotated type hints and included in the schema sent to the model.
Passing tools to the agent
from rtvoice import RealtimeAgent
agent = RealtimeAgent(
instructions="Answer weather questions using get_weather.",
tools=tools,
)
await agent.run()
Decorator options
@tools.action(
"Search the knowledge base for relevant articles",
name="search_kb", # override the tool name (default: function name)
result_instruction="Summarise the top result in one sentence.",
is_long_running=True, # enables a holding phrase while the tool runs
holding_instruction="Let me search for that…",
)
async def search_knowledge_base(query: str) -> str: ...
| Parameter | Description |
|---|---|
description |
Natural-language instruction shown to the model (required). |
name |
Override the tool name. Defaults to the function name. |
result_instruction |
Appended to the tool result to guide how the model presents it. |
is_long_running |
Set True for tools that take more than ~1 s. The assistant speaks a holding phrase while waiting. |
holding_instruction |
What the assistant says while the tool is running. Requires is_long_running=True. |
Auto-injected parameters
Some parameters are injected automatically by the framework — never include them in the model-facing schema, and annotate them with their exact Python type so the injector recognises them:
| Parameter name | Type | Injected value |
|---|---|---|
event_bus |
EventBus |
The session-scoped event bus |
conversation_history |
ConversationHistory |
Accumulated transcript turns |
context |
your custom type | Whatever you passed as context= to RealtimeAgent |
Example: shared context object
from dataclasses import dataclass
from typing import Annotated
from rtvoice import RealtimeAgent, Tools
from rtvoice.conversation import ConversationHistory
@dataclass
class AppContext:
user_id: str
preferences: dict
tools = Tools()
@tools.action("Save the user's preferred language")
async def save_language(
language: Annotated[str, "The language code, e.g. 'de'"],
context: AppContext, # injected automatically
) -> str:
context.preferences["language"] = language
return f"Language set to {language}."
ctx = AppContext(user_id="u-42", preferences={})
agent = RealtimeAgent(
instructions="Help the user configure their preferences.",
tools=tools,
context=ctx,
)
await agent.run()
Example: reading conversation history
@tools.action("Summarise the conversation so far")
async def summarise(conversation_history: ConversationHistory) -> str:
return conversation_history.format()
Synchronous tools
Sync functions work too — the framework detects async automatically:
@tools.action("Convert Celsius to Fahrenheit")
def celsius_to_fahrenheit(celsius: Annotated[float, "Temperature in °C"]) -> str:
return f"{celsius * 9/5 + 32:.1f}°F"
Full example
import asyncio
from typing import Annotated
from rtvoice import RealtimeAgent, Tools
tools = Tools()
@tools.action(
"Look up the current stock price for a ticker symbol",
result_instruction="State the price clearly and mention the currency.",
is_long_running=True,
holding_instruction="Let me check the markets for you.",
)
async def get_stock_price(
ticker: Annotated[str, "Stock ticker symbol, e.g. AAPL"],
) -> str:
# replace with real API call
return f"{ticker}: $192.50 USD"
async def main():
agent = RealtimeAgent(
instructions=(
"You are a financial assistant. "
"Use get_stock_price when the user asks about stock prices."
),
tools=tools,
)
await agent.run()
asyncio.run(main())
API reference
See Tools for the complete class documentation.