diff --git a/fern/openapi.json b/fern/openapi.json index 4fa4a0fc..fdf98425 100644 --- a/fern/openapi.json +++ b/fern/openapi.json @@ -8718,19 +8718,26 @@ "get": { "tags": ["conversations"], "summary": "List Conversations", - "description": "List all conversations for an agent.", + "description": "List all conversations for an agent (or all conversations if agent_id not provided).", "operationId": "list_conversations", "parameters": [ { "name": "agent_id", "in": "query", - "required": true, + "required": false, "schema": { - "type": "string", - "description": "The agent ID to list conversations for", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The agent ID to list conversations for (optional - returns all conversations if not provided)", "title": "Agent Id" }, - "description": "The agent ID to list conversations for" + "description": "The agent ID to list conversations for (optional - returns all conversations if not provided)" }, { "name": "limit", diff --git a/letta/server/rest_api/routers/v1/conversations.py b/letta/server/rest_api/routers/v1/conversations.py index c0d691ca..fef31b06 100644 --- a/letta/server/rest_api/routers/v1/conversations.py +++ b/letta/server/rest_api/routers/v1/conversations.py @@ -60,14 +60,14 @@ async def create_conversation( @router.get("/", response_model=List[Conversation], operation_id="list_conversations") async def list_conversations( - agent_id: str = Query(..., description="The agent ID to list conversations for"), + agent_id: Optional[str] = Query(None, description="The agent ID to list conversations for (optional - returns all conversations if not provided)"), limit: int = Query(50, description="Maximum number of conversations to return"), after: Optional[str] = Query(None, description="Cursor for pagination (conversation ID)"), summary_search: Optional[str] = Query(None, description="Search for text within conversation summaries"), server: SyncServer = Depends(get_letta_server), headers: HeaderParams = Depends(get_headers), ): - """List all conversations for an agent.""" + """List all conversations for an agent (or all conversations if agent_id not provided).""" actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id) return await conversation_manager.list_conversations( agent_id=agent_id, diff --git a/letta/services/conversation_manager.py b/letta/services/conversation_manager.py index 9c709ae5..7d374092 100644 --- a/letta/services/conversation_manager.py +++ b/letta/services/conversation_manager.py @@ -103,16 +103,16 @@ class ConversationManager: @trace_method async def list_conversations( self, - agent_id: str, + agent_id: Optional[str], actor: PydanticUser, limit: int = 50, after: Optional[str] = None, summary_search: Optional[str] = None, ) -> List[PydanticConversation]: - """List conversations for an agent with cursor-based pagination. + """List conversations for an agent (or all conversations) with cursor-based pagination. Args: - agent_id: The agent ID to list conversations for + agent_id: The agent ID to list conversations for (optional - returns all if not provided) actor: The user performing the action limit: Maximum number of conversations to return after: Cursor for pagination (conversation ID) @@ -126,16 +126,20 @@ class ConversationManager: if summary_search: from sqlalchemy import and_ + # Build where conditions + conditions = [ + ConversationModel.organization_id == actor.organization_id, + ConversationModel.summary.isnot(None), + ConversationModel.summary.contains(summary_search), + ] + + # Add agent_id filter if provided + if agent_id is not None: + conditions.append(ConversationModel.agent_id == agent_id) + stmt = ( select(ConversationModel) - .where( - and_( - ConversationModel.agent_id == agent_id, - ConversationModel.organization_id == actor.organization_id, - ConversationModel.summary.isnot(None), - ConversationModel.summary.contains(summary_search), - ) - ) + .where(and_(*conditions)) .order_by(ConversationModel.created_at.desc()) .limit(limit) )