Noesis / Integrations
Exotel
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:
# 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.