GuidesToolsSearch Tools

Search Tools

Agentic search represents one of the most compelling applications of agentic tool calling, with grok-4-1-fast specifically trained to excel in this domain. Leveraging its speed and reasoning capabilities, the model iteratively calls search tools—analyzing responses and making follow-up queries as needed—to seamlessly navigate web pages and X posts, uncovering difficult-to-find information or insights that would otherwise require extensive human analysis.

xAI Python SDK Users: Version 1.3.1 of the xai-sdk package is required to use the agentic tool calling API.

Available Search Tools

You can use the following server-side search tools in your request:

  • Web Search - allows the agent to search the web and browse pages
  • X Search - allows the agent to perform keyword search, semantic search, user search, and thread fetch on X

You can customize which tools are enabled in a given request by listing the needed tools in the tools parameter in the request.

ToolxAI SDKOpenAI Responses API
Web Searchweb_searchweb_search
X Searchx_searchx_search

Retrieving Citations

Citations provide traceability for sources used during agentic search. Access them from the response object:

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import web_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[web_search()],
)

chat.append(user("What is xAI?"))

is_thinking = True
for response, chunk in chat.stream():
    # View the server-side tool calls as they are being made in real-time
    for tool_call in chunk.tool_calls:
        print(f"\\nCalling tool: {tool_call.function.name} with arguments: {tool_call.function.arguments}")
    if response.usage.reasoning_tokens and is_thinking:
        print(f"\\rThinking... ({response.usage.reasoning_tokens} tokens)", end="", flush=True)
    if chunk.content and is_thinking:
        print("\\n\\nFinal Response:")
        is_thinking = False
    if chunk.content and not is_thinking:
        print(chunk.content, end="", flush=True)

print("\\n\\nCitations:")
print(response.citations)
print("\\n\\nUsage:")
print(response.usage)
print(response.server_side_tool_usage)
print("\\n\\nServer Side Tool Calls:")
print(response.tool_calls)
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is xAI?",
        },
    ],
    tools=[
        {
            "type": "web_search",
        },
    ],
)

# Access the response
print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is xAI?"
        }
    ],
    "tools": [
        {
            "type": "web_search",
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)

# Access the citations of the final response
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is xAI?"
    }
  ],
  "tools": [
    {
      "type": "web_search"
    }
  ]
}'

As mentioned in the overview page, the citations array contains the URLs of all sources the agent encountered during its search process, meaning that not every URL here will necessarily be relevant to the final answer, as the agent may examine a particular source and determine it is not sufficiently relevant to the user’s original query.

For complete details on citations, including when they’re available and usage notes, see the overview page.

Each search tool supports a set of optional search parameters to help you narrow down the search space and limit the sources/information the agent is exposed to during its search process.

ToolSupported Filter Parameters
Web Searchallowed_domains, excluded_domains, enable_image_understanding
X Searchallowed_x_handles, excluded_x_handles, from_date, to_date, enable_image_understanding, enable_video_understanding

Web Search Parameters

Only Search in Specific Domains

Use allowed_domains to make the web search only perform the search and web browsing on web pages that fall within the specified domains.

allowed_domains can include a maximum of five domains.

allowed_domains cannot be set together with excluded_domains in the same request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import web_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        web_search(allowed_domains=["wikipedia.org"]),
    ],
)

chat.append(user("What is xAI?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is xAI?",
        },
    ],
    tools=[
        {
            "type": "web_search",
            "filters": {"allowed_domains": ["wikipedia.org"]},
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is xAI?"
        }
    ],
    "tools": [
        {
            "type": "web_search",
            "filters": {"allowed_domains": ["wikipedia.org"]},
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is xAI?"
    }
  ],
  "tools": [
    {
      "type": "web_search",
      "filters": {"allowed_domains": ["wikipedia.org"]}
    }
  ]
}'
Exclude Specific Domains

Use excluded_domains to prevent the model from including the specified domains in any web search tool invocations and from browsing any pages on those domains.

excluded_domains can include a maximum of five domains.

excluded_domains cannot be set together with allowed_domains in the same request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import web_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        web_search(excluded_domains=["wikipedia.org"]),
    ],
)

chat.append(user("What is xAI?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is xAI?",
        },
    ],
    tools=[
        {
            "type": "web_search",
            "filters": {"excluded_domains": ["wikipedia.org"]},
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is xAI?"
        }
    ],
    "tools": [
        {
            "type": "web_search",
            "filters": {"excluded_domains": ["wikipedia.org"]},
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is xAI?"
    }
  ],
  "tools": [
    {
      "type": "web_search",
      "filters": {"excluded_domains": ["wikipedia.org"]}
    }
  ]
}'
Enable Image Understanding

Setting enable_image_understanding to true equips the agent with access to the view_image tool, allowing it to invoke this tool on any image URLs encountered during the search process. The model can then interpret and analyze image contents, incorporating this visual information into its context to potentially influence the trajectory of follow-up tool calls.

When the model invokes this tool, you will see it as an entry in chunk.tool_calls and response.tool_calls with the image_url as a parameter. Additionally, SERVER_SIDE_TOOL_VIEW_IMAGE will appear in response.server_side_tool_usage along with the number of times it was called when using the xAI Python SDK.

Note that enabling this feature increases token usage, as images are processed and represented as image tokens in the model’s context.

Enabling this parameter for Web Search will also enable the image understanding for X Search tool if it’s also included in the request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import web_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        web_search(enable_image_understanding=True),
    ],
)

chat.append(user("What is included in the image in xAI's official website?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is included in the image in xAI's official website?",
        },
    ],
    tools=[
        {
            "type": "web_search",
            "enable_image_understanding": True,
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is included in the image in xAI's official website?"
        }
    ],
    "tools": [
        {
            "type": "web_search",
            "enable_image_understanding": True,
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is included in the image in xAI's official website?"
    }
  ],
  "tools": [
    {
      "type": "web_search",
      "enable_image_understanding": true
    }
  ]
}'

X Search Parameters

Only Consider X Posts from Specific Handles

Use allowed_x_handles to consider X posts only from a given list of X handles. The maximum number of handles you can include is 10.

allowed_x_handles cannot be set together with excluded_x_handles in the same request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        x_search(allowed_x_handles=["elonmusk"]),
    ],
)

chat.append(user("What is the current status of xAI?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is the current status of xAI?",
        },
    ],
    tools=[
        {
            "type": "x_search",
            "allowed_x_handles": ["elonmusk"],
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is the current status of xAI?"
        }
    ],
    "tools": [
        {
            "type": "x_search",
            "allowed_x_handles": ["elonmusk"],
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is the current status of xAI?"
    }
  ],
  "tools": [
    {
      "type": "x_search",
      "allowed_x_handles": ["elonmusk"]
    }
  ]
}'
Exclude X Posts from Specific Handles

Use excluded_x_handles to prevent the model from including X posts from the specified handles in any X search tool invocations. The maximum number of handles you can exclude is 10.

excluded_x_handles cannot be set together with allowed_x_handles in the same request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        x_search(excluded_x_handles=["elonmusk"]),
    ],
)

chat.append(user("What is the current status of xAI?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is the current status of xAI?",
        },
    ],
    tools=[
        {
            "type": "x_search",
            "excluded_x_handles": ["elonmusk"],
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is the current status of xAI?"
        }
    ],
    "tools": [
        {
            "type": "x_search",
            "excluded_x_handles": ["elonmusk"],
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is the current status of xAI?"
    }
  ],
  "tools": [
    {
      "type": "x_search",
      "excluded_x_handles": ["elonmusk"]
    }
  ]
}'
Date Range

You can restrict the date range of search data used by specifying from_date and to_date. This limits the data to the period from from_date to to_date, including both dates.

Both fields need to be in ISO8601 format, e.g., “YYYY-MM-DD”. If you’re using the xAI Python SDK, the from_date and to_date fields can be passed as datetime.datetime objects.

The fields can also be used independently. With only from_date specified, the data used will be from the from_date to today, and with only to_date specified, the data used will be all data until the to_date.

import os
from datetime import datetime

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        x_search(
            from_date=datetime(2025, 10, 1),
            to_date=datetime(2025, 10, 10),
        ),
    ],
)

chat.append(user("What is the current status of xAI?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is the current status of xAI?",
        },
    ],
    tools=[
        {
            "type": "x_search",
            "from_date": "2025-10-01",
            "to_date": "2025-10-10",
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is the current status of xAI?"
        }
    ],
    "tools": [
        {
            "type": "x_search",
            "from_date": "2025-10-01",
            "to_date": "2025-10-10",
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is the current status of xAI?"
    }
  ],
  "tools": [
    {
      "type": "x_search",
      "from_date": "2025-10-01",
      "to_date": "2025-10-10"
    }
  ]
}'
Enable Image Understanding

Setting enable_image_understanding to true equips the agent with access to the view_image tool, allowing it to invoke this tool on any image URLs encountered during the search process. The model can then interpret and analyze image contents, incorporating this visual information into its context to potentially influence the trajectory of follow-up tool calls.

When the model invokes this tool, you will see it as an entry in chunk.tool_calls and response.tool_calls with the image_url as a parameter. Additionally, SERVER_SIDE_TOOL_VIEW_IMAGE will appear in response.server_side_tool_usage along with the number of times it was called when using the xAI Python SDK.

Note that enabling this feature increases token usage, as images are processed and represented as image tokens in the model’s context.

Enabling this parameter for X Search will also enable the image understanding for Web Search tool if it’s also included in the request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        x_search(enable_image_understanding=True),
    ],
)

chat.append(user("What images are being shared in recent xAI posts?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What images are being shared in recent xAI posts?",
        },
    ],
    tools=[
        {
            "type": "x_search",
            "enable_image_understanding": True,
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What images are being shared in recent xAI posts?"
        }
    ],
    "tools": [
        {
            "type": "x_search",
            "enable_image_understanding": True,
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What images are being shared in recent xAI posts?"
    }
  ],
  "tools": [
    {
      "type": "x_search",
      "enable_image_understanding": true
    }
  ]
}'
Enable Video Understanding

Setting enable_video_understanding to true equips the agent with access to the view_x_video tool, allowing it to invoke this tool on any video URLs encountered in X posts during the search process. The model can then analyze video content, incorporating this information into its context to potentially influence the trajectory of follow-up tool calls.

When the model invokes this tool, you will see it as an entry in chunk.tool_calls and response.tool_calls with the video_url as a parameter. Additionally, SERVER_SIDE_TOOL_VIEW_X_VIDEO will appear in response.server_side_tool_usage along with the number of times it was called when using the xAI Python SDK.

Note that enabling this feature increases token usage, as video content is processed and represented as tokens in the model’s context.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4-1-fast",  # reasoning model
    tools=[
        x_search(enable_video_understanding=True),
    ],
)

chat.append(user("What is the latest video talking about from the xAI official X account?"))

# stream or sample the response...
import os
from openai import OpenAI

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

response = client.responses.create(
    model="grok-4-1-fast",
    input=[
        {
            "role": "user",
            "content": "What is the latest video talking about from the xAI official X account?",
        },
    ],
    tools=[
        {
            "type": "x_search",
            "enable_video_understanding": True,
        },
    ],
)

print(response)
import os
import requests

url = "https://api.x.ai/v1/responses"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}
payload = {
    "model": "grok-4-1-fast",
    "input": [
        {
            "role": "user",
            "content": "What is the latest video talking about from the xAI official X account?"
        }
    ],
    "tools": [
        {
            "type": "x_search",
            "enable_video_understanding": True,
        }
    ]
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4-1-fast",
  "input": [
    {
      "role": "user",
      "content": "What is the latest video talking about from the xAI official X account?"
    }
  ],
  "tools": [
    {
      "type": "x_search",
      "enable_video_understanding": true
    }
  ]
}'