Class WebSearchTools

java.lang.Object
com.tnsai.tools.search.WebSearchTools

public class WebSearchTools extends Object
Function-shape web search tools — the LangChain-style replacement for the legacy DuckDuckGoTool, WikipediaTool, etc. (see issue #188).

This POJO grows method-by-method across Phase 2 batches as each legacy search engine is migrated:

MethodReplacesAPI key
duckduckgo(java.lang.String)DuckDuckGoToolnone
wikipedia(java.lang.String, int, java.lang.String)WikipediaToolnone

Subsequent sub-batches (4b, 4c) will append brave, serpapi, tavily, exa, searxng, wikidata, npm, maven_central, hackernews, stackoverflow methods to this same POJO. Per-API constructor injection lands together with the first key-bearing method (planned: 4b — Brave + SerpApi + Tavily + Exa).

Threading

The shared OkHttpClient and ObjectMapper fields are thread-safe; instances of this POJO can therefore be shared across roles and concurrent dispatches without synchronisation.

Since:
0.5.7 (Phase 2 batch 4 — built-in tool migration to function shape, see #188)
  • Constructor Details

    • WebSearchTools

      public WebSearchTools()
      Default constructor — picks API keys up from environment variables and uses a 15-second-per-call OkHttp client. This is the Role.tools() "just give me everything" entry point. Engines whose env var is unset stay configured but their tool methods raise IllegalStateException with a clear "missing key" message when the LLM tries to call them.
      EngineEnv var
      Brave SearchBRAVE_API_KEY
      SerpApiSERPAPI_API_KEY
      TavilyTAVILY_API_KEY
      ExaEXA_API_KEY
    • WebSearchTools

      public WebSearchTools(String braveApiKey, String serpApiKey, String tavilyApiKey, String exaApiKey)
      Explicit-keys constructor — for DI containers, multi-tenant deployments where each tenant carries its own API keys, or test scaffolds. Pass null for any engine you don't want to expose; that engine's tool method then raises IllegalStateException on call rather than dispatching with a missing credential.
    • WebSearchTools

      public WebSearchTools(String braveApiKey, String serpApiKey, String tavilyApiKey, String exaApiKey, okhttp3.OkHttpClient http, com.fasterxml.jackson.databind.ObjectMapper mapper)
      Full constructor — for tests that need to inject a
      invalid reference
      MockWebServer
      URL or share an OkHttp client with the rest of the application. The POJO does not own the HTTP client's lifecycle.
  • Method Details

    • duckduckgo

      @Tool(name="duckduckgo", description="Query the DuckDuckGo Instant Answer API for definitions, general knowledge, and factual lookups. No API key needed. Best for: \'what is X\', \'who is Y\', encyclopedic facts. Returns a structured Markdown summary with up to 5 related topics, or a \'no instant answers\' message if the API has nothing for the query (common for news / sports / real-time queries \u2014 try a web search engine instead).", keywords={"search","duckduckgo","ddg","definition","fact","knowledge"}, idempotent=true) public String duckduckgo(@ToolParam(description="The natural-language search query") String query) throws IOException
      Throws:
      IOException
    • wikipedia

      @Tool(name="wikipedia", description="Search Wikipedia via the MediaWiki API and return the top matching article titles + snippets. Returns the language edition\'s results (default English). No API key needed. Use this for encyclopedic depth \u2014 biographies, history, concepts. For real-time events / news, use a web search engine instead.", keywords={"search","wikipedia","wiki","encyclopedia","knowledge","biography"}, idempotent=true) public String wikipedia(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="Number of results (1..50; defaults to 5)",required=false,defaultValue="5") int limit, @ToolParam(description="Wikipedia language code (e.g. \"en\", \"tr\", \"de\"); defaults to \"en\"",required=false,defaultValue="en") String language) throws IOException
      Throws:
      IOException
    • brave

      @Tool(name="brave_search", description="Web search via the Brave Search API \u2014 fast, privacy- respecting, and good general-purpose recall including news / sports / real-time topics. Requires BRAVE_API_KEY. Returns a Markdown-formatted list of result titles, URLs, and short descriptions.", keywords={"search","brave","web","news"}, idempotent=true) public String brave(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="Number of results (1..20; defaults to 5)",required=false,defaultValue="5") int count) throws IOException
      Throws:
      IOException
    • serpapi

      @Tool(name="serpapi", description="Google search results via SerpApi (paid). Useful for complex queries where you want Google\'s relevance ranking \u2014 Knowledge Graph, answer boxes, organic results, and \"People Also Ask\" sections all parsed in one call. Requires SERPAPI_API_KEY.", keywords={"search","google","serpapi","serp"}, idempotent=true) public String serpapi(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="SerpApi engine \u2014 \"google\" (default), \"bing\", \"duckduckgo\", \"yahoo\", \"baidu\", \"yandex\"",required=false,defaultValue="google") String engine) throws IOException
      Throws:
      IOException
    • tavily

      @Tool(name="tavily", description="AI-optimized search via the Tavily API. Best for research-quality results: returns an LLM-summarized answer plus the source documents the answer is grounded in, all in one call. Requires TAVILY_API_KEY.", keywords={"search","tavily","ai","research","rag"}, idempotent=true) public String tavily(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="Search depth \u2014 \"basic\" (default, faster) or \"advanced\" (deeper crawl, slower)",required=false,defaultValue="basic") String depth) throws IOException
      Throws:
      IOException
    • exa

      @Tool(name="exa", description="Neural search via Exa (formerly Metaphor). Built specifically for LLM use cases \u2014 returns highlights and extracted text alongside URLs, with optional autoprompt for query refinement. Requires EXA_API_KEY.", keywords={"search","exa","neural","metaphor","highlights","rag"}, idempotent=true) public String exa(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="Number of results (1..25; defaults to 10)",required=false,defaultValue="10") int numResults) throws IOException
      Throws:
      IOException
    • wikidata

      @Tool(name="wikidata", description="Query Wikidata for structured-knowledge entities (people, places, concepts, \u2026) and return their QID, label, and short description. Returns up to {limit} matches in the requested language. No API key needed. Useful when you want canonical IDs to follow up with SPARQL queries against the Wikidata Query Service.", keywords={"search","wikidata","knowledge","entity","qid","linked-data"}, idempotent=true) public String wikidata(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="Number of results (1..50; defaults to 5)",required=false,defaultValue="5") int limit, @ToolParam(description="Wikidata language code (e.g. \"en\", \"tr\", \"de\"); defaults to \"en\"",required=false,defaultValue="en") String language) throws IOException
      Throws:
      IOException
    • searxng

      @Tool(name="searxng", description="Self-hosted meta-search via a SearXNG instance. Aggregates multiple search engines without tracking. {instance} accepts any SearXNG public or private instance URL; defaults to https://searx.be. {categories} narrows the search (\"general\", \"images\", \"news\", \"science\", \"social media\", \u2026); defaults to \"general\".", keywords={"search","searxng","self-hosted","meta-search","privacy"}, idempotent=true) public String searxng(@ToolParam(description="The natural-language search query") String query, @ToolParam(description="SearXNG instance base URL (no trailing /); defaults to https://searx.be",required=false,defaultValue="https://searx.be") String instance, @ToolParam(description="Comma-separated categories (general/images/news/science/\u2026); defaults to \"general\"",required=false,defaultValue="general") String categories, @ToolParam(description="Language code or \"auto\"; defaults to \"auto\"",required=false,defaultValue="auto") String language) throws IOException
      Throws:
      IOException
    • npm

      @Tool(name="npm", description="Search the public npm registry for JavaScript / TypeScript packages. No API key needed. Returns up to 10 matches with name, version, description, publisher, and keywords.", keywords={"search","npm","package","javascript","typescript","node"}, idempotent=true) public String npm(@ToolParam(description="Package-search query (name, keyword, or description fragment)") String query) throws IOException
      Throws:
      IOException
    • mavenCentral

      @Tool(name="maven_central", description="Search Maven Central for Java artifacts. No API key needed. Returns up to 10 matches with groupId, artifactId, latest version, packaging type, and Maven Central URL.", keywords={"search","maven","central","java","artifact","dependency"}, idempotent=true) public String mavenCentral(@ToolParam(description="Maven Central search query (artifact name, group, or full coordinate fragment)") String query) throws IOException
      Throws:
      IOException