tarzi 0.2.0

Rust-native lite search for AI applications
Documentation
API Search Examples
===================

This guide demonstrates tarzi's search access cascade: API → plain HTTP → headless browser.

Access Cascade
--------------

With ``search.mode = "auto"`` (default), tarzi tries:

1. **API** when the engine supports apiquery and a key is available
2. **Plain HTTP** to the engine's public search URL
3. **Headless browser** as a last resort

Forced modes:

- ``apiquery`` — API only (errors if unsupported or key missing)
- ``webquery`` — plain HTTP then browser (never uses API)

Supported API Engines
---------------------

- **Brave** (``brave``): Brave Search API via ``BRAVE_API_KEY`` or ``search.api_key``
- **Google Serper** (``google_serper`` / ``serper``): Serper API via ``SERPER_API_KEY`` or ``search.api_key``

``google`` remains web-only. There is no Google Custom Search (CSE) integration.

Basic API Search
----------------

Python
~~~~~~~

.. code-block:: python

   import tarzi

   config_str = """
   [search]
   engine = "brave"
   mode = "auto"
   limit = 5
   api_key = "your-brave-api-key"
   """

   config = tarzi.Config.from_str(config_str)
   search_engine = tarzi.SearchEngine.from_config(config)

   try:
       results = search_engine.search("artificial intelligence trends", 5)
       print(f"Found {len(results)} results:")
       for i, result in enumerate(results):
           print(f"{i+1}. {result.title}")
           print(f"   URL: {result.url}")
           print(f"   Snippet: {result.snippet[:150]}...")
   except Exception as e:
       print(f"Search failed: {e}")

Rust
~~~~

.. code-block:: rust

   use tarzi::{config::Config, search::SearchEngine};

   #[tokio::main]
   async fn main() -> Result<(), Box<dyn std::error::Error>> {
       let mut config = Config::new();
       config.search.engine = "brave".to_string();
       config.search.mode = "apiquery".to_string();
       config.search.limit = 5;
       config.search.api_key = Some("your-brave-api-key".to_string());

       let mut search_engine = SearchEngine::from_config(&config);

       match search_engine.search("machine learning applications", 5).await {
           Ok(results) => {
               println!("Found {} results:", results.len());
               for (i, result) in results.iter().enumerate() {
                   println!("{}. {}", i + 1, result.title);
                   println!("   URL: {}", result.url);
               }
           }
           Err(e) => println!("Search failed: {}", e),
       }

       Ok(())
   }

Google via Serper
-----------------

.. code-block:: toml

   [search]
   engine = "google_serper"
   mode = "auto"
   limit = 10
   # Prefer env: export SERPER_API_KEY=...
   # api_key = "your-serper-api-key"

Environment Variables
---------------------

- ``BRAVE_API_KEY`` — Brave Search API
- ``SERPER_API_KEY`` — Google Serper API

Environment variables take precedence over ``search.api_key`` in config.