# Server tools

Server tools are tools that kenari runs for you. Add one to the `tools` array of a request and the model decides when to call it. kenari runs the call and gives the result back to the model. You get a single finished answer. The model does not need built-in search, only support for function calling. `GET /v1/models` marks those models with `"tool_call": true`. See [Models and pricing](/en/docs/models).

| Tool | What it does | Billing |
| --- | --- | --- |
| `kenari:web_search` | Searches the web and gives the model titles, URLs and snippets. | Per search |
| `kenari:web_fetch` | Fetches one page and gives the model its text and links. | Per fetch |
| `kenari:x_search` | Searches live posts on X and gives the model a short answer with x.com sources. | Per search |
| `kenari:datetime` | Gives the model the current date and time. | Free |

Server tools work on Chat Completions, Messages and Responses. In all three you declare a server tool the same way, with a `type` of `kenari:<name>` and nothing else. `<name>` is a tool from the table.

## Add a tool to a request

```bash
curl https://kenari.id/v1/chat/completions \
  -H "Authorization: Bearer $KENARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "step-3-7-flash:free",
    "tools": [{"type": "kenari:web_search"}],
    "messages": [
      {"role": "user", "content": "What changed in the latest stable Rust release?"}
    ]
  }'
```

Declare several tools together, and keep your own function tools next to them:

```json
{
  "tools": [
    {"type": "kenari:web_search"},
    {"type": "kenari:datetime"},
    {"type": "function", "function": {"name": "save_note", "parameters": {"type": "object"}}}
  ]
}
```

kenari runs only the tools whose type starts with `kenari:`, and passes your own function tools through. A function that has the same name as an enabled server tool, such as `web_search`, `web_fetch`, `x_search` or `datetime`, can collide with it, so give your functions other names. The `kenari:*` declaration is the same on the other formats. Declarations of your own functions differ per format, see [Function calling](/en/docs/function-calling). For example, on Messages:

```bash
curl https://kenari.id/v1/messages \
  -H "x-api-key: $KENARI_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "step-3-7-flash:free",
    "max_tokens": 1024,
    "tools": [{"type": "kenari:web_search"}],
    "messages": [{"role": "user", "content": "What changed in the latest stable Rust release?"}]
  }'
```

A tool call is billed even when the model in the request is free. See [Billing](#billing).

## Streaming

Server tools work with `stream: true`. When the model decides to call a tool mid-stream, kenari runs it, feeds the result back and continues in the same stream. You see one coherent message, with no tool call in it. See [Streaming](/en/docs/streaming) for the event format.

kenari limits how many times the model can call tools in one request: up to 4 rounds without streaming and up to 2 with streaming. When the limit is reached, kenari removes the tools and the model has to answer with what it has.

## Sources

On Chat Completions, the sources a search found are returned in `sources`, a list of `{url, title}` objects. Without streaming it sits on the message. With streaming it arrives in one chunk near the end, in `delta.sources`. When the model cites a source as `[1]`, `[2]` and so on in its text, the message also carries `url_citation` entries in `annotations` for those markers. On Messages, the non-streaming response has the same `sources` list at the top level.

## x_search_filter

The model fills in the arguments of a tool call, so it chooses `x_search_filter` too. You cannot set it in the tool declaration. To steer it, say what you want in the prompt, for example "only posts from these handles since the first of the month". To fix the filter yourself, call [Web and X search](/en/docs/web-search) directly.

| Field | Type | Description |
| --- | --- | --- |
| `allowed_x_handles` | array of strings | Search only these accounts. |
| `excluded_x_handles` | array of strings | Leave these accounts out. Cannot be used with `allowed_x_handles`. |
| `from_date`, `to_date` | string | A date range in `YYYY-MM-DD`. `from_date` must not be after `to_date`. |
| `enable_image_understanding`, `enable_video_understanding` | boolean | Read the images or videos inside posts. |

Handles are written without the `@`, use only letters, digits and underscores, and are limited to 20 per list.

## datetime and timezone

`kenari:datetime` lets the model check what day it is instead of guessing from its training data. The model passes an optional `timezone`, either an IANA name such as `Asia/Jakarta` or `America/New_York`, or a common abbreviation such as `WIB`, `JST` or `UTC`. The default is `Asia/Jakarta`. The result has the current time in UTC and the time in that zone.

## Server tools or provider built-in tools

Some providers have their own search tools, such as `web_search_preview` on OpenAI or `web_search_20250305` on Anthropic. kenari does not run these. It forwards them to the provider unchanged, and they work only for models whose provider supports them. A `kenari:web_search` tool works with any model that can call functions, because kenari does the search. Use one kind of search tool per request.

## Billing

`kenari:web_search`, `kenari:web_fetch` and `kenari:x_search` are billed per call, separately from tokens, and only when the model actually calls them. `kenari:datetime` is free. A call that fails is not charged. How a plan's daily allowance and your balance apply is explained on [Subscriptions](/en/docs/subscriptions).

When a call cannot be funded, it does not run. The model is told the search was unavailable and still answers, so the request does not fail. See [How billing works](/en/docs/billing) and [Subscriptions](/en/docs/subscriptions).

A key restricted to certain models can use search and page fetch only with **Web search and page fetching** ticked under **Paid capabilities**, and X search only with **X search** ticked. See [Authentication and API keys](/en/docs/authentication).

## Calling the tools without a model

The same search, fetch and X search are available as plain endpoints, with no model involved. See [Web and X search](/en/docs/web-search).

## See also

- [Web and X search](/en/docs/web-search)
- [Function calling](/en/docs/function-calling)
- [Streaming](/en/docs/streaming)
- [How billing works](/en/docs/billing)
