> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.asi1.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.asi1.ai/_mcp/server.

# Web Search

> Give ASI:One models live web search on both endpoints, and control how much search context they use.

Web search lets a model look things up on the live web before answering. It is
available on every ASI:One model, on both endpoints, and it is opt-in per
request: a plain request behaves exactly as before, and the model answers from
its own knowledge.

## How it works

When search is enabled for a request, the model decides from the conversation
whether a web search would help. If it searches, the results are fed back into
the model and the answer is grounded in them. Search results count toward the
request's token usage, so a run that searches reports more prompt tokens than
one that does not - that is the cost of the live data, charged at normal token
rates.

Search runs on the model's own judgement: it searches when the question calls
for it and answers directly when it does not. You control how much search
context is used with `search_context_size`:

| Value    | Behavior                                           |
| -------- | -------------------------------------------------- |
| `low`    | Leaner: fewer search results for the model to read |
| `medium` | Balanced. The default                              |
| `high`   | Richer: more search results for the model to read  |

More context improves answer quality on research-heavy questions and costs
more tokens; `low` is the economical choice for simple lookups.

## On the Responses API

Add the hosted `web_search` tool to `tools`:

#### cURL

```bash
curl -X POST https://api.asi1.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ASI_ONE_API_KEY" \
  -d '{
    "model": "asi1",
    "input": "What is the population of Paris in 2026?",
    "tools": [
      {
        "type": "web_search",
        "search_context_size": "high"
      }
    ]
  }'
```

#### Python

```python
import os

from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("ASI_ONE_API_KEY"),
    base_url="https://api.asi1.ai/v1",
)

response = client.responses.create(
    model="asi1",
    input="What is the population of Paris in 2026?",
    tools=[{"type": "web_search", "search_context_size": "high"}],
)

print(response.output_text)
```

`search_context_size` is optional and defaults to `medium`. The `web_search`
tool may be specified at most once per request.

### Reading the search from the output

When the model searches, the response's `output` array contains a
`web_search_call` item alongside the final message, recording the query the
model ran and the status of the call:

```json
{
  "id": "ws_5c58a1c0426f",
  "type": "web_search_call",
  "status": "completed",
  "action": {
    "type": "search",
    "query": "Paris population 2026 INSEE"
  }
}
```

On a streaming response, the search is surfaced the same way, as
`response.output_item.added` and `response.output_item.done` events carrying
the `web_search_call` item, together with the lifecycle events
`response.web_search_call.in_progress`,
`response.web_search_call.searching` and
`response.web_search_call.completed`.

## On the Chat Completions API

Pass the `web_search_options` object. Its presence is the opt-in - an empty
object is enough:

#### cURL

```bash
curl -X POST https://api.asi1.ai/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ASI_ONE_API_KEY" \
  -d '{
    "model": "asi1",
    "messages": [
      { "role": "user", "content": "What is the population of Paris in 2026?" }
    ],
    "web_search_options": {
      "search_context_size": "high"
    }
  }'
```

#### Python

```python
import os

from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("ASI_ONE_API_KEY"),
    base_url="https://api.asi1.ai/v1",
)

completion = client.chat.completions.create(
    model="asi1",
    messages=[{"role": "user", "content": "What is the population of Paris in 2026?"}],
    web_search_options={"search_context_size": "high"},
)

print(completion.choices[0].message.content)
```

The same `search_context_size` values apply, with the same `medium` default.
The object accepts no other keys; anything else is rejected with a `400`
naming the field.

## What to know before you ship it

* **Both endpoints, all models.** Search is available on `asi1`, `asi1-ultra`
  and `asi1-mini`, on `/v1/chat/completions` and `/v1/responses`.
* **Opt-in per request.** Without the `web_search` tool (Responses) or
  `web_search_options` (Chat Completions), nothing changes: no search, no
  extra tokens.
* **Billed as tokens.** Search results are tokenized and counted in the
  request's prompt tokens at normal rates. There is no separate charge for a
  search call.
* **Failures are surfaced, not hidden.** A failed search appears in the
  Responses output as a `web_search_call` item with `status: "failed"` and the
  attempted query, so a run is never silently missing its search.

## Next steps

1. **[Tool Calling](/documentation/build-with-asi-one/tool-calling)** - Define your own functions alongside the hosted search
2. **[Responses API](/documentation/build-with-asi-one/responses)** - The endpoint reference, including streamed event types
3. **[Reasoning](/documentation/build-with-asi-one/reasoning)** - Let the model think before it answers