Skip to main content

ai-search-browser-use

Use this skill when a task needs AI-assisted web research via a real browser. Uses Chrome CDP (Chrome DevTools Protocol) as the primary automation method, with browser-use as fallback. Supports Gemini + Qwen queries with consolidated answers and citations.

Source facts

Repository
JWCodeWrote/Agent_Skills_Plugin
Last source activity
January 26, 2026 at 06:36
Detected SKILL.md language
English
Stars
3
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
5 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
ai-search-browser-use
description
Use this skill when a task needs AI-assisted web research via a real browser. Uses Chrome CDP (Chrome DevTools Protocol) as the primary automation method, with browser-use as fallback. Supports Gemini + Qwen queries with consolidated answers and citations.
# AI Search Browser Use ## Overview Enable reliable AI-assisted web research by using **Chrome CDP** as the primary automation method. This approach connects to a Chrome instance with remote debugging enabled, allowing direct control over browser tabs for Gemini + Qwen queries. **Key Advantage**: CDP uses your logged-in Chrome profile, so no additional authentication is needed for Gemini and Qwen. ## Workflow ### 0) Check Prerequisites **Required: Python + websockets** ```bash python3 --version python3 -m pip show websockets ``` If `websockets` is missing, install in a venv: ```bash python3 -m venv .venv ./.venv/bin/pip install websockets ``` **Required: Google Chrome** Verify Chrome is installed: ```bash "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --version ``` If not installed: - macOS: `brew install --cask google-chrome` - Windows: `winget install --id Google.Chrome -e` ### 1) Launch Chrome with CDP (Remote Debugging) **CRITICAL**: CDP requires a **non-default user data directory**. This serves two purposes: 1. **Allows running alongside your normal Chrome**: By using a separate `--user-data-dir`, the CDP Chrome runs as an independent process. You can continue using your regular Chrome without any conflicts. 2. **Preserves login state**: By cloning your existing Chrome profile, the CDP Chrome inherits your logged-in sessions for Gemini, Qwen, and other sites. **Clone your existing Chrome profile**: ```bash # Clean and clone profile (only needed once, or when login expires) rm -rf /tmp/chrome-ai-profile rsync -a "$HOME/Library/Application Support/Google/Chrome/" /tmp/chrome-ai-profile/ # Launch CDP Chrome (runs independently from your normal Chrome!) "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ --remote-debugging-port=9222 \ --user-data-dir="/tmp/chrome-ai-profile" \ "https://gemini.google.com/app" "https://chat.qwen.ai/" & ``` > **Note**: You will see two Chrome icons in your dock - one is your normal Chrome, the other is the CDP instance. **For Windows**: ```powershell # Clone profile Remove-Item -Recurse -Force "$env:TEMP\chrome-ai-profile" -ErrorAction SilentlyContinue Copy-Item -Recurse "$env:LOCALAPPDATA\Google\Chrome\User Data" "$env:TEMP\chrome-ai-profile" # Launch Chrome with remote debugging Start-Process "chrome.exe" -ArgumentList "--remote-debugging-port=9222", "--user-data-dir=$env:TEMP\chrome-ai-profile", "https://gemini.google.com/app", "https://chat.qwen.ai/" ``` ### 2) Verify CDP Connection Confirm Chrome is listening on the debugging port: ```bash curl -s http://localhost:9222/json | python3 -m json.tool ``` You should see a JSON array containing page entries for both `gemini.google.com` and `chat.qwen.ai`: ```json [ { "type": "page", "url": "https://gemini.google.com/app", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/..." }, { "type": "page", "url": "https://chat.qwen.ai/", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/..." } ] ``` ### 3) Run AI Queries via CDP Use the CDP Query Script to send queries to both AI engines: **ai_query.py**: ```python import asyncio import websockets import json import subprocess import sys def find_page(pages, host): for page in pages: if page.get("type") == "page" and host in page.get("url", ""): return page return None async def send_query(ws_url, query_text, wait_seconds=30): async with websockets.connect(ws_url) as ws: input_js = f""" (function() {{ const editor = document.querySelector('div[contenteditable="true"]') || document.querySelector('textarea'); if (editor) {{ editor.focus(); document.execCommand('insertText', false, `{query_text}`); editor.dispatchEvent(new Event('input', {{bubbles: true}})); return 'input-ok'; }} return 'editor-not-found'; }})() """ await ws.send(json.dumps({"id": 1, "method": "Runtime.evaluate", "params": {"expression": input_js}})) await ws.recv() click_js = """ (function() { const btn = document.querySelector('button[aria-label*="傳送"]') || document.querySelector('button[aria-label*="Send"]') || document.querySelector('button[type="submit"]'); if (btn) { btn.click(); return 'clicked'; } return 'button-not-found'; })() """ await ws.send(json.dumps({"id": 2, "method": "Runtime.evaluate", "params": {"expression": click_js}})) await ws.recv() await asyncio.sleep(wait_seconds) extract_js = """ (function() { const md = document.querySelectorAll('.markdown'); if (md.length > 0) return md[md.length - 1].innerText; return 'No response found'; })() """ await ws.send(json.dumps({"id": 3, "method": "Runtime.evaluate", "params": {"expression": extract_js}})) response = await ws.recv() result = json.loads(response) return result.get("result", {}).get("result", {}).get("value", "No content") async def main(query): result = subprocess.run(["curl", "-s", "http://localhost:9222/json"], capture_output=True, text=True) pages = json.loads(result.stdout) gemini = find_page(pages, "gemini.google.com") qwen = find_page(pages, "chat.qwen.ai") if not gemini or not qwen: print("Error: Gemini or Qwen page not found.") return g = await send_query(gemini["webSocketDebuggerUrl"], query) q = await send_query(qwen["webSocketDebuggerUrl"], query) print("GEMINI RESPONSE:\\n" + g) print("\\n" + "=" * 50 + "\\n") print("QWEN RESPONSE:\\n" + q) if __name__ == "__main__": query = sys.argv[1] if len(sys.argv) > 1 else "請用繁體中文回答:什麼是區塊鏈?" asyncio.run(main(query)) ``` Run: ```bash python3 ai_query.py "你的查詢問題" ``` ### 4) Synthesize and Cite Results - Consolidate results from Gemini and Qwen into a single, coherent answer. - Highlight consensus points first, then disagreements or uncertainties. - Provide citations for each major claim using this format: - `Source Title — Domain — URL` - If the AI answers do not provide sources, open the referenced sites and cite the primary sources directly. ### 5) Close AI Pages (Recommended) or Chrome Instance After completing the task, you have two options: #### Option A: Close only the AI pages (keep Chrome running) Use CDP to close only the Gemini and Qwen tabs, keeping the Chrome instance running for other tasks: **close_ai_pages.py**: ```python import json import subprocess import asyncio import websockets async def close_page(browser_ws_url, target_id): async with websockets.connect(browser_ws_url) as ws: await ws.send(json.dumps({ "id": 1, "method": "Target.closeTarget", "params": {"targetId": target_id} })) await ws.recv() def main(): result = subprocess.run(["curl", "-s", "http://localhost:9222/json"], capture_output=True, text=True) pages = json.loads(result.stdout) # Get browser WebSocket URL version = subprocess.run(["curl", "-s", "http://localhost:9222/json/version"], capture_output=True, text=True) browser_ws = json.loads(version.stdout).get("webSocketDebuggerUrl") for page in pages: url = page.get("url", "") if "gemini.google.com" in url or "chat.qwen.ai" in url: target_id = page.get("id") print(f"Closing: {url}") asyncio.run(close_page(browser_ws, target_id)) if __name__ == "__main__": main() ``` Run: ```bash python3 close_ai_pages.py ``` Or use a quick one-liner (bash + Python): ```bash # Get page IDs and close them curl -s http://localhost:9222/json | python3 -c " import json, sys, subprocess, asyncio, websockets pages = json.load(sys.stdin) version = json.loads(subprocess.run(['curl', '-s', 'http://localhost:9222/json/version'], capture_output=True, text=True).stdout) browser_ws = version.get('webSocketDebuggerUrl') async def close(browser_ws, tid, url): async with websockets.connect(browser_ws) as ws: await ws.send(json.dumps({'id': 1, 'method': 'Target.closeTarget', 'params': {'targetId': tid}})) await ws.recv() print(f'Closed: {url}') for p in pages: url = p.get('url', '') if 'gemini.google.com' in url or 'chat.qwen.ai' in url: asyncio.run(close(browser_ws, p['id'], url)) " ``` #### Option B: Close the entire CDP Chrome instance If you want to close the entire Chrome instance (releases port 9222): ```bash # macOS pkill -f "Google Chrome.*--remote-debugging-port=9222" ``` ```powershell # Windows Get-Process chrome | Where-Object {$_.CommandLine -match "remote-debugging-port=9222"} | Stop-Process -Force ``` --- ## CDP Troubleshooting | Problem | Cause | Solution | | ----------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | `curl: (7) Failed to connect` | Chrome not running with `--remote-debugging-port` | Re-launch Chrome with the CDP flags | | WebSocket connection refused | Page ID changed | Re-fetch `http://localhost:9222/json` for new WebSocket URLs | | `editor not found` | Page not fully loaded | Wait a few seconds and retry | | Login page instead of `/app` | Profile lacks login state | Re-clone a properly logged-in Chrome profile | | `DevTools remote debugging requires a non-default data directory` | Using default profile | Always use `/tmp/chrome-ai-profile` or custom path | | Port 9222 already in use | Previous CDP instance not closed | Kill the previous instance first | --- ## Best Practices 1. **Always use CDP as the primary method** for authenticated queries. 2. **Clone the profile each time** to ensure a fresh, logged-in state. 3. **Wait longer for complex prompts** (30–60 seconds). 4. **Close the CDP Chrome instance after use** to release port 9222. 5. **Update the cloned profile** if login expires. --- ## Fallback: browser-use If CDP is unavailable (e.g., Chrome not installed, or CDP setup fails), use `browser-use` as a fallback: ### Install browser-use ```bash brew install pipx
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub