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 Commands

Call commands are sent over the per-call media connection associated with an `ActiveCall`. The control connection delivers events and manages connection health, but it does not carry `answer()`, `connect()`, `close()`, or `disconnect()`.

## `answer()`

Answers an incoming call and establishes the audio stream between your server and the caller.

```python
await call.answer()
```

After answering, the call enters the **ANSWERED** state. Your server is now responsible for audio:
- Use `call.audio_stream()` to receive the caller's audio
- Use `call.send_audio()` to play audio back to the caller
- If you don't send any audio, the caller hears silence

## `connect(ring_time_seconds=60)`

Connects the call to the original callee (the SIM card or called number associated with the connector). This initiates a 3-way conference between the caller, the callee, and your agent.

**Parameters:**
- `ring_time_seconds` (optional, default: 60) - How long to ring the callee before giving up.

```python
await call.connect()
```

After a successful connect, the call enters the **CONNECTED** state. Your agent stays in the call and can:
- Listen to the conversation
- Send audio to the conference
- Switch between `barge()`, `whisper()`, and `spy()` modes
- Leave the conference with `close()`

> **Note:** The destination cannot be changed. `connect()` always routes to the original callee (SIM or called number). To route calls to alternate destinations, **Transfer** and **Forward** commands will be available in a future release.

## `whisper()`

Switches the agent's audio mode so that only the callee (the connected third party) can hear the agent. The caller cannot hear the agent's audio.

```python
await call.connect()
await call.whisper()
await call.send_audio(private_guidance_audio)
```

## `barge()`

Switches the agent's audio mode so that both the caller and callee can hear the agent. This is the default mode after `connect()`.

```python
await call.barge()
await call.send_audio(announcement_audio)
```

## `spy()`

Switches the agent to listen-only mode. Neither the caller nor the callee can hear the agent, but the agent can still receive audio from the call.

```python
await call.spy()
async for chunk in call.audio_stream():
    await analyze_audio(chunk)
```

## `close()`

Closes the call and releases SDK resources. The behavior depends on the current call state:

- After `connect()`, the agent leaves the call while the caller and callee remain connected to each other
- After `answer()` without `connect()`, the call ends for both the agent and the caller

Raises `WSSCallError` if the close command fails.

```python
await call.close()
```

## `disconnect()`

Ends the call for all parties. Use this when your application wants the server to terminate the conversation entirely.

```python
await call.disconnect()
```

---

## Common Call Flows

These patterns combine the commands above into typical real-world scenarios.

### 1. Basic AI Agent (Answer and Talk)

The simplest flow: answer the call and let the AI handle the conversation.

```python
@client.on(events.INCOMING_CALL)
async def handle_call(call: ActiveCall):
    await call.answer()

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

    await call.close()
```

**State flow:** PENDING -> ANSWERED -> DISCONNECTED

### 2. AI Front-desk (Answer, Gather Info, Connect and Leave)

The agent answers to greet or authenticate the caller, then connects to the original callee and leaves the call.

```python
@client.on(events.INCOMING_CALL)
async def front_desk_flow(call: ActiveCall):
    await call.answer()

    # AI gathers information, verifies identity, etc.
    # ...

    # Connect to the original callee, then leave the conference
    await call.connect()
    await call.close()
```

**State flow:** PENDING -> ANSWERED -> CONNECTED -> DISCONNECTED

### 3. AI Assistant (Connect and Whisper)

The agent connects the caller to the callee and privately coaches one side.

```python
@client.on(events.INCOMING_CALL)
async def assistant_flow(call: ActiveCall):
    await call.answer()

    # Connect the caller to the original callee
    await call.connect()

    # Switch to whisper mode to privately guide the callee
    await call.whisper()
    await call.send_audio(private_guidance_pcm)
```

**State flow:** PENDING -> ANSWERED -> CONNECTED

### 4. Direct Routing (Connect Without Answering)

Route the call to the original callee without your agent answering first. The caller stays on ringing.

```python
@client.on(events.INCOMING_CALL)
async def route_call(call: ActiveCall):
    await call.connect()
```

**State flow:** PENDING -> CONNECTED

### 5. End the Call for Everyone

Use `disconnect()` when your application needs to terminate the conversation instead of just leaving it.

```python
@client.on(events.INCOMING_CALL)
async def route_or_end(call: ActiveCall):
    await call.answer()
    await call.send_audio(await tts.synthesize("Goodbye."))
    await call.disconnect()
```

## Next Steps

- [Call States](/concepts/call-states-and-lifecycle) - Understand which states allow which commands
- [Audio Streaming](/concepts/audio-streaming) - How to send and receive audio
- [Use Cases](/use-cases/database-lookup) - See these commands applied in real-world scenarios