Developer Dashboard

Web Search Tool

Allow models to search the web for the latest information before generating a response.

Using the Responses API, you can enable web search by configuring it in the tools array in an API request to generate content. Like any other tool, the model can choose to search the web or not based on the content of the input prompt.

Choose an integration

AvalAI offers two complementary search paths:

Use caseRecommended pathNotes
New AI answers with citations/v1/responses + tools: [{"type": "web_search"}]Best default for Responses-first apps; the model decides when to search unless you force tool_choice.
Raw search results for your app/v1/searchReturns URLs, snippets, and provider-specific metadata without LLM synthesis.
Existing Chat Completions search apps/v1/chat/completions with an AvalAI-supported search modelKeep existing integrations, but prefer Responses web_search for new work.

Use search_context_size: "low" for fast lookups, "medium" as the balanced default, and "high" when the answer needs richer source context.

Web search tool example

javascript
import OpenAI from "openai";
const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,

  baseURL: "https://api.avalai.ir/v1",
}); // Use custom base URL

const response = await client.responses.create({
  model: "gpt-5.5",
  tools: [{ type: "web_search" }],
  input: "What was a positive news story from today?",
});

console.log(response.output_text);
python
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",  # Custom API endpoint
)  # Use custom base URL

response = client.responses.create(
    model="gpt-5.5",
    tools=[{"type": "web_search"}],
    input="What was a positive news story from today?",
)

print(response.output_text)
bash
curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
 "model": "gpt-5.5",
 "tools": [{"type": "web_search"}],
 "input": "what was a positive news story from today?"
 }'
go
package main

import (
	"context"
	"fmt"
	"github.com/openai/openai-go" // OpenAI Go client
	"github.com/openai/openai-go/option"
	"os"
)

func main() {
	apiKey := os.Getenv("AVALAI_API_KEY")
	client := openai.NewClient(
		option.WithAPIKey(apiKey),
		option.WithBaseURL("https://api.avalai.ir/v1"), // Use custom base URL
	)

	resp, err := client.Responses.Create(
		context.Background(),
		openai.ResponsesCreateParams{
			Model: "gpt-5.5",
			Tools: []openai.ToolParamUnion{
				openai.ToolParam{
					Type: openai.F("web_search"),
				},
			},
			Input: "What was a positive news story from today?",
		},
	)

	if err != nil {
		fmt.Printf("Response creation error: %v\n", err)
		return
	}

	fmt.Println(resp.OutputText)
}
php
<?php
require_once(__DIR__ . '/vendor/autoload.php'); // Assuming Composer autoload

$apiKey = getenv('AVALAI_API_KEY');
$client = OpenAI::client($apiKey, ["base_uri" => "https://api.avalai.ir/v1"]); // Using OpenAI PHP client with custom base URL

$response = $client->responses()->create([
'model' => 'gpt-5.5',
'tools' => [['type' => 'web_search']],
'input' => 'What was a positive news story from today?',
]);

echo $response->output_text;
?>

Web search tool versions

Use web_search for new Responses API integrations. The older web_search_preview tool remains available for legacy integrations, but it does not support newer controls such as filters, live-access control, and returned-token budgets.

You can force web search with the tool_choice parameter, for example { "type": "web_search" }, when search must run for a request.

Migration path from legacy search models

Do not remove existing Chat Completions search integrations just because newer Responses tooling exists. AvalAI still lists gpt-4o-search-preview and gpt-4o-mini-search-preview in data/models.json, so they remain documented while they are active. For new work, prefer /v1/responses with gpt-5.5 and tools: [{"type": "web_search"}].

Current integrationKeep or migrate?Recommended next step
/v1/responses + web_search_previewMigrateReplace the tool with {"type": "web_search"} to use filters, source metadata, live-access control, and returned-token budget controls.
/v1/chat/completions + gpt-4o-search-previewKeep only for legacy appsPlan migration before the scheduled July 23, 2026 shutdown listed in deprecations; move new search UX to Responses web_search.
/v1/chat/completions + gpt-4o-mini-search-previewKeep only for legacy appsSame migration path as above; use Responses for optional search, domain filters, and richer web_search_call metadata.
Raw search endpoint /v1/searchKeep when you need raw resultsUse it for URL/snippet retrieval without LLM synthesis; use Responses when the model should synthesize cited answers.

There are three practical search modes to design for:

  • Quick lookup: low or medium search_context_size, optional search, and short answers.
  • Agentic research: reasoning models can search, inspect results, and continue searching when the prompt requires more evidence.
  • Deep research: use higher reasoning effort and background processing for long reports that can take minutes.

Output and citations

Model responses that use the web search tool will include two parts:

  • A web_search_call output item with the ID of the search call and an action field. Depending on the model and search path, the action can be search, open_page, or find_in_page.
  • A message output item containing:
    • The text result in message.content[0].text
    • Annotations message.content[0].annotations for the cited URLs

By default, the model's response will include inline citations for URLs found in the web search results. In addition to this, the url_citation annotation object will contain the URL, title and location of the cited source.

When displaying web results or information contained in web results to end users, inline citations must be made clearly visible and clickable in your user interface.

json
[
  {
    "type": "web_search_call",
    "id": "ws_67c9fa0502748190b7dd390736892e100be649c1a5ff9609",
    "status": "completed",
    "action": {
      "type": "search",
      "query": "latest news about AI"
    }
  },
  {
    "id": "msg_67c9fa077e288190af08fdffda2e34f20be649c1a5ff9609",
    "type": "message",
    "status": "completed",
    "role": "assistant",
    "content": [
      {
        "type": "output_text",
        "text": "On March 6, 2025, several news...",
        "annotations": [
          {
            "type": "url_citation",
            "start_index": 2606,
            "end_index": 2758,
            "url": "https://...",

            "title": "Title..."
          }
        ]
      }
    ]
  }
]

Citation rendering checklist

Use this checklist when turning web_search output into a product UI:

  • Render inline url_citation annotations as visible, clickable source links near the generated claim.
  • Preserve each citation's url, title, and text span so users can inspect what the model relied on.
  • Request include: ["web_search_call.action.sources"] when you need the complete consulted-source list for audits, not only the citations selected for the final answer.
  • Store the web_search_call.action object with your trace logs so you can debug whether the model searched, opened a page, or searched within a page.
  • If a response has no citations for a freshness-sensitive answer, treat it as ungrounded and retry with tool_choice: "required" or a narrower prompt.

User location

To refine search results based on geography, you can specify an approximate user location using country, city, region, and/or timezone.

  • The city and region fields are free text strings, like Minneapolis and Minnesota respectively.
  • The country field is a two-letter ISO country code, like US.
  • The timezone field is an IANA timezone like America/Chicago.

User location is a hint for local relevance, not a proof of the user's precise position. Do not use it for compliance, billing, access-control, or safety decisions. It is also not supported for deep-research web-search runs; keep those prompts source-focused instead of location-personalized.

Customizing user location

python
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",  # Custom API endpoint
)  # Use custom base URL

response = client.responses.create(
    model="gpt-5.5",
    tools=[
        {
            "type": "web_search",
            "user_location": {
                "type": "approximate",
                "country": "GB",
                "city": "London",
                "region": "London",
            },
        }
    ],
    input="What are the best restaurants around Granary Square?",
)

print(response.output_text)
javascript
import OpenAI from "openai";
const openai = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,

  baseURL: "https://api.avalai.ir/v1",
}); // Use custom base URL

const response = await openai.responses.create({
  model: "gpt-5.5",
  tools: [
    {
      type: "web_search",
      user_location: {
        type: "approximate",
        country: "GB",
        city: "London",
        region: "London",
      },
    },
  ],
  input: "What are the best restaurants around Granary Square?",
});
console.log(response.output_text);
bash
curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
 "model": "gpt-5.5",
 "tools": [{
 "type": "web_search",
 "user_location": {
 "type": "approximate",
 "country": "GB",
 "city": "London",
 "region": "London"
 }
 }],
 "input": "What are the best restaurants around Granary Square?"
 }'
go
package main

import (
	"context"
	"fmt"
	"github.com/openai/openai-go" // OpenAI Go client
	"github.com/openai/openai-go/option"
	"os"
)

func main() {
	apiKey := os.Getenv("AVALAI_API_KEY")
	client := openai.NewClient(
		option.WithAPIKey(apiKey),
		option.WithBaseURL("https://api.avalai.ir/v1"), // Use custom base URL
	)

	resp, err := client.Responses.Create(
		context.Background(),
		openai.ResponsesCreateParams{
			Model: "gpt-5.5",
			Tools: []openai.ToolParamUnion{
				openai.ToolParam{
					Type: openai.F("web_search"),
					UserLocation: &openai.UserLocation{
						Type:    openai.F("approximate"),
						Country: openai.F("GB"),
						City:    openai.F("London"),
						Region:  openai.F("London"),
					},
				},
			},
			Input: "What are the best restaurants around Granary Square?",
		},
	)

	if err != nil {
		fmt.Printf("Response creation error: %v\n", err)
		return
	}

	fmt.Println(resp.OutputText)
}
php
<?php
require_once(__DIR__ . '/vendor/autoload.php'); // Assuming Composer autoload

$apiKey = getenv('AVALAI_API_KEY');
$client = OpenAI::client($apiKey, ["base_uri" => "https://api.avalai.ir/v1"]); // Using OpenAI PHP client with custom base URL

$response = $client->responses()->create([
'model' => 'gpt-5.5',
'tools' => [[
'type' => 'web_search',
'user_location' => [
'type' => 'approximate',
'country' => 'GB',
'city' => 'London',
'region' => 'London',
]
]],
'input' => 'What are the best restaurants around Granary Square?',
]);

echo $response->output_text;
?>

Search context size

When using this tool, the search_context_size parameter controls how much web-result context is made available before the model formulates a response. It is a quality/cost/latency control, not an exact token count, source count, or citation guarantee.

Choosing a context size impacts:

  • Cost: Pricing of our search tool varies based on the value of this parameter. Higher context sizes are more expensive. See tool pricing here.
  • Quality: Higher search context sizes generally provide richer context, resulting in more accurate, comprehensive answers.
  • Latency: Higher context sizes require processing more tokens, which can slow down the tool's response time.

Available values:

  • high: Most comprehensive context, highest cost, slower response.
  • medium (default): Balanced context, cost, and latency.
  • low: Least context, lowest cost, fastest response, but potentially lower answer quality.

Check the pricing page for costs associated with each context size, and treat the setting as a retrieval-depth control rather than a persistence mechanism across turns.

Customizing search context size

python
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",  # Custom API endpoint
)  # Use custom base URL

response = client.responses.create(
    model="gpt-5.5",
    tools=[
        {
            "type": "web_search",
            "search_context_size": "low",
        }
    ],
    input="What movie won best picture in 2025?",
)

print(response.output_text)
javascript
import OpenAI from "openai";
const openai = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,

  baseURL: "https://api.avalai.ir/v1",
}); // Use custom base URL

const response = await openai.responses.create({
  model: "gpt-5.5",
  tools: [
    {
      type: "web_search",
      search_context_size: "low",
    },
  ],
  input: "What movie won best picture in 2025?",
});
console.log(response.output_text);
bash
curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
 "model": "gpt-5.5",
 "tools": [{
 "type": "web_search",
 "search_context_size": "low"
 }],
 "input": "What movie won best picture in 2025?"
 }'
go
package main

import (
	"context"
	"fmt"
	"github.com/openai/openai-go" // OpenAI Go client
	"github.com/openai/openai-go/option"
	"os"
)

func main() {
	apiKey := os.Getenv("AVALAI_API_KEY")
	client := openai.NewClient(
		option.WithAPIKey(apiKey),
		option.WithBaseURL("https://api.avalai.ir/v1"), // Use custom base URL
	)

	resp, err := client.Responses.Create(
		context.Background(),
		openai.ResponsesCreateParams{
			Model: "gpt-5.5",
			Tools: []openai.ToolParamUnion{
				openai.ToolParam{
					Type:              openai.F("web_search"),
					SearchContextSize: openai.F("low"),
				},
			},
			Input: "What movie won best picture in 2025?",
		},
	)

	if err != nil {
		fmt.Printf("Response creation error: %v\n", err)
		return
	}

	fmt.Println(resp.OutputText)
}
php
<?php
require_once(__DIR__ . '/vendor/autoload.php'); // Assuming Composer autoload

$apiKey = getenv('AVALAI_API_KEY');
$client = OpenAI::client($apiKey, ["base_uri" => "https://api.avalai.ir/v1"]); // Using OpenAI PHP client with custom base URL

$response = $client->responses()->create([
'model' => 'gpt-5.5',
'tools' => [[
'type' => 'web_search',
'search_context_size' => 'low',
]],
'input' => 'What movie won best picture in 2025?',
]);

echo $response->output_text;
?>

Advanced search controls

Use these controls when the selected model and AvalAI routing support them:

  • Domain filtering: filters.allowed_domains and filters.blocked_domains constrain search to trusted sources or exclude low-quality domains. Omit https:// from domain names, for example who.int.
  • Source metadata: add include: ["web_search_call.action.sources"] when your app needs the complete list of consulted URLs, not only inline citations.
  • Live access control: set external_web_access: false to prefer cached/indexed results for offline or restricted runs. The default is live access.
  • Long research: return_token_budget: "unlimited" can allow larger returned search context for high-effort research, but may increase latency and cost.
  • Image search: search_content_types: ["image", "text"] plus image_settings can return visual web results when the UI needs current product photos, landmarks, or event images.

Domain filters accept up to 100 allowed domains or up to 100 blocked domains. Enter bare domains such as who.int or pubmed.ncbi.nlm.nih.gov; do not include https://, and expect subdomains to be included. return_token_budget supports default and unlimited; use unlimited only for GPT-5-family reasoning searches where the route supports longer web research, and combine it with background processing when a report may take minutes.

For privacy-sensitive workflows, treat live web search as an external data flow. OpenAI's data-controls guide distinguishes live internet access from offline/cache-only search modes; in AvalAI, only use external_web_access: false or make HIPAA/BAA, ZDR, or residency claims after the selected model route explicitly confirms support. Never send private account data, secrets, or raw personal identifiers in search queries.

Trusted-source search with source metadata

Use domain filters when your answer must come from a known source set, and request source metadata when your application needs to audit or render every consulted URL. external_web_access: false is useful for cache-only/restricted runs when the selected model and route support it.

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

response = client.responses.create(
    model="gpt-5.5",
    input="Summarize the latest WHO guidance on diabetes treatment and cite sources.",
    tools=[
        {
            "type": "web_search",
            "search_context_size": "medium",
            "filters": {
                "allowed_domains": ["who.int", "cdc.gov", "fda.gov"],
                "blocked_domains": ["reddit.com", "quora.com"],
            },
        }
    ],
    include=["web_search_call.action.sources"],
    tool_choice="auto",
)

print(response.output_text)
for item in response.output:
    if item.type == "web_search_call":
        print(item.action)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

const response = await client.responses.create({
  model: "gpt-5.5",
  input: "Summarize the latest WHO guidance on diabetes treatment and cite sources.",
  tools: [
    {
      type: "web_search",
      search_context_size: "medium",
      filters: {
        allowed_domains: ["who.int", "cdc.gov", "fda.gov"],
        blocked_domains: ["reddit.com", "quora.com"],
      },
    },
  ],
  include: ["web_search_call.action.sources"],
  tool_choice: "auto",
});

console.log(response.output_text);
console.log(response.output.filter((item) => item.type === "web_search_call"));
bash
curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
    "model": "gpt-5.5",
    "input": "Summarize the latest WHO guidance on diabetes treatment and cite sources.",
    "tools": [
      {
        "type": "web_search",
        "search_context_size": "medium",
        "filters": {
          "allowed_domains": ["who.int", "cdc.gov", "fda.gov"],
          "blocked_domains": ["reddit.com", "quora.com"]
        }
      }
    ],
    "include": ["web_search_call.action.sources"],
    "tool_choice": "auto"
  }'

Image search results

When a product or research UI needs visual references, request image results explicitly and inspect the web_search_call.results items instead of relying only on output_text.

Each image result can include image_url, source_website_url, thumbnail_url, and caption. Validate the source domain and image URL before rendering or proxying the asset in your application.

python
response = client.responses.create(
    model="gpt-5.5",
    input="Find recent product images of electric cargo bikes and summarize design trends.",
    tools=[
        {
            "type": "web_search",
            "search_content_types": ["image", "text"],
            "image_settings": {"max_results": 3, "caption": True},
        }
    ],
    include=["web_search_call.results"],
)

for item in response.output:
    if item.type == "web_search_call":
        print(item.results)
javascript
const imageResponse = await client.responses.create({
  model: "gpt-5.5",
  input: "Find recent product images of electric cargo bikes and summarize design trends.",
  tools: [
    {
      type: "web_search",
      search_content_types: ["image", "text"],
      image_settings: { max_results: 3, caption: true },
    },
  ],
  include: ["web_search_call.results"],
});

console.log(imageResponse.output);

Limitations

Below are a few notable implementation considerations when using web search.

  • Chat Completions search models use a specialized model path and do not support the newer Responses web_search controls such as domain filters, full source lists, live-access control, or returned-token budget control.
  • OpenAI's current docs recommend newer Chat Completions search models for that path; in AvalAI docs, only use model IDs that exist in data/models.json.
  • With tool_choice: "auto", search is optional. Use tool_choice: "required" or a specific web-search tool choice when search must run.
  • When used as a tool in the Responses API, web search follows the selected model's tiered rate limits plus tool pricing.
  • Review the Privacy Policy and Content Policy for data handling, residency, retention, and safety expectations.