---
title: Hermes plugin | Tabstack
description: Install the tabstack plugin for Hermes Agent and get cited answers from live sources without the model running its own search loop.
---

[Hermes Agent](https://hermes-agent.nousresearch.com) runs your model. `tabstack-hermes` is a Hermes plugin that hands the web work to Tabstack, so the model asks one question and receives a finished answer with its sources.

Hermes already ships web search and extraction backends. This plugin is not a replacement for search. It adds the calls that finish the job: a cited answer across sources, schema-enforced extraction, and multi-step browser tasks.

The plugin is open source under MIT at [Mozilla-Ocho/tabstack-hermes](https://github.com/Mozilla-Ocho/tabstack-hermes) and published to PyPI as [`tabstack-hermes`](https://pypi.org/project/tabstack-hermes/).

---

## Install

Requires Python 3.11 or newer, the same floor as `hermes-agent`, and an API key from the [console](https://console.tabstack.ai).

Terminal window

```
pip install tabstack-hermes
hermes plugins enable tabstack
hermes env set TABSTACK_API_KEY <your-key>
```

Plugins are opt-in. The pip install puts the plugin on Hermes’ discovery path; `hermes plugins enable tabstack` is what lets it load.

To install from git instead of PyPI:

Terminal window

```
hermes plugins install Mozilla-Ocho/tabstack-hermes/tabstack_hermes --enable
```

The `/tabstack_hermes` suffix is the subdirectory holding the plugin. Hermes renames the installed directory to the manifest name, so it lands at `~/.hermes/plugins/tabstack/` either way.

Confirm it loaded:

Terminal window

```
hermes plugins list      # tabstack, enabled, 5 tools
hermes tools             # the tabstack toolset
```

## The job: a current answer with sources

This is the one flow worth running first. Ask Hermes something its model cannot know, and watch which tool it reaches for.

```
> What changed in the most recent Node.js LTS release?
```

With the plugin enabled, the model calls `research_question` once. Tabstack plans the queries, finds and reads the sources, checks for gaps, iterates where it needs to, and returns a synthesized answer with the pages it cited. Your model receives the answer and its sources.

The tool returns a JSON string, which Hermes hands to the model:

```
{
  "answer": "Node.js 24 entered long-term support in October 2025...",
  "sources": [
    {
      "title": "Node.js Releases",
      "url": "https://nodejs.org/en/blog/release"
    }
  ]
}
```

What did not happen: no search-result ranking in the model’s context, no page fetching, no markup to recover readable text from, no second search to close a gap, and no citation assembly. The model spent its context on your conversation instead of on raw page content.

Without the plugin, the same question either runs through `web_search` and leaves the model to work the results, or gets answered from training data.

`research_question` takes an optional `mode`. The plugin defaults to `balanced`, which requires a [paid plan](/pricing/index.md); on Trial or Starter pass `mode: "fast"`. Research bills per action, so a broader call costs more. See the [Research guide](/guides/research/index.md).

## The tools

All five land in the `tabstack` toolset, so they enable and disable as a unit in `hermes tools`.

| Tool                       | What it does                                                      |
| -------------------------- | ----------------------------------------------------------------- |
| `research_question`        | Synthesized answer with cited sources across multiple pages.      |
| `extract_page_content`     | Fetch a page as clean markdown.                                   |
| `extract_structured_data`  | Pull specific fields from a URL into a JSON shape you define.     |
| `generate_structured_data` | Fetch a page, then transform it into derived or reshaped JSON.    |
| `automate_browser_task`    | Run a multi-step, natural-language browser task on a public site. |

Names, descriptions, and inputs match [`langchain-tabstack`](/integrations/langchain-python/index.md) and the TypeScript adapters, so a Tabstack tool behaves the same whichever framework calls it. Tools return a JSON string; `extract_page_content` returns markdown directly.

### Optional inputs

Sent only when the model provides them, so omitting them keeps Tabstack’s defaults. Exception: when `mode` is omitted, the plugin sends `"balanced"`.

- `extract_structured_data`, `extract_page_content`, `generate_structured_data`:

  - `effort`: `"min"`, `"standard"`, or `"max"`. Use `"max"` for JavaScript-heavy pages. See [Effort levels](/guides/effort-levels/index.md).
  - `nocache`: `true` to bypass the cache.
  - `country`: ISO 3166-1 alpha-2 code for [geotargeting](/guides/geotargeting/index.md).

- `research_question`: `mode` (`"fast"` or `"balanced"`), `nocache`.

- `automate_browser_task`: `url` (starting page), `guardrails` (constraints on what the agent may do), `data` (context for form filling), `country`, `max_iterations`, `max_validation_attempts`.

## Tabstack as the web extract backend

The plugin also registers a `tabstack` web provider, so Hermes’ built-in `web_extract` tool can fetch through Tabstack without the model learning a new tool:

\~/.hermes/config.yaml

```
web:
  extract_backend: "tabstack"
```

Extract only. Tabstack has no ranked search endpoint, so `supports_search` is `False` and `web_search` keeps using whichever backend you already have. For synthesis across sources, use `research_question` rather than a search backend.

How it behaves:

- URLs come back in the order they went in, because `web_extract` re-interleaves them with the ones it rejected as unsafe.
- A batch fans out 5 URLs at a time with a 60 second ceiling per URL. One failing URL returns an `error` entry for that URL and does not fail the batch.
- `format="html"` is ignored. Tabstack returns markdown.

## Configuration

| Variable            | Purpose                                                             |
| ------------------- | ------------------------------------------------------------------- |
| `TABSTACK_API_KEY`  | Required. Create one in the [console](https://console.tabstack.ai). |
| `TABSTACK_BASE_URL` | Optional. Point the SDK at a different API base URL.                |

Keys are read through Hermes’ config layer first (`~/.hermes/.env`, written by `hermes env set`), then the process environment. Credentials therefore work in gateway sessions, delegated children, and subprocess agent runs where the variable was never exported.

Without a key the plugin still loads and the tools still appear in `hermes tools`, but a `check_fn` keeps them out of dispatch until a key is set. The SDK is imported and the client built on the first tool call, so a session that never calls Tabstack pays no cold-start cost.

## Error handling

Handlers never raise. A failure returns JSON the model can act on, with the HTTP status when the API supplied one:

```
{ "error": "Extract failed for https://example.com", "status": 429 }
```

See the [error reference](/production/error-reference/index.md) for what each status means.

## Limits

- `automate_browser_task` runs on public websites and cannot log in. For automation against a browser you control, see [Pilo](/guides/pilo/index.md).
- The plugin covers extraction, not ranked search. Keep your existing `web_search` backend.
- Requests are hosted calls to the Tabstack API. See [Data Handling](/trust/data-handling/index.md) for what is stored.

## Next steps

- [Research guide](/guides/research/index.md): modes, the event stream, and timeout strategy.
- [Search versus research](/guides/search-vs-research/index.md): which steps Tabstack runs inside the call.
- [Other integrations](/integrations/index.md): the same five tools in LangChain, Vercel AI SDK, Mastra, and more.
