Hey,
I am currently working on a new app that requires an AI to have access to tools so that it can iterate by itself, interact with the app’s database and resolve the user’s queries. I’ve been working on implementing something like that for a while but it’s super hard. There’s a lot that needs to be done for this to work and putting it in a nice, easy to use API is even harder.
When Apple announced FoundationModels, I was super stoked because the API and naming schemes they have come up with felt incredibly nice and intuitive. So I decided to build a Swift SDK that feels as close to Apple’s FoundationModels
as possible, while even using some of its types directly, like @Generable
or GeneratedContent
and GenerationSchema
.
It’s called SwiftAgent.
It’s still super early and not ready for any serious use but the basic agent loop including tool calling is already working (using OpenAI as a provider, and only supporting text input/output right now). Using an agent is super simple:
// Create an agent with tools
let agent = Agent<OpenAIProvider>(
tools: [WeatherTool()],
instructions: "You are a helpful assistant."
)
// Run your agent
let response = try await agent.respond(
to: "What's the weather like in San Francisco?",
using: .gpt5
)
print(response.content)
// You can even specify an output type
let response = try await agent.respond(
to: "What's the weather like in San Francisco?",
generating: WeatherReport.self,
using: .gpt5
)
You can define tools just like you would inside FoundationModels
:
struct WeatherTool: AgentTool {
let name = "get_weather"
let description = "Get current weather for a location"
@Generable
struct Arguments {
@Guide(description: "City name")
let city: String
@Guide(description: "Temperature unit", .oneOf(["celsius", "fahrenheit"]))
let unit: String = "celsius"
}
@Generable
struct Output {
let temperature: Double
let condition: String
let humidity: Int
}
func call(arguments: Arguments) async throws -> Output {
// Your weather API implementation
return Output(
temperature: 22.5,
condition: "sunny",
humidity: 65
)
}
}
The agent class is also @Observable
and exposes a transcript
object, which is an enum
very similar to the Transcript
type in FoundationModels
:
// Continue conversations naturally
try await agent.respond(to: "What was my first question?")
// Access conversation history
for entry in agent.transcript.entries {
switch entry {
case .prompt(let prompt):
print("User: \(prompt.content)")
case .response(let response):
print("Agent: \(response.content)")
case .toolCalls(let calls):
print("Tool calls: \(calls.calls.map(\.name))")
// ... handle other entry types
}
}
Right now, I’ve only implemented a configuration where you pass in your api key from app side. That’s obviously not recommended for a production version of any app, but it’s nice to test things. I will add other relay configurations later (to route requests through your own backend, for example). I will need that for my app as well, so it’s kind of high priority once the basic feature set is done.
Even though this project is still in its beginning, I wanted to share it and hear what people think about it I welcome feedback and ideas for future directions for this. Maybe it’ll help some people get started with AI agents easier (it helped me, at least
)
Link to the repository: GitHub - SwiftedMind/SwiftAgent: Native Swift SDK for building autonomous AI agents with Apple's FoundationModels design philosophy
Link to FoundationModels: Foundation Models | Apple Developer Documentation