Skill: phheng/web-research-assistant (version 0.1.0)

--- name: web-research-assistant description: AI-powered web research assistant that leverages BrowserAct API to supplement restricted web access by searching the internet for additional information. Designed for OpenClaw and Claude Code. --- # Web Research Assistant This skill leverages **BrowserAct API** to provide powerful web research capabilities. When primary web access is restricted or blocked, it automatically searches the internet to find and extract relevant information, ensuring your research tasks are completed successfully. ## ✨ OpenClaw & Claude Code Optimized **🚀 Works Seamlessly with OpenClaw and Claude Code** | Platform | Status | Installation | |----------|--------|--------------| | **OpenClaw** | ✅ **Highly Recommended** | Copy to `~/.openclaw/skills/` | | **Claude Code** | ✅ **Highly Recommended** | Native skill support | | **OpenCode** | ✅ Fully Supported | Copy to `~/.opencode/skills/` | | **Cursor** | ✅ Fully Supported | Copy to `~/.cursor/skills/` | **Why This Skill?** - 🎯 **Purpose-built for OpenClaw and Claude Code** - 🔄 **Auto-recovery** when web access is restricted - 🌐 **Global access** - no IP or geoblocking issues - 💰 **Cost-effective** - saves token usage - ⚡ **Fast execution** - BrowserAct powered ## 🎯 When to Use **Web Access Restricted? No Problem!** Use this skill when: - 🔒 Target websites block AI assistant access - 🌍 Geographic restrictions limit content access - 🔐 Paywalls prevent data extraction - ⏱️ Need quick supplemental information - 📊 Research requires multiple data sources - 🔍 Need current information beyond cached data ## 🔑 API Key Guidance Before running, check the `BROWSERACT_API_KEY` environment variable. If not set, request the API key from the user: **Required Message**: > "Please provide your BrowserAct API Key from [BrowserAct Console](https://www.browseract.com/reception/integrations) to enable web research capabilities." ## 🛠️ Input Parameters Configure research based on your needs: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `query` | string | - | Research topic or question | | `engine` | string | google | Search engine (google, bing, duckduckgo) | | `max_results` | number | 10 | Results to retrieve (1-50) | | `content_type` | string | all | Content filter (all, news, articles, data) | | `time_range` | string | past_month | Time filter (anytime, past_day/week/month/year) | ## 💻 Quick Start ```bash # Basic research python web-research-assistant/scripts/research.py "AI technology trends" # Deep research with more results python web-research-assistant/scripts/research.py "competitor analysis" --max-results 20 # Current news research python web-research-assistant/scripts/research.py "market trends" --content-type news # Save to file python web-research-assistant/scripts/research.py "industry data" -o research_report.md ``` ## 📊 Output **Structured Research Data:** - Titles, URLs, snippets, and relevance scores - Key facts and statistics extraction - Source citations and references - Comprehensive research report ## 🎪 What This Skill Does 1. **🔄 Auto-Supplement** - When direct access fails, automatically searches the web 2. **🌐 Global Search** - Bypasses geographic restrictions via BrowserAct 3. **📈 Multi-Source** - Aggregates data from multiple search results 4. **✅ Validation** - Cross-references information for accuracy 5. **📋 Report Generation** - Creates comprehensive research reports --- ## 能力特性 （Features） 1.**没有幻觉，确保稳定精准提取数据**：预设工作流，规避AI 生成式幻觉。 2.**没有人机验证问题**：内置绕过机制，无需处理 reCAPTCHA 或其他验证挑战。 3.**没有 IP 访问限制和电子围栏**：突破地域 IP 限制，确保全球范围内稳定访问。 4.**执行速度更敏捷**：相比纯 AI 驱动的浏览器自动化方案，任务执行更快速。 5.**极高的成本效益**：相比大量消耗 Token 的 AI 方案，能显著降低数据获取成本。 --- ## 🔧 BrowserAct API Integration ``` Research Request → BrowserAct Search → Data Extraction → Validation → Final Report ``` **Powered by BrowserAct MCP** for reliable, unrestricted web access. --- ## ⚠️ Error Handling - **Invalid API Key**: Report to user, do not retry - **Search Failed**: Automatic retry with fallback engine - **No Results**: Return partial data with notification - **Timeout**: Extended timeout for large research tasks --- ## 📖 Best Practices 1. Use **specific queries** for targeted results 2. Apply **time filters** for current information 3. **Cross-reference** key findings 4. Choose **appropriate content types** for research goals 5. **Validate** statistics with multiple sources --- ## 🔗 Related Skills - `amazon-competitor-analyzer` - Amazon competitive intelligence - `google-maps-search-api-skill` - Business data extraction - `google-news-api-skill` - News monitoring --- **Version**: 1.0.0 **Updated**: 2026-02-08 **API**: BrowserAct MCP **Template ID**: `TEMPLATE_ID_HERE`

path: scripts/research.py
content: #!/usr/bin/env python3
"""
Web Research Assistant - BrowserAct Skill

This script performs web research and searches the internet for information
when primary web access is restricted or blocked.

Template ID: TEMPLATE_ID_HERE
"""

import os
import json
import argparse
import requests
from typing import Optional, Dict, List


BROWSERACT_API_KEY = os.environ.get("BROWSERACT_API_KEY")
BROWSERACT_MCP_TOKEN = os.environ.get("BROWSERACT_MCP_TOKEN")
MCP_SERVER_URL = "https://mcp.browseract.com/"


def execute_web_search(query: str, search_engine: str = "google", max_results: int = 10, 
                       content_type: str = "all", time_range: str = "past_month") -> Dict:
    """
    Execute a web search using BrowserAct MCP.
    
    Args:
        query: Search query string
        search_engine: Search engine to use (google, bing, duckduckgo)
        max_results: Maximum number of results
        content_type: Type of content (all, news, articles, reports, data)
        time_range: Time filter (anytime, past_day, past_week, past_month, past_year)
    
    Returns:
        Dictionary containing search results
    """
    payload = {
        "action": "search",
        "query": query,
        "engine": search_engine,
        "max_results": max_results,
        "content_type": content_type,
        "time_range": time_range,
        "options": {
            "extract_data": True,
            "include_snippets": True,
            "follow_redirects": True
        }
    }
    
    response = requests.post(
        MCP_SERVER_URL,
        headers={
            "Authorization": f"Bearer {BROWSERACT_MCP_TOKEN}",
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=60000
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Search failed: {response.status_code} - {response.text}")


def extract_key_information(results: Dict) -> Dict:
    """
    Extract key information from search results.
    
    Args:
        results: Search results dictionary
    
    Returns:
        Dictionary with extracted key information
    """
    extracted = {
        "total_results": 0,
        "key_facts": [],
        "statistics": [],
        "sources": [],
        "summary": ""
    }
    
    if "results" in results:
        extracted["total_results"] = len(results["results"])
        
        for result in results["results"][:10]:
            if "title" in result:
                extracted["sources"].append({
                    "title": result["title"],
                    "url": result.get("url", ""),
                    "snippet": result.get("snippet", "")
                })
            
            # Extract potential statistics (numbers with context)
            if "snippet" in result:
                snippet = result["snippet"]
                # Simple heuristic for extracting statistics
                if any(char.isdigit() for char in snippet):
                    extracted["statistics"].append(snippet[:200])
    
    # Generate summary
    if extracted["sources"]:
        extracted["summary"] = f"Found {extracted['total_results']} relevant sources"
    
    return extracted


def format_research_report(results: Dict, extracted: Dict, query: str) -> str:
    """
    Format research report as markdown.
    
    Args:
        results: Raw search results
        extracted: Extracted key information
        query: Original search query
    
    Returns:
        Formatted markdown report
    """
    report = f"# Web Research Report\n\n"
    report += f"**Query**: {query}\n\n"
    report += f"**Date**: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
    
    report += "## Executive Summary\n\n"
    report += f"{extracted['summary']}\n\n"
    
    report += "## Key Findings\n\n"
    for i, fact in enumerate(extracted["key_facts"][:5], 1):
        report += f"{i}. {fact}\n"
    
    if not extracted["key_facts"]:
        report += "_No specific key facts extracted from search results._\n"
    
    report += "\n## Statistics & Data\n\n"
    for stat in extracted["statistics"][:5]:
        report += f"- {stat}\n"
    
    if not extracted["statistics"]:
        report += "_No statistics found in search results._\n"
    
    report += "\n## Data Sources\n\n"
    for i, source in enumerate(extracted["sources"][:10], 1):
        report += f"### {i}. {source['title']}\n"
        report += f"**URL**: {source['url']}\n"
        report += f"**Snippet**: {source['snippet'][:300]}...\n\n"
    
    report += "\n## Recommendations\n\n"
    report += "- Verify key findings with additional sources\n"
    report += "- Cross-reference statistics with official data\n"
    report += "- Check publication dates for currency\n"
    report += "- Consider multiple perspectives on the topic\n"
    
    return report


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        description="Web Research Assistant - Supplement restricted web access with internet search"
    )
    parser.add_argument("query", help="Research topic or question to search for")
    parser.add_argument("--engine", "-e", default="google", 
                       choices=["google", "bing", "duckduckgo"],
                       help="Search engine to use")
    parser.add_argument("--max-results", "-m", type=int, default=10,
                       help="Maximum number of results (1-50)")
    parser.add_argument("--content-type", "-c", default="all",
                       choices=["all", "news", "articles", "reports", "data"],
                       help="Type of content to search for")
    parser.add_argument("--time-range", "-t", default="past_month",
                       choices=["anytime", "past_day", "past_week", "past_month", "past_year"],
                       help="Time filter for results")
    parser.add_argument("--output", "-o", help="Output file path for report")
    parser.add_argument("--format", "-f", default="markdown",
                       choices=["markdown", "json"],
                       help="Output format")
    parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
    
    args = parser.parse_args()
    
    if not BROWSERACT_MCP_TOKEN:
        print("Error: BROWSERACT_MCP_TOKEN environment variable not set")
        print("Get your token from: https://www.browseract.com/reception/integrations")
        return 1
    
    try:
        if args.verbose:
            print(f"Researching: {args.query}")
            print(f"Using engine: {args.engine}")
            print(f"Content type: {args.content_type}")
            print(f"Time range: {args.time_range}")
        
        # Execute search
        results = execute_web_search(
            args.query,
            args.engine,
            args.max_results,
            args.content_type,
            args.time_range
        )
        
        # Extract key information
        extracted = extract_key_information(results)
        
        # Generate report
        if args.format == "markdown":
            report = format_research_report(results, extracted, args.query)
        else:
            report = json.dumps({
                "query": args.query,
                "results": results,
                "extracted": extracted
            }, indent=2, ensure_ascii=False)
        
        # Output
        if args.output:
            with open(args.output, 'w', encoding='utf-8') as f:
                f.write(report)
            if args.verbose:
                print(f"Report saved to: {args.output}")
        else:
            print(report)
        
        if args.verbose:
            print(f"\nTotal sources found: {extracted['total_results']}")
            print(f"Sources used in report: {len(extracted['sources'])}")
        
        return 0
    
    except Exception as e:
        print(f"Error: {e}")
        return 1


if __name__ == "__main__":
    exit(main())


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)