Genesys
Genesys Cloud AudioHook sessions with GenesysAudioHookSerializer, used with FastAPIWebsocketTransport.
Overview
GenesysAudioHookSerializer speaks Genesys Cloud's AudioHook protocol, so a contact-center
call flow can hand a caller to a bot and get results back:
- Binary μ-law audio at 8 kHz both ways, resampled to and from the pipeline's rate. In stereo
(
externalandinternal), only the caller's (left) channel reaches the pipeline. - The handshake is answered for you:
open→opened,ping→pong,close→closed, each returned fromdeserializeas anOutputTransportMessageUrgentFramethe transport sends back. pausestops audio until you sendcreateResumedResponse();updaterefreshes the participant;dtmfbecomes anInputDTMFFrame.- Architect variables in (
inputVariables, fromopen) and out (setOutputVariables(), sent inclosedanddisconnect). - An
InterruptionFramesends a barge-in event; anEndFrameorCancelFramesendsdisconnect.
Upstream page
Pipecat's documentation for the same serializer.
Source
packages/serializer-genesys/src/genesys.ts.
Genesys docs
The AudioHook protocol.
Installation
bun add @pipedog/serializer-genesys @pipedog/transport-websocketimport {
AudioHookChannel,
GenesysAudioHookSerializer,
} from "@pipedog/serializer-genesys/genesys";Prerequisites
- A Genesys Cloud org with an AudioHook Monitor or AudioConnector integration whose connection URI is your WebSocket URL, and an Architect flow that uses it.
GenesysAudioHookSerializer
Configuration
Prop
Type
InputParams
params is a GenesysAudioHookSerializer.InputParams (GenesysAudioHookSerializerInputParams):
| Param | Type | Default | Description |
|---|---|---|---|
genesysSampleRate | number | 8000 | Sample rate Genesys uses, in Hz. |
sampleRate | number | null | null | Override for the pipeline input rate. null uses the pipeline's. |
channel | AudioHookChannel | EXTERNAL | Channels to offer: EXTERNAL, INTERNAL or BOTH. Updated from Genesys's open. |
mediaFormat | AudioHookMediaFormat | PCMU | Audio format. Only PCMU is implemented, as upstream. |
processExternal | boolean | true | Process the caller's audio. |
processInternal | boolean | false | Process the agent's audio. |
supportedLanguages | string[] | null | null | Languages sent in opened. |
selectedLanguage | string | null | null | Language selected in opened. |
startPaused | boolean | false | Ask Genesys to start the session paused. |
resamplerClearAfterSecs | number | null | 0.2 | Seconds of silence after which the resamplers clear their history. null (never) suits Genesys's irregular chunks. |
ignoreRtviMessages | boolean | true | Drop RTVI messages. |
Usage
import { AudioHookChannel, GenesysAudioHookSerializer } from "@pipedog/serializer-genesys/genesys";
import {
FastAPIWebsocketParams,
FastAPIWebsocketTransport,
} from "@pipedog/transport-websocket/fastapi";
import { websocketFetchHandler } from "@pipedog/transport-websocket/fetch";
import type { WebsocketConnection } from "@pipedog/transport-websocket/socket";
async function runSession(connection: WebsocketConnection): Promise<void> {
const serializer = new GenesysAudioHookSerializer({
params: new GenesysAudioHookSerializer.InputParams({
channel: AudioHookChannel.EXTERNAL,
supportedLanguages: ["en-US", "es-ES"],
selectedLanguage: "en-US",
}),
});
const transport = new FastAPIWebsocketTransport(
connection,
new FastAPIWebsocketParams({
audioInEnabled: true,
audioOutEnabled: true,
serializer,
// Genesys rate-limits (HTTP 429) many small audio messages.
fixedAudioPacketSize: 1600,
}),
);
// ... build and run the pipeline with transport.input() and transport.output()
}
// The AudioHook integration's connection URI points here.
const handler = websocketFetchHandler(runSession);Read the caller's details and return variables to the flow:
const serializer = new GenesysAudioHookSerializer();
serializer.eventHandler("on_open", async () => {
// From Genesys's "open" message.
const ani = serializer.participant?.ani;
const queue = serializer.inputVariables?.queue_name;
console.log(`call from ${ani} for ${queue}`);
});
// Returned to the Architect flow in "closed" (and "disconnect").
serializer.setOutputVariables({ intent: "billing", resolved: true });Events
| Event | When |
|---|---|
on_open | Genesys opened the session (before opened is sent). |
on_close | Genesys closed the session. |
on_ping | A ping arrived. |
on_pause | Genesys paused the stream (e.g. on hold). |
on_update | An update arrived. |
on_error | Genesys reported an error. |
on_dtmf | A digit was pressed. |
Notes
- Audio is dropped until the session is open, and while it is paused.
- Only transport messages that are AudioHook messages (with a
versionfield) are sent; others are dropped. - Positions are ISO 8601 durations with millisecond precision (
PT12.500S), echoed from the last client message.
Runtime notes
| Runtime | Works | What it needs |
|---|---|---|
| Bun | ✅ yes | Nothing. |
| Node.js | ✅ yes | Nothing. |
| Deno | ✅ yes | Nothing. |
| Cloudflare Workers | ✅ yes | Nothing. |
Generated from pipecat.runtimes and pipecat.compat in packages/serializer-genesys/package.json: ✅ means the compat smoke test passes on that runtime.
Runs on Bun, Node, Deno and Cloudflare Workers. The package's golden tests replay AudioHook sessions recorded from upstream, message by message.
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).