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.

Read the docs
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,
}) {}
01

Install

npm install the packages you need. No repo to clone — Syrinx ships on npm as @kuralle-syrinx/*.

02

Build

Wire an STT/LLM/TTS cascade or a realtime front, plug in your reasoner, and add tools.

03

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.