Class: Rubino::Tools::WebSearchTool
- Defined in:
- lib/rubino/tools/websearch_tool.rb
Overview
Tool for performing web searches via external search APIs.
Backends, in priority order:
1. Tavily (TAVILY_API_KEY) — high-quality, preferred
2. SearXNG (SEARXNG_URL) — self-hosted, full web index
3. DuckDuckGo Instant Answer JSON — keyless DEFAULT (no key needed)
Why not scrape html/lite.duckduckgo.com keyless? DuckDuckGo now serves an anomaly/bot-challenge page (zero results) to datacenter egress IPs, so the old single-regex HTML scrape returned “No results” 100% of the time — a silent failure that looked like success. The Instant Answer JSON API (api.duckduckgo.com) is keyless, returns structured JSON, and is NOT bot-walled, so it is the robust keyless default. Its coverage is narrower (topic/entity answers, not a full web index): when it yields nothing we degrade to an EXPLICIT “search unavailable” message that points the user at TAVILY_API_KEY / SEARXNG_URL — never a silent zero-results-that-looks-like-a-real-answer.
Instance Attribute Summary
Attributes inherited from Base
#cancel_token, #read_tracker, #stream_chunk, #stream_kind
Instance Method Summary collapse
- #call(arguments) ⇒ Object
-
#config_key ⇒ Object
Gated by ‘tools.web` (shared with webfetch), not `tools.websearch`.
- #description ⇒ Object
- #input_schema ⇒ Object
- #name ⇒ Object
- #risk_level ⇒ Object
Methods inherited from Base
#cancellation_requested?, #emit_chunk, #risky?, #to_tool_definition, workspace_root, workspace_roots
Instance Method Details
#call(arguments) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/rubino/tools/websearch_tool.rb', line 63 def call(arguments) query = arguments["query"] || arguments[:query] max_results = arguments["max_results"] || arguments[:max_results] || 5 if ENV["TAVILY_API_KEY"] search_tavily(query, max_results) elsif ENV["SEARXNG_URL"] search_searxng(query, max_results) else search_ddg(query, max_results) end rescue StandardError => e "Search error: #{e.}" end |
#config_key ⇒ Object
Gated by ‘tools.web` (shared with webfetch), not `tools.websearch`.
32 33 34 |
# File 'lib/rubino/tools/websearch_tool.rb', line 32 def config_key "web" end |
#description ⇒ Object
36 37 38 39 40 |
# File 'lib/rubino/tools/websearch_tool.rb', line 36 def description "Search the web for information. Returns relevant results with titles, " \ "URLs, and snippets. Useful for finding documentation, researching " \ "dependencies, and answering questions about external topics." end |
#input_schema ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/rubino/tools/websearch_tool.rb', line 42 def input_schema { type: "object", properties: { query: { type: "string", description: "The search query" }, max_results: { type: "integer", description: "Maximum number of results (default: 5)" } }, required: %w[query] } end |
#name ⇒ Object
27 28 29 |
# File 'lib/rubino/tools/websearch_tool.rb', line 27 def name "websearch" end |
#risk_level ⇒ Object
59 60 61 |
# File 'lib/rubino/tools/websearch_tool.rb', line 59 def risk_level :low end |