web.search

The web.search tool searches the web using DuckDuckGo Lite and returns structured results with titles, URLs, and snippets.

Capability Required

tool.invoke:web.search

Network access also requires appropriate spec.network.policy.

Input Schema

{
  "type": "object",
  "required": ["query"],
  "properties": {
    "query": {
      "type": "string",
      "description": "The search query."
    }
  }
}

Output Schema

{
  "type": "object",
  "properties": {
    "results": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "title":   { "type": "string", "description": "Page title." },
          "link":    { "type": "string", "description": "URL." },
          "snippet": { "type": "string", "description": "Description snippet." }
        }
      }
    }
  }
}

Examples

#![allow(unused)]
fn main() {
let result = agent.invoke_tool("web.search", json!({
    "query": "renewable energy breakthroughs 2026"
})).await?;

for r in result["results"].as_array().unwrap_or(&vec![]) {
    println!("- {}", r["title"]);
    println!("  {}", r["link"]);
    println!("  {}", r["snippet"]);
}
}
ash tools invoke <agent-id> web.search '{"query": "Rust async programming"}'

Implementation

web.search uses DuckDuckGo Lite (https://duckduckgo.com/lite) with HTML parsing via the scraper crate. Results are returned as a list of {title, link, snippet} objects, with no JavaScript execution or API key required.

Network Policy

spec:
  network:
    policy: allowlist
    allowlist:
      - "duckduckgo.com:443"

Or use policy: full for unrestricted access.

Cost

Estimated cost: 0.5

Error Cases

ErrorCause
network policy denies outboundduckduckgo.com not in allowlist
no resultsDuckDuckGo returned no results (empty array, not an error)
parse errorDuckDuckGo changed their HTML structure