Module: Pikuri::Tool::WebSearch

Defined in:
lib/pikuri/tool/web_search.rb

Overview

Builder for the LLM-facing web-search tool. The search orchestration lives in Search::Engines; this module owns only the WebSearch.build factory that wires a configured Search::Engines into a Pikuri::Tool.

Unlike the stateless bundled tools (CALCULATOR / WEB_SCRAPE / FETCH, shared value constants), web_search is host-configured: the paid providers (Brave / Exa) join the cascade only when the host passes their API key, so the tool is built per-wiring — like Code::Bash — rather than handed out as a single shared constant. pikuri reads no key from the environment; the host supplies them (the bundled bin/ examples load a JSON config file by convention). See CLAUDE.md “Environment is not a secret store”.

Constant Summary collapse

DESCRIPTION =

Description shown to the LLM, opencode-shape (summary + Usage:).

Returns:

  • (String)
<<~DESC
  Searches the web for a query and returns the top results as a Markdown list of titles, URLs, and short snippets.

  Usage:
  - Use this to find candidate URLs, then call web_scrape on the most promising one(s) for full content. Snippets alone rarely answer a question.
DESC

Class Method Summary collapse

Class Method Details

.build(brave_key: nil, exa_key: nil) ⇒ Tool

Build the web_search tool. It calls Search::Engines#search, which cascades through DuckDuckGo (always) plus whichever keyed providers were configured, in random order, falling back on temporary-unavailability errors and rendering the winning provider’s rows into a stable Markdown shape.

Parameters:

  • brave_key (String, nil) (defaults to: nil)

    Brave Search API key; when present (non-blank) Brave joins the cascade. Get one at api-dashboard.search.brave.com.

  • exa_key (String, nil) (defaults to: nil)

    Exa API key; when present (non-blank) Exa joins the cascade. Get one at exa.ai.

Returns:

  • (Tool)

    the web_search tool in OpenAI tool-call shape



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/pikuri/tool/web_search.rb', line 40

def self.build(brave_key: nil, exa_key: nil)
  engines = Search::Engines.new(brave_key: brave_key, exa_key: exa_key)
  Tool.new(
    name: 'web_search',
    description: DESCRIPTION,
    parameters: Parameters.build { |p|
      p.required_string :query,
                        'The search query, e.g. "BigDecimal precision Ruby".'
      p.optional_integer :max_results,
                         'Maximum number of result entries to return. ' \
                         'Defaults to 10; most providers cap this at 20.'
    },
    execute: ->(query:, max_results: 10) { engines.search(query, max_results: max_results) }
  )
end