Tools
Tools let a model ask your Swift code to do discrete work, then continue with the tool result.
import SwiftAISDK
@mainstruct ToolsExample { static func main() async throws { let weather = AITool( name: "weather", description: "Get the current weather in a city.", parameters: [ "type": "object", "properties": [ "city": ["type": "string"], ], "required": ["city"], ] ) { arguments in let city = arguments["city"]?.stringValue ?? "unknown" return [ "city": .string(city), "forecast": "sunny", "temperatureCelsius": 24, ] }
let provider = try AIProviders.openAI() let model = try provider.languageModel("gpt-4.1-mini")
let answer = try await model.generateText( "What should I wear in Tokyo today?", tools: LanguageToolOptions([weather], maxSteps: 3) )
print(answer.text) }}Tool Shape
Section titled “Tool Shape”An AITool has:
- a stable
name - an optional
description - a JSON Schema
parametersvalue - an async
executefunction - optional
strictmode, provider metadata, provider options, and input examples - optional argument refinement, approval policy, context schema, streamed-input callbacks, and model-facing output mapping
Use maxSteps to let the model call tools, receive results, and make a follow-up model call until it returns a final answer or the step limit is reached.
Tool Loops
Section titled “Tool Loops”Tool-enabled generateText and streamText can be customized with LanguageToolOptions:
let options = LanguageToolOptions( [weather], maxSteps: 5, stopWhen: [.hasToolCall("weather")], prepareStep: { context in AIPrepareStepResult(request: context.request) })
let result = try await model.generateText( "Plan my afternoon.", tools: options)Each tool-loop result records steps, toolCalls, toolResults, approval parts, and responseMessages so you can inspect what happened or continue the conversation.
Tool choice is enforced at the facade boundary. If toolChoice is required,
or names a particular tool, and the provider completes without the required
call, generation throws AIToolChoiceViolationError. The error retains the
requested choice, provider/model identity, finish reason, and returned content
for diagnostics.
Approvals
Section titled “Approvals”Use needsApproval on a tool when a specific tool call should pause for approval, or use a call-level approval policy when one central policy should evaluate every tool call.
let transfer = AITool( name: "transfer_funds", description: "Transfer money between accounts.", parameters: [ "type": "object", "properties": ["amount": ["type": "number"]], "required": ["amount"], ], needsApproval: { input, _ in input["amount"]?.numberValue ?? 0 > 100 }) { input in ["status": "queued", "amount": input["amount"] ?? .null]}Approval requests and responses are represented as typed result and stream parts. When you use signed approval replay, pass a toolApprovalSecret so approvals from persisted messages can be verified before a tool is executed. Invalid or tampered signatures fail with AIInvalidToolApprovalSignatureError.
An approval policy can return context.userApproval(reason: "...") to preserve
a human-readable justification on AIToolApprovalRequest.reason and in
telemetry. Returning .userApproval remains the reason-free shorthand.
If an approved persisted call no longer validates against the current tool
schema, SwiftAISDK does not execute it; the model receives a tool-error result
and can continue the turn safely.
AIToolApprovalRequest.descriptor retains opaque provider-computed display
information through validation and telemetry. Treat it as untrusted UI metadata,
not as authorization evidence. A failed tool result’s provider metadata is also
restored onto its associated model-facing call when a provider needs a namespace
or replay identifier.
Streamed Tool Input
Section titled “Streamed Tool Input”Tools can observe streamed arguments before execution:
let search = AITool( name: "search", parameters: ["type": "object"], onInputDelta: { context in print("tool input delta:", context.inputTextDelta) }) { input in ["results": []]}Use onInputStart, onInputDelta, and onInputAvailable to update a UI as a model is still producing arguments. These callbacks receive the tool call ID, request messages, abort signal, and per-tool context.
Model-Facing Output
Section titled “Model-Facing Output”Set toModelOutput when the value your app stores should differ from the value sent back to the model. The public AIToolResult keeps both result and optional modelOutput.
Dynamic Tools
Section titled “Dynamic Tools”Use dynamic tools when the exact schema is discovered at runtime, such as tools loaded from MCP.
let dynamicTool = AITool.dynamic( name: "runtime_search", description: "Search a runtime index.", parameters: ["type": "object"]) { arguments in ["ok": true, "input": arguments]}OpenAI Responses Allow Lists
Section titled “OpenAI Responses Allow Lists”OpenAI 4.0.43 allowedTools limits the tools that Responses may choose while
still sending the complete request tool set. Declare tool names in the OpenAI
provider options (or the equivalent extraBody shape):
let request = LanguageModelRequest( messages: [.user("Search the docs, but do not edit anything.")], tools: [ "docs": OpenAITools.mcp( serverLabel: "docs", serverURL: "https://mcp.example.com" ), "computer": OpenAITools.computer() ], providerOptions: [ "openai": [ "allowedTools": [ "toolNames": ["docs", "computer"], "mode": "required" ] ] ])Function tools, supported hosted tools, labeled MCP servers, custom tools, and
OpenAITools.computer() map to tool_choice.allowed_tools. Deferred,
namespaced, tool-search, and legacy computerUse(...) entries warn and are
removed; an allow-list containing only unrepresentable entries is rejected.
The current computer tool is distinct from the older computer_use wire
shape.
OpenAITools.imageGeneration(action:) and
AzureOpenAITools.imageGeneration(action:) expose the current hosted image-tool
action alongside background, fidelity, mask, model, output, quality, and size
options.
The generic Open Responses 2.0.28 provider intentionally does not gain this execution surface: provider-defined tools emit an unsupported warning and are dropped, matching upstream behavior.