Tools

Tools give agents the ability to act: look things up, call APIs, run code, read files. The model decides which tools to call and when.

Tool() API

Write a normal Swift function, wrap it with Tool() and a description. The tool name and parameter schema are inferred automatically from the description.

Defining toolsSwift
func wordCount(text: String) -> Int {
    text.split(whereSeparator: \.isWhitespace).count
}
let wordCountTool = Tool(wordCount, "Count the number of words in a block of text.")

func calculator(expression: String) -> String {
    guard let result = NSExpression(format: expression)
        .expressionValue(with: nil, context: nil) else {
        return "Error: invalid expression"
    }
    return "\(result)"
}
let calculatorTool = Tool(calculator, "Evaluate a mathematical expression and return the result.")

let agent = Agent(model: provider, tools: [wordCountTool, calculatorTool])

Your functions stay regular Swift functions -- you can still call them directly:

Swift
let count = wordCount(text: "hello world")  // 2

Type mapping

Swift TypeJSON Schema
String"type": "string"
Int, Int64, …"type": "integer"
Double, Float"type": "number"
Bool"type": "boolean"
T? or default valueMarked optional in schema (omitted from required)

Optional parameters and defaults

Parameters with a default value or ? type are treated as optional: included in the schema but excluded from required:

Swift
func getWeather(
    city: String,              // required
    unit: String = "celsius",  // optional (has a default)
    detailed: Bool = false     // optional (has a default)
) async throws -> String {
    return "22°C, partly cloudy in \(city)"
}
let getWeatherTool = Tool(getWeather, "Look up current weather for a city.")

Async and throwing tools

Tools can be async, throws, or both. The generated wrapper handles await and catches errors automatically:

Swift
func searchWeb(query: String, maxResults: Int = 5) async throws -> String {
    let url = URL(string: "https://api.search.example.com?q=\(query)")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return String(data: data, encoding: .utf8) ?? "No results"
}
let searchWebTool = Tool(searchWeb, "Search the web and return a summary of the top results.")

Concurrent Tool Execution

When a model requests multiple tools in a single response, the agent runs them all concurrently using Swift structured concurrency. This means a model can call searchWeb, calculator, and getWeather simultaneously and wait for all results before continuing.

💡

Make your tools async whenever they perform I/O (network, disk) so concurrent execution is truly parallel rather than serialized.

MCP Tool Providers

The SDK supports the Model Context Protocol (MCP). Connect any MCP server as a tool provider and all its tools become available to the agent automatically:

Swift
let mcpProvider = MCPToolProvider(serverURL: URL(string: "http://localhost:3000")!)
let tools = try await mcpProvider.tools()
let agent = Agent(model: provider, tools: tools)