Docs
LiveKit voice agent routing
Point a LiveKit AgentSession at Speko: one base URL and one key across all three slots, in Python and TypeScript.
Slots
| Slot | Class | Route | Routable |
|---|---|---|---|
| stt | openai.STT | /v1/audio/transcriptions | 15 of 16 |
| llm | openai.LLM | /v1/chat/completions | 16 of 17 |
| tts | openai.TTS | /v1/audio/speech | 15 of 17 |
Setup
mkdir speko-livekit && cd speko-livekit
uv init --bare --python 3.11
uv add "livekit-agents[openai]~=1.6" "python-dotenv>=1.0,<2"
export SPEKO_API_KEY=sk_live_...Catalog
curl -s https://api.speko.ai/v1/modelsResponse
{"data": [{"id": "deepgram:nova-3", "object": "model", "provider": "Deepgram",
"model": "Nova-3", "api": "stt", "routable": true}]}Agent
"""Minimal LiveKit Agents voice worker using Speko's OpenAI-compatible API."""
from __future__ import annotations
import os
from dotenv import load_dotenv
from livekit import agents
from livekit.agents import Agent, AgentServer, AgentSession, JobContext
from livekit.plugins import openai
from openai import AsyncOpenAI
load_dotenv()
SPEKO_API_KEY = os.getenv("SPEKO_API_KEY")
SPEKO_BASE_URL = "https://api.speko.ai/v1"
SPEKO_OBJECTIVE = os.getenv("SPEKO_OBJECTIVE", "balanced")
SPEKO_LANGUAGE = os.getenv("SPEKO_LANGUAGE", "en")
if not SPEKO_API_KEY:
raise RuntimeError("SPEKO_API_KEY is required")
def speko_client() -> AsyncOpenAI:
"""Build one OpenAI-compatible client shared by all three stages."""
return AsyncOpenAI(
api_key=SPEKO_API_KEY,
base_url=SPEKO_BASE_URL,
default_headers={
"X-Speko-Objective": SPEKO_OBJECTIVE,
"X-Speko-Language": SPEKO_LANGUAGE,
},
)
server = AgentServer()
@server.rtc_session()
async def entrypoint(ctx: JobContext) -> None:
client = speko_client()
session = AgentSession(
# Segmented STT is used here so the example works with Speko's
# transcription route instead of opening a speech-to-speech socket.
stt=openai.STT(
client=client,
model="auto",
use_realtime=False,
language=SPEKO_LANGUAGE,
),
llm=openai.LLM(
client=client,
model="auto",
),
# The Python LiveKit OpenAI TTS transport expects the raw PCM route.
# "tts-1" is routed, not pinned: the router still picks the provider.
# Pin one with a catalog id instead, e.g. model="cartesia:sonic-3.5".
tts=openai.TTS(
client=client,
model="tts-1",
voice="alloy",
response_format="pcm",
),
)
await session.start(
Agent(
instructions=(
"You are a helpful voice assistant. "
"Keep replies concise and conversational."
)
),
room=ctx.room,
)
await ctx.connect()
await session.generate_reply(
instructions="Greet the caller in one short sentence and offer help."
)
if __name__ == "__main__":
agents.cli.run_app(server)Run
| Language | Command | Needs |
|---|---|---|
| Python | uv run python agent.py console | Save the Python example as agent.py. Talks in the terminal; no LiveKit credentials. |
| TypeScript | bunx tsx agent.ts dev | Needs LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET. |
Override per request
import os
from livekit.plugins import openai
from openai import AsyncOpenAI
client = AsyncOpenAI(
api_key=os.environ["SPEKO_API_KEY"],
base_url="https://api.speko.ai/v1",
default_headers={"X-Speko-Objective": "latency", "X-Speko-Language": "es"},
)
stt = openai.STT(client=client, model="auto", language="es")
llm = openai.LLM(client=client, model="auto")
tts = openai.TTS(client=client, model="tts-1", voice="alloy", response_format="pcm")Limits
| model="auto" on openai.TTS, Python only | The plugin parses SSE and hears silence. Use model="tts-1"; the router still picks the provider. |
|---|---|
| detect_language=True | Sends an empty language field, which the router rejects with invalid_routing_header. |
| vad=None | Re-arms the RuntimeError a segmented speech-to-text raises on the first user turn. Omit the argument. |
| use_realtime / useRealtime | Opens the speech-to-speech socket instead of the transcription route this page configures. |
Reference
| Quickstart | Routing headers, response headers, errors |
|---|---|
| Pipecat | The same wiring in a Pipecat pipeline |
| Models | The measured rows the ranking reads |
| LiveKit Agents | Framework documentation |
| Node API reference | Class signatures |