From 939ba75e97ce17bf6b5ac5be8006c0c7cd5db6cf Mon Sep 17 00:00:00 2001 From: Kian Jones <11655409+kianjones9@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:23:30 -0800 Subject: [PATCH] fix: properly limit runs query (#6357) * letta * tweak * cancellation to 100 * openapi changes --- fern/openapi.json | 6 ++++-- letta/server/rest_api/routers/v1/agents.py | 1 + letta/server/rest_api/routers/v1/internal_runs.py | 2 +- letta/server/rest_api/routers/v1/runs.py | 4 ++-- letta/services/run_manager.py | 8 +++++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/fern/openapi.json b/fern/openapi.json index ffc387f1..d3f52665 100644 --- a/fern/openapi.json +++ b/fern/openapi.json @@ -10782,7 +10782,8 @@ "anyOf": [ { "type": "integer", - "maximum": 1000 + "maximum": 1000, + "minimum": 1 }, { "type": "null" @@ -13722,7 +13723,8 @@ "anyOf": [ { "type": "integer", - "maximum": 1000 + "maximum": 1000, + "minimum": 1 }, { "type": "null" diff --git a/letta/server/rest_api/routers/v1/agents.py b/letta/server/rest_api/routers/v1/agents.py index abf08ef3..960d0944 100644 --- a/letta/server/rest_api/routers/v1/agents.py +++ b/letta/server/rest_api/routers/v1/agents.py @@ -1596,6 +1596,7 @@ async def cancel_message( statuses=[RunStatus.created, RunStatus.running], ascending=False, agent_id=agent_id, # NOTE: this will override agent_ids if provided + limit=100, # Limit to 10 most recent active runs for cancellation ) run_ids = [run.id for run in run_ids] else: diff --git a/letta/server/rest_api/routers/v1/internal_runs.py b/letta/server/rest_api/routers/v1/internal_runs.py index d8af05c4..6788141c 100644 --- a/letta/server/rest_api/routers/v1/internal_runs.py +++ b/letta/server/rest_api/routers/v1/internal_runs.py @@ -52,7 +52,7 @@ async def list_runs( after: Optional[str] = Query( None, description="Run ID cursor for pagination. Returns runs that come after this run ID in the specified sort order" ), - limit: Optional[int] = Query(100, description="Maximum number of runs to return", le=1000), + limit: Optional[int] = Query(100, description="Maximum number of runs to return", ge=1, le=1000), order: Literal["asc", "desc"] = Query( "desc", description="Sort order for runs by creation time. 'asc' for oldest first, 'desc' for newest first" ), diff --git a/letta/server/rest_api/routers/v1/runs.py b/letta/server/rest_api/routers/v1/runs.py index d4b9ee8b..1d6451bc 100644 --- a/letta/server/rest_api/routers/v1/runs.py +++ b/letta/server/rest_api/routers/v1/runs.py @@ -61,7 +61,7 @@ async def list_runs( after: Optional[str] = Query( None, description="Run ID cursor for pagination. Returns runs that come after this run ID in the specified sort order" ), - limit: Optional[int] = Query(100, description="Maximum number of runs to return", le=1000), + limit: Optional[int] = Query(100, description="Maximum number of runs to return", ge=1, le=1000), order: Literal["asc", "desc"] = Query( "desc", description="Sort order for runs by creation time. 'asc' for oldest first, 'desc' for newest first" ), @@ -132,7 +132,7 @@ async def list_active_runs( agent_ids = None active_runs = await runs_manager.list_runs( - actor=actor, statuses=[RunStatus.created, RunStatus.running], agent_ids=agent_ids, background=background + actor=actor, statuses=[RunStatus.created, RunStatus.running], agent_ids=agent_ids, background=background, limit=100 ) return active_runs diff --git a/letta/services/run_manager.py b/letta/services/run_manager.py index 21a94070..da2e67f7 100644 --- a/letta/services/run_manager.py +++ b/letta/services/run_manager.py @@ -267,9 +267,11 @@ class RunManager: query = await _apply_pagination_async(query, before, after, session, ascending=ascending) - # Apply limit - if limit: - query = query.limit(limit) + # Apply limit (always enforce a maximum to prevent unbounded queries) + # If no limit specified, default to 100; enforce maximum of 1000 + effective_limit = limit if limit is not None else 100 + effective_limit = min(effective_limit, 1000) + query = query.limit(effective_limit) result = await session.execute(query) rows = result.all()