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.

# Call States and Lifecycle

Every call in Telcoflow progresses through a defined set of states. Understanding these states is critical for building correct call flows.

![Call States Diagram](https://files.buildwithfern.com/b3networks.docs.buildwithfern.com/89fd5bab0a9f4c6113d618715bfe1f90f59fc6a19fec86a85935943b32bef2bd/docs/telcoflow_call_states_and_methods.png)

## States Explained

| State | Description | Available Methods |
|---|---|---|
| **PENDING** | The call has just arrived. No action has been taken yet. The caller hears ringing. | `answer()`, `connect()` |
| **ANSWERED** | The call has been answered with `answer()`. Your server's WebSocket is actively streaming audio with the caller. You are responsible for feeding audio via `send_audio()`. If you do not send audio, the caller hears silence. | `send_audio()`, `audio_stream()`, `clear_send_audio_buffer()`, `connect()`, `close()`, `disconnect()` |
| **CONNECTED** | A `connect()` call succeeded. The caller, the original callee, and your agent are now in a conference. | `barge()`, `whisper()`, `spy()`, `send_audio()`, `close()`, `disconnect()` |
| **DISCONNECTED** | The call has been terminated by `close()`, `disconnect()`, server-side termination, or another party hanging up. | (none, call is over) |

## State Transitions

| From | Event / Method | To |
|---|---|---|
| (start) | Incoming call | PENDING |
| PENDING | `call.answer()` succeeds | ANSWERED |
| PENDING | `call.answer()` fails | PENDING (via `call.answer_failed`) |
| PENDING | `call.connect()` succeeds | CONNECTED |
| PENDING | `call.connect()` fails | PENDING (via `call.connect_failed`) |
| ANSWERED | `call.connect()` succeeds | CONNECTED |
| ANSWERED | `call.close()` | DISCONNECTED (agent and caller disconnect) |
| ANSWERED | `call.disconnect()` | DISCONNECTED |
| CONNECTED | `call.barge()`, `call.whisper()`, `call.spy()` | CONNECTED |
| CONNECTED | `call.close()` | DISCONNECTED from the SDK's perspective (agent leaves, caller and callee may remain connected) |
| CONNECTED | `call.disconnect()` | DISCONNECTED |
| PENDING | Server terminates call (`call.terminated`) | DISCONNECTED |
| ANSWERED | Server terminates call (`call.terminated`) | DISCONNECTED |
| CONNECTED | Server terminates call (`call.terminated`) | DISCONNECTED |

## Key Behaviors

- **Pre-answer connect**: You can call `connect()` directly from the PENDING state without answering the call first. This lets you route calls to the original callee before your agent picks up the caller.
- **Answered media session**: After `answer()`, the call enters ANSWERED and your application is responsible for the live audio exchange with the caller.
- **Agent stays in call**: After a successful `connect()`, your agent remains in the conference. You can use `barge()`, `whisper()`, and `spy()` to control who hears your agent's audio.
- **Connect then leave**: To replicate a handoff pattern where the agent exits after connecting the other parties, use `connect()` followed by `close()`.
- **Close behavior depends on state**: In ANSWERED, `close()` ends the call for the agent and caller. In CONNECTED, `close()` removes the agent while the caller and callee can remain connected.
- **Universal termination**: Any active state can transition to DISCONNECTED when the call is terminated server-side. Your application can also end the call explicitly with `disconnect()`.

## Next Steps

- [Call Commands](/concepts/call-commands) - Detailed reference for each command
- [Event Handling](/concepts/event-handling) - How to listen for state change events
- [API Reference](/reference/api-reference) - Full `ActiveCall` method reference