Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
"filename": "README.md",
"hashed_secret": "73140b88094aaf220a03532196b27b58a03c9b09",
"is_verified": false,
"line_number": 307
"line_number": 328
}
],
"deploy/.env.example": [
Expand All @@ -142,7 +142,7 @@
"filename": "deploy/.env.example",
"hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684",
"is_verified": false,
"line_number": 30
"line_number": 33
}
],
"deploy/compose/README.md": [
Expand Down Expand Up @@ -290,5 +290,5 @@
}
]
},
"generated_at": "2026-05-22T20:01:44Z"
"generated_at": "2026-05-27T12:29:06Z"
}
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ This project is for:


**Optional requirements:**
- Tavily API key (for web search functionality)
- Tavily, Exa, Brave, or TinyFish API key (for web search functionality)
- Serper API key (for academic paper search functionality)

> **Note:** Configure at least one data source (Tavily web search, Serper search tool, or knowledge layer) to enable research functionality.
> **Note:** Configure at least one data source (web search, Serper search tool, or knowledge layer) to enable research functionality.

If these optional API keys are not provided, the agent continues to operate without the corresponding search capabilities. Refer to [Obtain API Keys](#obtain-api-keys) for details.

Expand Down Expand Up @@ -181,6 +181,9 @@ uv pip install -e ./frontends/benchmarks/freshqa

# Install data sources (pick what you need)
uv pip install -e ./sources/tavily_web_search
uv pip install -e ./sources/exa_web_search
uv pip install -e ./sources/brave_web_search
uv pip install -e ./sources/tinyfish_web_search
uv pip install -e ./sources/google_scholar_paper_search
uv pip install -e "./sources/knowledge_layer[llamaindex,foundational_rag]"
```
Expand All @@ -192,6 +195,9 @@ uv pip install -e "./sources/knowledge_layer[llamaindex,foundational_rag]"
| ---------- | -------------------- | ------------------------- | ----------------------------------------------------------- |
| NVIDIA API | `NVIDIA_API_KEY` | LLM inference through NIM | Yes |
| Tavily | `TAVILY_API_KEY` | Web search | No (if not specified, agent continues without web search) |
| Exa | `EXA_API_KEY` | Web search | No (if not specified, agent continues without Exa search) |
| Brave | `BRAVE_API_KEY` | Web search | No (if not specified, agent continues without Brave search) |
| TinyFish | `TINYFISH_API_KEY` | Web search | No (if not specified, agent continues without TinyFish search) |
| Serper | `SERPER_API_KEY` | Academic paper search | No (if not specified, agent continues without paper search) |


Expand All @@ -206,6 +212,21 @@ uv pip install -e "./sources/knowledge_layer[llamaindex,foundational_rag]"
2. Navigate to your dashboard
3. Generate an API key

#### Obtain an Exa API Key

1. Sign in to [Exa](https://exa.ai/)
2. Generate an API key from your dashboard

#### Obtain a Brave Search API Key

1. Sign in to [Brave Search API](https://api.search.brave.com/)
2. Subscribe to a search plan and generate a subscription token

#### Obtain a TinyFish API Key

1. Review the [TinyFish Search API docs](https://docs.tinyfish.ai/search-api)
2. Generate an API key from your TinyFish dashboard

#### Obtain a Serper API Key

1. Sign in to [Serper](https://serper.dev/)
Expand Down
5 changes: 4 additions & 1 deletion deploy/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ AIQ_DEV_ENV=cli
NVIDIA_API_KEY=


# Web search (Required)
# Web search (Tavily is used by the shipped default configs)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indicate that at least one of these are required

TAVILY_API_KEY=
# EXA_API_KEY= # optional, required when using exa_web_search
# BRAVE_API_KEY= # optional, required when using brave_web_search
# TINYFISH_API_KEY= # optional, required when using tinyfish_web_search

# Paper search (Optional)
# SERPER_API_KEY= # to enable, set API key and update the relevant config in configs/ directory
Expand Down
2 changes: 2 additions & 0 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ RUN uv pip install --no-deps -e . \
&& uv pip install --no-deps -e ./sources/google_scholar_paper_search \
&& uv pip install --no-deps -e ./sources/tavily_web_search \
&& uv pip install --no-deps -e ./sources/exa_web_search \
&& uv pip install --no-deps -e ./sources/brave_web_search \
&& uv pip install --no-deps -e ./sources/tinyfish_web_search \
&& uv pip install --no-deps -e "./sources/knowledge_layer[all]" \
&& uv pip install --no-deps -e ./frontends/aiq_api \
&& uv pip install "psycopg[binary]>=3.0.0"
Expand Down
49 changes: 49 additions & 0 deletions docs/source/customization/configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,55 @@ functions:
- **`fast`** -- Optimized for low latency. Returns results quickly at the cost of recall and semantic depth. Use for interactive UIs, high-volume calls, or when the query is narrow and keyword-like.
- **`deep`** -- Optimized for thoroughness. Runs a more expensive semantic search with broader retrieval. Use for research-quality queries where completeness matters more than speed.

### `brave_web_search`

Web search powered by the [Brave Search API](https://api.search.brave.com/).

```yaml
functions:
web_search_tool:
_type: brave_web_search
max_results: 5
country: US
search_lang: en
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `max_results` | `int` | `5` | Maximum number of web results to return. Brave supports up to 20 web results per request. |
| `api_key` | `str` | `None` | Brave Search API subscription token. Falls back to `BRAVE_API_KEY` environment variable. |
| `max_retries` | `int` | `3` | Number of retry attempts on search failure. |
| `country` | `str` | `"US"` | Two-character country code for search results. |
| `search_lang` | `str` | `"en"` | Language code for search results. |
| `safesearch` | `str` | `"moderate"` | Adult-content filtering mode: `off`, `moderate`, or `strict`. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Follow the style that was used for Tavily's search_type options

| `freshness` | `str` | `None` | Optional page-age filter such as `pd`, `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD`. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List out the options and descriptions for each one. Use the same format as used by the Tavily search_type options

Last 24 Hours (pd): Get the latest updates and recent content
Last 7 Days (pw): Track weekly trends and recent discussions
Last 31 Days (pm): Monitor monthly developments
Last Year (py): Search content from the past year
Custom Date Range: Specify exact timeframes (e.g., 2022-04-01to2022-07-30)

| `timeout` | `float` | `20.0` | HTTP request timeout in seconds. |
| `max_content_length` | `int` | `10000` | Truncate each result's snippet text to this many characters. Set to `None` to disable truncation. |

### `tinyfish_web_search`

Web search powered by the [TinyFish Search API](https://docs.tinyfish.ai/search-api).

```yaml
functions:
web_search_tool:
_type: tinyfish_web_search
max_results: 5
location: US
language: en
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `max_results` | `int` | `5` | Maximum number of search results to return from the response, up to `20`. |
| `api_key` | `str` | `None` | TinyFish API key. Falls back to `TINYFISH_API_KEY` environment variable. |
| `max_retries` | `int` | `3` | Number of retry attempts on search failure. |
| `location` | `str` | `"US"` | Country code for geo-targeted results. |
| `language` | `str` | `"en"` | Language code for result language. |
| `page` | `int` | `0` | Search result page number, starting from `0`. |
| `timeout` | `float` | `20.0` | HTTP request timeout in seconds. |
| `max_content_length` | `int` | `10000` | Truncate each result's snippet text to this many characters. Set to `None` to disable truncation. |

### `paper_search`

Academic paper search through Google Scholar (using the [Serper API](https://serper.dev/)).
Expand Down
2 changes: 1 addition & 1 deletion docs/source/customization/tools-and-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Tools not listed in any data source entry (e.g., utility tools like "think") are
| `name` | string | *required* | Display name shown in the UI |
| `description` | string | `""` | Human-readable description shown in the UI |
| `tools` | list[string] | `[]` | NAT function names or function group names belonging to this source |
| `requires_auth` | bool | `false` | If `true`, the UI greys out this source until the user signs in. Use for sources that need user-level OAuth tokens (e.g., enterprise SSO). Sources that use backend API keys (Tavily, Serper) should leave this `false`. |
| `requires_auth` | bool | `false` | If `true`, the UI greys out this source until the user signs in. Use for sources that need user-level OAuth tokens (e.g., enterprise SSO). Sources that use backend API keys (Tavily, Exa, Brave, TinyFish, Serper) should leave this `false`. |
| `default_enabled` | bool | `true` | Whether the source is enabled by default when a user first loads the UI |

## Auto-Inherit: Agents Get All Registry Tools by Default
Expand Down
2 changes: 2 additions & 0 deletions docs/source/deployment/docker-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ The builder stage handles all compilation and package installation:
- `sources/google_scholar_paper_search` -- Google Scholar search
- `sources/tavily_web_search` -- Tavily web search
- `sources/exa_web_search` -- Exa web search
- `sources/brave_web_search` -- Brave web search
- `sources/tinyfish_web_search` -- TinyFish web search
- `sources/knowledge_layer[all]` -- Knowledge layer with all extras
- `frontends/aiq_api` -- [FastAPI](https://fastapi.tiangolo.com/) frontend
- `psycopg[binary]>=3.0.0` -- PostgreSQL driver (psycopg v3, installed non-editable)
Expand Down
2 changes: 2 additions & 0 deletions docs/source/deployment/docker-compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ The sections below explain each group of variables.
| `NVIDIA_API_KEY` | Yes | NVIDIA API key for NIM model access. |
| `TAVILY_API_KEY` | Conditional | Web search provider key (required if using `tavily_web_search`). |
| `EXA_API_KEY` | Conditional | Web search provider key (required if using `exa_web_search`). |
| `BRAVE_API_KEY` | Conditional | Web search provider key (required if using `brave_web_search`). |
| `TINYFISH_API_KEY` | Conditional | Web search provider key (required if using `tinyfish_web_search`). |
| `SERPER_API_KEY` | No | Google Scholar paper search key (optional). |

### API keys (optional)
Expand Down
2 changes: 2 additions & 0 deletions docs/source/deployment/kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ For complete examples with NGC-specific flags, see `deploy/helm/README.md` in th
| Key | Description |
|-----|-------------|
| `EXA_API_KEY` | Exa API key for web search |
| `BRAVE_API_KEY` | Brave Search API key for web search |
| `TINYFISH_API_KEY` | TinyFish API key for web search |
| `SERPER_API_KEY` | Serper API key for Google search |
| `JINA_API_KEY` | Jina API key |
| `WANDB_API_KEY` | Weights & Biases API key |
Expand Down
2 changes: 2 additions & 0 deletions docs/source/extending/adding-a-data-source.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ async def search(self, query: str) -> str:
|---|---|---|---|
| Tavily Web Search | `tavily_web_search` | `sources/tavily_web_search` | General web search through Tavily API |
| Exa Web Search | `exa_web_search` | `sources/exa_web_search` | General web search through Exa API |
| Brave Web Search | `brave_web_search` | `sources/brave_web_search` | General web search through Brave Search API |
| TinyFish Web Search | `tinyfish_web_search` | `sources/tinyfish_web_search` | General web search through TinyFish Search API |
| Google Scholar | `paper_search` | `sources/google_scholar_paper_search` | Academic papers through Serper/Google Scholar |
| Knowledge Layer | `knowledge_retrieval` | `sources/knowledge_layer` | Document retrieval through pluggable backends |

Expand Down
2 changes: 2 additions & 0 deletions docs/source/extending/adding-a-tool.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,8 @@ f'<Document href="{url}">\n<title>\n{title}\n</title>\n{content}\n</Document>'
|---|---|---|---|
| Tavily Web Search | `tavily_web_search` | `sources/tavily_web_search` | `TAVILY_API_KEY` |
| Exa Web Search | `exa_web_search` | `sources/exa_web_search` | `EXA_API_KEY` |
| Brave Web Search | `brave_web_search` | `sources/brave_web_search` | `BRAVE_API_KEY` |
| TinyFish Web Search | `tinyfish_web_search` | `sources/tinyfish_web_search` | `TINYFISH_API_KEY` |
| Google Scholar | `paper_search` | `sources/google_scholar_paper_search` | `SERPER_API_KEY` |
| Knowledge Layer | `knowledge_retrieval` | `sources/knowledge_layer` | (varies by backend) |

Expand Down
8 changes: 6 additions & 2 deletions docs/source/get-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The script performs the following steps:
3. Installs the core package with dev dependencies
4. Installs all frontends (CLI, debug console, API server)
5. Installs benchmark packages (freshqa, deepsearch_qa)
6. Installs all data source plugins (Tavily, Exa, Google Scholar, knowledge layer)
6. Installs all data source plugins (Tavily, Exa, Brave, TinyFish, Google Scholar, knowledge layer)
7. Sets up pre-commit hooks
8. Copies `deploy/.env.example` to `deploy/.env` if no `.env` file exists
9. Installs UI npm dependencies (if Node.js is available)
Expand Down Expand Up @@ -96,6 +96,8 @@ uv pip install -e ./frontends/aiq_api # Unified API server (includes debug)
# Data sources (pick what you need)
uv pip install -e ./sources/tavily_web_search
uv pip install -e ./sources/exa_web_search
uv pip install -e ./sources/brave_web_search
uv pip install -e ./sources/tinyfish_web_search
uv pip install -e ./sources/google_scholar_paper_search
uv pip install -e "./sources/knowledge_layer[llamaindex,foundational_rag]"

Expand Down Expand Up @@ -132,9 +134,11 @@ Then edit `deploy/.env` and fill in your keys.
|----------|----------|---------|
| `TAVILY_API_KEY` | [Tavily](https://tavily.com/) | Web search (Tavily provider) |
| `EXA_API_KEY` | [Exa](https://exa.ai/) | Web search (Exa provider) |
| `BRAVE_API_KEY` | [Brave Search API](https://api.search.brave.com/) | Web search (Brave provider) |
| `TINYFISH_API_KEY` | [TinyFish](https://docs.tinyfish.ai/search-api) | Web search (TinyFish provider) |
| `SERPER_API_KEY` | [Serper](https://serper.dev/) | Academic paper search (Google Scholar). To enable, uncomment `paper_search_tool` in your config file |

At minimum, you need `NVIDIA_API_KEY` for LLM inference and one of `TAVILY_API_KEY` or `EXA_API_KEY` for web search. Paper search (`SERPER_API_KEY`) is disabled by default in the shipped configs -- refer to the comments in your config file to enable it.
At minimum, you need `NVIDIA_API_KEY` for LLM inference and one configured web-search provider key (`TAVILY_API_KEY`, `EXA_API_KEY`, `BRAVE_API_KEY`, or `TINYFISH_API_KEY`) for web search. Paper search (`SERPER_API_KEY`) is disabled by default in the shipped configs -- refer to the comments in your config file to enable it.

## Verify Installation

Expand Down
4 changes: 3 additions & 1 deletion docs/source/get-started/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ Edit `deploy/.env` and set at minimum:
```bash
NVIDIA_API_KEY=nvapi-...
TAVILY_API_KEY=tvly-...
# Or, to use Exa instead of Tavily for web search:
# Or, after updating your config to use another web-search provider:
# EXA_API_KEY=...
# BRAVE_API_KEY=...
# TINYFISH_API_KEY=...
```

## Step 2: Choose a Mode
Expand Down
2 changes: 2 additions & 0 deletions docs/source/resources/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ If `enable_escalation: true` in the workflow config, the orchestrator evaluates

- **Tavily Web Search** — General web search (requires `TAVILY_API_KEY`)
- **Exa Web Search** — General web search via Exa (requires `EXA_API_KEY`)
- **Brave Web Search** — General web search via Brave Search API (requires `BRAVE_API_KEY`)
- **TinyFish Web Search** — General web search via TinyFish Search API (requires `TINYFISH_API_KEY`)
- **Google Scholar Paper Search** — Academic paper search (requires `SERPER_API_KEY`)
- **Knowledge Layer** — Document retrieval from local or hosted vector stores

Expand Down
2 changes: 2 additions & 0 deletions docs/source/resources/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Common issues and solutions for the AI-Q blueprint.
| `Gateway timeout (504)` | Model endpoint overloaded or unavailable | Retry, or switch to a different model in config |
| Tavily search returns empty | Invalid `TAVILY_API_KEY` | Verify key at [tavily.com](https://tavily.com) |
| Exa search returns empty or 401 | Invalid or missing `EXA_API_KEY` | Verify key at [exa.ai](https://exa.ai) |
| Brave search returns empty or 401 | Invalid or missing `BRAVE_API_KEY` | Verify key at [api.search.brave.com](https://api.search.brave.com/) |
| TinyFish search returns empty or 401 | Invalid or missing `TINYFISH_API_KEY` | Verify key using the [TinyFish Search API docs](https://docs.tinyfish.ai/search-api) |
| Serper search fails | Missing `SERPER_API_KEY` | Set key or remove `paper_search_tool` from config |

## Runtime Issues
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ dev = [
"google-scholar-paper-search",
"tavily-web-search",
"exa-web-search",
"brave-web-search",
"tinyfish-web-search",
"knowledge-layer[all]",
"aiq-api",
"aiq-research-cli",
Expand Down Expand Up @@ -231,6 +233,8 @@ aiq-agent = { workspace = true }
google-scholar-paper-search = { workspace = true }
tavily-web-search = { workspace = true }
exa-web-search = { workspace = true }
brave-web-search = { workspace = true }
tinyfish-web-search = { workspace = true }
knowledge-layer = { workspace = true }
aiq-api = { workspace = true }
aiq-research-cli = { workspace = true }
Expand Down
2 changes: 2 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ echo ""
echo "Installing data sources..."
"${UV_BIN}" pip install -e ./sources/tavily_web_search
"${UV_BIN}" pip install -e ./sources/exa_web_search
"${UV_BIN}" pip install -e ./sources/brave_web_search
"${UV_BIN}" pip install -e ./sources/tinyfish_web_search
"${UV_BIN}" pip install -e ./sources/google_scholar_paper_search
"${UV_BIN}" pip install -e "./sources/knowledge_layer[llamaindex,foundational_rag]"
echo "Data Sources installed"
Expand Down
16 changes: 16 additions & 0 deletions sources/brave_web_search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Brave Web Search

NAT tool package for the Brave Search API web search endpoint.

## Configuration

```yaml
functions:
web_search_tool:
_type: brave_web_search
max_results: 5
country: US
search_lang: en
```

Set `BRAVE_API_KEY` in the environment, or provide `api_key` in the workflow config.
36 changes: 36 additions & 0 deletions sources/brave_web_search/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

[build-system]
build-backend = "setuptools.build_meta"
requires = ["setuptools >= 64", "setuptools-scm>=8"]

[tool.setuptools]
packages = ["brave_web_search"]
package-dir = {"brave_web_search" = "src"}

[project]
name = "brave-web-search"
version = "1.0.0"
description = "NAT-based Brave Search API web search tool"
readme = "README.md"
requires-python = ">=3.11,<3.14"
license = {text = "Apache-2.0"}
dependencies = [
"pydantic>=2.0.0",
]

[project.entry-points."nat.plugins"]
brave_web_search = "brave_web_search.register"
20 changes: 20 additions & 0 deletions sources/brave_web_search/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .register import brave_web_search # noqa: F401

__all__ = [
"brave_web_search",
]
Loading