Console
Guides/Tako search guide

Tako search guide

Make a model search live, sourced data with tako:search: a first request, reading the cards, the playground, cost at $0.007 a search, and fixes.

/llms.txt

tako:search gives a chat model live, sourced data from Tako: financial, economic, sports, weather and company series as charted "cards", plus web results. You add it to tools, the model decides when to search, the gateway runs each search, and you get one finished answer with the cards it used. This page takes you from a key to your first cards, and through the things that go wrong. Server tools is the full reference.

Quickstart

1. Get a key

Sign in and create a key at API keys. Use an organization key: tako:search is billed per search to an organization.

2. Add paid credit

Add credit in Billing. Each search needs its $0.007 in credit before it runs, on top of the model's own turns.

3. Export the key

bash
export TM_API_KEY=tm_vk_...

The same request three ways. It asks a question that needs data newer than the model's training, allows at most 3 searches, and asks the model to search first.

curl
curl -i https://api.routerplus.com/v1/chat/completions \
  -H "Authorization: Bearer $TM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-haiku-4-5",
    "messages": [{"role": "user", "content": "How did US CPI inflation change each month from January to September 2026?"}],
    "tools": [{"type": "tako:search", "parameters": {"max_uses": 3}}],
    "tool_choice": {"type": "tako:search"}
  }'
python
The official openai SDK, with the tool in extra_body
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.routerplus.com/v1", api_key=os.environ["TM_API_KEY"])

completion = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{"role": "user", "content": "How did US CPI inflation change each month from January to September 2026?"}],
    extra_body={
        "tools": [{"type": "tako:search", "parameters": {"max_uses": 3}}],
        "tool_choice": {"type": "tako:search"},
    },
    timeout=180,  # a whole answer comes when the request is done, within 110 s
)

message = completion.choices[0].message
print(message.content)
tako = getattr(message, "tako", None) or {}  # absent when no search succeeded
for card in tako.get("cards", []):
    print(card["title"], card["embed_url"], card["coverage_end"])
usage = completion.usage
print(usage.server_tool_use["tako_search_requests"], "searches, cost $", usage.cost)
typescript
The official openai SDK, with a cast
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.routerplus.com/v1",
  apiKey: process.env.TM_API_KEY,
  timeout: 180_000, // a whole answer comes when the request is done, within 110 s
});

type TakoCard = {
  title: string; webpage_url: string; embed_url: string;
  image_url: string; source_names: string[]; coverage_end: string;
};

// The SDK's types know only function and custom tools, so the body is cast; it is sent as is.
const completion = await client.chat.completions.create({
  model: "claude-haiku-4-5",
  messages: [{ role: "user", content: "How did US CPI inflation change each month from January to September 2026?" }],
  tools: [{ type: "tako:search", parameters: { max_uses: 3 } }],
  tool_choice: { type: "tako:search" },
} as unknown as OpenAI.Chat.ChatCompletionCreateParamsNonStreaming);

const message = completion.choices[0].message as OpenAI.Chat.ChatCompletionMessage & { tako?: { cards: TakoCard[] } };
const usage = completion.usage as OpenAI.CompletionUsage & { cost: number; server_tool_use?: { tako_search_requests: number } };
console.log(message.content);
for (const card of message.tako?.cards ?? []) console.log(card.title, card.embed_url, card.coverage_end); // absent when no search succeeded
console.log(usage.server_tool_use?.tako_search_requests ?? 0, "searches, cost $", usage.cost);

The SDKs do not know the tako:search tool type. In Python, tools and tool_choice go in extra_body, which the SDK merges into the request body unchanged, and the answer's extra fields read as plain dicts (message.tako["cards"], usage.server_tool_use["tako_search_requests"]). In TypeScript, the request is cast to ChatCompletionCreateParamsNonStreaming (the SDK sends the body as written) and the answer is cast to add tako and server_tool_use.

Adding the tool lets the model search; it does not make it search. Whether a model calls tako_search is the model's own choice, and any model can answer from what it already knows instead. In the playground, a receipt that says "0 Tako searches" means the model chose not to search, not that Tako failed.

Two things help:

  • Ask for the first search. tool_choice: {"type": "tako:search"} asks the model to search on its first turn. It applies to the first turn only; later turns are "auto", so the model decides whether to search again.
  • Ask for data the model cannot know. Name a series and a recent period, newer than the model's training. For example:
    • "How did US CPI inflation change each month from January to September 2026?"
    • "What was Nvidia's quarterly revenue in each of the last four quarters, through 2026?"
    • "How did the US unemployment rate move over the last 12 months?"
    • "What was the 10-year US Treasury yield at the end of each week in October 2026?"

The playground has no tool_choice control: there you get a search by the prompt alone. To force one, open Code in the composer ("This request as code"), copy the request, and add "tool_choice": {"type": "tako:search"} to it.

Read the answer

The answer is an ordinary chat.completion with two additions:

  • choices[0].message.tako.cards: the cards the searches found, at most 20, one per title. Each has title, webpage_url, embed_url, image_url, source_names and coverage_end (where the card's data ends, such as "2026-09"). Use embed_url to show Tako's chart in your app, and webpage_url to link to it. When no search succeeded, tako is absent.
  • usage.server_tool_use.tako_search_requests: the number of searches billed. The header x-tm-server-tools: tako_search=<n> says the same. On a streamed answer it comes as an HTTP trailer, after the body: read usage.server_tool_use there instead.

usage.cost is in USD: the model's turns plus the searches. usage.prompt_tokens is the last turn's prompt (the context after the request), completion_tokens adds up every turn's output, and usage.server_tool_turns lists each turn's own usage (Server tools). To see the header with curl on a whole (non-streamed) answer, add -i (as above) or -D -:

bash
curl -s -D - -o /dev/null https://api.routerplus.com/v1/chat/completions \
  -H "Authorization: Bearer $TM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "claude-haiku-4-5", "messages": [{"role": "user", "content": "How did the US unemployment rate move over the last 12 months?"}], "tools": [{"type": "tako:search"}], "tool_choice": {"type": "tako:search"}}' \
  | grep -i x-tm-server-tools

With "stream": true the response starts at once and sends a keep-alive every 10 seconds; the whole answer still comes at the end. See Server tools for the stream's events.

Parameters

FieldValuesDefault
max_usesa whole number from 1 to 10: searches per request, across all turns5
counta whole number from 1 to 5: results of each source per search3
effort"instant" or "fast""fast"
sourcesa non-empty list of "data" (cards) and "web" (web results)both

max_tokens and the rest of your request are sent with each model turn, so max_tokens limits each turn, not the whole request.

Playground

To try it without code, open the Playground:

  1. 01
    Pick a chat model, open Parameters in the composer, and turn on Tako search. The switch is off in every new chat, so turn it on in each one.
  2. 02
    Set the options if you like:
    • Effort: fast or instant. Instant answers from Tako's cached cards and is quicker; fast fetches fresh data. Same price.
    • Most searches per request (1–10): max_uses, 5 by default.
    • Results per source (1–5): count, 3 by default.
    • Sources: data cards, web results, or both (at least one).
  3. 03
    Send a prompt that needs live data (see Make the model search). While the gateway searches, the pending reply says it is searching Tako, and nothing appears until the answer is ready.
  4. 04
    The cards appear under the reply, and the receipt shows "N Tako searches ($x)", such as "1 Tako search ($0.007)" or "3 Tako searches ($0.021)".

Cost

A search costs $0.007 ($7 per 1,000 searches), Tako's list price, with no markup. A search that fails is not billed. The model's turns are billed as ordinary chat requests, at the model's price. A request has at most max_uses + 1 model turns.

SearchesSearch fees
1$0.007
3$0.021
at most 5 (the default max_uses)at most $0.035
at most 10 (max_uses 10)at most $0.070

The sample answer in Server tools made one search: its usage.cost of 0.009324 is $0.007 for the search plus $0.002324 for the model's turns. See Pricing & billing for the billing math.

Troubleshooting

0 searches. The model chose not to search and answered from what it knows. Tako did not fail. Send tool_choice: {"type": "tako:search"}, or ask for a named series over a recent period (see Make the model search).

400 server_tool_unsupported "not enabled on this gateway". The gateway you called does not serve tako:search, so nothing was searched or billed. Ask support to turn it on, or remove tako:search from tools (or the x-tm-tools header) to send the request without it.

503 "turned on but not configured". tako:search is turned on for the gateway you called, but our Tako key is not in place yet. Ask support; retrying will not help until the key is configured.

Nothing arrives for a long time. This is expected: a whole (non-streamed) answer arrives when the request is done, within 110 seconds. A streamed answer starts at once, on every endpoint, and sends a keep-alive every 10 seconds; the request can take up to 150 seconds. Set your client's read timeout above 150 seconds.

Claude Code or Codex. Send the header x-tm-tools: tako:search: see Claude Code and Codex.

504 after 110 seconds. A request that is not streamed has 110 seconds (a streamed one has 150), and each search has 15. Searches that finished are billed. Retry with "stream": true, or use effort: "instant" or a lower max_uses.

400 that names a field or the endpoint. A parameter out of range, an unknown parameter, an effort other than "instant" or "fast", a second tako:search entry, or a tool of your own named tako_search. The tool is a 400 server_tool_unsupported on a composite model (tm/...) and on a dedicated endpoint, on POST /v1/messages beside another server tool (with a tools entry; with the header alone such a request is served without Tako), mcp_servers or container, and on POST /v1/responses beside previous_response_id, background or a hosted tool other than web search. Use a catalog model on POST https://api.routerplus.com/v1/chat/completions, /v1/messages or /v1/responses. Nothing is searched or billed.

429 insufficient_quota. Your balance, or a monthly spend cap, does not cover the next search's $0.007. Add credit in Billing or raise the cap.

The model says a search failed or a limit was reached. The model saw a tool result of {"error":"tako_search failed"} (Tako refused, timed out after 15 seconds, or answered in a form we cannot read; not billed) or {"error":"tako_search limit for this request reached; continue without it"} (it asked for more than max_uses searches). At most 60 searches a minute run per organization; a search over that rate is not sent or billed, and the model gets an error result and goes on. Raise max_uses, or ask a narrower question.

Data

Only the query the model writes goes to Tako, a third party, never your messages, your key or your organization. The model's turns are kept like any chat request. See Data policy and Server tools.

Where next

Markdown source for agents: /docs/tako-search.md · index at /llms.txt