Skip to main content

Overview

The Web Search plugin enables real-time web searching using Tavily AI’s powerful search API. Get relevant, up-to-date information from across the web directly in your Nadoo workflows.
Category: Utility | Author: Nadoo Team | Version: 1.0.0 | License: MIT

Features

Real-time Search

Get up-to-date information from the web

AI-Powered

Tavily AI ranks results by relevance

Configurable Depth

Choose between basic and advanced search

Country Filtering

Filter results by country

Installation

Prerequisites

You need a Tavily API key:
  1. Visit tavily.com
  2. Sign up for a free account
  3. Get your API key from the dashboard

Set Environment Variable

export TAVILY_API_KEY="tvly-xxxxxxxxxxxxx"

Download Pre-built

# Download from releases
wget https://github.com/nadoo-ai/official-plugins/releases/download/v1.0.0/web-search-1.0.0.nadoo-plugin

# Install to workspace
nadoo-plugin install web-search-1.0.0.nadoo-plugin --workspace your-workspace-id

Build from Source

# Clone repository
git clone https://github.com/nadoo-ai/official-plugins
cd official-plugins

# Build web-search plugin
python build_plugins.py

# Install
nadoo-plugin install dist/web-search-1.0.0.nadoo-plugin --workspace your-workspace-id

Tools

Search the web and get relevant results.

Parameters

ParameterTypeRequiredDefaultDescription
querystringYes-Search query
max_resultsnumberNo5Number of results (1-20)
search_depthstringNo"basic"Search depth: "basic" or "advanced"
countrystringNo-Country filter (e.g., “south korea”, “united states”)

Response Format

{
  "success": true,
  "query": "latest AI news",
  "results": [
    {
      "title": "Article Title",
      "url": "https://example.com/article",
      "content": "Article content snippet...",
      "score": 0.95
    }
  ],
  "answer": "Direct answer to the query (if available)",
  "images": []
}

Usage Examples

from nadoo_plugin.api import ToolsClient

tools = ToolsClient(base_url, token, context)

# Simple search
result = tools.invoke(
    tool_name="web-search:search",
    parameters={"query": "latest AI news"}
)

# Access results
for item in result["results"]:
    print(f"{item['title']}: {item['url']}")
    print(f"Relevance: {item['score']}")
    print(f"Content: {item['content'][:200]}...")
# More comprehensive search with advanced depth
result = tools.invoke(
    tool_name="web-search:search",
    parameters={
        "query": "machine learning trends 2024",
        "max_results": 10,
        "search_depth": "advanced"
    }
)

# Advanced search provides:
# - More results
# - Better relevance ranking
# - Deeper analysis
# Search within specific country
result = tools.invoke(
    tool_name="web-search:search",
    parameters={
        "query": "AI companies",
        "country": "south korea",
        "max_results": 5
    }
)

# Get news from specific region
result = tools.invoke(
    tool_name="web-search:search",
    parameters={
        "query": "tech news today",
        "country": "united states"
    }
)

In AI Agent Workflow

from nadoo_flow import BaseNode, NodeResult, NodeContext, WorkflowContext

class WebSearchNode(BaseNode):
    """Node that searches the web"""

    def __init__(self):
        super().__init__(
            node_id="web_search",
            node_type="search",
            name="WebSearch",
            config={}
        )

    async def execute(
        self,
        node_context: NodeContext,
        workflow_context: WorkflowContext
    ) -> NodeResult:
        # Get query from user input
        query = node_context.input_data.get("query", "")

        if not query:
            return NodeResult(
                success=False,
                error="No search query provided"
            )

        # Search the web
        result = await self.call_tool(
            tool_name="web-search:search",
            parameters={
                "query": query,
                "max_results": 5,
                "search_depth": "basic"
            }
        )

        if result.get("success"):
            return NodeResult(
                success=True,
                output={
                    "query": query,
                    "results": result["results"],
                    "answer": result.get("answer")
                }
            )
        else:
            return NodeResult(
                success=False,
                error=result.get("error", "Search failed")
            )

RAG Pattern (Search + LLM)

from nadoo_plugin.api import ToolsClient, LLMClient

class RAGSearchNode(BaseNode):
    """Search web and generate answer with LLM"""

    async def execute(
        self,
        node_context: NodeContext,
        workflow_context: WorkflowContext
    ) -> NodeResult:
        query = node_context.input_data.get("question")

        # Step 1: Search the web
        search_result = await self.call_tool(
            tool_name="web-search:search",
            parameters={
                "query": query,
                "max_results": 5,
                "search_depth": "advanced"
            }
        )

        if not search_result.get("success"):
            return NodeResult(success=False, error="Search failed")

        # Step 2: Build context from search results
        context = "\n\n".join([
            f"[{i+1}] {r['title']}\n{r['content']}"
            for i, r in enumerate(search_result["results"])
        ])

        # Step 3: Generate answer with LLM
        llm_result = await self.call_llm(
            messages=[
                {
                    "role": "system",
                    "content": "Answer based on the provided search results. Include source numbers."
                },
                {
                    "role": "user",
                    "content": f"Question: {query}\n\nSearch Results:\n{context}"
                }
            ]
        )

        return NodeResult(
            success=True,
            output={
                "question": query,
                "answer": llm_result.content,
                "sources": [
                    {"title": r["title"], "url": r["url"]}
                    for r in search_result["results"]
                ]
            }
        )
# Search multiple topics and aggregate
queries = [
    "Python async programming",
    "FastAPI tutorials",
    "LangChain documentation"
]

all_results = []

for query in queries:
    result = tools.invoke(
        tool_name="web-search:search",
        parameters={
            "query": query,
            "max_results": 3
        }
    )

    if result.get("success"):
        all_results.extend(result["results"])

# Now process all_results

Search Depth Comparison

Error Handling

result = tools.invoke(
    tool_name="web-search:search",
    parameters={"query": "AI news"}
)

if result.get("success"):
    # Process results
    for item in result["results"]:
        print(item["title"])
else:
    # Handle error
    error = result.get("error", "Unknown error")
    print(f"Search failed: {error}")

    # Common errors:
    # - "TAVILY_API_KEY not set"
    # - "Invalid API key"
    # - "Rate limit exceeded"
    # - "Network error"

Rate Limits

Tavily API has rate limits based on your plan:
Free Tier: 1,000 requests/monthPro Tier: Higher limits availableCheck your usage at tavily.com/dashboard

Best Practices

  • Be specific: “Python async best practices 2024” vs “Python async”
  • Use keywords, not full sentences
  • Include context when needed
  • Use basic for most queries (faster, cheaper)
  • Use advanced for research or ambiguous queries
  • Monitor your API usage
  • Check success before processing
  • Use score field to rank results
  • Consider using top 3-5 results for context
  • Use RAG pattern for better answers
  • Let LLM synthesize information from multiple sources
  • Include source citations

Use Cases

Research Assistant

Help users research topics with up-to-date information

News Monitoring

Track latest news and trends in specific domains

Fact Checking

Verify information against current web sources

Content Discovery

Find relevant articles, tutorials, and resources

Troubleshooting

Error: TAVILY_API_KEY environment variable not setSolution:
export TAVILY_API_KEY="your-key-here"
Error: Invalid API keySolution:
  • Verify your API key at tavily.com
  • Ensure no extra spaces or quotes
  • Check if key is active
Error: Rate limit exceededSolution:
  • Wait before retrying
  • Upgrade your Tavily plan
  • Implement caching to reduce calls
Error: Empty results arraySolution:
  • Try different query phrasing
  • Use more general terms
  • Check if topic is too niche

Contributing

Want to improve this plugin? Contributions welcome!
  1. Fork official-plugins
  2. Make your changes to web-search/main.py
  3. Test with your Tavily API key
  4. Submit a pull request

License

MIT License - Nadoo Team

Support