Why Hermes + Tabstack
Hermes ships with web search and extraction backends already. 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.
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:
hermes plugins install Mozilla-Ocho/tabstack-hermes/tabstack_hermes --enableThe /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:
hermes plugins list # tabstack, enabled, 5 tools
hermes tools # the tabstack toolsetThe 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:
# ~/.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_extractre-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
errorentry 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. |
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:
{"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_extractthrough Tabstack without touching prompts. - Drive a multi-step web task (navigate, fill, extract) with no browser on the host.