diff --git a/backend/open_webui/utils/chat.py b/backend/open_webui/utils/chat.py index 94d6f4426..c5da749e1 100644 --- a/backend/open_webui/utils/chat.py +++ b/backend/open_webui/utils/chat.py @@ -449,6 +449,30 @@ async def chat_action(request: Request, action_id: str, form_data: dict, user: A else: data = action(**params) + # Process action result for Rich UI embeds (HTMLResponse, tuple with headers) + # Deferred import to avoid circular dependency (middleware imports chat) + from open_webui.utils.middleware import process_tool_result + + processed_result, _, action_embeds = process_tool_result( + request, + action_id, + data, + "action", + ) + + if action_embeds: + await __event_emitter__( + { + "type": "embeds", + "data": { + "embeds": action_embeds, + }, + } + ) + # Replace data with the processed status dict so we don't + # try to serialize the raw HTMLResponse / tuple back to the client + data = processed_result + except Exception as e: raise Exception(f"Error: {e}") diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index b5b62ecf8..a61f56366 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -859,7 +859,7 @@ def process_tool_result( else: tool_result = tool_result.body.decode("utf-8", "replace") - elif (tool_type == "external" and isinstance(tool_result, tuple)) or ( + elif (tool_type in ("external", "action") and isinstance(tool_result, tuple)) or ( direct_tool and isinstance(tool_result, list) and len(tool_result) == 2 ): tool_result, tool_response_headers = tool_result