Each strip below is a full, runnable main.py for that provider, not a fragment. Swap in your own API key and it deploys as shown. Hume has no HTTP-tool concept, so its tools register with transport="client"; AssemblyAI and ElevenLabs default to transport="http" and can host the tool for you.
AssemblyAIdefault provider
deploy() creates a persistent agent record on AssemblyAI's servers. local=True starts a local tool server and tunnels it publicly via ngrok, so AssemblyAI can call get_weather over HTTP.
main.py
from minmo import VoiceAgent
agent = VoiceAgent(
prompt="You are a friendly voice assistant. Keep answers short.",
api_key="YOUR_ASSEMBLYAI_API_KEY",
)
@agent.tooldef get_weather(city: str) -> str:
"""Get the current weather for a city."""returnf"It's sunny in {city}."
result = agent.deploy(local=True)
print(result["info"])
token = agent.mint_token() # short-lived client token# open a voice session with `token` (browser SDK, phone bridge, etc.)
Connect:mint_token() returns a short-lived client token. Open a voice session with it (AssemblyAI's browser SDK or a phone bridge); that live session is what actually calls get_weather.
ElevenLabs
Closest analog to AssemblyAI: deploy() creates a persistent agent, and both tool transports work. provider_options picks the LLM and voice; both have defaults (gemini-2.5-flash, ElevenLabs' "Rachel" voice) if omitted.
main.py
from minmo import VoiceAgent
from minmo.providers.elevenlabs import ElevenLabsProvider
agent = VoiceAgent(
prompt="You are a friendly voice assistant. Keep answers short.",
api_key="YOUR_ELEVENLABS_API_KEY",
provider=ElevenLabsProvider(),
provider_options={"voice_id": "21m00Tcm4TlvDq8ikWAM"}, # optional, this is the default
)
@agent.tooldef get_weather(city: str) -> str:
"""Get the current weather for a city."""returnf"It's sunny in {city}."
result = agent.deploy(local=True)
print(result["info"])
signed_url = agent.mint_token() # a signed WebSocket URL, not a bare token
Connect:mint_token() returns a signed WebSocket URL, not a bare token. Open a conversation directly against it.
Humeclient tools only
Hume has no HTTP-tool concept, so get_weather registers with transport="client". Hume issues an api_key and a secret_key separately; pass the secret through provider_options. Hume's prompts, tools, and configs are name-unique versioned resources: redeploying with the same name adds a new version instead of erroring.
main.py
from minmo import VoiceAgent
from minmo.providers.hume import HumeProvider
agent = VoiceAgent(
prompt="You are a friendly voice assistant. Keep answers short.",
api_key="YOUR_HUME_API_KEY",
provider=HumeProvider(),
provider_options={
"secret_key": "YOUR_HUME_SECRET_KEY",
"voice": {"name": "Ava Song", "provider": "HUME_AI"}, # optional, this is the default
},
)
@agent.tool(transport="client")
def get_weather(city: str) -> str:
"""Get the current weather for a city."""returnf"It's sunny in {city}."
result = agent.deploy() # no HTTP tools registered, nothing to host or tunnelprint(result["info"])
access_token = agent.mint_token() # OAuth token, needs the secret_key above
Connect:mint_token() exchanges your api_key + secret_key for an OAuth access token. Start an EVI session with it; your own app code (not minmo) handles each tool.call over that session.