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

# After-hours Voicemail and Notification

Handle calls outside business hours by collecting a message, transcribing it, and notifying the team.

## Overview

This use case demonstrates:
- Time-of-day routing (business hours vs. after hours)
- Pre-answer connect during business hours
- AI voicemail recording and transcription
- Database storage of voicemails
- Team notification via Slack/webhook

**State flow (business hours):** PENDING -> CONNECTED -> DISCONNECTED

**State flow (after hours):** PENDING -> ANSWERED -> DISCONNECTED

## Example

```python
@client.on(events.INCOMING_CALL)
async def after_hours_handler(call: ActiveCall):
    current_hour = datetime.now().hour
    is_business_hours = 9 <= current_hour < 17

    if is_business_hours:
        # During business hours: connect to the original callee and leave
        await call.connect()
        await call.close()
        return

    # After hours: AI takes a message
    await call.answer()
    await call.send_audio(
        await tts.synthesize(
            "Thank you for calling. Our office is currently closed. "
            "Please leave a message and we'll get back to you "
            "on the next business day."
        )
    )

    # Record the caller's message
    audio_chunks = []
    async for chunk in call.audio_stream():
        audio_chunks.append(chunk)

        # Detect end of message (silence detection via AI)
        if await ai_model.detect_end_of_message(chunk):
            break

    # Transcribe and store the message
    full_audio = b"".join(audio_chunks)
    transcript = await stt.transcribe(full_audio)

    await db.save_voicemail(
        caller=call.caller_number,
        audio=full_audio,
        transcript=transcript,
    )

    # Notify the team
    await slack.send_message(
        channel="#incoming-calls",
        text=f"Voicemail from {call.caller_number}:\n{transcript}",
    )

    await call.send_audio(
        await tts.synthesize("Thank you. Your message has been recorded. Goodbye.")
    )
    await call.disconnect()
```

## How It Works

1. When a call arrives, the handler checks the current time
2. **During business hours**: the call is connected to the original callee using `connect()` without answering, and the agent leaves with `close()`. The caller goes straight to ringing the callee.
3. **After hours**: the AI answers, plays a voicemail prompt, and records the caller's message
4. The AI detects when the caller has finished speaking (silence detection)
5. The recorded audio is transcribed using a speech-to-text service
6. Both the raw audio and transcript are saved to the database
7. A notification is sent to a Slack channel (or any webhook) with the caller's number and transcript
8. The AI confirms the message was recorded and ends the call

## Key Commands Used

- [`connect()`](/concepts/call-commands#connectring_time_seconds60) - Route to the original callee during business hours (pre-answer)
- [`close()`](/concepts/call-commands#close) - Leave the call after connecting the caller to the callee
- [`answer()`](/concepts/call-commands#answer) - Answer for voicemail after hours
- [`audio_stream()`](/concepts/audio-streaming#receiving-audio) - Record the caller's message
- [`send_audio()`](/concepts/audio-streaming#sending-audio) - Play the voicemail prompt
- [`disconnect()`](/concepts/call-commands#disconnect) - End the voicemail call after the goodbye prompt

## Related

- [AI Receptionist with Database Lookup](/use-cases/database-lookup) - Answering with CRM context
- [Interactive Notifications](/use-cases/interactive-notifications) - Following up on recorded messages