From d9c14d5591f8a74ef9058d8883e5c115b28a0795 Mon Sep 17 00:00:00 2001 From: Daniel Reis Date: Wed, 7 Oct 2026 16:01:40 +0100 Subject: [PATCH] [FIX] ai_tool: allow tool use by users without Administration rights Since Odoo 19.0, ir.model is no longer readable by internal users (base.group_user gets perm_read=0). _get_tool_definition and _execute_tool read model_id.model to dispatch the tool, so a call made under a non-admin environment raised an AccessError. Read the related model through sudo() only for the ir.model lookup; the returned env stays bound to the calling user, so tool methods still run with the caller's permissions. Assisted-by: Devin:SWE-2 High --- ai_tool/models/ai_tool.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ai_tool/models/ai_tool.py b/ai_tool/models/ai_tool.py index 68cd76d3..7d23c854 100644 --- a/ai_tool/models/ai_tool.py +++ b/ai_tool/models/ai_tool.py @@ -36,7 +36,7 @@ class AiTool(models.Model): ) def _get_tool_definition(self): - func = getattr(self.env[self.model_id.model], self.function_name) + func = getattr(self.env[self.model_id.sudo().model], self.function_name) return { "name": self.name, "description": self.description, @@ -77,18 +77,18 @@ def _ai_post_message_parse_body(self, message): def _execute_tool(self, *args, record=None, **kwargs): if self.kind == "generic": - return getattr(self.env[self.model_id.model], self.function_name)( + return getattr(self.env[self.model_id.sudo().model], self.function_name)( *args, **kwargs ) if not record: raise ValueError("Record must be provided for non-generic tools") if self.kind == "generic_model": - return getattr(self.env[self.model_id.model], self.function_name)( + return getattr(self.env[self.model_id.sudo().model], self.function_name)( *args, record=record, **kwargs ) - elif record._name != self.model_id.model: + elif record._name != self.model_id.sudo().model: raise ValueError( f"Record model {record._name} does not match tool " - f"model {self.model_id.model}" + f"model {self.model_id.sudo().model}" ) return getattr(record, self.function_name)(*args, **kwargs) or {}