From 3763bef2caa90b1643c68c04f8acd2b117006239 Mon Sep 17 00:00:00 2001 From: Cameron Pfiffer Date: Mon, 15 Dec 2025 13:47:25 -0800 Subject: [PATCH] Fix OAuth session persistence and function model filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three critical fixes for Letta OAuth integration: 1. OAuth session storage (oauth_sessions.py:126) - Cast expires_at to int to fix Pydantic validation error - Was causing sessions to fail silently with float timestamp 2. Model filtering (models.py:389) - Allow function/pipe models to pass through filter - Letta agents aren't in database, were being filtered out 3. Model access check (models.py:343) - Allow function/pipe models to pass access checks - Return early if model_info is None instead of raising error Without these fixes: - OAuth tokens weren't persisted (401 errors on all API calls) - Letta agents loaded but filtered out (empty model list) - Chat requests failed with "Model not found" (400 errors) 👾 Generated with Letta Code Co-Authored-By: Letta --- backend/open_webui/models/oauth_sessions.py | 2 +- backend/open_webui/utils/models.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/models/oauth_sessions.py b/backend/open_webui/models/oauth_sessions.py index b0e465dbe..a2da2f884 100644 --- a/backend/open_webui/models/oauth_sessions.py +++ b/backend/open_webui/models/oauth_sessions.py @@ -123,7 +123,7 @@ class OAuthSessionTable: "user_id": user_id, "provider": provider, "token": self._encrypt_token(token), - "expires_at": token.get("expires_at"), + "expires_at": int(token.get("expires_at")) if token.get("expires_at") else None, "created_at": current_time, "updated_at": current_time, } diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index a87a7487e..ff5b61069 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -340,7 +340,9 @@ def check_model_access(user, model): else: model_info = Models.get_model_by_id(model.get("id")) if not model_info: - raise Exception("Model not found") + # Model not in database (e.g., function/pipe models like Letta agents) + # Allow access by default + return elif not ( user.id == model_info.user_id or has_access( @@ -384,6 +386,10 @@ def get_filtered_models(models, user): ) ): filtered_models.append(model) + else: + # Model not in database (e.g., function/pipe models like Letta agents) + # Allow through by default + filtered_models.append(model) return filtered_models else: -- 2.51.2