# Contact centers

Let Nur answer calls behind your own phone system: G.711 audio over a WebSocket, your systems as tools, and a hand-off to a person when it's needed.

Nur sits behind your telephony. Your phone system carries the call as it does
today, and for each call it opens a WebSocket to Nur and streams the call's
audio both ways. There is no SIP endpoint and no connector for contact-center
platforms: the WebSocket is how calls reach Nur.

What you get:

- Phone audio as it is: G.711 µ-law or A-law at 8 kHz in, the same format
  back, as binary WebSocket frames.
- Callers can talk over Nur and it stops; it waits through their pauses
  instead of cutting in.
- Your systems as tools. Nur looks up an order or books a slot through
  functions your bridge runs, and passes the call to a person through one you
  define.
- What the caller said and Nur's words, as events on the same socket.
- Arabic dialects and more than a hundred languages, switching when the caller
  does.

## Run it

`answer(call)` handles one call. `call` is your phone system's side of it:
the caller's audio as it arrives, and a way to play, stop and transfer.

```bash
pip install "websockets>=14"
export EESI_API_KEY=sk-eesi-...
```

```python bridge.py
import asyncio, json, os

import websockets

URL = "wss://api.eesi.ai/v1/realtime?model=nur-v1"
SESSION = {
    "type": "realtime",
    "instructions": "You answer the phone for Example Deliveries. Help with orders and delivery times. Keep answers short.",
    "audio": {
        "input": {"format": {"type": "audio/pcmu"}, "transport": "binary"},
        "output": {"format": {"type": "audio/pcmu"}, "transport": "binary"},
    },
    "tools": [{
        "type": "function",
        "name": "transfer_to_agent",
        "description": "Pass the call to a person when the caller asks for one or you cannot help.",
        "parameters": {"type": "object", "properties": {}},
    }],
}


async def answer(call):
    async with websockets.connect(URL, additional_headers={"Authorization": f"Bearer {os.environ['EESI_API_KEY']}"}) as nur:
        await nur.send(json.dumps({"type": "session.update", "session": SESSION}))
        await nur.send(json.dumps({"type": "response.create"}))  # Nur answers the phone

        async def caller_to_nur():
            async for frame in call.audio():  # 20 ms of µ-law at a time, as it arrives
                await nur.send(frame)

        pump = asyncio.create_task(caller_to_nur())
        async for message in nur:
            if isinstance(message, bytes):  # Nur's voice, µ-law
                await call.play(message)
                continue
            event = json.loads(message)
            if event["type"] == "input_audio_buffer.speech_started":
                await call.clear()  # the caller cut in: stop playing at once
            elif event["type"] == "response.function_call_arguments.done":
                await nur.send(json.dumps({"type": "conversation.item.create", "item": {
                    "type": "function_call_output", "call_id": event["call_id"], "output": "Transferring now."}}))
                await call.transfer()
                break
        pump.cancel()
```

Use `{"type": "audio/pcma"}` for A-law. Send audio at the pace the call
produces it: Nur hears the end of a turn from the timing.

## Make it yours

- **Look things up.** Add function tools such as `check_order` and answer each
  call with its result, then `response.create`. See
  [Tools and MCP servers](/realtime/tools).
- **Say a disclosure word for word.** A `force_message` with
  `"interruptible": false` plays before anything the caller says is heard. See
  [Scripted lines](/realtime/live#scripted-lines).
- **Names and product words.** List them in
  `audio.input.transcription.keyterms` so the transcript expects them.
- **Keep the record.** `conversation.item.input_audio_transcription.completed`
  carries each caller turn as text, and `response.output_audio_transcript.done`
  each of Nur's.
- **Call customers back.** Nur can also place calls itself. See
  [Phone calls](/quickstarts/phone-calls).

Sessions are billed per minute and can last up to three hours. Recordings and
transcripts follow your organization's settings in the console.

## Next

<CardGroup cols={2}>
  <Card title="Live conversation" icon="bolt" href="/realtime/live">
    Session settings, binary audio, interruptions and every event.
  </Card>
  <Card title="Tools and MCP servers" icon="wrench" href="/realtime/tools">
    Functions your bridge runs, and servers EESI runs for you.
  </Card>
  <Card title="Voices" icon="microphone" href="/speech/voices">
    Built-in voices, or a clone of your brand's own.
  </Card>
  <Card title="Phone calls" icon="phone" href="/quickstarts/phone-calls">
    Nur places a call and holds the conversation you describe.
  </Card>
</CardGroup>
