Swift SDK
The official Swift SDK for ModelRelay. Provides idiomatic Swift patterns with async/await support, strong typing, and Codable integration.
Installation
Swift Package Manager
Add ModelRelay to your Package.swift:
.package(url: "https://github.com/modelrelay/modelrelay-swift", from: "0.3.5"),
Or in Xcode: File > Add Package Dependencies, then enter:
https://github.com/modelrelay/modelrelay-swift
Quick Start
import ModelRelay
let client = try ModelRelayClient.fromAPIKey(ProcessInfo.processInfo.environment["MODELRELAY_API_KEY"]!)
let answer = try await client.responses.text(
model: "claude-sonnet-4-5",
system: "You are a helpful assistant.",
user: "What is the capital of France?"
)
print(answer)
// "The capital of France is Paris."
Convenience API
Ask — Get a Quick Answer
import ModelRelay
let client = try ModelRelayClient.fromAPIKey(ProcessInfo.processInfo.environment["MODELRELAY_API_KEY"]!)
let answer = try await client.ask(model: "claude-sonnet-4-5", prompt: "What is 2 + 2?")
print(answer) // "4"
Configuration
From API Key
import ModelRelay
// From API key string
let client = try ModelRelayClient.fromAPIKey("mr_sk_...")
// With custom base URL
let client = try ModelRelayClient.fromAPIKey(
"mr_sk_...",
baseURL: URL(string: "https://api.modelrelay.ai/api/v1")!
)
Making Requests
ResponseBuilder
The ResponseBuilder provides a fluent API for constructing requests:
let response = try await client.responses.create(
client.responses
.builder()
.model("claude-sonnet-4-5")
.system("You are a helpful assistant.")
.user("What is 2 + 2?")
.maxOutputTokens(256)
.temperature(0.7)
)
print(response.text())
Multi-Turn Conversations
Build conversations with multiple messages:
let response = try await client.responses.create(
client.responses
.builder()
.model("claude-sonnet-4-5")
.system("You are a helpful assistant.")
.user("My name is Alice.")
.assistant("Hello Alice! How can I help you today?")
.user("What's my name?")
)
Customer-Attributed Requests
For metered billing, attribute requests to customers:
let response = try await client.responses.create(
client.responses
.builder()
.model("claude-sonnet-4-5")
.customerId("customer-123")
.system("You are helpful.")
.user("Hello!")
)
Streaming
Stream Events
For real-time response streaming:
let stream = try await client.responses.stream(
client.responses
.builder()
.model("claude-sonnet-4-5")
.user("Write a haiku about programming.")
)
for try await event in stream {
if event.type == .messageDelta, let delta = event.textDelta {
print(delta, terminator: "")
}
}
print()
Structured Output
Parse to Typed Struct
Use Codable structs to parse responses:
import ModelRelay
struct Review: Decodable {
let risk: String
}
let schema: JSONValue = .object([
"type": .string("object"),
"properties": .object([
"risk": .object(["type": .string("string")])
]),
"required": .array([.string("risk")])
])
let review: Review = try await client.responses.object(
model: "claude-sonnet-4-5",
schema: schema,
prompt: "Classify the risk as low/medium/high"
)
print(review.risk)
SQL Tool Loop
The SDK includes helpers for SQL query generation with validation:
let handlers = SQLToolLoopHandlers(
listTables: { [SQLTableInfo(name: "users")] },
describeTable: { _ in SQLTableDescription(table: "users", columns: []) },
sampleRows: { args in
SQLExecuteResult(columns: ["id"], rows: [["id": .number(1)]])
},
executeSQL: { args in
SQLExecuteResult(columns: ["id"], rows: [["id": .number(1)]])
}
)
let result = try await client.sqlToolLoop(
model: "claude-sonnet-4-5",
prompt: "Count users",
handlers: handlers,
profileId: "profile_1",
maxAttempts: 3,
resultLimit: 100
)
print(result.summary)
SQL Tool Loop (Streaming)
let stream = client.sqlToolLoopStream(
model: "claude-sonnet-4-5",
prompt: "List recent users",
handlers: handlers,
profileId: "profile_1"
)
for try await event in stream {
switch event {
case .summaryDelta(let delta):
print(delta, terminator: "")
case .executeSQL(let exec):
print("Rows:", exec.result.rows.count)
case .result(let result):
print("Final SQL:", result.sql)
default:
break
}
}
Customer-Scoped Requests
Create a customer-scoped client for attributed requests:
let customer = try client.forCustomer("customer-123")
let text = try await customer.responses.text(
model: "claude-sonnet-4-5",
user: "Say hi"
)
print(text)
Customer Token Provider
For frontend use with minted tokens:
let provider = try CustomerTokenProvider(CustomerTokenProviderConfig(
secretKey: "mr_sk_...",
request: CustomerTokenRequest(customerExternalId: "customer-123")
))
let tokenClient = try ModelRelayClient.fromTokenProvider(provider)
let text = try await tokenClient.responses.text(
model: "claude-sonnet-4-5",
user: "Hi"
)
Workflows + Runs
let spec: JSONValue = .object([
"version": .string("v1"),
"nodes": .array([])
])
let compile = try await client.workflows.compile(spec: spec)
if case .success(_, let planHash) = compile {
let run = try await client.runs.createFromPlan(planHash: planHash)
print(run.runId)
}
Platform Support
| Platform | Minimum Version |
|---|---|
| macOS | 13.0 |
| iOS | 16.0 |
| tvOS | 16.0 |
| watchOS | 9.0 |
Next Steps
- First Request - Make your first API call
- Streaming - Real-time response streaming
- Tool Use - Let models call functions
- Structured Output - Get typed JSON responses