Noesis / Integrations

Stream an Exotel call to a relay with the Stream or Voicebot applet, and forward the callee's 16-bit PCM audio to Noesis.

Exotel's Stream and Voicebot applets send a call's audio to a WebSocket as JSON messages, with 16-bit PCM audio at 8 kHz in base64. Run a relay that decodes the audio and forwards it to Noesis.

1. Stream the call to your relay

In your call flow, add a Stream applet (or a Voicebot applet) and set its URL to your relay, for example wss://relay.example.com/exotel. Exotel calls the relay when the applet runs.

2. Forward the audio to Noesis

The relay uses noesis_relay.py from the relay helper:

Python
# exotel_relay.py: Exotel stream -> your server -> Noesis
import asyncio, base64, json

import websockets

from noesis_relay import NoesisCall

async def on_answer(event):
    if event["type"] == "classification":
        print(event["call_id"], event["label"])     # your own logic

async def handle(exotel):
    call = None
    try:
        async for raw in exotel:
            msg = json.loads(raw)
            if msg.get("event") == "start":
                call = NoesisCall(on_answer, encoding="pcm_s16le", sample_rate=8000,
                                  call_id=msg["start"].get("call_sid"))
                await call.open()
            elif msg.get("event") == "media" and call is not None:
                await call.send(base64.b64decode(msg["media"]["payload"]))   # 16-bit PCM
            elif msg.get("event") == "stop":
                break
    except websockets.ConnectionClosed:
        pass
    if call is not None:
        await call.close()

async def main():
    async with websockets.serve(handle, "0.0.0.0", 8080):
        await asyncio.Future()                      # run until stopped

asyncio.run(main())

If your stream is set to 16 kHz, use sample_rate=16000. To not record calls, create each call with record="false" as well.