Documentation Lookup for a Coding Agent
Give a coding agent a tool that reads current documentation instead of answering from training data. Uses /extract/markdown for a known URL and /research when the right page is unknown.
A coding agent’s worst answers come from documentation it learned two model versions ago: a renamed flag, a removed option, a breaking change it never saw. The fix is not a bigger model, it is letting the agent read the current page.
This example wires two tools into an agent loop. readDocs takes a URL the agent already has and returns the page as clean markdown. findInDocs takes a question when the agent does not know which page holds the answer, and returns a cited answer. Both are one call.
import Tabstack from "@tabstack/sdk";
const client = new Tabstack();
/** The agent has a URL. Return the current page as markdown. */async function readDocs(url: string) { const result = await client.extract.markdown({ url, // Documentation sites change. Skip the shared cache for anything // version-sensitive, at the cost of a slower fetch. nocache: true, });
return result.content;}
/** The agent has a question but not a URL. Return a cited answer. */async function findInDocs(question: string) { const stream = await client.agent.research({ query: question, mode: "fast", });
for await (const event of stream) { if (event.event === "error") { throw new Error(event.data.error?.message ?? "Documentation lookup failed"); }
if (event.event === "complete") { const sources = (event.data.metadata.citedPages ?? []).map((p) => p.url); return { answer: event.data.report, sources }; } }
throw new Error("Stream ended before the complete event");}
// The agent already knows where to look.const page = await readDocs("https://docs.tabstack.ai/guides/research");console.log(page.slice(0, 500));
// The agent does not.const { answer, sources } = await findInDocs( "What is the current default value of the Tabstack research mode parameter?",);console.log(answer);console.log("Sources:", sources);from tabstack import Tabstack
client = Tabstack()
def read_docs(url: str) -> str: """The agent has a URL. Return the current page as markdown.""" result = client.extract.markdown( url=url, # Documentation sites change. Skip the shared cache for anything # version-sensitive, at the cost of a slower fetch. nocache=True, ) return result.content
def find_in_docs(question: str) -> dict: """The agent has a question but not a URL. Return a cited answer.""" for event in client.agent.research(query=question, mode="fast"): if event.event == "error": message = event.data.error.message if event.data.error else "Documentation lookup failed" raise RuntimeError(message)
if event.event == "complete": sources = [p.url for p in (event.data.metadata.cited_pages or [])] return {"answer": event.data.report, "sources": sources}
raise RuntimeError("Stream ended before the complete event")
# The agent already knows where to look.page = read_docs("https://docs.tabstack.ai/guides/research")print(page[:500])
# The agent does not.result = find_in_docs( "What is the current default value of the Tabstack research mode parameter?")print(result["answer"])print("Sources:", result["sources"])# Read a page you already have the URL fortabstack extract markdown https://docs.tabstack.ai/guides/research --nocache
# Ask when you do not know which page holds the answertabstack agent research "What is the current default value of the Tabstack research mode parameter?" --mode fastHow it works
Section titled “How it works”- Two tools, not one. Reading a known URL and finding an unknown one are different jobs with different costs.
/extract/markdownis 10 credits and deterministic;/researchruns several actions and bills for each. Giving the agent both lets it pick the cheap path when it can. - Markdown is what a model wants.
/extract/markdownstrips navigation, ads, and boilerplate before the content reaches your context window, so a long page costs what its prose costs rather than what its markup costs. nocache: truematters here specifically. Page content is cached by URL, effort, and region rather than by account. For documentation that changes between releases, a cached copy is the exact failure you were trying to avoid. See Data Handling.- The citations are the point. When the agent answers from
findInDocs,citedPagesgives you the URLs behind the claim, so a reviewer can check the answer instead of trusting it.
Wiring it into an agent
Section titled “Wiring it into an agent”If your agent runs on a framework, skip the hand-rolled tools: the maintained packages expose extract_page_content and research_question with the same names across languages. See LangChain (Python), the Vercel AI SDK, or the Hermes plugin.
For a coding agent in a terminal, the CLI is often enough. It prints human-readable output in a terminal and switches to JSON when piped.
Installation
Section titled “Installation”npm install @tabstack/sdkpip install tabstackSet your API key before running:
export TABSTACK_API_KEY=your_api_key