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.

# AI Agent with Human Escalation

The AI handles the conversation but can escalate to a human agent when it detects it cannot help, with full context handoff.

## Overview

This use case demonstrates:
- AI-first handling with continuous conversation
- Intelligent escalation detection
- Saving full conversation context to a database for the human agent
- Seamless handoff via `connect()` and `close()`

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

## Example

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

    escalate = False
    conversation_summary = []

    async for chunk in call.audio_stream():
        transcript = await stt.transcribe(chunk)
        conversation_summary.append({"role": "caller", "text": transcript})

        # Check if the AI decides to escalate
        ai_response = await ai_model.generate(chunk)
        response_text = await stt.transcribe(ai_response)
        conversation_summary.append({"role": "ai", "text": response_text})

        if await ai_model.should_escalate(conversation_summary):
            escalate = True
            break

        await call.send_audio(ai_response)

    if escalate:
        # Save conversation context for the human agent
        await db.save_call_context(
            call_id=call.call_id,
            caller=call.caller_number,
            summary=conversation_summary,
        )

        await call.send_audio(
            await tts.synthesize(
                "Let me connect you with a specialist who can help."
            )
        )

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

## How It Works

1. The AI answers the call and begins a normal conversation
2. Each turn is transcribed and added to a running conversation summary
3. After each AI response, the model evaluates whether it should escalate (e.g., the caller is frustrated, the request is outside the AI's capabilities, or the caller explicitly asks for a human)
4. If escalation is triggered:
   - The full conversation summary is saved to a database, keyed by `call.call_id`
   - The caller hears a brief transition message
   - The call is connected to the original callee using `connect()`, then the agent leaves with `close()`
5. The human agent can retrieve the conversation context from the database to continue seamlessly
6. If the AI handles the call successfully, it ends the call with `disconnect()`

## Key Commands Used

- [`answer()`](/concepts/call-commands#answer) - Answer the incoming call
- [`audio_stream()`](/concepts/audio-streaming#receiving-audio) - Receive caller audio
- [`send_audio()`](/concepts/audio-streaming#sending-audio) - Play AI responses
- [`connect()`](/concepts/call-commands#connectring_time_seconds60) - Connect to the original callee
- [`close()`](/concepts/call-commands#close) - Leave the call after connecting the caller to the callee
- [`disconnect()`](/concepts/call-commands#disconnect) - End the call when the AI fully handled it

## Related

- [AI Receptionist with Database Lookup](/use-cases/database-lookup) - Route based on caller identity
- [Call Monitoring and Coaching](/use-cases/call-monitoring-and-coaching) - Human-AI collaboration during calls