Voice CLI
Run a two-way voice call from your terminal with the Python voice_cli example — OS microphone and speaker, live transcript, clean shutdown.
voice_cli is a pip-installable Python package that turns your terminal into a voice call. It enables the default OS microphone and speaker with one call each — session.set_microphone_enabled(True) and session.set_speaker_enabled(True) — then streams the live transcript to stdout while the agent speaks its replies out loud. The SDK supplies the audio I/O, so there is no audio code in the example at all.
Full source: examples/python/voice_cli in the examples repo. To build the same app from an empty file — and grow it into a tool-using assistant — follow Build a Python voice CLI, which uses this example as its base code.
Prerequisites
- Python 3.10+
- A workspace API key with the
realtime:startscope (API keys), or a priorcosmo login - A microphone and speaker
- On Linux, the PortAudio native library for speaker playback (
apt install libportaudio2); the macOS and Windows wheels bundle it
Run it
-
Clone the examples repo and install the package:
git clone https://github.com/socratic-ai/cosmo-ai cd cosmo-ai/examples/python/voice_cli pip install -e . -
Start a call:
cosmo-voice --api-key cosmo_...With
COSMO_API_KEYexported — or aftercosmo login— plaincosmo-voiceworks too: the flag defaults to the environment, then the credentials file.--voiceand--modeloverride the server defaults when you want a specific voice or model. -
Speak into your microphone. Press Enter on a blank line (or Ctrl-C) to end the session cleanly.
How it works
The whole program is cosmo_voice_cli/__main__.py. The session runs inside two async with blocks — leaving them is what guarantees teardown — and a background task prints every event while the main task blocks on stdin:
async with RealtimeClient(api_key=api_key) as client:
agent = client.agent(voice=voice, model=model)
async with agent.start() as session:
print(f"Joined room: {session.response.room_name}")
printer = asyncio.create_task(_print_events(session))
await session.set_microphone_enabled(True)
await session.set_speaker_enabled(True)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, sys.stdin.readline) # block until Enter
await session.end()
await printerThe event printer is a plain async for over the session, matching on the typed event classes:
async for event in session:
if isinstance(event, ReadyEvent):
print(f"[ready] session_id={session.session_id}")
elif isinstance(event, TranscriptDeltaEvent):
marker = "»" if event.is_final else "…"
print(f" [{event.role.value}] {event.text}{marker}")
elif isinstance(event, ToolCallEvent):
print(f" [tool] {event.name} (id={event.tool_call_id})")
elif isinstance(event, ErrorEvent):
print(f" [error] {event.code.value}: {event.message}", file=sys.stderr)
elif isinstance(event, SessionEndedEvent):
print(f" [ended] {event.reason}")Non-final transcript deltas carry the newest fragment (printed with …); the final delta carries the whole turn (printed with »). A real UI would replace the accumulated fragments with the final text — the CLI just prints both, which makes the contract visible.
Sample output
Session ids are UUIDs and room names are server-generated; the agent's words vary run to run:
Connecting…
Joined room: cosmo-9f2ce46a1b7d43aa9c013d7e
Enabling microphone…
Enabling speaker…
[ready] session_id=3f1c9b2e-8a41-4b6f-9d27-5e0c8a913f64
Speak into your microphone — the agent replies out loud. Press Enter (blank line) to end.
[user] Hey, can you hear me?…
[user] Hey, can you hear me?»
[assistant] Loud and clear — what can I do for you?»
Ending session…
[ended] client endedTroubleshooting
Issue: OSError: PortAudio library not found on startup.
Cause: speaker playback needs the PortAudio native library, which Linux wheels don't bundle.
Solution: install it from your package manager, for example apt install libportaudio2, then rerun.
Next steps
- Build a Python voice CLI — the guided walkthrough that grows this into a tool-using assistant
- Agent recipes — tools, skills, hooks, and MCP in the same event-loop shape
- Python reference — every event class the printer can match on
Browser voice page
Run the smallest complete browser app — RealtimeProvider, a live transcript, mic control, and one client tool — from the realtime-page example.
Agent recipes
Run the small Python examples one capability at a time — a typed client tool, just-in-time skills, hooks that guard tools, MCP servers, and an outbound phone call.