# Hermes Agent + Tabstack

> Give your Hermes agents reliable web access. Schema-enforced extraction, research, generation, and browser automation as a native Hermes toolset.

Category: Agent Frameworks
Language: Python
Package: `tabstack-hermes`
Canonical URL: https://tabstack.ai/integrations/hermes-agent

## Why Hermes + Tabstack

Hermes ships with web search and extraction backends already. [`tabstack-hermes`](https://pypi.org/project/tabstack-hermes/) adds the parts they do not cover: schema-enforced extraction where you define the JSON shape and get that shape back, JS-heavy pages rendered server-side with no browser to install or patch on the box Hermes lives on, research that returns a synthesized answer plus its sources, and multi-step browser automation driven in natural language.

Five tools land in a single `tabstack` toolset, and the plugin also registers a `tabstack` web provider so Hermes' built-in `web_extract` can fetch through Tabstack without the model learning a new tool.

## Quickstart

Requires Python 3.11 or newer, the same floor as `hermes-agent`.

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

Plugins are opt-in: pip puts the plugin on Hermes' discovery path, and `hermes plugins enable tabstack` lets it load.

To install from git instead of PyPI:

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

The `/tabstack_hermes` suffix is the subdirectory holding the plugin, where `plugin.yaml` sits next to the code. Either path lands at `~/.hermes/plugins/tabstack/`.

Confirm it loaded:

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

## The tools

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

All five land in the `tabstack` toolset, so they enable and disable as a unit in `hermes tools`. Names, descriptions, and inputs match the `langchain-tabstack` package 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 are passed only when the model provides them, so omitting them keeps Tabstack's defaults: `effort` (`"min"` | `"standard"` | `"max"`, use `"max"` for JS-heavy pages), `nocache`, and `country` on the extract and generate tools; `mode` (`"fast"` | `"balanced"`) and `nocache` on `research_question`; `data`, `country`, `max_iterations`, and `max_validation_attempts` on `automate_browser_task`.

## Tabstack as the web extract backend

Point Hermes' own `web_extract` tool at Tabstack and the model keeps calling the tool it already knows:

```yaml
# ~/.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, reach for the `research_question` tool instead.

Behavior worth knowing:

- 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 60s 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. Get one at [console.tabstack.ai](https://console.tabstack.ai/signup). |
| `TABSTACK_BASE_URL` | Optional. Point the SDK at a different API base URL. |

Keys are read through Hermes' config layer first (`~/.hermes/.env` via `hermes env set`), then the process environment, so credentials 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.

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

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

## Common use cases

- Give a Hermes agent cited research in one call instead of a search-then-read loop.
- Extract a fixed JSON shape from a page and hand it straight to the next step.
- Route Hermes' existing `web_extract` through Tabstack without touching prompts.
- Drive a multi-step web task (navigate, fill, extract) with no browser on the host.

## Next steps

- [Adapter on GitHub](https://github.com/Mozilla-Ocho/tabstack-hermes)
- [tabstack-hermes on PyPI](https://pypi.org/project/tabstack-hermes/)
- [Hermes plugin docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/plugins)
- [Get an API key](https://console.tabstack.ai/signup)

---

- All integrations: https://tabstack.ai/integrations
- Agent quickstart, every endpoint in one file: https://tabstack.ai/agents.md
- Full documentation: https://docs.tabstack.ai/
