Skip to main content
A support line that answers by voice needs three models and one rule: never say anything about an order you have not looked up. This pipeline transcribes the caller, streams a tool-calling model that must call your order system first, and hands each finished sentence to text-to-speech while the model is still writing the next one. On the proof run the first spoken sentence was ready 4.1 seconds after the caller stopped, for 1.4 cents a call.

Build it in your project

Paste this line into your agent (Claude Code, Codex, Cursor, OpenCode, Cline). It sets up your key, then builds the pipeline in your project:

The code

One file per language. Both read RUNCRATE_API_KEY from the environment; nothing secret is in the code.

What the proof run cost

The Python file on a 6.4-second recorded question (“where is my order A one zero four two?”). Times are from the start of the script. Measured on 2026-10-23 against api.runcrate.ai; costs are what the account was billed, read from each response’s X-LLM-Cost header or usage.cost. The first Python run, with a cold start, had its first audio at 5.5 s; the TypeScript file had its first audio at 6.4 s for $0.0129. Every run looked the order up before answering.

Scale it

  • This is turn-based, a few seconds a turn. For sub-second replies, run an open speech model and LLM on one GPU instance next to your telephony and keep the same tool loop.
  • The model is the latency dial: one-shot first-token times on the day were Claude Haiku 5.5 0.65 s, Llama 4 Scout 0.79 s, gpt-oss-20b 0.88 s, gpt-oss-120b 1.41 s (free tier), DeepSeek V4.1 Flash 1017 2.18 s. Set VOICE_LLM to switch.
  • Calls in parallel: each call is independent; the account’s rate limit (600 requests a minute on the proof key) is the ceiling, not the code.

Gotchas found in the proof run

  • Without the tool, several models answered “what are your opening hours?” with invented hours. The system prompt makes the lookup mandatory, and the agent says nothing about an order before the tool answers.
  • Kokoro’s response is chunked but not generated incrementally: the first 4 KB of a sentence arrived after about 2.2 s as PCM and 3.4 s as MP3. Split into sentences and send them in parallel; one long request is slower.
  • Whisper heard “A 1042” for “A one zero four two”. Normalise ids in the tool (upper case, no spaces) rather than trusting the transcript.