Metadata-Version: 2.5
Name: nemo-helix-tavily-plugin
Version: 0.2.0
Summary: Tavily web search and extraction for NeMo Helix agents.
Project-URL: Homepage, https://github.com/tavily-ai/nemo-helix-tavily
Project-URL: Source, https://github.com/tavily-ai/nemo-helix-tavily
Project-URL: Issues, https://github.com/tavily-ai/nemo-helix-tavily/issues
Project-URL: Changelog, https://github.com/tavily-ai/nemo-helix-tavily/releases
Author-email: Tavily by Nebius <tavily-integrations@nebius.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,mcp,nemo-helix,tavily,web-search
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: <3.15,>=3.12
Requires-Dist: httpx<1,>=0.27.0
Requires-Dist: nemo-helix-plugin>=0.9
Requires-Dist: pydantic>=2.0.0
Description-Content-Type: text/markdown

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 Alpha AI Technologies Inc dba Tavily -->
<!-- SPDX-License-Identifier: MIT -->

# Tavily plugin

Gives NeMo Helix agents live web search and page extraction through [Tavily](https://tavily.com). Agents get two tools, `tavily_search` and `tavily_extract`, from Tavily's hosted MCP server.

## How it works

```
agent ──MCP──▶ /apis/tavily/v2/workspaces/<ws>/mcp ──MCP──▶ mcp.tavily.com/mcp
               (this plugin:
                 • adds the workspace's Tavily key from Helix Secrets
                 • tags traffic with X-Client-Name: nemo-helix
                 • lists and allows only tavily_search and tavily_extract)
```

The proxy forwards MCP traffic unchanged apart from those three things. Tool schemas, descriptions and behavior come from the hosted server, so Tavily's improvements reach Helix agents without a plugin release. Agents never see the Tavily API key.

| Surface | Entry point | What it provides |
|---|---|---|
| Service | `nemo.services` → `tavily` | MCP proxy at `POST /apis/tavily/v2/workspaces/{workspace}/mcp`, and `GET .../status` for the URL agents use |
| CLI | `nemo.cli` → `tavily` | `nemo tavily setup`, `enable`, `disable`, `status`, `search`, `extract` |
| Skill | `nemo.skills` → `tavily` | `nemo-tavily-web-search`, for coding assistants |

## Enable Tavily

Installing the plugin serves nothing. The proxy stays off until a platform operator turns it on, so an installed but unused plugin mounts no routes and never contacts Tavily. Enabling web search for an agent takes three steps:

| Step | Who | How often |
|---|---|---|
| 1. Turn on the proxy | Platform operator | Once per platform |
| 2. Store a Tavily API key | Workspace user | Once per workspace |
| 3. Enable Tavily on an agent | Workspace user | Once per agent |

Requires NeMo Helix 0.9 or later. Earlier releases have a different agents API, and the plugin does not load on them.

The plugin is published to PyPI as [`nemo-helix-tavily-plugin`](https://pypi.org/project/nemo-helix-tavily-plugin/). It depends only on NeMo Helix's plugin SDK (`nemo-helix-plugin`), not on `nemo-helix`, so it never installs or upgrades the platform. Install it into an environment that already has NeMo Helix. Each [GitHub release](https://github.com/tavily-ai/nemo-helix-tavily/releases) also attaches the wheel, with its SHA-256 and a build provenance attestation, if you prefer to pin by URL.

### 1. Turn on the proxy (platform operator)

The proxy reads `enabled` at startup, so every change needs a platform restart.

**Local platform.** Install the plugin into the environment that runs `nemo services`, then restart with the proxy on:

```bash
pip install nemo-helix-tavily-plugin
NEMO_TAVILY_ENABLED=true nemo services restart
```

The restarted platform takes the variable from your shell, so set it every time you start the platform (for example, export it in your shell profile). Alternatively, set `tavily: {enabled: true}` in the platform config file.

**Kubernetes (Helm).** The plugin must be installed in the API image, because the chart cannot add Python packages at runtime. If your `nhx-api` image does not include it, build one that does, and point both `api.image` and `core.image` at it:

```dockerfile
FROM <your nhx-api image>
RUN /app/.venv/bin/pip install --no-cache-dir --no-deps "nemo-helix-tavily-plugin==<version>"
```

Keep `--no-deps`. NeMo Helix images report their own packages as version `0.0.0`, so without it pip would try to replace them from PyPI to satisfy the plugin's `nemo-helix-plugin>=0.9` requirement. The image already has every dependency the plugin needs.

If your image builds have no internet access, download the wheel once (`pip download --no-deps nemo-helix-tavily-plugin==<version>`, or from the GitHub release), then `COPY` it into the build and install it from the file instead.

Then turn the proxy on in your Helm values and upgrade the release. Pass all of your existing values files as well; a value left out of `helm upgrade` goes back to its default.

```yaml
platformConfig:
  tavily:
    enabled: true
```

```bash
helm upgrade <release> <chart> -n <namespace> -f values.yaml -f values-tavily.yaml --wait
```

**Check.** `nemo tavily status --workspace <ws>` prints `Tavily proxy: enabled, agents use <url>`. On Kubernetes the URL names the in-cluster API Service, for example `http://nemo-helix-api:8080/...`, not `localhost`. If it prints `Tavily proxy: disabled`, the platform did not pick up the setting: check that it restarted.

### 2. Store a Tavily API key (workspace user)

The `nemo tavily` commands come from the same plugin, so install it wherever your `nemo` CLI runs too (`pip install nemo-helix-tavily-plugin` next to `nemo-helix`; the plugin does not bring the CLI with it). Then store the key for the workspace. The command prompts for it, so the key stays out of shell history:

```bash
nemo tavily setup --workspace <ws>
```

The key is saved as the workspace secret `tavily-api-key`. If the proxy is off, `setup` still stores it and prints how to turn the proxy on.

**Check.** Search from the CLI. This goes through the same proxy agents use, with the workspace's key, so it needs no key on your machine:

```bash
nemo tavily search "latest nemotron release" --workspace <ws> -n 3
```

### 3. Enable Tavily on an agent (workspace user)

```bash
nemo tavily enable <agent> --workspace <ws>
```

`enable` rebuilds and redeploys the agent, so it asks for confirmation; `--yes` skips the prompt. The agent is redeployed in the same mode and with the same image it had. Only `nemo-agents-spec-v1` agents are supported.

**Check.** `nemo tavily status --workspace <ws>` lists the agent as `enabled`. Then ask the agent something recent. Its answer should cite web sources, and its traces show `tavily_search` calls.

To turn web search off for an agent:

```bash
nemo tavily disable <agent> --workspace <ws>
```

### Calling the tools directly

`search` and `extract` call Tavily without an agent, for checking a key or looking something up:

```bash
nemo tavily search "latest nemotron release" --workspace <ws> -n 5
nemo tavily extract https://example.com --workspace <ws> -f json > page.json
```

They use the workspace's key, the tool allowlist and the `X-Client-Name` attribution, like agents do. `search` prints a table of results and `extract` prints each page as markdown; `-f json` gives Tavily's full response.

### What `enable` changes

`enable` adds this to the agent's config stored in Helix (not your local `agent.yaml`), then rebuilds the agent the same way `nemo agents redeploy` does:

```yaml
mcp:
  servers:
    tavily:
      transport: streamable-http
      url: <platform>/apis/tavily/v2/workspaces/<ws>/mcp
```

The platform reports `<platform>` from `GET /apis/tavily/v2/workspaces/<ws>/status`, as an address deployed agents can reach: the in-cluster API Service on Kubernetes (`NHX_INTERNAL_BASE_URL`, set by the Helm chart), otherwise the platform's own base URL. `enable` adjusts it for the agent's deployment mode: Docker containers reach a loopback host through `host.docker.internal`. Pass `--mcp-url` to override.

## Configuration

| Setting | Env var | Default |
|---|---|---|
| Serve the proxy (read at startup) | `NEMO_TAVILY_ENABLED` | `false` |
| Upstream MCP URL | `NEMO_TAVILY_MCP_URL` | `https://mcp.tavily.com/mcp` |
| Tools agents can use | `NEMO_TAVILY_ALLOWED_TOOLS` | `["tavily_search","tavily_extract"]` |
| Upstream read timeout (s) | `NEMO_TAVILY_TIMEOUT_SECONDS` | `300` |

Set these in the platform's environment, or under the `tavily` key in the platform config file (Helm: `platformConfig.tavily`).

## Limits

- Only `nemo-agents-spec-v1` agents.
- Subprocess, Docker and Kubernetes deployments get a reachable MCP URL automatically. Other deployment modes need `--mcp-url`.
- With platform auth on, container agents need their deployment to authenticate calls to the proxy; this is not handled yet.

## Development

```bash
uv sync                      # plugin, NeMo Helix (the `helix` dev group) and the test and lint tools
uv run pytest
uv run ruff check && uv run ruff format --check && uv run ty check
```

Keep `nemo-helix` out of the runtime `dependencies`; it is only a dev dependency.

`scripts/smoke.py` checks that an installed build loads and runs on a NeMo Helix platform: entry-point discovery, no routes while disabled, clean authz, and a live platform that serves the proxy only when enabled. It never contacts Tavily. Run it with the Python of a Helix environment the plugin is installed in, for example inside an `nhx-api` image:

```bash
pip install --no-deps dist/nemo_helix_tavily_plugin-*.whl
python scripts/smoke.py
```

## License

MIT. See [LICENSE](LICENSE).
