For clean Markdown of any page, append .md to the page URL. For a complete documentation index, see https://docs.telcoflow.com/concepts/llms.txt. For full documentation content, see https://docs.telcoflow.com/concepts/llms-full.txt.

# Architecture

The SDK follows a **dual-connection architecture**:

```
┌─────────────────────────────────────────────────────┐
│                   Your Application                   │
│                                                      │
│   ┌──────────────────┐    ┌───────────────────────┐  │
│   │  TelcoflowClient │    │     ActiveCall (x N)  │  │
│   └────────┬─────────┘    └───────────┬───────────┘  │
│            │                          │               │
└────────────┼──────────────────────────┼───────────────┘
             │                          │
    ┌────────▼─────────┐    ┌───────────▼───────────┐
    │ Control Connection│    │   Media Connection    │
    │   (Persistent)    │    │ (Ephemeral, per call) │
    │                   │    │                       │
    │  - Call events    │    │  - Audio streaming    │
    │  - Heartbeat      │    │  - Call commands      │
    │  - Reconnection   │    │  - Binary frames      │
    │                   │    │  - Flow control       │
    └────────┬──────────┘    └───────────┬───────────┘
             │                           │
             └───────────┬───────────────┘
                         │
                ┌────────▼────────┐
                │ Telcoflow Server │
                └─────────────────┘
```

## Control Connection

A persistent WebSocket connection that handles:

- **Call events** - Incoming call notifications and call state changes
- **Heartbeat** - Keeping the connection alive
- **Reconnection** - Automatic reconnection on connection loss

## Media Connection

An ephemeral WebSocket connection created per call for:

- **Audio streaming** - Bidirectional PCM audio
- **Call commands** - Per-call operations like `answer()`, `connect()`, `close()`, and `disconnect()`
- **Binary frames** - Raw audio data transport
- **Flow control** - Pull-based buffering to prevent jitter

Once an `ActiveCall` exists, call-specific commands are issued on the media connection, not the control connection.

## What Happens on an Incoming Call

When an `events.INCOMING_CALL` event is received:

1. The SDK automatically creates an `ActiveCall` object
2. The SDK automatically establishes the media connection
3. Your handler receives the `ActiveCall` with media already connected

You do not need to manage connections manually. The SDK handles the full lifecycle of both control and media connections.

## Concurrency Model

- Each incoming call is processed in its own dedicated background task
- Each `ActiveCall` runs independently in its own asyncio task
- Control connection heartbeat runs in a separate task
- Reconnection logic runs in a separate task
- All operations are non-blocking
- The SDK automatically manages task lifecycle and cleanup

## Next Steps

- [Call States](/concepts/call-states-and-lifecycle) - Understand the call lifecycle and state machine
- [Call Commands](/concepts/call-commands) - Learn the commands you can issue on a call
- [Audio Streaming](/concepts/audio-streaming) - How audio flows between your app and the caller