Skip to main content
Geko is the speak step of a voice agent. It’s text-to-speech only — it doesn’t transcribe audio and it doesn’t run an LLM. You bring your own speech-to-text and your own model; Geko turns the model’s text into a voice, fast enough to feel live.
The trick to making it feel responsive is streaming: as the LLM produces text, pipe it into geko.tts.stream() and play each WAV chunk the moment it arrives. The caller hears speech roughly one sentence after the model starts talking, not after the whole reply is written and rendered.

Keep it low-latency

Two settings and one habit do most of the work:
  • nfe: 16. Half the diffusion steps of the default 32, noticeably faster, still very usable for a conversation. Save 32 for narration you’ll ship. See Latency & quality.
  • Stream, don’t wait. Use tts.stream() so playback starts on the first sentence instead of the full reply.
  • Stay warm. The GPU backend scales to zero when idle, so the first call after a lull can cold-start for tens of seconds. On a live line that’s a dead pause. Keep a container hot with predictable traffic or a pre-warm call before a session — see cold starts.

Choosing a voice

Pick one that fits the role. Aigerim (warm, professional) reads well for reception and support; there are male and female alternatives (Arman, Ainur, Aruzhan, Sanzhar, Yerlan). Audition them on the voices page and set voice once for the whole session.
Synthesis stays server-side. Your sk-tokay-… key is server-only — never ship it in a browser or mobile bundle. In a voice agent, the media pipeline (telephony, the model, Geko) lives on your backend; the client only sends and plays audio. See Use it in your app.

Wiring the LLM into Geko

Here’s the Geko half of the loop: take an async iterable of text as the model produces it, batch it into sentences, and stream each sentence through tts.stream() — yielding WAV chunks you feed straight to the caller’s audio channel.
Drive it from your loop:
The pieces outside Geko — the phone/SIP transport, the STT, the LLM, and turning the caller’s speech into llmTextStream — are yours to wire up; Geko slots in as the voice at the end. Batching on sentence boundaries keeps latency low without chopping words: each unit is big enough to sound natural and small enough to start fast.
Streams aren’t retried, so on a live call bound each turn with a per-call timeout and use signal to cancel on barge-in or hang-up. See Errors & retries.

Next steps

Streaming audio

The full streaming API and the raw wav-frames protocol.

Latency & quality

nfe, cold starts, and keeping the backend warm.

Pick a voice

Audition Aigerim, Arman, and the rest of the catalog.

Errors & retries

Timeouts, cancellation, and why streams don’t retry.