Tabstack plugin for Hermes Agent. Schema-enforced web extraction, research, AI transformation, and browser automation, plus a Tabstack web extract backend.
Project description
tabstack-hermes
Tabstack web intelligence for Hermes Agent. Five native
tools in a tabstack toolset, plus a tabstack backend for Hermes' own web_extract tool, all
backed by the official Tabstack SDK.
Why Tabstack
Hermes ships with web search and extraction backends already. Tabstack adds the parts they do not cover:
- Schema-enforced extraction. You define the JSON shape, you get that shape back. No prompt-engineering the JSON out of page text.
- No browser to run. JS-heavy pages render server side. Nothing to install, nothing to keep patched on the box Hermes lives on.
- Research with citations. One call returns a synthesised answer plus the sources it used.
- Browser automation. Multi-step, natural-language web tasks that navigate, fill, and extract across pages.
Install
Requires Python 3.11 or newer (same floor as hermes-agent) and a Tabstack API key from
console.tabstack.ai.
pip install tabstack-hermes
hermes plugins enable tabstack
hermes env set TABSTACK_API_KEY <your-key>
Plugins are opt-in, so hermes plugins enable tabstack is required: the pip package puts the plugin
on Hermes' discovery path, the enable step lets it load.
Prefer to install from git instead of PyPI:
hermes plugins install Mozilla-Ocho/tabstack-hermes/tabstack_hermes --enable
The /tabstack_hermes suffix is the subdirectory holding the plugin: plugin.yaml sits next to the
code so one directory serves both install paths. Hermes renames the installed directory to the
manifest name, so it lands at ~/.hermes/plugins/tabstack/ either way.
Confirm it loaded:
hermes plugins list # tabstack, enabled, 5 tools
hermes tools # the tabstack toolset
The tools
| Tool | 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 |
Synthesised 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
Passed only when the model provides them, so omitting them keeps Tabstack's defaults.
extract_structured_data,extract_page_content,generate_structured_data:effort:"min"|"standard"|"max". Use"max"for JS-heavy pages (full server-side browser rendering).nocache:trueto bypass the cache.country: ISO 3166-1 alpha-2 code (for example"US") for geotargeted fetches.
research_question:mode("fast"|"balanced"),nocache.automate_browser_task: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 (brave-free, ddgs, exa, tavily, firecrawl, and so on).
For synthesis across sources, use the research_question tool rather than a search backend.
Behaviour 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, 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 their
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}
Alternative: MCP
Tabstack's CLI ships a stdio MCP server, which is a config-only path with no plugin install:
# ~/.hermes/config.yaml
mcp_servers:
tabstack:
command: "tabstack"
args: ["mcp"]
That exposes the raw API surface as mcp_tabstack_* tools. This plugin is the better default: the
tool names match Tabstack's other framework integrations, the tools are one toolset the user can
toggle, there is no subprocess per session, and web_extract can route through Tabstack.
Development
uv venv --python 3.11 && uv pip install -e ".[test,dev]"
pytest # 44 tests, no network
ruff check . && ruff format --check .
hermes-agent is not a dependency of this package: it is the host process. Install it in the dev
environment (uv pip install hermes-agent) to exercise the tests that need it, which is the web
provider glue plus an end-to-end load through Hermes' own plugin loader, tool registry, and web
provider registry. They skip without it.
Releases are cut from a GitHub Release tagged vX.Y.Z: the tag's version is written into
pyproject.toml, plugin.yaml, and __version__ at build time, and the package is published to
PyPI through trusted publishing after lint and tests pass.
See CONTRIBUTING.md for the contributor guide and AGENTS.md for the architecture, conventions, and the host API surface this plugin depends on.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tabstack_hermes-0.0.1.tar.gz.
File metadata
- Download URL: tabstack_hermes-0.0.1.tar.gz
- Upload date:
- Size: 20.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c33239b597a133672b279833a0dc8af7d8cdd4096524fe4bfb7cc4c1f476e7d6
|
|
| MD5 |
a7d7653a342f76d98a798d2212911e63
|
|
| BLAKE2b-256 |
aabfbfa95f9377b5c987273402c6c19686373dabcf2f1063745552be93ad150e
|
Provenance
The following attestation bundles were made for tabstack_hermes-0.0.1.tar.gz:
Publisher:
publish.yml on Mozilla-Ocho/tabstack-hermes
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tabstack_hermes-0.0.1.tar.gz -
Subject digest:
c33239b597a133672b279833a0dc8af7d8cdd4096524fe4bfb7cc4c1f476e7d6 - Sigstore transparency entry: 2336174744
- Sigstore integration time:
-
Permalink:
Mozilla-Ocho/tabstack-hermes@f55103fad90588e7edffc1cd9afbf05e82e3f3de -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/Mozilla-Ocho
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f55103fad90588e7edffc1cd9afbf05e82e3f3de -
Trigger Event:
release
-
Statement type:
File details
Details for the file tabstack_hermes-0.0.1-py3-none-any.whl.
File metadata
- Download URL: tabstack_hermes-0.0.1-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73340c2e388c40708bad6f9da7e8487fcbd4715d808397531f6addd1f061d303
|
|
| MD5 |
bdf511e0b53e2fb5b350635d9aadd0dc
|
|
| BLAKE2b-256 |
5f049aeaa1a3ab43a1a389a2808a54b8273ca9a71c2d5487ef02933761af3928
|
Provenance
The following attestation bundles were made for tabstack_hermes-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on Mozilla-Ocho/tabstack-hermes
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tabstack_hermes-0.0.1-py3-none-any.whl -
Subject digest:
73340c2e388c40708bad6f9da7e8487fcbd4715d808397531f6addd1f061d303 - Sigstore transparency entry: 2336174777
- Sigstore integration time:
-
Permalink:
Mozilla-Ocho/tabstack-hermes@f55103fad90588e7edffc1cd9afbf05e82e3f3de -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/Mozilla-Ocho
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f55103fad90588e7edffc1cd9afbf05e82e3f3de -
Trigger Event:
release
-
Statement type: