or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/pipecat-ai@0.0.x

docs

core-concepts.mdindex.mdpipeline.mdrunner.mdtransports.mdturns.md
tile.json

tessl/pypi-pipecat-ai

tessl install tessl/pypi-pipecat-ai@0.0.0

An open source framework for building real-time voice and multimodal conversational AI agents with support for speech-to-text, text-to-speech, LLMs, and multiple transport protocols

extensions.mddocs/utilities/

Extensions

Pipecat extensions provide specialized functionality for telephony and call handling applications.

IVR Navigator

Automated Interactive Voice Response (IVR) menu navigation system.

IVRNavigator

{ .api }
from pipecat.extensions.ivr.ivr_navigator import IVRNavigator, IVRMenu, IVRStatus

class IVRNavigator(FrameProcessor):
    """Navigate IVR phone menus automatically.

    Automates navigation through phone tree menus using:
    - DTMF tone sequencing
    - Menu state machine
    - Verbal response handling
    - Timeout management

    Use Cases:
    - Automated phone tree navigation
    - IVR system testing
    - Call routing automation
    - Menu option selection

    Args:
        menu: IVR menu structure definition
        timeout_seconds: Timeout for menu responses
        retry_attempts: Number of retry attempts per menu

    Example:
        # Define menu structure
        menu = IVRMenu(
            id="main",
            prompt_keywords=["main menu", "options"],
            options=[
                IVROption(digit="1", next_menu_id="sales"),
                IVROption(digit="2", next_menu_id="support")
            ]
        )

        # Create navigator
        navigator = IVRNavigator(
            menu=menu,
            timeout_seconds=10
        )

        # Add to pipeline
        pipeline = Pipeline([
            transport.input(),
            stt,
            navigator,
            # ... rest of pipeline
        ])
    """

    def __init__(
        self,
        menu: IVRMenu,
        timeout_seconds: int = 10,
        retry_attempts: int = 3
    ):
        pass

    async def navigate(self, target_menu_id: str):
        """Navigate to a specific menu.

        Args:
            target_menu_id: ID of target menu
        """
        pass

    async def select_option(self, digit: str):
        """Select a menu option by digit.

        Args:
            digit: DTMF digit (0-9, *, #)
        """
        pass

    def get_current_status(self) -> IVRStatus:
        """Get current navigation status.

        Returns:
            Current IVR status
        """
        pass

IVR Data Structures

{ .api }
from pipecat.extensions.ivr.ivr_navigator import IVRMenu, IVROption, IVRStatus

class IVRMenu:
    """IVR menu definition.

    Attributes:
        id (str): Unique menu identifier
        prompt_keywords (List[str]): Keywords to detect this menu
        options (List[IVROption]): Available menu options
        timeout_seconds (int): Menu timeout
        parent_menu_id (Optional[str]): Parent menu for back navigation
    """

    def __init__(
        self,
        id: str,
        prompt_keywords: List[str],
        options: List[IVROption],
        timeout_seconds: int = 10,
        parent_menu_id: Optional[str] = None
    ):
        pass


class IVROption:
    """IVR menu option.

    Attributes:
        digit (str): DTMF digit for this option (0-9, *, #)
        description (str): Option description
        next_menu_id (Optional[str]): Next menu to navigate to
        action (Optional[Callable]): Action to execute
    """

    def __init__(
        self,
        digit: str,
        description: str = "",
        next_menu_id: Optional[str] = None,
        action: Optional[Callable] = None
    ):
        pass


class IVRStatus(Enum):
    """IVR navigation status.

    Values:
        IDLE: Not navigating
        LISTENING: Listening for menu prompt
        NAVIGATING: Actively navigating
        COMPLETED: Navigation completed
        FAILED: Navigation failed
        TIMEOUT: Navigation timed out
    """
    IDLE = "idle"
    LISTENING = "listening"
    NAVIGATING = "navigating"
    COMPLETED = "completed"
    FAILED = "failed"
    TIMEOUT = "timeout"

Voicemail Detection

Automated voicemail and answering machine detection system.

VoicemailDetector

{ .api }
from pipecat.extensions.voicemail.voicemail_detector import VoicemailDetector, VoicemailDetectionResult

class VoicemailDetector(FrameProcessor):
    """Detect voicemail and answering machines.

    Detects voicemail systems using:
    - Beep detection
    - Machine/human discrimination
    - Pattern recognition
    - Duration analysis

    Use Cases:
    - Skip voicemail in outbound calls
    - Leave automated messages
    - Call disposition handling
    - Call completion testing

    Args:
        beep_threshold: Threshold for beep detection
        min_silence_duration_ms: Minimum silence for voicemail
        max_greeting_duration_ms: Maximum greeting length
        on_voicemail_detected: Callback for voicemail detection

    Example:
        # Define callback
        async def handle_voicemail(result: VoicemailDetectionResult):
            if result.is_voicemail:
                print("Voicemail detected, leaving message")
                await task.queue_frame(
                    TTSSpeakFrame("Please call us back")
                )

        # Create detector
        detector = VoicemailDetector(
            beep_threshold=0.7,
            on_voicemail_detected=handle_voicemail
        )

        # Add to pipeline
        pipeline = Pipeline([
            transport.input(),
            stt,
            detector,
            # ... rest of pipeline
        ])
    """

    def __init__(
        self,
        beep_threshold: float = 0.7,
        min_silence_duration_ms: int = 1000,
        max_greeting_duration_ms: int = 30000,
        on_voicemail_detected: Optional[Callable] = None
    ):
        pass

    async def start_detection(self):
        """Start voicemail detection."""
        pass

    async def stop_detection(self):
        """Stop voicemail detection."""
        pass

    def is_detecting(self) -> bool:
        """Check if actively detecting.

        Returns:
            True if detection is active
        """
        pass

    def get_detection_result(self) -> Optional[VoicemailDetectionResult]:
        """Get current detection result.

        Returns:
            Detection result or None
        """
        pass

Voicemail Data Structures

{ .api }
from pipecat.extensions.voicemail.voicemail_detector import VoicemailDetectionResult

class VoicemailDetectionResult:
    """Voicemail detection result.

    Attributes:
        is_voicemail (bool): True if voicemail detected
        confidence (float): Detection confidence (0.0-1.0)
        beep_detected (bool): True if beep was detected
        greeting_duration_ms (float): Greeting duration
        detection_time_ms (float): Time to detection
        method (str): Detection method used
    """

    def __init__(
        self,
        is_voicemail: bool,
        confidence: float,
        beep_detected: bool = False,
        greeting_duration_ms: float = 0.0,
        detection_time_ms: float = 0.0,
        method: str = "pattern"
    ):
        pass

Usage Patterns

IVR Navigation Example

{ .api }
from pipecat.extensions.ivr.ivr_navigator import IVRNavigator, IVRMenu, IVROption

# Define multi-level menu structure
main_menu = IVRMenu(
    id="main",
    prompt_keywords=["main menu", "options", "press"],
    options=[
        IVROption(digit="1", description="Sales", next_menu_id="sales"),
        IVROption(digit="2", description="Support", next_menu_id="support"),
        IVROption(digit="0", description="Operator", action=transfer_to_operator)
    ]
)

sales_menu = IVRMenu(
    id="sales",
    prompt_keywords=["sales", "department"],
    options=[
        IVROption(digit="1", description="New customer"),
        IVROption(digit="2", description="Existing customer"),
        IVROption(digit="9", description="Return", next_menu_id="main")
    ],
    parent_menu_id="main"
)

# Create navigator with menu tree
navigator = IVRNavigator(
    menu=main_menu,
    timeout_seconds=15,
    retry_attempts=2
)

# Navigate to specific option
await navigator.navigate("sales")
await navigator.select_option("1")  # Select new customer

# Check status
status = navigator.get_current_status()
if status == IVRStatus.COMPLETED:
    print("Navigation successful")

Voicemail Handling Example

{ .api }
from pipecat.extensions.voicemail.voicemail_detector import VoicemailDetector

# Define voicemail callback
async def on_voicemail(result: VoicemailDetectionResult):
    """Handle voicemail detection."""
    print(f"Voicemail detected (confidence: {result.confidence})")

    if result.beep_detected:
        # Leave message after beep
        await task.queue_frames([
            TTSSpeakFrame(
                "Hello, this is an automated message. "
                "Please call us back at 555-1234. Thank you."
            ),
            EndFrame()  # End call after message
        ])
    else:
        # Hang up if no beep
        await task.queue_frame(EndFrame())

# Create detector
detector = VoicemailDetector(
    beep_threshold=0.75,
    min_silence_duration_ms=1500,
    max_greeting_duration_ms=25000,
    on_voicemail_detected=on_voicemail
)

# Add to outbound call pipeline
pipeline = Pipeline([
    transport.input(),
    stt,
    detector,
    user_agg,
    llm,
    tts,
    transport.output()
])

Combined IVR + Voicemail Example

{ .api }
from pipecat.extensions.ivr.ivr_navigator import IVRNavigator
from pipecat.extensions.voicemail.voicemail_detector import VoicemailDetector

async def outbound_call_pipeline():
    """Complete outbound call handling pipeline."""

    # Configure voicemail detection
    async def handle_voicemail(result):
        if result.is_voicemail:
            print("Voicemail detected, leaving message")
            await task.queue_frame(
                TTSSpeakFrame("This is an important message...")
            )
            await task.cancel()  # End after message

    detector = VoicemailDetector(
        on_voicemail_detected=handle_voicemail
    )

    # Configure IVR navigation
    menu = IVRMenu(
        id="main",
        prompt_keywords=["main menu"],
        options=[
            IVROption(digit="2", description="Support")
        ]
    )

    navigator = IVRNavigator(menu=menu)

    # Build pipeline
    pipeline = Pipeline([
        transport.input(),
        stt,
        detector,      # Detect voicemail first
        navigator,     # Navigate IVR if human answers
        user_agg,
        llm,
        tts,
        transport.output()
    ])

    task = PipelineTask(pipeline)
    await task.run()

Best Practices

IVR Navigation

{ .api }
# Good: Define complete menu structure
menu = IVRMenu(
    id="main",
    prompt_keywords=["menu", "options", "press"],
    options=[
        IVROption("1", "Sales", next_menu_id="sales"),
        IVROption("2", "Support", next_menu_id="support")
    ],
    timeout_seconds=10
)

# Good: Handle navigation failures
@navigator.event_handler("on_navigation_failed")
async def handle_failure(reason: str):
    logger.error(f"IVR navigation failed: {reason}")
    # Fallback to operator
    await transfer_to_operator()

# Bad: No error handling
navigator = IVRNavigator(menu=menu)
# What happens if navigation fails?

Voicemail Detection

{ .api }
# Good: Conservative thresholds
detector = VoicemailDetector(
    beep_threshold=0.75,          # High confidence
    min_silence_duration_ms=1500, # Allow for pauses
    max_greeting_duration_ms=30000 # Standard greeting length
)

# Good: Handle both outcomes
async def handle_detection(result):
    if result.is_voicemail:
        if result.confidence > 0.8:
            # High confidence - leave message
            await leave_message()
        else:
            # Low confidence - hang up
            await end_call()
    else:
        # Human answered - continue conversation
        pass

# Bad: Aggressive thresholds
detector = VoicemailDetector(
    beep_threshold=0.3,  # Too sensitive
    min_silence_duration_ms=500  # Too short
)
# Will false-positive on human pauses

Resource Management

{ .api }
# Good: Clean up resources
async def run_outbound_call():
    detector = VoicemailDetector()
    navigator = IVRNavigator(menu=menu)

    try:
        pipeline = Pipeline([
            transport.input(),
            detector,
            navigator,
            # ... rest
        ])

        task = PipelineTask(pipeline)
        await task.run()

    finally:
        # Clean up
        await detector.stop_detection()
        await navigator.cancel()