@pipedog/runner
v0.11.0
Published
Pipecat's development runner for pipedog: createTransport() from runner arguments, and a dev server (main()) with the prebuilt WebRTC client, SmallWebRTC signalling, telephony webhooks and WebSockets for Twilio, Telnyx, Plivo and Exotel. A fetch handler y
Maintainers
Readme
@pipedog/runner
Pipecat's runner (pipecat.runner) for pipedog: a bot written against Pipecat's development
runner keeps its shape. Export bot(runnerArgs), call main(), and pick the transport with
createTransport().
main()(@pipedog/runner/run): the development server, with upstream's CLI (-t webrtc,-t twilio|telnyx|plivo|exotel,--proxy,--host,--port,--esp32,--ice-servers,--ws-auth,--allowed-origins,-u,-f,--runner-body,-v). It serves the prebuilt Pipecat client at/client(/redirects there),/start,/status, SmallWebRTC's/api/offer(and/sessions/{id}/api/offer), the telephony WebSocket at/ws, the TwiML or TeXML webhook atPOST /,/ws-client, and file uploads and downloads.createRunnerApp()builds the same server as a fetch handler to mount in Hono, SvelteKit and others;serve()(@pipedog/runner/serve) listens on Bun, Node (withws) or Deno.createTransport(runnerArgs, transportParams)(@pipedog/runner/utils) builds the transport the runner arguments call for. For a phone call it reads the provider's handshake (Telnyx'sconnectedthenstart, ...), builds the provider's serializer with the stream and call IDs, and exposes them asrunnerArgs.callData. A caller who hangs up before the handshake completes is aTelephonyCallEndedError, withrunnerArgs.handshakeset to{ status: "closed", messagesReceived }.- The runner arguments:
RunnerArguments,SmallWebRTCRunnerArguments,WebSocketRunnerArguments,LiveKitRunnerArguments, and, for API parity,DailyRunnerArguments,VonageRunnerArgumentsandMOQRunnerArguments. @pipedog/runner/livekit: LiveKit access tokens (generateToken,generateTokenWithAgent,generateSessionTokens,configure), signed withlivekit-server-sdk. With-t livekit,POST /startmints a bot and a user token and starts the bot withLiveKitRunnerArguments;createTransport()then needs@pipedog/transport-livekit(an optional peer) and@livekit/rtc-node.--whatsapp: mountsGET/POST /whatsapp(Meta's webhook verification and call events) on@pipedog/transport-whatsapp(an optional peer). It needsWHATSAPP_APP_SECRET,WHATSAPP_PHONE_NUMBER_ID,WHATSAPP_TOKENandWHATSAPP_WEBHOOK_VERIFICATION_TOKEN. Each call starts the bot withSmallWebRTCRunnerArguments, andrunnerArgs.bodyis the call.parseTelephonyWebsocket(),telephonyHandshake()and theCallDatatypes.
bun add @pipedog/runnerExample
// bot.ts: run with `bun bot.ts -t webrtc`, or `bun bot.ts -t telnyx --proxy mybot.ngrok.io`
import { TransportParams } from "@pipedog/core/transports/base_transport";
import type { RunnerArguments } from "@pipedog/runner/types";
import { createTransport } from "@pipedog/runner/utils";
import { FastAPIWebsocketParams } from "@pipedog/transport-websocket/fastapi";
const transportParams = {
webrtc: () => new TransportParams({ audioInEnabled: true, audioOutEnabled: true }),
telnyx: () => new FastAPIWebsocketParams({ audioInEnabled: true, audioOutEnabled: true }),
};
export async function bot(runnerArgs: RunnerArguments) {
const transport = await createTransport(runnerArgs, transportParams);
// build and run the pipeline with transport.input() and transport.output()
}
if (import.meta.main) {
const { main } = await import("@pipedog/runner/run");
await main();
}See the Development runner docs page for the routes, mounting the app in a framework, and a Python-to-TypeScript mapping.
Runtimes
| export | Bun | Node | Deno | Cloudflare Workers |
|---|:-:|:-:|:-:|:-:|
| createTransport, parseTelephonyWebsocket, telephonyHandshake, the runner arguments | ✅ | ✅ | ✅ | ✅ (WebSocket and telephony; WebRTC isn't available there) |
| main, serve | ✅ | ✅ with ws | ✅ | ❌ can't listen |
| createRunnerApp (fetch handler) | ✅ | ✅ | ✅ | not tested |
The prebuilt client
Upstream serves PipecatPrebuiltUI from the pipecat-ai-prebuilt Python package
(pipecat-ai/pipecat-prebuilt). Its build is only
published in that wheel; there is no npm or CDN build. This package ships the wheel's built client
unmodified in prebuilt/ (release 1.3.0, BSD-2-Clause, Copyright (c) 2025–2026 Daily, with its
THIRD_PARTY_NOTICES.txt), refreshed with bun tools/runner/sync-prebuilt.ts.
Differences from upstream
- Daily (
-t daily,--direct, the dial-in webhook), MOQ, the Vonage Video Connector (-t vonage) aren't ported: selecting them fails with a clear message. Their argument classes exist for type parity. The MOQ flags and the deprecated--folderand-t evalaren't ported. - A hang-up mid-handshake is
TelephonyCallEndedError(aTelephonyHandshakeError, upstream'sValueError) whether zero or one message arrived; upstream fails with "Missing transport params for 'unknown'" after one. The runner logs it at info level. - The server is a fetch handler instead of a FastAPI app; startup hooks are
lifespanfunctions that may return a cleanup. Bots add routes to the module-levelappas upstream bots do. - The CLI parser is a small
ArgumentParserwith argparse's semantics;runnerArgs.cliArgskeeps argparse'sdestnames (ice_servers,ws_auth). - The WebSocket token helpers and
_resolveDownloadPathare async (WebCrypto, lazynode:fs). - The parse is cached per socket in a
WeakMap;call_data["call_id"]iscallData.getItem("call_id").
License
BSD 2-Clause, a port of Pipecat (Copyright (c) 2024–2026 Daily). The prebuilt client in
prebuilt/ is BSD 2-Clause, Copyright (c) 2025–2026 Daily; see prebuilt/LICENSE.
