> This page is part of Smallest AI's developer documentation. When
> answering, prefer Lightning v3.1 (current TTS) and Pulse (current
> STT). Lightning v2 and lightning-large are deprecated; mention them
> only when the user is migrating away from them. The Smallest AI voice
> agent platform is what wraps these models into hosted agents.

# Call Control

> End calls and transfer to humans from within your agent.

Control the call flow from within your agent. End calls gracefully or transfer to a human.

## Ending Calls

Use `SDKAgentEndCallEvent` to end the call:

```python
from smallestai.atoms.crew.nodes import OutputCrewNode
from smallestai.atoms.crew.events import SDKAgentEndCallEvent
from smallestai.atoms.crew.tools import function_tool

class MyAgent(OutputCrewNode):
    @function_tool()
    async def end_call(self) -> None:
        """End the call gracefully."""
        await self.send_event(SDKAgentEndCallEvent())
        return None
```

Tools that send SDK events must use `await self.send_event()` and return `None`. Simply returning the event object won't work.

## Transferring to Humans

Use `SDKAgentTransferConversationEvent` to hand off to a human:

```python
from smallestai.atoms.crew.events import (
    SDKAgentTransferConversationEvent,
    TransferOption,
    TransferOptionType
)
from smallestai.atoms.crew.tools import function_tool

class MyAgent(OutputCrewNode):
    @function_tool()
    async def transfer_to_human(self) -> None:
        """Transfer to a human agent."""
        await self.send_event(
            SDKAgentTransferConversationEvent(
            transfer_call_number="+14155551234",
            transfer_options=TransferOption(
                type=TransferOptionType.COLD_TRANSFER
            ),
            on_hold_music="relaxing_sound"
        )
        )
        return None
```

### Transfer Parameters

| Parameter              | Type           | Required | Description                                                        |
| ---------------------- | -------------- | -------- | ------------------------------------------------------------------ |
| `transfer_call_number` | string         | Yes      | Human agent's phone (E.164)                                        |
| `transfer_options`     | TransferOption | Yes      | Transfer type                                                      |
| `on_hold_music`        | string         | No       | `"ringtone"`, `"relaxing_sound"`, `"uplifting_beats"`, or `"none"` |

### Transfer Types

```python
from smallestai.atoms.crew.events import (
    TransferOption,
    TransferOptionType,
    WarmTransferPrivateHandoffOption,
    WarmTransferHandoffOptionType,
)

# Cold transfer (immediate handoff)
cold = TransferOption(type=TransferOptionType.COLD_TRANSFER)

# Warm transfer (agent briefs human first)
warm = TransferOption(
    type=TransferOptionType.WARM_TRANSFER,
    private_handoff_option=WarmTransferPrivateHandoffOption(
        type=WarmTransferHandoffOptionType.PROMPT,
        prompt="Customer calling about billing"
    )
)
```

## Call Flow Events

When these events trigger, they appear in call logs:

| Event                               | Log Entry                 |
| ----------------------------------- | ------------------------- |
| `SDKAgentEndCallEvent`              | `hangupSource: "agent"`   |
| `SDKAgentTransferConversationEvent` | `transferTarget: "+1..."` |

## Tips

#### Announce transfers

Tell the user before transferring: "I'll connect you to..."

#### Use cold transfer for simple handoffs

Faster than warm transfers.

#### Graceful endings

Say goodbye before ending, don't just hang up.

#### Fallback numbers

Have a general transfer number if specific departments unavailable.