Answers in the Vercel AI SDK
@hyperresearch/ai-sdk adds Answers to the
Vercel AI SDK as two tools:
hyperresearchAnswerasks one factual question and returns one short answer with the quotes it rests on, each checked word for word against its page. When no source supports an answer, it returnsnot_foundinstead of a guess. The research runs on our side, so the model makes one tool call and no pages land in its context.hyperresearchSearchreturns ranked raw sources from the open web and about 45 structured sources (company filings, statistics agencies, scholarly indexes, books, government records), each with the passages that matched, copied word for word. No summary.
Package: @hyperresearch/ai-sdk on npm.
Source: github.com/jordan-gibbs/hyperresearch-answers
(packages/). MIT licensed.
Install
Section titled “Install”npm install @hyperresearch/ai-sdk# pnpm add @hyperresearch/ai-sdk · yarn add @hyperresearch/ai-sdk · bun add @hyperresearch/ai-sdkPeer dependencies: ai 6 or 7, and zod 3.25 or later (4 works).
API key
Section titled “API key”Create a key with the answers:ask scope on the
API keys page and put it in the
environment:
export HYPERRESEARCH_API_KEY=hr_live_...Use an hr_live_ key. Answers has no fixture mode, so hr_test_ keys are
refused. Every account gets free credit to start; prices per call are on
Answers pricing. Keep the key out of anything you commit.
Example
Section titled “Example”import { generateText, isStepCount } from 'ai';import { hyperresearchAnswer } from '@hyperresearch/ai-sdk';
const { text } = await generateText({ model: 'openai/gpt-5-mini', prompt: 'How old must a US senator be?', tools: { answer: hyperresearchAnswer(), }, stopWhen: isStepCount(3),});
console.log(text);The examples use isStepCount, the ai 7 name. On ai 6 the same helper is
stepCountIs.
hyperresearchTools() returns both tools sharing one client:
import { generateText, isStepCount } from 'ai';import { hyperresearchTools } from '@hyperresearch/ai-sdk';
const { text } = await generateText({ model: 'anthropic/claude-sonnet-4.6', prompt: 'What was Nvidia revenue in fiscal 2026, and where is it reported?', tools: hyperresearchTools(), stopWhen: isStepCount(5),});Exports and options
Section titled “Exports and options”| Export | What it is |
|---|---|
hyperresearchAnswer(options?) |
The ask tool |
hyperresearchSearch(options?) |
The search tool |
hyperresearchTools(options?) |
Both, sharing one client |
HyperresearchClient |
The REST client the tools use, for direct calls |
HyperresearchError |
Thrown for any non-2xx response |
hyperresearchAnswer({ apiKey: process.env.HYPERRESEARCH_API_KEY, // the default mode: 'fast', // fix the mode instead of letting the model choose maxCostCents: 10, // cap every call; a standard ask capped below its escalated price never escalates askTimeoutMs: 360_000, // end to end, including waiting for a long ask});
hyperresearchSearch({ mode: 'max', // every provider, plus structured data rows and PDF tables maxResults: 5, // 1 to 25, default 10});Without mode, the model picks it per call (fast, standard or max for
ask; standard or max for search), and standard is the default. Every
factory also takes baseUrl, fetch, headers, maxRetries (default 2) and
a shared client.
The client works on its own:
import { HyperresearchClient } from '@hyperresearch/ai-sdk';
const hr = new HyperresearchClient();const r = await hr.ask({ question: 'When was the Peace of Westphalia signed?', mode: 'fast' });console.log(r.status, r.answer, r.evidence[0]?.quote, r.price_cents);What the model gets back
Section titled “What the model gets back”hyperresearchAnswer:
{ "id": "ans_01J...", "status": "answered", "answer": "At least 30 years old (US Constitution, Article I, Section 3).", "evidence": [ { "url": "https://www.archives.gov/founding-docs/constitution-transcript", "title": "The Constitution of the United States: A Transcription", "quote": "No Person shall be a Senator who shall not have attained to the Age of thirty Years", "check": "verified" } ], "price_cents": 5}status is one of answered, false_premise, unconfirmed, not_found or
error. caveat appears when the check could not settle something, and
escalated: true when a standard ask dug further.
hyperresearchSearch returns results, each with rank, url, title,
source and passages (text, verified), plus price_cents.
Answers and passages are text from web pages. Treat them as data, not as instructions.
Long asks
Section titled “Long asks”A max ask can take a few minutes. The client sends
Prefer: respond-async; wait=50; if the answer is not ready by then, the API
answers 202 with the call’s id and status: "pending", and the client
collects it from GET /v1/answers/{id}?wait=45 until it finishes. The call is
charged once, when it finishes. askTimeoutMs (default six minutes) bounds the
whole wait.
Errors
Section titled “Errors”- Our failures come back as
200withstatus: "error"anderror.code: "engine_unavailable". They cost nothing. - Non-2xx responses are thrown as
HyperresearchError, carryingstatus,type,code,message,param,requestIdandretryAfterfrom the error envelope. 402 insufficient_balance: add credit in the console.402 wallet_frozen: write to support.409 idempotency_key_reuseoridempotency_in_flight: the client sends a freshIdempotency-Keyper call and reuses it on its own retries, so these mean two callers shared one key.429(rate limit or too many calls running) and503 answers_capacityare retried up tomaxRetriestimes, waitingRetry-After. Neither is charged.
ask and search together are limited to 60 calls a minute per API key and
120 a minute per workspace. See rate limits.
Without the SDK
Section titled “Without the SDK”The tools call the Answers REST API: POST /v1/answers,
POST /v1/answers/search and GET /v1/answers/{id} on
https://api.hyperresearch.ai. Every field is in the
API reference. The same two tools are also
an MCP server at https://answers.hyperresearch.ai/mcp; see Answers.