Tabstack tools for LangChain. Schema-enforced web extraction and research, backed by the official Tabstack SDK.
Project description
langchain-tabstack
Give your LangChain agents reliable web access. Schema-enforced extraction, multi-source research, AI transformation, and browser automation, all as native LangChain tools backed by the official Tabstack SDK.
Why Tabstack
LangChain's built-in loaders (WebBaseLoader, PlaywrightURLLoader) are fine for prototypes and
brittle in production: unpredictable parsing, Playwright binaries to install and maintain, and
behaviour that drifts across LangChain releases.
Tabstack replaces them with a hosted API:
- Schema-enforced output. You define the shape, you get that shape back. No prompt-engineering the JSON out of raw text.
- No browser to run. JS-heavy pages render server-side. No Playwright, no binaries.
- Version-independent. It is an SDK call, not a loader coupled to your LangChain version.
- Sync and async. Every tool supports
invokeand nativeainvoke.
Install
pip install langchain-tabstack
Requires Python 3.9+. For the agent example below you also need a chat model, for example
pip install langchain langchain-openai. Set your API key (get one at
console.tabstack.ai):
export TABSTACK_API_KEY="your-key-here"
Quickstart
from langchain.agents import create_agent
from langchain_tabstack import TABSTACK_TOOLS
agent = create_agent(
"openai:gpt-4o",
tools=TABSTACK_TOOLS,
system_prompt=(
"You are a research assistant with web intelligence tools. "
"Use extract_structured_data for specific fields from a URL, "
"extract_page_content for full page text, and research_question for multi-source research."
),
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What are Vercel's pricing plans?"}]}
)
print(result["messages"][-1].content)
TABSTACK_TOOLS reads TABSTACK_API_KEY from the environment and is ready to drop into any agent.
Using LangChain 0.x?
create_agentis the LangChain 1.x replacement forAgentExecutor+create_tool_calling_agent. The tools themselves work with either.
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. |
Every tool is exported individually too, so you can use one directly without an agent. Tools return
a JSON string (use json.loads); extract_page_content returns markdown text directly.
extract_structured_data
import json
from langchain_tabstack import extract_structured_data_tool
raw = extract_structured_data_tool.invoke(
{
"url": "https://news.ycombinator.com",
# json_schema_json is a JSON-encoded JSON Schema describing the fields you want.
"json_schema_json": json.dumps(
{
"type": "object",
"properties": {
"stories": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"points": {"type": "number", "description": "Story points"},
},
},
}
},
}
),
}
)
data = json.loads(raw)
print(data["stories"])
extract_page_content
from langchain_tabstack import extract_page_content_tool
markdown = extract_page_content_tool.invoke({"url": "https://example.com/blog/article"})
research_question
import json
from langchain_tabstack import research_question_tool
result = json.loads(
research_question_tool.invoke(
{"query": "What are the latest developments in quantum error correction?"}
)
)
print(result["answer"])
for source in result["sources"]: # [{"title": ..., "url": ...}, ...]
print(source["url"])
generate_structured_data
import json
from langchain_tabstack import generate_structured_data_tool
raw = generate_structured_data_tool.invoke(
{
"url": "https://news.ycombinator.com",
"instructions": "For each story, categorize it and write a one-sentence summary.",
"json_schema_json": json.dumps(
{
"type": "object",
"properties": {
"summaries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"category": {"type": "string"},
"summary": {"type": "string"},
},
},
}
},
}
),
}
)
automate_browser_task
import json
from langchain_tabstack import automate_browser_task_tool
result = json.loads(
automate_browser_task_tool.invoke(
{
"task": "Find the top 3 trending repositories and their star counts",
"url": "https://github.com/trending",
"guardrails": "browse and extract only, do not submit forms",
}
)
)
# {"answer", "success", "iterations", "actions", "duration_ms", "extracted", "pages_visited"}
Optional inputs
Pass these alongside the required inputs for finer control. They are sent only when provided, 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, thePlaywrightURLLoaderreplacement).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.
# Render a JS-heavy SPA, fresh, from the UK:
extract_page_content_tool.invoke(
{"url": url, "effort": "max", "nocache": True, "country": "GB"}
)
Async
Every tool supports ainvoke natively, backed by AsyncTabstack, so it runs in your event loop
without a thread-pool bounce:
markdown = await extract_page_content_tool.ainvoke({"url": "https://example.com"})
Configuration
For a custom API key or base URL, or to reuse one client, build the tools explicitly:
from langchain_tabstack import create_tabstack_tools
tools = create_tabstack_tools(api_key="...")
# or pass clients you already have:
# create_tabstack_tools(client=..., async_client=...)
Error handling
Tool calls raise TabstackToolError with a normalised message and, for API failures, an HTTP
status:
from langchain_tabstack import TabstackToolError, extract_page_content_tool
try:
extract_page_content_tool.invoke({"url": "https://example.com"})
except TabstackToolError as err:
print(f"Tabstack failed ({err.status or 'no status'}): {err}")
Good to know
automate_browser_taskruns non-interactively. It does not pause for human-in-the-loop form input, so it never blocks. It returns the final answer plus the data it extracted and the pages it visited.- The client is created lazily, so importing the package never requires an API key to be set.
- The tool names, descriptions, and inputs match the
@tabstack/langchain(LangChain.js) and@tabstack/ai(Vercel AI SDK) packages, so behaviour is consistent across languages and frameworks. Those return native objects with camelCase keys; this package returns JSON strings with snake_case keys, the LangChain-Python convention. The data is the same.
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 langchain_tabstack-0.1.0.tar.gz.
File metadata
- Download URL: langchain_tabstack-0.1.0.tar.gz
- Upload date:
- Size: 13.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b64420a38d02b7a8fcb057c3f8ec33cac300afddb172452558e1fe6e9ab704f0
|
|
| MD5 |
9c1135f27a13f9c1467351222a045bfb
|
|
| BLAKE2b-256 |
776a163f8c77dbf213bc8d237832384d68afe05ab672311f241daa368b1ce5ea
|
Provenance
The following attestation bundles were made for langchain_tabstack-0.1.0.tar.gz:
Publisher:
publish.yml on Mozilla-Ocho/tabstack-langchain-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langchain_tabstack-0.1.0.tar.gz -
Subject digest:
b64420a38d02b7a8fcb057c3f8ec33cac300afddb172452558e1fe6e9ab704f0 - Sigstore transparency entry: 2169712530
- Sigstore integration time:
-
Permalink:
Mozilla-Ocho/tabstack-langchain-python@b9b53437dfe5c22ff4471d815695a6689c85ea4f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Mozilla-Ocho
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b9b53437dfe5c22ff4471d815695a6689c85ea4f -
Trigger Event:
release
-
Statement type:
File details
Details for the file langchain_tabstack-0.1.0-py3-none-any.whl.
File metadata
- Download URL: langchain_tabstack-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
466b379bd88206ad48d8c6012c3c3c8e176cf2a57fcca0bb8dacd7af22802986
|
|
| MD5 |
0d54ca295db18f85f0fe04353bbe4de3
|
|
| BLAKE2b-256 |
3ca1c52363d02df87224d28961fd6a08c884e85be86afa45c1262911632e2b31
|
Provenance
The following attestation bundles were made for langchain_tabstack-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Mozilla-Ocho/tabstack-langchain-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langchain_tabstack-0.1.0-py3-none-any.whl -
Subject digest:
466b379bd88206ad48d8c6012c3c3c8e176cf2a57fcca0bb8dacd7af22802986 - Sigstore transparency entry: 2169712533
- Sigstore integration time:
-
Permalink:
Mozilla-Ocho/tabstack-langchain-python@b9b53437dfe5c22ff4471d815695a6689c85ea4f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Mozilla-Ocho
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b9b53437dfe5c22ff4471d815695a6689c85ea4f -
Trigger Event:
release
-
Statement type: