From 7aed9291cd53282b5148deafdc1804cca155003f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Wed, 8 Apr 2026 18:22:27 +0200 Subject: [PATCH] fix(ai-chat): preload web_search action tool when driver is enabled (#19461) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - When `WEB_SEARCH_DRIVER` is set to a non-native driver (e.g. `EXA`), the `web_search` action tool was only listed in the tool catalog and had to be discovered via `learn_tools` before use. Worse, `system-prompt-builder` explicitly instructed the model **not** to call `web_search` whenever it wasn't in the preloaded set, so even setting `EXA_API_KEY` correctly resulted in the model never calling Exa. - Fix: preload `web_search` from the registry alongside the other action tools when `shouldUseNativeSearch()` is false, mirroring how native provider search is already injected into `directTools`. The system prompt builder picks this up automatically and advertises `web_search` as a ready-to-use tool. - Unrelated: pass `isSystemBuild: true` to the messageThread upgrade command's migration build. ## Test plan - [ ] With `WEB_SEARCH_DRIVER=EXA` and `EXA_API_KEY` set, ask the chat agent for current/news information and verify it calls `web_search` directly (not via `learn_tools` / `execute_tool`) and that Exa is hit. - [ ] With `WEB_SEARCH_PREFER_NATIVE=true`, verify native provider search is still used and the action tool is not preloaded. - [ ] With `WEB_SEARCH_DRIVER=DISABLED`, verify behavior is unchanged (`shouldUseNativeSearch()` returns true → no Exa preload). - [ ] Run the 1-21 fix-message-thread-view-and-label-identifier upgrade command on a workspace and confirm the migration builds/runs as a system build. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 --- ...essage-thread-view-and-label-identifier.command.ts | 1 + .../ai/ai-chat/services/chat-execution.service.ts | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts index 737160af9d..dba76ce1a7 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500014000-fix-message-thread-view-and-label-identifier.command.ts @@ -155,6 +155,7 @@ export class FixMessageThreadViewAndLabelIdentifierCommand extends ActiveOrSuspe workspaceId, applicationUniversalIdentifier: twentyStandardFlatApplication.universalIdentifier, + isSystemBuild: true, }, ); diff --git a/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts b/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts index 2f062fcbbb..239e522981 100644 --- a/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/ai/ai-chat/services/chat-execution.service.ts @@ -142,8 +142,15 @@ export class ChatExecutionService { `Built tool catalog with ${toolCatalog.length} tools, ${skillCatalog.length} skills available`, ); + const useNativeSearch = this.webSearchService.shouldUseNativeSearch(); + + const toolNamesToPreload = [ + ...COMMON_PRELOAD_TOOLS, + ...(useNativeSearch ? [] : ['web_search']), + ]; + const preloadedTools = await this.toolRegistry.getToolsByName( - COMMON_PRELOAD_TOOLS, + toolNamesToPreload, toolContext, ); @@ -163,8 +170,6 @@ export class ChatExecutionService { registeredModel.modelId, ); - const useNativeSearch = this.webSearchService.shouldUseNativeSearch(); - const { tools: nativeSearchTools, callableToolNames: searchToolNames } = useNativeSearch ? this.getNativeWebSearchTools(registeredModel)