tako-sdk
v1.2.0
Published
JavaScript/TypeScript SDK for the Tako API
Readme
Tako TypeScript SDK
The Tako SDK provides typed access to the Tako API from Node.js (≥ 18), the browser, and edge runtimes. It ships fully typed request/response models, a Tako client, and a live agent-streaming API. Generated from Tako's OpenAPI spec with openapi-generator (typescript-fetch) — zero runtime dependencies.
Installation
npm install tako-sdkAuthentication
Create an API key from your Tako account and keep it out of source control:
import { Tako } from "tako-sdk";
const tako = new Tako({ apiKey: process.env.TAKO_API_KEY! });Usage
const results = await tako.search({ query: "S&P 500 performance this year" });
console.log(results.request_id);
for (const card of results.cards ?? []) {
console.log(card.title, card.webpage_url);
}Operations
| Method | Description |
| -------------------------- | ----------------------------------------------------------------------- |
| tako.search(request) | Search the Tako knowledge base; returns matching cards and web results. |
| tako.answer(request) | Get a written answer with supporting cards. |
| tako.createCard(request) | Build a visualization card from component configurations. |
| tako.contents(request) | Fetch downloadable content (e.g. a CSV) for a card or web URL. |
Fetch the underlying data for a card returned by a search (guard for cards with no exportable content):
const results = await tako.search({ query: "US Oil Prices" });
const card = (results.cards ?? []).find((c) => c.webpage_url && c.content);
if (card?.webpage_url) {
const contents = await tako.contents({ url: card.webpage_url });
for (const item of contents.contents ?? []) console.log(item.content_format, item.url); // url is populated only in URL delivery mode (url?: string | null)
}Async only. JavaScript is uniformly promise-based, so there is a single
Takoclient (unlike the Python SDK's separateTako/AsyncTako). Every operation returns aPromise.
Agents
Two agent products hang off tako.agent:
| Namespace | Endpoint | Product |
| ------------------------ | -------------------------- | ------------------------------------------------------------------------------------------------------ |
| tako.agent.retrieval.* | /v1/agent/retrieval/runs | Retrieval Agent — agentic data retrieval (multi-hop lookup, cohort resolution, structured outputs) |
| tako.agent.answer.* | /v1/agent/answer/runs | Answer Agent — opinionated agentic research returning cited prose |
Each exposes run(req) (202 dispatch → run handle), get(runId) (poll for status), and stream(req) (live SSE). (tako.agent.answer.*, the Answer Agent, is distinct from tako.answer(), the one-shot /v1/answer call.)
Streaming
Stream a run live over Server-Sent Events. The stream yields typed per-product envelopes (RetrievalAgentStreamEnvelope / AnswerAgentStreamEnvelope) and auto-reconnects (resuming via the last seq) on transient drops. Always close it (or use try/finally):
const stream = tako.agent.retrieval.stream({
query: "Which S&P 500 semis grew revenue fastest in 2024?",
});
try {
for await (const event of stream) {
console.log(event.seq, event.block.kind);
}
// The stream ends at stream_done. If it ended without a terminal result
// (and produced at least one event, so run_id is known), poll for status:
if (stream.result === null && stream.run_id !== null) {
const run = await tako.agent.retrieval.get(stream.run_id);
console.log(run.status);
}
} finally {
await stream.close();
}The Answer Agent is identical with tako.agent.answer.*. Tune reconnect behavior with the second argument — maxRetries (reconnect attempts after a transient drop, default 5) and readTimeoutMs (idle read before a connection is treated as dropped, default 120000):
const stream = tako.agent.retrieval.stream(
{ query: "..." },
{ maxRetries: 5, readTimeoutMs: 120_000 },
);Non-streaming dispatch/poll is also available: tako.agent.retrieval.run(req) returns a RetrievalAgentRun (202 dispatch); tako.agent.retrieval.get(runId) polls for status.
Structured output (Retrieval Agent)
Pass an output_schema (JSON Schema) to shape the response. Mark a property with "x-tako-dataset": true to request a dataset slot — filled with exact retrieved rows as a TakoDataset. Two helpers make this ergonomic:
deriveResponseSchema(schema)— the schemastructured_outputactually validates against (each slot becomesTakoDataset | null). Pair with a JSON Schema validator such as ajv.TakoDatasetView— a records view over a filled slot..recordsreturns one plain object per row (dependency-free).
import { Tako, TakoDatasetView, deriveResponseSchema } from "tako-sdk";
const schema = {
type: "object",
properties: {
headline: { type: "string" },
cohort: { "x-tako-dataset": true, columns: ["company", "revenue"] },
},
required: ["headline", "cohort"],
};
const tako = new Tako({ apiKey: process.env.TAKO_API_KEY! });
const dispatched = await tako.agent.retrieval.run({ query: "...", output_schema: schema });
const run = await tako.agent.retrieval.get(dispatched.run_id); // poll to a terminal status
const derived = deriveResponseSchema(schema); // validate with ajv against this
const output = run.result?.structured_output;
if (output) {
const view = new TakoDatasetView(output.cohort);
console.log(view.records); // [{ company: "Nvidia", revenue: 130497000000 }, ...]
}See examples/ for runnable scripts: retrieval_agent_streaming.ts, answer_agent_streaming.ts, and retrieval_agent_structured_output.ts.
Configuration
By default the client targets the Tako production API (https://tako.com/api). Override the base path for staging or self-host:
const tako = new Tako({ apiKey: "...", basePath: "https://staging.tako.com/api" });Error handling
Non-2xx responses throw a ResponseError carrying the raw Response:
import { ResponseError } from "tako-sdk";
try {
await tako.search({ query: "..." });
} catch (err) {
if (err instanceof ResponseError) {
console.error(err.response.status, await err.response.text());
} else {
throw err;
}
}TypeScript
All request/response models are exported as types:
import type {
SearchRequest,
SearchResponse, // .cards is Array<TakoCard>
AnswerResponse, // .cards is Array<TakoCard>
ContentsRequest,
ContentsResponse,
CreateCardRequest,
TakoCard, // card type returned by search() and answer()
ThinVizCard, // card type returned by createCard()
RetrievalAgentRunRequest,
RetrievalAgentStreamEnvelope,
AnswerAgentRunRequest,
AnswerAgentStreamEnvelope,
TakoDataset,
} from "tako-sdk";search and answer return TakoCard[] via SearchResponse.cards / AnswerResponse.cards. createCard returns a ThinVizCard.
License
MIT
