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.

# Event Handling

The SDK provides two mechanisms for handling events: decorator-based handlers for discrete events, and async iterators for continuous audio streams.

## Decorator-based Events

Use decorators for discrete, one-time events:

```python
# Client-level event
@client.on(events.INCOMING_CALL)
async def handle_call(call: ActiveCall):
    await call.answer()

# Call-level event
@call.on(events.CALL_TERMINATED)
def on_terminated():
    print("Call ended")
```

## Available Events

| Event | Level | Description |
|---|---|---|
| `events.INCOMING_CALL` | Client | A new call has arrived |
| `events.CALL_TERMINATED` | Call | The call has ended |
| `events.CALL_ANSWERED` | Call | The call was successfully answered |
| `events.CALL_CONNECTED` | Call | The connect (conference) succeeded |
| `events.CALL_CONNECT_FAILED` | Call | The connect failed |
| `events.CALL_ANSWER_FAILED` | Call | The answer attempt failed |

**Client-level events** are registered on the `TelcoflowClient` instance and fire for any call.

**Call-level events** are registered on a specific `ActiveCall` instance and fire only for that call.

## Async Iterators

Use async iterators for continuous audio streams:

```python
async for audio_chunk in call.audio_stream():
    processed = await process_audio(audio_chunk)
    await call.send_audio(processed)
```

The iterator yields audio chunks as they arrive. It terminates when the call ends or the media connection closes.

## Combining Events and Streams

A typical pattern combines a call-level event with the audio stream:

```python
@client.on(events.INCOMING_CALL)
async def handle_call(call: ActiveCall):
    @call.on(events.CALL_TERMINATED)
    def on_terminated():
        print("Call ended")

    await call.answer()

    async for chunk in call.audio_stream():
        response = await ai_model.generate(chunk)
        await call.send_audio(response)
```

The public `0.24.0` package docs also mention `ClientEvent` and `CallEvent` enums as type-safe alternatives to the string constants in `telcoflow_sdk.events`.

## Next Steps

- [Call States](/concepts/call-states-and-lifecycle) - See which events correspond to which state transitions
- [Call Commands](/concepts/call-commands) - Commands that trigger state changes
- [API Reference](/reference/api-reference) - Full method signatures for event registration