pipedog is an unofficial community port of Pipecat, not affiliated with Daily.
pipedog

Runtimes & compatibility

Running pipedog on Bun, Node, Deno and Cloudflare Workers, and which packages are verified where.

@pipedog/core and @pipedog/asyncio are runtime-agnostic: they run unchanged on Bun, Node.js (22 or later), Deno and Cloudflare Workers (workerd). Code that only works on some runtimes lives in its own package, and every package records where it is verified.

Compatibility table

Generated at build time from the pipecat.runtimes field of each packages/*/package.json:

PackageBunNode.jsDenoCloudflare Workers
@pipedog/asyncio✅✅✅✅
@pipedog/core
pipecat/frames, pipecat/processors/frame_processor.py, pipecat/pipeline, pipecat/workers, pipecat/observers, pipecat/clocks, pipecat/utils
✅✅✅✅
@pipedog/ai-sdk✅✅✅✅
@pipedog/anthropic
pipecat/adapters/llm/services/anthropic_adapter.py, pipecat/services/anthropic
✅✅✅✅
@pipedog/assemblyai
pipecat/services/assemblyai
✅✅✅✅
@pipedog/asyncai
pipecat/services/asyncai
✅✅✅✅
@pipedog/audio-ducking✅✅✅✅
@pipedog/audio-rnnoise-filter
pipecat/audio/filters/rnnoise_filter.py
✅✅✅✅
@pipedog/audio-silero
pipecat/audio/vad/silero.py, pipecat/audio/vad/data/silero_vad.onnx
✅✅✅✅
@pipedog/audio-smart-turn
pipecat/audio/turn/smart_turn/http_smart_turn.py, pipecat/audio/turn/smart_turn/data/smart-turn-v3.2-cpu.onnx
✅✅✅✅
@pipedog/audio-soundfile-mixer
pipecat/audio/mixers/soundfile_mixer.py
✅✅✅✅
@pipedog/audio-ten-vad✅✅—✅
@pipedog/aws
pipecat/adapters/llm/services/aws_nova_sonic_adapter.py, pipecat/adapters/llm/services/bedrock_adapter.py, pipecat/services/aws
✅✅✅✅
@pipedog/azure
pipecat/services/azure, pipecat/adapters/llm/services/azure_voice_live_adapter.py
✅✅✅✅
@pipedog/baseten
pipecat/services/baseten
✅✅✅✅
@pipedog/bland
pipecat/services/bland
✅✅✅✅
@pipedog/camb
pipecat/services/camb
✅✅✅✅
@pipedog/cartesia
pipecat/services/cartesia
✅✅✅✅
@pipedog/cerebras
pipecat/services/cerebras
✅✅✅✅
@pipedog/cli
pipecat/cli
✅✅✅n/a
@pipedog/cloudflare✅✅✅✅
@pipedog/crusoe
pipecat/services/crusoe
✅✅✅✅
@pipedog/deepgram
pipecat/services/deepgram
✅✅✅✅
@pipedog/deepseek
pipecat/adapters/llm/services/deepseek_adapter.py, pipecat/services/deepseek
✅✅✅✅
@pipedog/effect✅✅✅✅
@pipedog/elevenlabs
pipecat/services/elevenlabs
✅✅✅✅
@pipedog/espeak-ng✅✅✅n/a
@pipedog/evals
pipecat/evals, pipecat/cli/commands/eval.py
✅✅✅✅
@pipedog/extensions
pipecat/extensions
✅✅✅✅
@pipedog/fireworks
pipecat/services/fireworks
✅✅✅✅
@pipedog/fish
pipecat/services/fish
✅✅✅✅
@pipedog/flows
pipecat/flows
✅✅✅✅
@pipedog/funasr
pipecat/services/funasr/stt.py
✅✅✅n/a
@pipedog/gladia
pipecat/services/gladia
✅✅✅✅
@pipedog/google
pipecat/services/google
✅✅✅✅
@pipedog/gradium
pipecat/services/gradium
✅✅✅✅
@pipedog/grok
pipecat/services/grok/llm.py, pipecat/services/grok/realtime, pipecat/adapters/llm/services/grok_realtime_adapter.py
✅✅✅✅
@pipedog/groq
pipecat/services/groq
✅✅✅✅
@pipedog/heygen
pipecat/services/heygen
✅✅✅n/a
@pipedog/hume
pipecat/services/hume
✅✅✅✅
@pipedog/inception
pipecat/services/inception
✅✅✅✅
@pipedog/inworld
pipecat/services/inworld, pipecat/adapters/llm/services/inworld_realtime_adapter.py
✅✅✅✅
@pipedog/kokoro
pipecat/services/kokoro/tts.py
✅✅✅n/a
@pipedog/langchain
pipecat/processors/frameworks/langchain.py
✅✅✅✅
@pipedog/mcp✅✅n/an/a
@pipedog/mcp-client
pipecat/services/mcp_service.py
✅✅✅⚠️
@pipedog/meta
pipecat/services/meta
✅✅✅✅
@pipedog/minimax
pipecat/services/minimax
✅✅✅✅
@pipedog/mistral
pipecat/adapters/llm/services/mistral_adapter.py, pipecat/services/mistral
✅✅✅✅
@pipedog/moonshine
pipecat/services/moonshine/stt.py
✅✅✅n/a
@pipedog/nebius
pipecat/services/nebius
✅✅✅✅
@pipedog/neuphonic
pipecat/services/neuphonic
✅✅✅✅
@pipedog/novita
pipecat/services/novita
✅✅✅✅
@pipedog/nvidia
pipecat/adapters/llm/services/nvidia_omni_adapter.py, pipecat/services/nvidia
✅✅—✅
@pipedog/ollama
pipecat/services/ollama
✅✅✅✅
@pipedog/onnx✅✅✅✅
@pipedog/openai
pipecat/services/openai, pipecat/adapters/llm/services/open_ai_live_adapter.py, pipecat/adapters/llm/services/open_ai_realtime_adapter.py, pipecat/adapters/llm/services/open_ai_responses_adapter.py
✅✅✅✅
@pipedog/openrouter
pipecat/services/openrouter
✅✅✅✅
@pipedog/perplexity
pipecat/adapters/llm/services/perplexity_adapter.py, pipecat/services/perplexity
✅✅✅✅
@pipedog/piper
pipecat/services/piper/tts.py
✅✅✅✅
@pipedog/pocket-tts
pipecat/services/pocket_tts/tts.py
✅✅✅n/a
@pipedog/qwen
pipecat/services/qwen
✅✅✅✅
@pipedog/resampler-wasm✅✅✅✅
@pipedog/resembleai
pipecat/services/resembleai
✅✅✅✅
@pipedog/rime
pipecat/services/rime
✅✅✅✅
@pipedog/runner
pipecat/runner/__init__.py, pipecat/runner/livekit.py, pipecat/runner/run.py, pipecat/runner/types.py, pipecat/runner/utils.py
✅✅✅✅
@pipedog/sambanova
pipecat/services/sambanova
✅✅✅✅
@pipedog/sarvam
pipecat/services/sarvam
✅✅✅✅
@pipedog/sentencex-wasm✅✅✅✅
@pipedog/sentry
pipecat/processors/metrics/sentry.py
✅✅✅✅
@pipedog/serializer-exotel
pipecat/serializers/exotel.py
✅✅✅✅
@pipedog/serializer-genesys
pipecat/serializers/genesys.py
✅✅✅✅
@pipedog/serializer-plivo
pipecat/serializers/plivo.py
✅✅✅✅
@pipedog/serializer-protobuf
pipecat/serializers/protobuf.py
✅✅✅✅
@pipedog/serializer-rtvi-client
pipecat/serializers/rtvi_client.py
✅✅✅✅
@pipedog/serializer-telnyx
pipecat/serializers/telnyx.py
✅✅✅✅
@pipedog/serializer-twilio
pipecat/serializers/twilio.py
✅✅✅✅
@pipedog/serializer-vonage
pipecat/serializers/vonage.py
✅✅✅✅
@pipedog/smallest
pipecat/services/smallest
✅✅✅✅
@pipedog/soniox
pipecat/services/soniox
✅✅✅✅
@pipedog/speechify
pipecat/services/speechify
✅✅✅✅
@pipedog/speechmatics
pipecat/services/speechmatics
✅✅✅✅
@pipedog/together
pipecat/services/together
✅✅✅✅
@pipedog/tone
pipecat/processors/tone/reader/model.py, pipecat/processors/tone/tagger/model.py
✅✅—✅
@pipedog/tracing
pipecat/utils/tracing/setup.py
✅✅✅✅
@pipedog/transport-cloudflare-realtime✅✅✅✅
@pipedog/transport-heygen
pipecat/transports/heygen/transport.py
✅✅✅n/a
@pipedog/transport-livekit
pipecat/transports/livekit/transport.py, pipecat/transports/livekit/utils.py
✅✅✅n/a
@pipedog/transport-local
pipecat/transports/local/audio.py
✅✅✅n/a
@pipedog/transport-smallwebrtc
pipecat/transports/smallwebrtc/connection.py, pipecat/transports/smallwebrtc/request_handler.py, pipecat/transports/smallwebrtc/transport.py
✅✅✅n/a
@pipedog/transport-websocket
pipecat/transports/websocket/client.py, pipecat/transports/websocket/fastapi.py, pipecat/transports/websocket/rtvi_client.py, pipecat/transports/websocket/server.py
✅✅✅✅
@pipedog/transport-whatsapp
pipecat/transports/whatsapp/api.py, pipecat/transports/whatsapp/client.py
✅✅✅⚠️
@pipedog/ultravox
pipecat/services/ultravox
✅✅✅✅
@pipedog/whisper
pipecat/services/whisper/base_stt.py, pipecat/services/whisper/stt.py, pipecat/services/whisper/utils.py
✅✅✅✅
@pipedog/xai
pipecat/services/xai/llm.py, pipecat/services/xai/stt.py, pipecat/services/xai/tts.py, pipecat/services/xai/realtime, pipecat/adapters/llm/services/grok_realtime_adapter.py
✅✅✅✅
@pipedog/zoom-ai
pipecat/services/zoom_ai
✅✅—✅

✅ = a smoke test exercises the package on that runtime (pipecat.runtimes in its package.json). ⚠️ = only part of it works there. n/a = the runtime can't run it. — = not verified yet. Generated at build time from 96 packages.

runtimes lists only what is verified: the compat harness runs each package's smoke test (its compat/smoke.ts, or a default that imports every public entry) on each runtime, and bun run compat --write records the runtimes that passed. It is never edited by hand. An empty row means the package has not been run through the harness yet.

A package that cannot work on a runtime (SmallWebRTC on Workers, which has no UDP) lists it in pipecat.compat.unsupportedRuntimes; the harness skips it there. Optional peers a package's users are expected to install go in pipecat.compat.usesOptionalPeers; all other optional peers are made unresolvable during the run, so a package that silently depends on one fails.

Every package is verified on all four runtimes except @pipedog/transport-smallwebrtc (no UDP on Workers), @pipedog/transport-livekit, @pipedog/heygen and @pipedog/transport-heygen (LiveKit's media SDK is a native addon, which Workers can't load), the local models @pipedog/kokoro, @pipedog/moonshine, @pipedog/funasr, @pipedog/pocket-tts and the eSpeak NG phonemizer @pipedog/espeak-ng (model files and memory exceed what Workers allow), @pipedog/transport-local (it runs sox or ffmpeg on your machine), @pipedog/mcp (a stdio tool for Bun and Node) and @pipedog/cli (a command line tool: Bun, Node and Deno). The harness checks that each package loads and runs its smoke test; inside a verified package, a few entry points still need a server runtime:

Entry pointRuns onWhy
Google Cloud Speech-to-Text and Text-to-Speech, and Gemini TTS on GCP (@pipedog/google)Bun, Node, DenogRPC over HTTP/2 through Google's Node SDKs. The Gemini API services run on Workers too.
SageMakerBidiClient (@pipedog/aws)Bun, Node 22+ (Deno untested)Full-duplex HTTP/2 through the AWS SDK.
Nova Sonic with transport: "http2" (@pipedog/aws)Bun, Node (Deno untested)The default WebSocket transport runs everywhere, Workers included.
main(), serve() (@pipedog/runner)Bun, Node (with ws), DenoThey listen on a port. On Workers, use the fetch handler from createRunnerApp() (untested there).
serveFetch, websocketServe, SingleClientWebsocketServerTransport (@pipedog/transport-websocket)Bun, Node (with ws), DenoThey listen on a port. On Workers, use websocketFetchHandler.

Local turn detection (@pipedog/audio-silero, @pipedog/audio-smart-turn) runs on Workers with onnxruntime-web, but the models and runtime are large; provider-side turn detection is the usual choice there. See Turn detection.

What core avoids

To stay portable, @pipedog/core and @pipedog/asyncio:

  • import no node:* modules except node:async_hooks (for AsyncLocalStorage, in asyncio);
  • use Uint8Array for bytes, never Buffer (PCM is 16-bit little-endian);
  • use no Bun- or Deno-specific APIs;
  • use the global fetch and WebSocket for network I/O;
  • treat process signals as optional (WorkerRunner handles SIGINT/SIGTERM only where the runtime has them).

Bun, Node and Deno

The npm packages ship compiled JavaScript, and from a checkout Bun and Deno run the TypeScript sources directly (Node with its built-in type stripping). WorkerRunner installs a SIGINT handler by default, so Ctrl-C cancels the bot cleanly. Node needs version 22 or later.

On Bun and Node, a WebSocket is upgraded by the server rather than from the Request: serveFetch() from @pipedog/transport-websocket/serve serves a fetch handler with upgrades on Bun, Node (with the ws package) and Deno, and on Bun you can also pass the server Bun.serve gives fetch to websocketFetchHandler's handler. See WebSocket.

Cloudflare Workers

Workers are a good fit for pipedog bots that talk to clients over WebSockets, with a few constraints:

  • Enable nodejs_compat. Task tracking uses AsyncLocalStorage from node:async_hooks, which workerd provides under the nodejs_compat compatibility flag.

    wrangler.jsonc
    {
      "compatibility_flags": ["nodejs_compat"]
    }
  • No WebRTC. Workers can't run WebRTC, so the WebRTC-based transports (Daily, SmallWebRTC, LiveKit) don't work there. Use a WebSocket transport instead; WebSocket-based transports and serializers must work on Workers. Pipecat clients can connect over WebSocket with RTVI as usual. For WebRTC users, Cloudflare Realtime is the WebRTC peer and streams the audio to the bot over WebSockets.

  • WASM is imported as a module. workerd refuses to compile WebAssembly from bytes at runtime (WebAssembly.compile(buffer)), so a .wasm file must be imported. Packages with WASM ship two entries selected by the workerd export condition, which wrangler resolves automatically:

    package.json
    {
      "exports": {
        ".": {
          "types": "./src/index.ts",
          "workerd": "./src/workerd.ts",
          "default": "./src/index.ts"
        }
      }
    }

    The workerd entry does import wasm from "../wasm/x.wasm" and instantiates that WebAssembly.Module; the default entry loads the bytes (a fetch of new URL(..., import.meta.url)). Both accept an explicit WebAssembly.Module | BufferSource so apps can supply their own. @pipedog/resampler-wasm is built this way.

  • Models are never bundled. Packages that need a model (Silero VAD, Smart Turn) load it from a path or URL you give them, with the upstream file name as the default. On Workers, serve it from R2, KV, static assets or a fetch.

  • No threads, limited CPU. Upstream work done in a thread pool (run_in_executor) runs inline or in an injected runner. Keep per-call CPU low: Workers have CPU-time limits.

  • No process signals. handleSigint is a no-op; end the runner from your Worker code (for example when the WebSocket closes) with runner.end() or runner.cancel().

  • Many sessions per isolate. One isolate serves many requests and Durable Objects. @pipedog/asyncio runs each callback in the I/O context that scheduled it, so parallel sessions in separate Durable Objects don't do each other's I/O. examples/workers-durable-voice-agent tests this with parallel sessions on workerd.

Native and ML dependencies

Where Pipecat uses native modules (onnxruntime, Krisp, Koala, soxr), the pipedog package takes the model as an external file or URL and accepts an injected runtime: onnxruntime-node on Bun/Node, onnxruntime-web (WASM) on Workers. Pure-algorithm fallbacks, such as a linear resampler, may live in core.

pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.

Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).

On this page