Skip to content

Custom Tools

Conform to ToolProvider directly to expose any Swift function as a callable tool. The protocol has two requirements: listTools (declare what exists) and call (execute by name).

For a full explanation of AgentTool, ToolResult, ToolVisibility, and JSONValue, see Tools Overview.

The minimal pattern — one struct, one tool:

import AgentSquad
struct WeatherToolProvider: ToolProvider {
func listTools() async throws -> [AgentTool] {
[
AgentTool(
name: "get_weather",
description: "Returns current weather for a city.",
inputSchema: [
"type": "object",
"properties": [
"city": ["type": "string", "description": "City name"]
],
"required": ["city"]
]
)
]
}
func call(_ name: String, arguments: JSONValue) async throws -> ToolResult {
guard name == "get_weather" else {
return .failure("Unknown tool: \(name)")
}
guard case .string(let city) = arguments["city"] else {
return .failure("Missing required argument: city")
}
// ... call your API ...
let summary = "Sunny, 22 °C"
return ToolResult(
content: [.text(summary)],
structuredContent: ["city": .string(city), "summary": .string(summary)]
)
}
}

Pass the provider when constructing an agent — see Agents Overview.

You don’t need to hand-write a composite — AggregateToolProvider is built in. It fans out listTools in parallel, deduplicates by name (first-wins), and routes each call to the owning provider:

let tools = AggregateToolProvider([
myCustomProvider,
ToolKit([localTool, apiTool]),
MCPServer(url: "https://mcp/sse"),
])

Use ToolVisibility to restrict who can invoke a tool:

AgentTool(
name: "internal_audit_log",
description: "Records an audit event.",
visibility: .app // never offered to the model; only callable by host code
)
ValueEffect
.modelLLM may call it; host code may not
.appHost code may call it; never offered to the LLM
.allBoth (default)

MCP-backed tools arrive as a ToolProvider (MCPServer) from the AgentSquadMCP module. Combine them with your native tools using AggregateToolProvider:

let tools = AggregateToolProvider([
nativeProvider, // your custom ToolProvider
MCPServer(url: "https://mcp/sse"), // from AgentSquadMCP
])

See MCP servers for session setup. To plug a different MCP SDK or transport, conform your own type to MCPClient — see Custom MCP client.