TypeScript-native · Node + Cloudflare Workers · open source
A voice engine for
real-time agents.
Own the transport edge, swap the STT / LLM / TTS pipeline or run a native speech-to-speech model, and ship on Node or Cloudflare Workers — all from one session.
npm install @kuralle-syrinx/core @kuralle-syrinx/deepgram @kuralle-syrinx/cartesia // Cascade: STT -> your reasoner -> TTS
import { VoiceAgentSession } from '@kuralle-syrinx/core';
import { DeepgramSTTPlugin } from '@kuralle-syrinx/deepgram';
import { CartesiaTTSPlugin } from '@kuralle-syrinx/cartesia';
import { ReasoningBridge, fromStreamText } from '@kuralle-syrinx/aisdk';
const session = new VoiceAgentSession({
plugins: {
stt: { api_key: DEEPGRAM_API_KEY, model: 'nova-3', sample_rate: 16000 },
bridge: {},
tts: { api_key: CARTESIA_API_KEY, voice_id: CARTESIA_VOICE_ID },
},
endpointingOwner: 'provider_stt',
});
session.registerPlugin('stt', new DeepgramSTTPlugin());
session.registerPlugin('bridge', new ReasoningBridge(fromStreamText({ model, system })));
session.registerPlugin('tts', new CartesiaTTSPlugin()); // Native realtime: one speech-to-speech model
import { RealtimeBridge, fromOpenAIRealtime } from '@kuralle-syrinx/realtime';
session.registerPlugin(
'realtime',
new RealtimeBridge(fromOpenAIRealtime({ apiKey, socketFactory })),
);
// Same tools, resume, and observability as the cascade —
// swap OpenAI Realtime for Gemini Live with one import. // Ship on Cloudflare Workers — one hibernatable
// Durable Object per conversation, same engine.
import { Agent } from 'agents';
import { withVoice } from '@kuralle-syrinx/cf-agents';
export class VoiceConversation extends withVoice(Agent, {
pipeline: {
kind: 'cascaded',
stt: (env) => ({ plugin: new DeepgramSTTPlugin(createWorkersSocket), config }),
tts: (env) => ({ plugin: new CartesiaTTSPlugin(createWorkersSocket), config }),
},
reasoner,
}) {} Install
npm install the packages you need. No repo to clone — Syrinx ships on npm as @kuralle-syrinx/*.
Build
Wire an STT/LLM/TTS cascade or a realtime front, plug in your reasoner, and add tools.
Ship
Attach a browser or telephony transport and deploy — on Node or Cloudflare Workers.
One engine, every way to build voice.
Three architectures
Cascade (STT → LLM → TTS), native realtime speech-to-speech, and half-cascade — one session shell, one interaction policy.
Providers are thin adapters
Deepgram, Cartesia, ElevenLabs, Google, Grok, Gemini, OpenAI-compatible — each a small wire protocol over a shared streaming lifecycle.
The transport edge, solved
A resumable WebSocket audio protocol for browsers, plus PSTN termination for Twilio, Telnyx, and SmartPBX. Reconnect and mid-call resume built in.
Node and Cloudflare Workers
The same session runs on a Node server or as a hibernatable Durable Object on the edge — no rewrite to ship.
Turn-taking that isn’t a stopwatch
An interaction policy owns endpointing and barge-in, from a silence timer up to semantic end-of-turn and voice-activity projection.
Usage → dollars → cap
Every stage emits a usage packet; a versioned price catalog turns it into cost, and a spend cap bounds it.
Observability & dashboards
Low-cardinality metrics, usage, and acoustic signals stream to a MetricsExporter — point them at Prometheus, OpenTelemetry, or your own dashboard, with no per-provider instrumentation.
Start building.
Install from npm and run a live voice turn in a few minutes.