Bug: preToolUse / Agent hooks do not emit for built-in Web search in Cursor Agent (works in Claude Code)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Built-in web search is invoked during an Agent turn, but Cursor does not surface that tool usage through hooks (or not under a visible preToolUse) to our observer.

Same Hook is setup in Claude Code, it Fires a Hook with the “ToolSearch”

Steps to Reproduce

Ask a prompt like “Do a Search on Google to find best soccer player in 2026”

[Need a local Python server listening to all hooks]
Observe incoming hook events on the server (log hook_event_name and for preToolUse, the tool name).

(Optional control) Repeat with Claude Code wired to the same Agent Monitor endpoint and trigger WebSearch there.

Expected Behavior

When the Cursor Agent runs built-in web search, the hook pipeline should behave like other tools: at minimum preToolUse (and matching postToolUse) should fire with a recognizable tool name (e.g. WebSearch or equivalent), so third-party integrations can audit, deny, or log it.

Operating System

MacOS

Version Information

Version: 3.3.30
VSCode Version: 1.105.1
Commit: 3dc559280adc5f931ade8e25c7b85393842acf30
Date: 2026-05-09T18:28:42.332Z (5 days ago)
Layout: editor
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Darwin arm64 25.5.0

For AI issues: which model did you use?

Auto (mixed)

Does this stop you from using Cursor

No - Cursor works, but with this issue

I’m having the same issue. I’d like to screen URLs for security using custom tooling and I’m not seeing WebSearch tool in any of my hooks.

Thanks for the detailed bug report.

Before I can confirm whether this is a bug or a configuration gap, I need a few things:

  1. Do you see a “WebSearch” tool card in the agent UI when the agent runs a search? (Not just search-like text in the answer, but a visible tool step — similar to how Shell or Read show up.) If the model answered from its own knowledge without invoking the tool, hooks wouldn’t fire because no tool call occurred.

  2. Are other hook events working in the same session? For example, do preToolUse events fire for tools like Shell, Read, or Edit?

  3. What tool name are you matching on? Cursor’s built-in web search tool emits hooks with tool_name: "WebSearch" (PascalCase). Claude Code uses ToolSearch instead. If your hook script filters by tool name, make sure it matches WebSearch (or uses a catch-all).

  4. Could you try the same prompt with a specific model (e.g., Claude Sonnet 4.5 instead of Auto)? Auto mode routes to different backend configurations, and I want to narrow down whether the issue is model-dependent.

  5. Could you share your hooks.json configuration? Specifically, what steps you have configured for preToolUse.

One note: Cursor’s WebSearch hooks use a server-side mechanism that works differently from local tool hooks. I want to confirm what you’re seeing before filing this with our team.

  1. It does look like it did a search, but looks different that regular tool use indeed.

  2. Shell, Read, Edit are working fine, but I see a different in the UI:

  1. I log everything, so I log every event on “PreToolUse” and do not see it trigger

  2. We got a winner, with a specific model like claude-4.5, I do see the Hook fire with tool_name=WebSearch !

5 . see the hook config (redacted)


{

    "version": 1,

"hooks": {

"beforeSubmitPrompt": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"beforeShellExecution": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"afterShellExecution": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"beforeMCPExecution": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"afterMCPExecution": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"beforeReadFile": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"afterFileEdit": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"afterAgentResponse": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"afterAgentThought": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"stop": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"preToolUse": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"postToolUse": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"postToolUseFailure": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"sessionStart": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"sessionEnd": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"subagentStart": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ],

"subagentStop": [

        {

"command": "PUSH_KEY='XXXX' REMOTE_HOOKS_BASE_URL='http://localhost:8129' bash '/Users/XXXX/.cursor/hooks/script-hooks.sh' --client cursor"

        }

      ]

    }

  }




Thanks for the thorough answers. This implies it’s a bug on our side.

The issue is that Auto mode uses a different internal configuration path for WebSearch that doesn’t wire up the hook pipeline. The different UI rendering you noticed (“Explored 1 search” vs the standard tool card for Shell/Read) is a visual indicator of this same difference.

I will file this with our engineering team. In the meantime, using a named model is the workaround if you need hooks to fire reliably for WebSearch.

Thanks ! How can I track this bug to see when it will be released, our current project will depend on it.

I noticed the same thing with Web Fetch. Should I create a separate ticket or can these both be handled as part of the same problem? Thanks.

This is the same underlying issue. No need to create a separate ticket; the fix for one covers the other.

Same workaround applies: if you need hooks to fire reliably for WebFetch, use a named model instead of Auto for now.