Skip to content
Get started
Integrations

Tabstack for LangChain.js

Give your LangChain.js agents reliable web access with @tabstack/langchain: schema-enforced extraction, research, generation, and browser automation as native tools.

@tabstack/langchain gives your LangChain.js 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.

It replaces brittle loaders (WebBaseLoader, PlaywrightURLLoader) with a hosted API: schema enforced output, no Playwright binaries, no coupling to your LangChain version. See Tabstack vs. LangChain browser tools.

Terminal window
npm install @tabstack/langchain @langchain/core zod

@langchain/core (v1) and zod are peer dependencies, so your app’s single instance of each is shared. For the agent example below you also need the top-level langchain package (which exports createAgent) and a model provider, for example npm install langchain @langchain/openai.

Create and Setup Your API Key

Before you can start using Tabstack API, you’ll need to create an API key and set it up in your environment.

1. Create Your API Key

  1. Visit the Tabstack Console
  2. Sign in to your account (or create one if you haven’t already)
  3. Navigate to the API Keys section and click the “Manage API Keys”
  4. Once you are on the API Keys page, Click “Create New API Key”
  5. Give your key a descriptive name (e.g., “Development”, “Production”) and click the “Create API Key”
  6. Copy the generated API key and store it securely

2. Set Up Environment Variable

For security and convenience, we recommend storing your API key as an environment variable rather than hardcoding it in your scripts.

macOS/Linux
Terminal window
# Add to your shell profile (~/.bashrc, ~/.zshrc, or ~/.bash_profile)
export TABSTACK_API_KEY="your_api_key_here"
# Or set it temporarily for the current session
export TABSTACK_API_KEY="your_api_key_here"
# Reload your shell or run:
source ~/.bashrc # or ~/.zshrc
Windows (Command Prompt)
# Set temporarily for current session
set TABSTACK_API_KEY=your_api_key_here
# Set permanently (requires restart)
setx TABSTACK_API_KEY "your_api_key_here"
Windows (PowerShell)
# Set temporarily for current session
$env:TABSTACK_API_KEY = "your_api_key_here"
# Set permanently for current user
[Environment]::SetEnvironmentVariable("TABSTACK_API_KEY", "your_api_key_here", "User")

3. Verify Your Setup

Test that your environment variable is set correctly:

macOS/Linux/Windows (Git Bash):

Terminal window
echo $TABSTACK_API_KEY

Windows (Command Prompt):

Terminal window
echo %TABSTACK_API_KEY%

Windows (PowerShell):

Terminal window
echo $env:TABSTACK_API_KEY

You should see your API key printed in the terminal.

import { createAgent } from "langchain";
import { tabstackTools, TabstackToolError } from "@tabstack/langchain";
const agent = createAgent({
model: "openai:gpt-4o",
tools: tabstackTools,
systemPrompt:
"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.",
});
try {
const result = await agent.invoke({
messages: [
{ role: "user", content: "What are Vercel's pricing plans and how do they compare?" },
],
});
console.log(result.messages.at(-1)?.content);
} catch (err) {
if (err instanceof TabstackToolError) {
console.error(`Tabstack failed (${err.status ?? "no status"}): ${err.message}`);
} else {
throw err;
}
}

tabstackTools reads TABSTACK_API_KEY from the environment and is ready to drop into any agent.

ToolWhat it does
extract_structured_dataPull specific fields from a URL into a JSON shape you define.
extract_page_contentFetch a page as clean markdown.
research_questionSynthesize a cited answer across multiple pages.
generate_structured_dataFetch a page, then AI-transform it into derived or reshaped JSON.
automate_browser_taskRun a multi-step, natural-language browser task.

Every tool is exported individually too, so you can use one directly without an agent. Each returns a plain object (the framework serializes it for the model). Each also throws TabstackToolError on failure; the per-tool examples below omit the try/catch for brevity, see Error handling.

import { extractStructuredDataTool } from "@tabstack/langchain";
const data = await extractStructuredDataTool.invoke({
url: "https://news.ycombinator.com",
// json_schema_json is a JSON-encoded JSON Schema describing the fields you want.
json_schema_json: JSON.stringify({
type: "object",
properties: {
stories: {
type: "array",
items: {
type: "object",
properties: {
title: { type: "string" },
points: { type: "number", description: "Story points" },
},
},
},
},
}),
});
console.log(data.stories);

See Schema design for patterns that produce reliable extraction.

import { extractPageContentTool } from "@tabstack/langchain";
const markdown = await extractPageContentTool.invoke({ url: "https://example.com/blog/article" });
import { researchQuestionTool } from "@tabstack/langchain";
const { answer, sources } = await researchQuestionTool.invoke({
query: "What are the latest developments in quantum error correction?",
});
// sources: [{ title, url }, ...]
import { generateStructuredDataTool } from "@tabstack/langchain";
const result = await generateStructuredDataTool.invoke({
url: "https://news.ycombinator.com",
instructions: "For each story, categorize it and write a one-sentence summary.",
json_schema_json: JSON.stringify({
type: "object",
properties: {
summaries: {
type: "array",
items: {
type: "object",
properties: {
title: { type: "string" },
category: { type: "string" },
summary: { type: "string" },
},
},
},
},
}),
});
import { automateBrowserTaskTool } from "@tabstack/langchain";
const result = await automateBrowserTaskTool.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, durationMs, extracted, pagesVisited }

Pass these alongside the required inputs for finer control. They are sent only when provided.

  • extract_structured_data, extract_page_content, generate_structured_data:
    • effort: "min", "standard", or "max". Use "max" for JS-heavy pages (the PlaywrightURLLoader replacement). See Effort levels.
    • nocache: true to bypass the cache.
    • country: ISO 3166-1 alpha-2 code for geotargeting.
  • research_question: mode ("fast" or "balanced"), nocache.
  • automate_browser_task: guardrails, data (context for form filling), country, max_iterations, max_validation_attempts.
// Render a JS-heavy SPA, fresh, from the UK:
await extractPageContentTool.invoke({ url, effort: "max", nocache: true, country: "GB" });

For a custom API key or base URL, or to reuse one client, build the tools explicitly:

import { createTabstackLangchainTools } from "@tabstack/langchain";
const tools = createTabstackLangchainTools({ apiKey: process.env.MY_KEY });
// or pass an SDK client you already have: createTabstackLangchainTools({ client })

Tool calls throw TabstackToolError with a normalized message and, for API failures, an HTTP status:

import { TabstackToolError } from "@tabstack/langchain";
try {
await extractPageContentTool.invoke({ url: "https://example.com" });
} catch (err) {
if (err instanceof TabstackToolError) {
console.error(`Tabstack failed (${err.status ?? "no status"}): ${err.message}`);
}
}