# Parallel tools

The Parallel tools give a chat model the web through
[Parallel](https://parallel.ai):

- `parallel:search`: web search, with excerpts of each page;
- `parallel:extract`: reading the pages the model names;
- `parallel:image_search`: finding images (their URLs, source pages and sizes);
- `parallel:place_search`: finding places such as restaurants, shops and
  museums near a location;
- `parallel:decisions`: typed answers (a probability, a choice or a score) to
  questions, grounded in current web evidence, with the sources.

You add them to `tools` (or send one header), the model decides when to call
them, the gateway runs each call, and you get one finished answer. They work with
`tako:search` in the same request. This page takes you from a key to a first
answer; [Server tools](/docs/server-tools) is the full reference.

## Quickstart

### 1. Get a key

Sign in and create a key at [API keys](https://app.routerplus.com/console/keys). Use an
organization key: the Parallel tools are billed per call to an organization.

### 2. Add paid credit

Add credit in [Billing](https://app.routerplus.com/console/billing). Each search needs its
$0.001, and each extract $0.001 for each URL it sends, in credit before it
runs, on top of the model's own turns.

### 3. Export the key

```bash
export TM_API_KEY=tm_vk_...
```

### 4. Send a first 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": "Which RFC defines HTTP semantics, and what does it say a 404 means?"}],
    "tools": [
      {"type": "parallel:search", "parameters": {"max_uses": 3}},
      {"type": "parallel:extract", "parameters": {"max_urls": 2}}
    ],
    "tool_choice": {"type": "parallel:search"}
  }'
```

The same with the header instead of `tools` entries (default parameters):

```bash
curl https://api.routerplus.com/v1/chat/completions \
  -H "Authorization: Bearer $TM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-tm-tools: parallel:search, parallel:extract" \
  -d '{"model": "claude-haiku-4-5", "messages": [{"role": "user", "content": "Which RFC defines HTTP semantics?"}]}'
```

`x-tm-tools: tako:search, parallel:search, parallel:extract` turns on those three
server tools; the header takes any of the seven values `tako:search`,
`parallel:search`, `parallel:extract`, `parallel:image_search`,
`parallel:place_search`, `parallel:decisions` and `parallel:research` (see
[Parallel research](/docs/parallel-research)). It works on
`/v1/chat/completions`, `/v1/messages` and `/v1/responses`.

A place search and a decision, with `tools` entries:

```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": "Find two coffee shops open now in Shibuya, Tokyo, and tell me whether PostgreSQL 17 supports incremental backups."}],
    "tools": [
      {"type": "parallel:place_search", "parameters": {"max_results": 5}},
      {"type": "parallel:decisions", "parameters": {"max_questions": 3}}
    ]
  }'
```

## Claude Code and Codex

Set the harness up for RouterPlus first ([Install](/docs/install)). Then add the
header.

Claude Code, in the `env` block of `settings.json`:

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

Codex, in the `[model_providers.routerplus]` block of `~/.codex/config.toml`:

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

Add `tako:search` to the same value for Tako's data cards as well, for example
`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. With the header set every request your harness sends can use
the tools, and each answer arrives whole (no token streaming).

**Codex repeats its searches.** Codex does not keep the `parallel_search_call`
and `parallel_extract_call` items 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 call ($0.001 to $0.005 a call, $0.001 a URL for an
extract). A lower `max_uses` (in
a `tools` entry) bounds the calls per request. Claude Code keeps the blocks and
does not repeat them.

What ran live on dev (2026-11-04), with Claude Code 2.1.309 and Codex 0.163.0:
`parallel:search` with Claude Code on claude-sonnet-5-5 and z-ai/glm-5.3 and with
Codex on gpt-6-luna and moonshotai/kimi-k3; all three tools (`tako:search`,
`parallel:search`, `parallel:extract`) with 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 and 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.

## What the model sees

Each tool is one function the model calls:

- `parallel_search(objective, search_queries)`: a sentence saying what it needs,
  and 1 to 5 short keyword queries (3 to 6 words each). Each search returns up to
  `max_results` results: `url`, `title`, `publish_date` and `excerpts`.
- `parallel_extract(urls, objective)`: 1 to `max_urls` absolute http(s) URLs and,
  optionally, what to look for. It returns each page's `url`, `title`,
  `publish_date` and the `excerpts` that matter, `errors` (`url` and
  `error_type`, such as `http_error` for a 404 or `connect_error` for a host that
  does not exist) and `not_read` (the URLs over `max_urls`).
- `parallel_image_search(objective, search_queries)`: 1 to 5 short keyword
  queries and, optionally, a sentence saying what images it needs. It returns up
  to `max_results` images: `title`, `image_url`, `source_page_url`, `width` and
  `height` (null when Parallel does not know them).
- `parallel_place_search(query, location, latitude, longitude, max_distance_km,
  open_now)`: what to find (1 to 200 characters) and where: one `location` (2 to
  200 characters: a city, neighbourhood, address or postal code), or `latitude`
  and `longitude`, or both; optionally a radius (more than 0 and at most 200 km)
  and open places only. It returns up to `max_results` places: `name`, `url`,
  `address`, `phone`, `latitude`, `longitude`, `distance_km`, `rating`
  (`fair`, `good`, `great` or `excellent`), `price_level` (1 to 4),
  `opening_hours` (per weekday, `opens` and `closes` as `HH:MM`), `timezone` and
  `open_now`; any of them can be null.
- `parallel_decisions(state, questions)`: a JSON object of shared context, and
  1 to `max_questions` questions, each with a `name` (letters, digits, `_` or
  `-`, at most 64), a `type` and `instructions`: `noul` (Parallel's name for a
  yes/no question: is it true? a probability from 0 to 1; `criteria` optional,
  `{"true": ..., "false": ...}`), `choice` (`criteria`: 2 to 20 named options) or
  `score` (`criteria`: 2 to 10 levels, lowest first). It returns `answers` by
  name (`noul`; `choice` with each option's probability; `score` with its
  legend and probabilities; or `refusal` when Parallel gave no answer) and up to
  10 `citations` (`url` and `title`). A `choice` or `score` answer can carry
  `confidence`, Parallel's own confidence from 0 to 1, which is not the
  probability of the chosen option.

For image and place search, `mode` trades cost for quality: `fast` (the
default, $0.001 a call, about 1 second) or `advanced` ($0.005 a call, a few
seconds, better results for images, more complete results for places).

Nothing else from Parallel's reply reaches the model or you (no ids, usage,
warnings or Parallel error messages), and each result is at most 16 KB. 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. The gateway itself never opens a URL from a result: not a page, not
an image, not a place's website. If your app shows an image, your user's
browser loads it from that third-party site, and the image may be unsuitable or
under someone else's licence.

> [!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.

> [!WARNING]
> Web results are text from the open web: excerpts, image titles, place names
> and addresses, and citation titles. Any of them can try to give the model
> instructions. The limits narrow this, but they cannot remove it.

## Read the answer

On `/v1/chat/completions` the answer is an ordinary `chat.completion`;
`usage.server_tool_use` has a count of billed calls per tool on the request
(`parallel_search_requests`, `parallel_extract_requests`,
`parallel_image_search_requests`, `parallel_place_search_requests`,
`parallel_decisions_requests`), and `x-tm-server-tools` says the same
(`parallel_search=1, parallel_extract=1`). On `/v1/messages` each call is a
`server_tool_use` block and a `<function>_tool_result` block before the answer
(`parallel_search_tool_result`, `parallel_image_search_tool_result`, and so on);
on `/v1/responses` it is a `<function>_call` item (`parallel_search_call`,
`parallel_place_search_call`, and so on). `usage.cost` is the model's turns plus
every call, in USD.

## Parameters

| Tool | Field | Values | Default |
|---|---|---|---|
| `parallel:search` | `max_uses` | 1 to 10 | 5 |
| `parallel:search` | `mode` | `"turbo"`, `"fast"`, `"basic"` or `"advanced"` | `"fast"` |
| `parallel:search` | `max_results` | 1 to 10 | 5 |
| `parallel:extract` | `max_uses` | 1 to 10 | 3 |
| `parallel:extract` | `max_urls` | 1 to 5 | 3 |
| `parallel:image_search` | `max_uses` | 1 to 10 | 3 |
| `parallel:image_search` | `mode` | `"fast"` or `"advanced"` | `"fast"` |
| `parallel:image_search` | `max_results` | 1 to 20 | 10 |
| `parallel:place_search` | `max_uses` | 1 to 10 | 3 |
| `parallel:place_search` | `mode` | `"fast"` or `"advanced"` | `"fast"` |
| `parallel:place_search` | `max_results` | 1 to 20 | 10 |
| `parallel:decisions` | `max_uses` | 1 to 10 | 3 |
| `parallel:decisions` | `max_questions` | 1 to 20 | 10 |

A gateway that does not serve the search modes `"basic"` and `"advanced"`
answers them with a 400 that says to use `"turbo"` or `"fast"`. Any
other field (`full_content`, `fetch_policy`, `source_policy`, `session_id`,
`client_model`, `location`, a `mode` for decisions), a value out of range, a
second entry of the same tool, or a function of your own named like one of the
tools (`parallel_search`, `parallel_place_search`, and so on) is a 400
`invalid_request` naming the field.

## Cost

- **Search: $1 per 1,000 searches ($0.001 a search)**, Parallel's list price in
  `turbo` and `fast` mode with up to 10 results; **$5 per 1,000 searches ($0.005
  a search)** in `basic` and `advanced` mode.
- **Extract: $1 per 1,000 URLs ($0.001 a URL)**, for each URL Parallel read. A
  URL it could not read is not billed: in our probes Parallel counted only the
  URLs that returned a result.
- **Image search and place search: $1 per 1,000 calls ($0.001 a call)** in
  `fast` mode and **$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 any number of questions
  up to `max_questions`. A call Parallel answers is billed even when every
  answer is a refusal.
- A call that fails is not billed. The model's turns are billed as ordinary
  chat requests.
- A tool may be free for a while: [Tools](/tools) then shows its list price
  struck through with "Free", `/api/tools.json` says `"free": true`, and its
  calls are not charged (`server_tool_fee_usd` 0; with a balance of $0 a call is
  refused). The prices above are the list prices. See
  [Pricing](/docs/pricing#parallel-tools).

Each call is its own attempt in [GET /v1/usage & /v1/generation](/docs/api-usage):
provider `parallel`, model the tool (`parallel:search`, `parallel:image_search`,
and so on). See [Pricing & billing](/docs/pricing#parallel-tools).

## Limits

- At most `max_uses` calls of each tool per request. A call over it gives the
  model `{"error":"parallel_search limit for this request reached; continue without it"}`
  (or the tool's own name), is not sent, and is not billed. Once every server
  tool on the request is at its limit, the next turns offer only your own tools.
- At most 60 Parallel calls a minute per organization, every Parallel tool
  together; a call over the rate is not sent or billed, and the model is told.
- 15 seconds per search, 30 seconds per extract, 15 seconds per image search,
  20 seconds per place search, 15 seconds per decisions call. The whole request
  has 150 seconds when streamed and 110 seconds when not: send `"stream": true`
  for long research.
- A call Parallel refuses or times out on gives the model
  `{"error":"parallel_search failed"}` (or `parallel_extract`,
  `parallel_image_search`, and so on), is not billed, and the model goes on.
- A place search or decisions call the model wrote wrongly (no location, a
  duplicate question name) is not sent or billed: the model gets an error that
  says what to fix.

## Troubleshooting

- **400 `server_tool_unsupported`, "not enabled on this gateway"**: the gateway
  you called does not serve the tool the message names, so nothing was searched
  or billed. Ask support to turn it on, or remove it from the `x-tm-tools`
  header (or `tools`) to send the request without it.
- **503, "turned on but not configured"**: the tool is turned on for the gateway
  you called, but our Parallel key is not in place yet. Ask support; retrying
  will not help until the key is configured.
- **400 that names `parallel:search` while Tako works**: the gateway you called
  serves `tako:search` but not the Parallel tools. Drop the `parallel:*` values
  from the header (or the entries from `tools`) to send the request with Tako
  alone, or ask support.
- **400 "needs an organization key"**: use an organization key, not a static one.
- **400 naming `x-tm-tools`**: the header holds something other than the six
  values above.
- **400 naming `parallel:image_search`, `parallel:place_search` or
  `parallel:decisions` while `parallel:search` works**: the gateway you called
  does not serve that tool; drop it from the header or `tools`, or ask support.
- **`"basic" is not supported; use "turbo" or "fast"`**: the gateway you
  called does not serve the `basic` and `advanced` search modes. Use `"turbo"` or
  `"fast"`, or ask support.
- **A place search error, "give a location (or latitude and longitude)"**: a
  place search needs one place to search in. Put what in `query` and where in
  `location` (one place, not a list).
- **A decisions error**: each question needs a unique name of letters, digits,
  `_` or `-`; a `choice` needs 2 to 20 options and a `score` 2 to 10 levels;
  instructions and criteria together at most 4,000 characters, and the state at
  most 8,000 characters as JSON.
- **429 `insufficient_quota`**: your credit or a spend cap does not cover the
  next call.

## Data

**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. So are a place search's query and location (a place name,
an address or coordinates can say where someone is) and a decisions call's
state and questions, which the model can fill with anything from your
conversation. Place results carry businesses' public addresses and phone
numbers; image results are links to third-party images, which the gateway never
opens. 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. See [Data policy](/docs/data-policy).

## Where next

- [Server tools](/docs/server-tools) — the full reference, with Tako
- [Pricing & billing](/docs/pricing) — the billing math and `usage.cost`
- [Data policy](/docs/data-policy) — what is stored and by whom
