Skip to content
Ivan Magda
Go back

End-to-End Swift AI: One Language and One API from Device to Server

Suggest Changes

Most AI apps are split down the middle right now: a Swift client on the device, and a Python or TypeScript service in the cloud doing the heavy lifting that the phone can’t hold. That split quietly taxes us — we maintain the prompt logic, the guided-generation schemas, and the tool definitions twice, once per language, and the two copies drift apart one small edit at a time.

WWDC 2026 made that split optional. Apple announced that the Foundation Models framework will be open source later this summer, so the same Swift APIs we call in the app can run on our server too — a complete AI workflow anywhere we deploy Swift (What’s new in the Foundation Models framework, WWDC26). Set that next to how far Swift already reaches off Apple platforms, and the two-language AI stack stops being a default and starts being a choice.

What actually collapses when the model code is one language end to end? Let’s trace it.

The change that unlocks the rest

On their own, each piece is incremental. The framework going open source is interesting; Swift on servers is years old. The payoff is in the overlap.

The framework’s session model is built around a language model protocol — any provider can ship a Swift package that conforms to it, and one LanguageModelSession drives on-device models, Private Cloud Compute, and third-party server models alike (Bring an LLM provider to the Foundation Models framework, WWDC26). Once that framework is open source and runs server-side, this stops being a client-side convenience. The generable type we defined for an on-device feature, the tool we wrote, the prompt we tuned — let’s say they live in a shared package, something like this:

// In a package that both the app target and the Swift server target import.
@Generable
struct Summary {
    @Guide(description: "A one-line title for the note")
    var title: String
    var bullets: [String]
}

struct FetchNotes: Tool {
    let description = "Fetch the person's notes in a date range"

    @Generable
    struct Arguments {
        @Guide(description: "ISO-8601 start date") var from: String
        @Guide(description: "ISO-8601 end date") var to: String
    }

    func call(arguments: Arguments) async throws -> String {
        try await notesStore.fetch(from: arguments.from, to: arguments.to)
    }
}

That @Generable type and that Tool compile and run unchanged in a Swift service — the device target hands them to SystemLanguageModel.default, the server target hands the very same types to a larger model. The line between “what the app does” and “what the backend does” is no longer a language boundary we pay to cross.

Swift earns the move because it already runs in most places we’d deploy. The tooling for server-side Swift is mature, and the language reaches Linux, Windows, Android, and the web through SDKs on Swift.org — including a Swift SDK for WebAssembly and C++ interoperability that folds Swift into systems we already have without a rewrite. The State of the Union pointed at teams already living this: Flighty sharing airport-tracking code between app and backend, GoodNotes reusing over a hundred thousand lines through Swift for WebAssembly to reach the web and Android, Frameo bridging Swift and Java. They proved we can carry one Swift codebase across the stack; open-sourcing Foundation Models extends that proof to the AI layer.

What collapses, concretely

When the model API is one library in one language end to end, a handful of recurring costs disappear:

Apple is applying the same instinct one layer down, in the language itself. Swift keeps moving down the stack on purpose: Foundation went native Swift, the QUIC transport layer was rewritten in Swift and open-sourced through SwiftNIO, security-critical WebKit components are being replaced through C++ interop, and parts of the operating-system kernel are now Swift. The case for one language from firmware to UI is the case for one language from device to model server — fewer seams, fewer translations, fewer places for two implementations to drift (About Swift, Swift.org).

The shape of an end-to-end feature

Put together, an end-to-end Swift AI feature looks like this. We define our generable types and tools in a shared package. The device target runs them against the on-device model or Private Cloud Compute for private, low-latency work. The server target — the very same package — runs them against a larger model for batch jobs, heavy workflows, or work that needs data the device doesn’t have. The agent-building pieces come along too, so the Dynamic Profiles and skills we compose in the app aren’t stranded on the client. One repository, one language, one model API, deployed in two places.

What this subtracts

The value here is subtraction. Open-sourcing one framework isn’t dramatic by itself; what it removes is the translation layer between our app’s intelligence and our backend’s. If we’re maintaining a feature split across Swift and a second language today, the experiment worth running this summer is small: pull the model code into a shared package, point both targets at it, and measure how much of the seam disappears.

One honest caveat before we go — “the same APIs run on the server” is not the same as “the work is done.” We still choose models, budget for cost, and handle server-side concerns the device never had. But doing all of that in one language, against one API, is a very different day than babysitting two stacks. Thanks for reading!


Suggest Changes
Share this post on:

Previous Post
An Agent Framework Hiding Inside a Session: Dynamic Profiles in Foundation Models