# Genesys

> Genesys Cloud AudioHook sessions with GenesysAudioHookSerializer, used with FastAPIWebsocketTransport.

Source: https://polvallverdu.github.io/pipedog/docs/serializers/genesys/



## Overview [#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
  (`external` and `internal`), only the caller's (left) channel reaches the pipeline.
* The handshake is answered for you: `open` → `opened`, `ping` → `pong`, `close` → `closed`, each
  returned from `deserialize` as an `OutputTransportMessageUrgentFrame` the transport sends back.
* `pause` stops audio until you send `createResumedResponse()`; `update` refreshes the participant;
  `dtmf` becomes an `InputDTMFFrame`.
* Architect variables in (`inputVariables`, from `open`) and out (`setOutputVariables()`, sent in
  `closed` and `disconnect`).
* An `InterruptionFrame` sends a barge-in event; an `EndFrame` or `CancelFrame` sends `disconnect`.

<Cards>
  <Card title="Upstream page" href="https://docs.pipecat.ai/api-reference/server/services/serializers/genesys">
    Pipecat's documentation for the same serializer.
  </Card>

  <Card title="Source" href="https://github.com/polvallverdu/pipedog/tree/main/packages/serializer-genesys/src">
    `packages/serializer-genesys/src/genesys.ts`.
  </Card>

  <Card title="Genesys docs" href="https://developer.genesys.cloud/devapps/audiohook">
    The AudioHook protocol.
  </Card>
</Cards>

## Installation [#installation]

```bash
bun add @pipedog/serializer-genesys @pipedog/transport-websocket
```

```ts
import {
  AudioHookChannel,
  GenesysAudioHookSerializer,
} from "@pipedog/serializer-genesys/genesys";
```

## Prerequisites [#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 [#genesysaudiohookserializer]

### Configuration [#configuration]

| Option | Type | Required | Description |
|---|---|---|---|
| `params` | `GenesysAudioHookSerializerInputParams \| null \| undefined` | no | Configuration parameters. |
| `name` | `string \| null \| undefined` | no | Custom name; defaults to `ClassName#count`. |
| `taskManager` | `BaseTaskManager \| null \| undefined` | no | Task manager for handling tasks. |

### InputParams [#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 [#usage]

```ts title="genesys.ts"
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:

```ts
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 [#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 [#notes]

* Audio is dropped until the session is open, and while it is paused.
* Only transport messages that are AudioHook messages (with a `version` field) are sent; others
  are dropped.
* Positions are ISO 8601 durations with millisecond precision (`PT12.500S`), echoed from the last
  client message.

## Runtime notes [#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.
