From f078df78058ae82a02ce5b23e9e3a99a0917a53d Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Sun, 26 Apr 2026 10:16:25 -0400 Subject: [PATCH 1/2] runner: expire Daily rooms after 4h to mirror Pipecat Cloud session limit Runner-created Daily rooms previously had no expiration when callers posted partial `dailyRoomProperties` (e.g. `{"start_video_off": true}`). The model-default `exp=None` and `eject_at_room_exp=False` meant Daily's cron never cleaned them up, so rooms accumulated indefinitely. Encode the policy in the runner: define `PIPECAT_CLOUD_ROOM_EXP_HOURS=4.0`, inject `exp` and `eject_at_room_exp=True` into user-supplied properties via `setdefault` (so explicit caller values still win), and pass `room_exp_duration` to all four `configure()` call sites. --- src/pipecat/runner/run.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index a53dea519..be0b8575e 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -70,6 +70,7 @@ import asyncio import mimetypes import os import sys +import time import uuid from contextlib import asynccontextmanager from http import HTTPMethod @@ -106,6 +107,9 @@ os.environ["ENV"] = "local" TELEPHONY_TRANSPORTS = ["twilio", "telnyx", "plivo", "exotel"] +# Mirror Pipecat Cloud's 4-hour max session limit so dev rooms get cleaned up. +PIPECAT_ROOM_EXP_HOURS = 4.0 + RUNNER_DOWNLOADS_FOLDER: str | None = None RUNNER_HOST: str = "localhost" RUNNER_PORT: int = 7860 @@ -546,7 +550,7 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): from pipecat.runner.daily import configure async with aiohttp.ClientSession() as session: - room_url, token = await configure(session) + room_url, token = await configure(session, room_exp_duration=PIPECAT_ROOM_EXP_HOURS) # Start the bot in the background with empty body for GET requests bot_module = _get_bot_module() @@ -604,6 +608,11 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): # Parse dailyRoomProperties if provided room_properties = None if daily_room_properties_dict: + # Apply Pipecat Cloud's session policy if caller didn't override. + daily_room_properties_dict.setdefault( + "exp", time.time() + PIPECAT_ROOM_EXP_HOURS * 3600 + ) + daily_room_properties_dict.setdefault("eject_at_room_exp", True) try: room_properties = DailyRoomProperties(**daily_room_properties_dict) logger.debug(f"Using custom room properties: {room_properties}") @@ -624,7 +633,10 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): # Continue without custom properties room_url, token = await configure( - session, room_properties=room_properties, token_properties=token_properties + session, + room_exp_duration=PIPECAT_ROOM_EXP_HOURS, + room_properties=room_properties, + token_properties=token_properties, ) runner_args = DailyRunnerArguments(room_url=room_url, token=token, body=body) result = { @@ -699,7 +711,11 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): # Create Daily room with SIP capabilities async with aiohttp.ClientSession() as session: try: - room_config = await configure(session, sip_caller_phone=data.get("From")) + room_config = await configure( + session, + sip_caller_phone=data.get("From"), + room_exp_duration=PIPECAT_ROOM_EXP_HOURS, + ) except Exception as e: logger.error(f"Failed to create Daily room: {e}") raise HTTPException( @@ -819,7 +835,7 @@ async def _run_daily_direct(args: argparse.Namespace): logger.info("Running with direct Daily connection...") async with aiohttp.ClientSession() as session: - room_url, token = await configure(session) + room_url, token = await configure(session, room_exp_duration=PIPECAT_ROOM_EXP_HOURS) # Direct connections have no request body, so use empty dict runner_args = DailyRunnerArguments(room_url=room_url, token=token) From ef183d0c96361d5455575a948eed95b032bf2acb Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Sun, 26 Apr 2026 10:17:03 -0400 Subject: [PATCH 2/2] Add changelog for #4374 --- changelog/4374.changed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/4374.changed.md diff --git a/changelog/4374.changed.md b/changelog/4374.changed.md new file mode 100644 index 000000000..30ef7f2b6 --- /dev/null +++ b/changelog/4374.changed.md @@ -0,0 +1 @@ +- Daily rooms created by the development runner (`pipecat.runner.run`) now expire after 4 hours with `eject_at_room_exp=True`, mirroring Pipecat Cloud's max session limit. Previously, runner-created rooms inherited a 2-hour expiration on the default code paths and had no expiration at all when callers posted partial `dailyRoomProperties` (e.g. `{"start_video_off": true}`) to `/start`, causing rooms to accumulate indefinitely. Explicit `exp` and `eject_at_room_exp` values in `dailyRoomProperties` are still respected.