Search and server tools

Combine your Swift tools with provider-hosted search, files, and code execution.

Covers the provider tool examples in Examples/Providers/OpenAI/, Anthropic/, Google/, and xAI/, plus Examples/Features/23-WorkflowGuides.swift.

Local function tools run your Swift closure. Server tools run inside the provider's infrastructure. Both conform to the same tool protocol and can be passed to generateText or streamText together.

Start with a local function tool

struct WeatherArgs: Decodable { let city: String }

let weather = Tool.typed(
  name: "get_weather",
  description: "Get the current weather for a city from Open-Meteo.",
  parameters: [
    "type": "object",
    "properties": ["city": ["type": "string"]],
    "required": ["city"]
  ]
) { (arguments: WeatherArgs) in
  try await OpenMeteoWeather.current(city: arguments.city)
}

The agentic loop executes this closure locally and feeds its result back to the model. OpenMeteoWeather is the compile-checked geocoding and current forecast client used throughout the examples; see An agent with tools.

Add provider-hosted tools

let tools: [any AIToolProtocol] = [
  weather,
  OpenAIModel.Tools.webSearch(allowedDomains: ["swift.org"]),
  OpenAIModel.Tools.codeInterpreter()
]

let result = try await generateText(
  model: OpenAIModel("gpt-5.6-sol"),
  prompt: "Find the latest stable Swift release and compare its number with 5.9.",
  tools: tools,
  stopWhen: [stepCountIs(6)]
)

Domain restrictions and resource ids should be as narrow as the task allows.

Render citations

Providers that expose citations emit them as sources:

print(result.text)
for source in result.sources {
  print(source.title ?? source.url, source.url)
}

For streaming UIs, watch fullStream for .source parts and attach them to the answer as they arrive.

Choose the provider catalog

Each provider has its own server-side capabilities:

ProviderBuilders available in Swift AI
OpenAIWeb search, web-search preview, file search, code interpreter
AnthropicWeb search, web fetch, code execution, bash, text editor, computer, memory
GoogleGoogle Search, URL context, code execution, enterprise web search, Maps, file search
xAIWeb search, X search, code execution, file search, MCP server, image and X-video viewing
let anthropicTools: [any AIToolProtocol] = [
  AnthropicModel.Tools.webSearch(allowedDomains: ["swift.org"]),
  AnthropicModel.Tools.webFetch(allowedDomains: ["swift.org"]),
  AnthropicModel.Tools.codeExecution()
]

Builder arguments are provider-native. A vector-store id from OpenAI, for example, cannot be passed to Google's file-search builder.

Use search-native providers when tools are unnecessary

Perplexity searches as part of ordinary generation, while xAI can also take search configuration through provider options:

let result = try await generateText(
  model: PerplexityModel("sonar-pro"),
  prompt: "What changed in the latest Swift release?"
)
for source in result.sources { print(source.url) }

Use this shape when the whole request is research. Use explicit tools when the model must decide whether to search among several possible actions.

Treat powerful tools as privileged operations

Code execution, shell access, computer use, and external MCP servers can touch data outside the prompt. Restrict domains and resources, separate trusted from untrusted content, and place user approval in front of dangerous local actions. See Human-in-the-loop approvals.

Final code

ResearchAssistant.swift
import AI

struct WeatherArgs: Decodable { let city: String }

let weather = Tool.typed(
  name: "get_weather",
  description: "Get the current weather for a city from Open-Meteo.",
  parameters: [
    "type": "object",
    "properties": ["city": ["type": "string"]],
    "required": ["city"]
  ]
) { (arguments: WeatherArgs) in
  try await OpenMeteoWeather.current(city: arguments.city)
}

func research(_ question: String) async throws -> GenerateTextResult {
  let tools: [any AIToolProtocol] = [
    weather,
    OpenAIModel.Tools.webSearch(allowedDomains: ["swift.org"]),
    OpenAIModel.Tools.codeInterpreter()
  ]

  return try await generateText(
    model: OpenAIModel("gpt-5.6-sol"),
    prompt: question,
    tools: tools,
    stopWhen: [stepCountIs(6)]
  )
}

The complete builder catalogs live in the OpenAI, Anthropic, Google, and xAI provider pages.