# Server tools

A server tool is a tool the gateway runs for the model. You add it to `tools`,
the model decides when to call it, the gateway runs each call and gives the
result back to the model, and you get one finished answer. There are seven
server tools, for any chat model on `POST https://api.routerplus.com/v1/chat/completions`,
`POST https://api.routerplus.com/v1/messages` and `POST https://api.routerplus.com/v1/responses`:

- `tako:search`: live, sourced data from [Tako](https://tako.com) (financial,
  economic, sports, weather and company series, as charted "cards", plus web
  results);
- `parallel:search`: web search from [Parallel](https://parallel.ai), with
  excerpts of each page;
- `parallel:extract`: Parallel reads the web pages the model names and returns
  the excerpts that matter;
- `parallel:image_search`: images from the web (URLs, source pages, sizes);
- `parallel:place_search`: places such as restaurants, shops and museums near a
  location;
- `parallel:decisions`: typed answers (a probability, a choice or a score) to
  the model's questions, grounded in web evidence, with citations;
- `parallel:research`: Parallel researches one question the model writes and
  returns a cited answer (see [below](#parallelresearch)).

One request can use any of them, together. Coding agents that cannot add a tool
turn them on with a header (see [Claude Code and Codex](#claude-code-and-codex)).

New to it? Start with the [Tako search guide](/docs/tako-search).

## A request

```bash
curl 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 Nvidia revenue change over the last 4 quarters?"}],
    "tools": [{"type": "tako:search", "parameters": {"max_uses": 3}}]
  }'
```

The model sees one function tool named `tako_search` with one argument,
`query`. When it calls it, the gateway sends the query to Tako, hands the model
the result as the tool's answer, and asks the model again. This goes on until
the model answers without calling the tool, or the limits below stop it.

`tako:search` works with your own function tools in the same `tools` list. If
a turn of the model calls one of your tools, you get that turn back as usual
(`finish_reason: "tool_calls"`), with your calls only. Any `tako_search` calls
in that turn are not run and not billed. The searches of earlier turns in the
same request stay billed, and their results are not in the message you get
back. To keep every search's cards, let the model search and answer in turns
of their own: ask for the search first (`tool_choice` below), or send a lower
`max_uses`.

To try it without code, open the [Playground](/docs/playground), turn on
**Tako search** under Parameters, and send: the cards appear under the reply,
with the searches and their cost in its receipt. (The Playground has no
Parallel switch.)

The Parallel tools go in the same list, alone or with Tako:

```json
"tools": [
  {"type": "parallel:search", "parameters": {"max_uses": 3, "max_results": 5}},
  {"type": "parallel:extract", "parameters": {"max_urls": 3}}
]
```

The model then sees `parallel_search(objective, search_queries)` (a sentence
saying what it needs, and 1 to 5 short keyword queries) and
`parallel_extract(urls, objective)` (1 to `max_urls` absolute http(s) URLs, and
optionally what to look for on them). `parallel:image_search`,
`parallel:place_search` and `parallel:decisions` go in the same list; the model
sees `parallel_image_search(objective, search_queries)`,
`parallel_place_search(query, location, latitude, longitude, max_distance_km,
open_now)` and `parallel_decisions(state, questions)`.
[Parallel tools](/docs/parallel-search) walks through a first request and what
each function takes and returns.

## Parameters

| Field | Values | Default |
|---|---|---|
| `max_uses` | a whole number from 1 to 10 | 5 |
| `sources` | a non-empty list of `"data"` (Tako's cards) and `"web"` (web results) | both |
| `count` | a whole number from 1 to 5: results of each source per search | 3 |
| `effort` | `"instant"` or `"fast"` (Tako's search effort) | `"fast"` |

`max_uses` counts every search the model asks for in the request, across all
its turns and parallel calls. `count` is per source: with both sources, a
search returns up to `count` cards and `count` web results.

Any other field, a value out of range, `effort: "deep"`, a second `tako:search`
entry, or a tool of your own named `tako_search` is a 400
`invalid_request` that names the field. Nothing is searched or billed then.

`tool_choice` applies to the model's first turn. `{"type": "tako:search"}` there
asks the model to search first. Later turns use `"auto"`. `"none"` (on Messages,
`{"type": "none"}`) is kept even when the server tools are your only tools: the model
then writes its answer without searching, and nothing is billed. On
`POST /v1/responses`, a server tool can also be forced as `{"type": "function", "name": "tako_search"}`
(its function's name, with no `namespace`).

`parallel:search` takes:

| Field | Values | Default |
|---|---|---|
| `max_uses` | a whole number from 1 to 10 | 5 |
| `mode` | `"turbo"`, `"fast"`, `"basic"` or `"advanced"` (Parallel's search modes; `basic` and `advanced` only on a gateway that serves them) | `"fast"` |
| `max_results` | a whole number from 1 to 10: results per search | 5 |

`parallel:extract` takes:

| Field | Values | Default |
|---|---|---|
| `max_uses` | a whole number from 1 to 10 | 3 |
| `max_urls` | a whole number from 1 to 5: URLs read per call | 3 |

`parallel:image_search` and `parallel:place_search` each take:

| Field | Values | Default |
|---|---|---|
| `max_uses` | a whole number from 1 to 10 | 3 |
| `mode` | `"fast"` or `"advanced"` | `"fast"` |
| `max_results` | a whole number from 1 to 20: results per call | 10 |

`parallel:decisions` takes:

| Field | Values | Default |
|---|---|---|
| `max_uses` | a whole number from 1 to 10 | 3 |
| `max_questions` | a whole number from 1 to 20: questions per call | 10 |

Each tool has its own `max_uses` and its own count. Any other field
(`full_content`, `fetch_policy`, `source_policy`, `session_id`, `client_model`,
`location`, `advanced_settings`, a `mode` for decisions), `basic` or `advanced`
search on a gateway that does not serve them, a value out of range, a second entry of
the same tool, or a tool of your own named like one of the tools' functions
(`parallel_search`, `parallel_decisions`, and so on) while that tool is on is a
400 `invalid_request` that names the field. `{"type": "parallel:search"}` as
`tool_choice` asks the model to search with Parallel first.

Every other field of your request (`max_tokens`, `temperature`, `response_format`
and the rest) is sent with each model turn. `max_tokens` therefore limits each
turn, not the request: the answer's `usage.completion_tokens` is the sum over
the turns and can be higher than `max_tokens`.

## Where it works

`tako:search` works on `POST /v1/chat/completions`, `POST /v1/messages` and
`POST /v1/responses`, with an organization key, for catalog models. Ask for it
with a `tools` entry `{"type": "tako:search", ...}`, or with the request header
`x-tm-tools: tako:search` (D87's default parameters; a `tools` entry, when you
send one too, wins). The Parallel tools work the same way and in the same
places.

`x-tm-tools` takes a comma-separated list of `tako:search`, `parallel:search`,
`parallel:extract`, `parallel:image_search`, `parallel:place_search`,
`parallel:decisions` and `parallel:research`, in any case and any order; a value named twice counts
once. For example, Tako with search and extract:

```text
x-tm-tools: tako:search, parallel:search, parallel:extract
```

The header and `tools` entries combine: a tool named in either is on, and a
`tools` entry's parameters win for its tool.

A request the gateway cannot serve with the tools it names is refused before
anything runs, and nothing is searched or billed:

- **400 `server_tool_unsupported`, "not enabled on this gateway"**: the gateway
  you called does not serve the tool the message names. Ask support to turn it
  on, or remove it from the `x-tm-tools` header (or `tools`) to send the request
  without it; the message ends with the way to do that.
- **503 `gateway_error`, "turned on but not configured"**: the tool is turned on
  for the gateway you called, but our key for its provider (Tako or Parallel) is
  not in place yet. Ask support; retrying will not help until the key is
  configured.

The 400 carries `x-tm-error-code: server_tool_unsupported` and an `error.param`
(`tools`, or `x-tm-tools` when the header asked); the 503 carries
`x-tm-error-code: gateway_error`. The same 400 `server_tool_unsupported`, with
the same header and `error.param`, answers a request that has:

- a composite model (`tm/...`), a dedicated endpoint, or a key that is not an
  organization's;
- on `/v1/messages`: another server tool (`web_search_*`, `code_execution_*`)
  next to a `tools` entry for one of ours, an Anthropic-defined client tool
  (`bash_*`, `text_editor_*`, `computer_*`, `memory_*`; send your own tools as
  custom tools), `mcp_servers` or `container`;
- on `/v1/responses`: `previous_response_id`, `conversation`, `background`, or
  a hosted tool other than web search (`file_search`, for example). A hosted
  `web_search` (Codex sends one by default) is left out instead and named in
  `x-tm-dropped-params`: the model searches with the server tools you turned on.

On `/v1/messages`, when only the header asks for our tools and the request
carries one of Anthropic's own server tools (`web_search_*`, `web_fetch_*`,
`code_execution_*`), the request is served as if the header were absent: no
server tool of ours runs, and `x-tm-dropped-params` names `header:x-tm-tools`.
This is the request Claude Code's WebSearch sends, so WebSearch keeps working
with the header set (see [Claude Code and Codex](#claude-code-and-codex)). As
with any drop, `"provider": {"require_parameters": true}` refuses that request
instead.

`x-tm-tools` with any other value is a 400 `invalid_request` naming the header
and its values. A refusal for a request with a Parallel tool ends with
`Remove the x-tm-tools header (or the parallel:* tools) to send this request without them.`
When the gateway serves the other Parallel tools but not one you named (image
search, place search, decisions), it names just that one instead: `Remove parallel:image_search from the
x-tm-tools header (or the tools list) to send this request without it.`
Without the tool, nothing changes: a request is served exactly as before.

How it runs: on `/v1/chat/completions` and `/v1/messages` the model's turns are
chat completions on the gateway. On `/v1/responses`, a model served by OpenAI's
own Responses API runs there, with your tools exactly as you sent them (custom
tools and their grammars, namespaces); `store` is always false and each model
turn is a separate billed Responses request. Other models on `/v1/responses`
run as chat completions. Each model turn carries these headers of your request:
`anthropic-beta`, `x-tm-auto-cache`, `x-session-id`, `x-session-affinity`,
`x-claude-code-session-id` and `User-Agent`. It never carries `x-tm-tools` or
your other credentials.

On `/v1/messages` each search comes back as a `server_tool_use` block and a
`tako_search_tool_result` block (the same cards and web results the model
saw), before the model's answer:

```jsonc
// the two blocks, abridged
{"type": "server_tool_use", "id": "srvtoolu_toolu_01", "name": "tako_search",
 "input": {"query": "US consumer price inflation 2026"}}
{"type": "tako_search_tool_result", "tool_use_id": "srvtoolu_toolu_01",
 "content": {"cards": [{"title": "United States Inflation Rate (Consumer Prices)", "...": "..."}],
             "web_results": [{"title": "CPI report", "url": "https://...", "snippet": "..."}]}}
```

and `usage.server_tool_use.tako_search_requests` counts them. On
`/v1/responses` each search is a `tako_search_call` output item before the
answer's items, and the response carries `tako.cards` and `usage.server_tool_use`:

```jsonc
// one item
{"id": "ts_8f2c_0", "type": "tako_search_call", "status": "completed",
 "action": {"type": "search", "query": "US consumer price inflation 2026"}}
```

A Parallel call comes back the same way, under its own names: on `/v1/messages`
a `server_tool_use` block named `parallel_search` or `parallel_extract`, then a
`parallel_search_tool_result` or `parallel_extract_tool_result` block (an error
is `{"type": "parallel_search_tool_result_error", "error": "..."}`); on
`/v1/responses` a `parallel_search_call` item (`"action": {"type": "search",
"queries": [...]}`) or a `parallel_extract_call` item (`"action": {"type":
"extract", "urls": [...]}`), with `status` `completed` or `failed`;
`usage.server_tool_use` gains `parallel_search_requests` and
`parallel_extract_requests`. The other Parallel tools follow the same pattern:

| Tool | Messages result block | Responses item and its `action` | `usage.server_tool_use` |
|---|---|---|---|
| `parallel:image_search` | `parallel_image_search_tool_result` | `parallel_image_search_call`, `{"type": "image_search", "queries": [...]}` | `parallel_image_search_requests` |
| `parallel:place_search` | `parallel_place_search_tool_result` | `parallel_place_search_call`, `{"type": "place_search", "query": "...", "location": "..."}` | `parallel_place_search_requests` |
| `parallel:decisions` | `parallel_decisions_tool_result` | `parallel_decisions_call`, `{"type": "decisions", "questions": [names]}` | `parallel_decisions_requests` |

With several tools, the blocks and items come in the order the model called
them.

A streamed answer starts at once, on every surface, and sends a keep-alive
(`ping` on `/v1/messages`, an SSE comment elsewhere) every 10 seconds until the
answer is ready, then the whole answer.
While it searches, your harness looks idle: up to 150 seconds, with nothing
but keep-alives. On a streamed answer, `x-tm-server-tools`, `x-tm-provider` and
`x-tm-dropped-params` come as HTTP trailers, after the body (the response starts
before any search runs); read the count from `usage.server_tool_use`. A whole
answer carries them as headers. A whole answer has 110 seconds, not 150 (see
[Limits and failures](#limits-and-failures)): stream long searches. Send the
blocks and items back in your next request as your client keeps them: with
the tool on they become the calls the model made, and without it they are left
out before anything reaches a provider.

## Claude Code and Codex

What ran live on dev (2026-11-04), with Claude Code 2.1.309 and Codex 0.163.0:

- `tako:search`: Claude Code on claude-sonnet-5-5 and z-ai/glm-5.3, Codex on
  gpt-6-luna and moonshotai/kimi-k3.
- `parallel:search`: Claude Code on claude-sonnet-5-5 and z-ai/glm-5.3, Codex on
  gpt-6-luna and moonshotai/kimi-k3.
- All three tools together: Claude Code on claude-sonnet-5-5.

Not run: `parallel:extract` with Codex, Codex with all three tools, Codex on a
Claude model, other harnesses, other versions, and any production gateway.
`parallel:image_search`, `parallel:place_search` and `parallel:decisions` were
probed against Parallel's API (2026-11-06), not run through Claude Code or
Codex.
They should work the same, but we have not seen them work.

With the header set, every request your harness sends asks for the server
tools it names, title and quota requests included: each answer arrives whole
(no token streaming), and the model may call a tool on any of them. The one
exception is a request that carries one of Anthropic's own server tools:
Claude Code's WebSearch sends one, and it is served without our tools (the
search is billed as a web search, [Pricing](/docs/pricing)). With a search tool
of ours on, the model often uses it instead of WebSearch.

**Codex repeats its searches.** Codex does not keep the search and extract
items (`tako_search_call`, `parallel_search_call`, `parallel_extract_call`) in
the history it sends back, so the model does not see that it already searched
and may search again in each new request. You pay for each search it makes
($0.007 for Tako, $0.001 to $0.005 a call for Parallel). A lower `max_uses` (in a `tools` entry)
bounds the searches per request; the header's default allows 5. In our runs a
Codex task made 2 to 9 searches. Claude Code keeps the blocks and does not
repeat them.

Prompt caching works while the header is set. On a Claude model the turns carry
Claude Code's own `cache_control` markers, with the gateway's marker for the
newest turn beside them. Each turn reads the turn before it whole from the
cache: in our run on dev (2026-11-06, claude-sonnet-5-5), a request's second and
third turns read 16,480 and 21,472 tokens. The next request's first turn reads
at least Claude Code's tools and system prompt (12,947 of its 16,526 tokens in
that run). A turn's prompt is the size of Claude Code's own request without the
header, plus the server tools' definitions. The answer's `usage` shows the
cache: see [The answer](#the-answer).

> [!NOTE]
> Change, 2026-11: before this change, a Claude model's turns ran without Claude
> Code's system prompt while the header was set, and were about 5,000 tokens
> smaller for it. They now carry it, as a request without the header does.

Claude Code: set it up for RouterPlus first ([Install](/docs/install)), then
add the header to the `env` block of its `settings.json`:

```json
"env": { "ANTHROPIC_CUSTOM_HEADERS": "x-tm-tools: tako:search" }
```

or in your shell:

```bash
export ANTHROPIC_CUSTOM_HEADERS="x-tm-tools: tako:search"
claude -p "Use tako_search to look up US consumer price inflation in 2026."
```

Codex: set it up for RouterPlus first ([Install](/docs/install)), then add
this one line to the `[model_providers.routerplus]` block you made there in
`~/.codex/config.toml`:

```toml
http_headers = { "x-tm-tools" = "tako:search" }
```

Codex also sends its own hosted web search tool. With any server tool on, the
gateway leaves it out and names it in `x-tm-dropped-params` (for example
`x-tm-dropped-params: tools[8].web_search` with Codex 0.163.0, the place of
Codex's tool in its list, which can differ by version), so nothing else is needed. If you want Codex to stop offering it
altogether, add `web_search = "disabled"` at the top of the file (optional).

The same header turns the Parallel tools on, alone or with Tako. All three in
Claude Code:

```json
"env": { "ANTHROPIC_CUSTOM_HEADERS": "x-tm-tools: tako:search,parallel:search,parallel:extract" }
```

(`ANTHROPIC_CUSTOM_HEADERS` takes one header per line: if you already send one,
put `x-tm-tools: ...` on a line of its own, `"Header-A: a\nx-tm-tools: ..."` in
JSON.) And in Codex's `[model_providers.routerplus]` block:

```toml
http_headers = { "x-tm-tools" = "tako:search,parallel:search,parallel:extract" }
```

If a request is refused with `server_tool_unsupported`, the message says what
was not supported; remove the header (unset `ANTHROPIC_CUSTOM_HEADERS`, or the
`http_headers` line) to send it without the server tools.

## 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-06"`). Use `embed_url` to show Tako's chart. Present when at least
  one search succeeded.
- `usage.server_tool_use.tako_search_requests`: the searches billed. The
  header `x-tm-server-tools: tako_search=<n>` says the same.

With Parallel on, `usage.server_tool_use` also has `parallel_search_requests`
and `parallel_extract_requests` (billed calls), and `x-tm-server-tools` lists
every tool on the request, such as
`tako_search=1, parallel_search=2, parallel_extract=0`. The Parallel results
are not added to the message; the model's answer cites what it used.

`usage` describes the conversation as the model sees it now, then the cost:

- `prompt_tokens` and `prompt_tokens_details` (`cached_tokens`,
  `cache_write_tokens`) are the last turn's prompt: the size of the context
  after the request. Agents read their context from these fields.
- `completion_tokens` and `completion_tokens_details.reasoning_tokens` add up
  every turn's output. `total_tokens` is the two together.
- `cost` is the whole request in USD: every turn, cached tokens at their price,
  and every search.
- `server_tool_turns` lists each turn's own usage, in order (`model`,
  `prompt_tokens`, `completion_tokens` and their details). Add up its
  `prompt_tokens` for the input the request was billed for.

On `/v1/responses` the same holds in the Responses names (`input_tokens`,
`input_tokens_details`, `output_tokens`), with `server_tool_turns`. On
`/v1/messages`, `usage` follows Anthropic's own server tools: `input_tokens`,
`output_tokens`, `cache_read_input_tokens` and `cache_creation_input_tokens` add
up every turn, and `usage.iterations` holds one `{"type": "message", ...}` entry
per turn with that turn's own counts. The last entry is the context after the
request; Claude Code reads it there.

> [!NOTE]
> Change, 2026-11: `prompt_tokens` (and `input_tokens` on `/v1/responses`) used
> to add up every turn's prompt, which made a three-turn request look about
> three times its context, and the cache fields were missing.

A tool call's `id` is the provider's own when it is unique in the request and
uses only letters, digits, `_` and `-`. Otherwise the gateway gives the call an
id of its own (`call_` and 24 hex characters).

An answer after one search:

```json
{
  "id": "6f1c2a9e-3b7d-4c55-9a51-0d2f7e8b1c44",
  "object": "chat.completion",
  "created": 1793040000,
  "model": "claude-haiku-4-5",
  "choices": [{
    "index": 0,
    "finish_reason": "stop",
    "message": {
      "role": "assistant",
      "content": "Nvidia's quarterly revenue rose in each of the last four quarters (S&P Global).",
      "tako": {
        "cards": [{
          "title": "Nvidia quarterly revenue",
          "webpage_url": "https://tako.com/card/…",
          "embed_url": "https://tako.com/embed/…",
          "image_url": "https://tako.com/img/….png",
          "source_names": ["S&P Global"],
          "coverage_end": "2026-06"
        }]
      }
    }
  }],
  "usage": {
    "prompt_tokens": 1840,
    "completion_tokens": 96,
    "total_tokens": 1936,
    "prompt_tokens_details": { "cached_tokens": 1536, "cache_write_tokens": 304 },
    "completion_tokens_details": { "reasoning_tokens": 0 },
    "cost": 0.009324,
    "server_tool_use": { "tako_search_requests": 1 },
    "server_tool_turns": [
      { "model": "claude-haiku-4-5", "prompt_tokens": 1536, "completion_tokens": 30,
        "prompt_tokens_details": { "cached_tokens": 0, "cache_write_tokens": 1536 }, "completion_tokens_details": { "reasoning_tokens": 0 } },
      { "model": "claude-haiku-4-5", "prompt_tokens": 1840, "completion_tokens": 66,
        "prompt_tokens_details": { "cached_tokens": 1536, "cache_write_tokens": 304 }, "completion_tokens_details": { "reasoning_tokens": 0 } }
    ]
  }
}
```

With `"stream": true` the response starts at once: the 200, then an SSE comment
(`: keep-alive`) every 10 seconds while the model and the searches run, then the
finished answer as one sequence of four events. Tokens are not streamed one by
one. The whole request can take up to 150 seconds (several model turns and
searches). `x-tm-server-tools`, `x-tm-provider` and `x-tm-dropped-params` come
as HTTP trailers. An error after the 200 is a last chunk with
`finish_reason: "error"` and an `error` object, then `data: [DONE]`. The
trailers come with it too: `x-tm-server-tools` counts the searches already
billed. The events:

```text
: keep-alive

data: {"id":"…","object":"chat.completion.chunk","created":1793040000,"model":"claude-haiku-4-5","choices":[{"index":0,"delta":{"role":"assistant","content":"Nvidia's quarterly revenue rose…","tako":{"cards":[…]}},"finish_reason":null}]}

data: {"id":"…","object":"chat.completion.chunk","created":1793040000,"model":"claude-haiku-4-5","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"…","object":"chat.completion.chunk","created":1793040000,"model":"claude-haiku-4-5","choices":[],"usage":{"prompt_tokens":1840,"completion_tokens":96,"total_tokens":1936,"cost":0.009324,"server_tool_use":{"tako_search_requests":1}}}

data: [DONE]
```

When the model's last turn calls your own tools, the first event's `delta`
carries `tool_calls` instead of `content`. With
`stream_options: {"include_usage": false}` the usage event is left out, so the
body then has neither `usage.cost` nor `tako_search_requests`; the
`x-tm-server-tools` trailer still gives the count.

Anything the request sent that did not reach the model is named in
`x-tm-dropped-params`, as on a plain request: what the Messages or Responses
translation left out, and what each turn's route left out. For example,
`messages[*].reasoning_content` is reasoning a route cannot take back, and
`messages[0].content[0].cache_control` is a cache marker a route does not
read. With `"provider": {"require_parameters": true}`, a Messages or Responses
request whose translation would leave anything out is a 400 `invalid_request`,
"require_parameters is set and <the first name> would be dropped", before any
turn or search: nothing is billed.

## Price

**$7 per 1,000 searches ($0.007 a search)**, Tako's own list price for a
search at `instant` or `fast` effort, passed on with no markup. The gateway
always sends `include_contents: false` and `variable_cost: false`, so no row or
premium-source charge is ever added; you cannot turn them on. A search that
fails is not billed. The model's turns are billed as ordinary chat requests, at
the model's price.

In [GET /v1/usage & /v1/generation](/docs/api-usage), each search is its own
attempt under the request's id: provider `tako`, model `tako:search`, no
tokens, `server_tool_use.web_search_requests: 1` and
`server_tool_fee_usd: 0.007`. Each model turn is its own request there, with
its own id.

**Parallel search: $1 per 1,000 searches ($0.001 a search)** in `turbo` or
`fast` mode, with up to 10 results. **Parallel extract: $1 per 1,000 URLs
($0.001 a URL)**, for each URL Parallel read: the gateway charges the URLs
Parallel counts as read, and in our probes a URL it could not read (a 404, a
host that does not exist) was not counted. Both are Parallel's list prices,
passed on with no markup. Search in `basic` or `advanced` mode is **$5 per 1,000
searches ($0.005 a search)**. **Image search and place search: $1 per 1,000
calls ($0.001 a call)** in `fast` mode, **$5 per 1,000 calls ($0.005 a call)**
in `advanced` mode, up to 20 results either way. **Decisions: $1 per 1,000
calls ($0.001 a call)** for up to `max_questions` questions, billed even when
every answer is a refusal. Each call holds its price first (an extract holds
$0.001 for each URL it sends) and is its own attempt: provider `parallel`, model
the tool (`parallel:search`, `parallel:image_search`, `parallel:place_search`,
`parallel:decisions`: `web_search_requests: 1`) or `parallel:extract`
(`web_fetch_requests`: the URLs billed). A call that fails is not billed.

## Limits and failures

- At most `max_uses` searches per request. A call over the limit is not sent to
  Tako. The model gets `{"error":"tako_search limit for this request reached; continue without it"}`
  as its result. Once every server tool on the request has reached its limit,
  the next turns offer only your own tools, so the model can go on with them
  (or answer). A request without tools of your own sends those turns with
  `tool_choice: "none"` instead. A request has at most `max_uses + 1` model
  turns.
- At most 60 searches a minute per organization. A call over that rate is not
  sent or billed; the model gets an error result and goes on.
- A streamed request has 150 seconds in all, then it ends with an error event.
  A request that is not streamed has 110 seconds, then a 504: nothing reaches
  you until it ends, and Cloudflare cuts a silent response at 125 seconds. For
  long searches, send `"stream": true`. Each search has 15 seconds.
- A model turn cut short by `max_tokens` or a content filter runs none of its
  server-tool calls. The answer is that turn, with its reason (`length`;
  `max_tokens` on `/v1/messages`; `incomplete` on `/v1/responses`) and your own
  tool calls, if it made any.
- When the last turn the request allows still asks only for server tools and
  writes no text, the request ends with a 502 `gateway_error`: "the model kept
  calling server tools after this request's limit; no answer was written". The
  searches already made stay billed.
- A search that Tako refuses, times out on, or answers in a form we cannot read
  gives the model `{"error":"tako_search failed"}` and is not billed; the model
  goes on.
- A model turn that fails ends the request with that turn's status and error
  (a 429 rate limit, for example). Searches already done stay billed.
- Every end after a search names what was billed: `x-tm-server-tools` counts the
  searches made, and `x-tm-dropped-params` names what was left out. They are
  headers, or trailers when the stream had already started (the error then
  arrives inside the stream).
- Each search needs credit for its $0.007 before it runs. When your balance or a
  monthly spend cap does not cover it, no search is made and the request ends
  with the same 429 `insufficient_quota` a chat request gets.
- If you disconnect, no further search or turn starts, and the ones in flight
  are stopped. A search stopped that way is not billed.

The same limits hold for each Parallel tool, with its own names: at most
`max_uses` calls of each per request (the model gets
`{"error":"parallel_search limit for this request reached; continue without it"}`,
and once every tool on the request has reached its limit the next turns offer
only your own tools, or are sent with `tool_choice: "none"` when you have
none); at most 60 Parallel calls a minute per organization,
every Parallel tool together; 15 seconds per search, 30 seconds per extract, 15
seconds per image search, 20 seconds per place search and 15 seconds per
decisions call; a call
Parallel refuses, times out on, or answers in a form we cannot read gives the
model `{"error":"parallel_search failed"}` (or `parallel_extract`) and is not
billed. An extract with more URLs than `max_urls` reads the first `max_urls` and
names the rest in the result (`not_read`). A URL that is not an absolute
http(s) URL is an error result, with nothing read or billed. So is a place
search without a location or coordinates (or with a value out of range), and a
decisions call with a bad or repeated question name, too many questions or
options, or a question or state that is too long: the model is told what to fix.

## What the model sees

The tool's result is JSON with `cards` (`title`, `description`, `webpage_url`,
`embed_url`, `image_url`, `source_names`, `coverage_end`) and `web_results`
(`title`, `url`, `snippet` of at most 1,000 characters, `publish_date`). Nothing
else from Tako's reply reaches the model, and the whole result is at most 16 KB
(the last results are left out to fit). The gateway never opens a link found in
a result.

A Parallel result is JSON with `results` (`url`, `title`, `publish_date` and
`excerpts`, each excerpt at most 4,000 characters) and, for an extract,
`errors` (`url` and `error_type`) and `not_read`. Results whose URL is not
http(s) are left out. Parallel's own ids, usage and warnings never reach the
model or you, and the result is at most 16 KB (excerpts are shortened, then the
last results left out). The gateway asks for excerpts only, never a page's full
content. A `parallel:search` call reads Parallel's index: the gateway never asks it to
fetch pages live, Parallel documents that search does not fetch unless asked,
and in our probes (2026-11-06) no search result held a fresh page's per-run marker,
in `fast`, `basic` or `advanced` mode, even when the query was a fresh URL. That
shows no live-fetched content came back in the results, not that Parallel made no
request to the page. Image search,
place search and decisions were not probed for live fetching, and Parallel does
not document whether they fetch.
An extract can make Parallel fetch the page from its website at call time:
that is Parallel's default for extract, and no setting turns it off. That site
then sees a request from Parallel (never from you or from us) for the full URL
the model gave, query string included.

> [!NOTE]
> Correction, 2026-11-06: until then this page said the gateway never caused a
> live fetch. That was wrong for `parallel:extract`, as described above.

An image search result is `results` (`title`, `image_url`, `source_page_url`,
`width`, `height`), both URLs absolute http(s). A place search result is
`results` (`name`, `url`, `address`, `phone`, `latitude`, `longitude`,
`distance_km`, `rating`, `price_level`, `opening_hours`, `timezone`,
`open_now`; unknown values null). A decisions result is `answers` by question
name (`noul`, Parallel's name for a yes/no probability; `choice` with
`probabilities`; `score` with `legend` and `probabilities`; `choice` and
`score` can carry Parallel's own `confidence`; or `refusal`) and up to 10
`citations` (`url`, `title`). For image and place search, `advanced` costs
more and is slower than `fast` and gives better (images) or more complete
(places) results.
Each is at most 16 KB (the last results, or the citations, go first). The
gateway never opens an image, a place's website or a citation.

> [!WARNING]
> Web results are text from the open web (with Parallel: excerpts, image
> titles, place names and addresses, and citation titles), and any of them can
> try to give the model instructions. The limits above narrow this, but they cannot remove it. Treat
> a search-backed answer as you would treat any web content.

## Data

**Your model's search queries are sent to Tako, a third party.** Only the
query the model writes goes to Tako, with our key, never your messages, your
key or your organization. Tako's API terms and retention apply to the query;
we treat it as retained by Tako (see [Data policy](/docs/data-policy)).

Our process log and billing ledger keep only the count, status, time and fee
of each search, never the query or the result. The model's turns, though, are
ordinary chat requests, so they are kept in the
[request log](/docs/data-policy#request-logging) under its usual rules: for up
to 30 days, unless your organization has opted out (dedicated endpoints do not
take this tool). Those records hold the query (in the model's `tako_search`
call), the result (in the tool message) and the answer with its cards.

**With a Parallel tool, the queries, objectives and URLs the model writes are
sent to Parallel, a third party in the United States**, with our key; never
your messages as such, your key or your organization. The model writes them
from your conversation, so they can quote or paraphrase what you wrote. Under Parallel's standard terms
it may use inputs and outputs, not linked to any individual, to improve its
models (zero data retention is an Enterprise plan); until our account terms
with Parallel are settled, assume it does. A place search sends its query and
location (an address or coordinates can say where someone is), and a decisions
call its state and questions. The same logging as for Tako
applies: counts, statuses, times and fees in our logs and ledger, and the
model's turns in the request log.

## parallel:research

`parallel:research` sends one complete question the model writes to Parallel's Responses API and
gives the model a cited answer, not search results. A gateway that serves the other Parallel
tools may not serve it: a request that names it there is a 400 `server_tool_unsupported`
naming `parallel:research` (see [Where it works](#where-it-works) for what to do). The model
sees `parallel_research(question, effort)`; a missing `effort` is `"low"`. [Parallel
research](/docs/parallel-research) walks through a first request.

**Parameters.**

| Field | Values | Default |
|---|---|---|
| `max_uses` | a whole number from 1 to 3 | 1 |
| `max_effort` | `"low"` or `"medium"` | `"medium"` |

`max_uses` times the per-call timeout of `max_effort` may not pass 100 seconds (up to 3 calls at
low, 2 at medium). `max_effort: "high"`, any other field (`tools`, `data_sources`, `mcp`,
`previous_response_id`, `instructions`, `stream`, `background`, ...), a value out of range or a
breach of that budget is a 400 `invalid_request` naming the field.

**Price.** Parallel's list price for the effort the call ran at, with no markup:
**$0.01 a call at low, $0.05 at medium** ($10 and $50 per 1,000). Each call holds the price of
the effort asked for, is charged for the effort Parallel ran it at (never more than it held), and
is its own attempt: provider `parallel`, model `parallel:research`, `web_search_requests: 1`. A
call that fails, times out or is stopped is not billed. `usage.server_tool_use` has
`parallel_research_requests`.

**Limits.** At most `max_uses` calls per request (then
`{"error":"parallel_research limit for this request reached; continue without it"}`), counted in the same 60
Parallel calls a minute per organization as search and extract; 30 seconds per call at low and 50
at medium, inside the request's 150 seconds (110 seconds when the answer is not streamed). The result is `answer`, `citations` (`url`, `title`;
at most 20) and `effort`, at most 16 KB; a call Parallel refuses, times out on or does not finish
gives the model `{"error":"parallel_research failed"}`. The question the model writes goes to
Parallel, which stores Responses API answers (see [Data policy](/docs/data-policy)).

## Where next

- [Pricing & billing](/docs/pricing) — the billing math and `usage.cost`
- [POST /v1/chat/completions](/docs/api-chat-completions) — the rest of the request
- [Data policy](/docs/data-policy) — what is stored and by whom
- [Tako search guide](/docs/tako-search) — a first search, making the model search, and troubleshooting
- [Parallel tools](/docs/parallel-search) — web search, page reading, images, places and decisions with Parallel, alone or with Tako
- [Parallel research](/docs/parallel-research) — one cited, researched answer per call, at $0.01 or $0.05
