# Apple's Foundation Models

Use Nur as the model behind a LanguageModelSession on Apple platforms 27, with Apple's chat completions model.

Apple's Foundation Models framework runs a `LanguageModelSession` on any model
that conforms to its `LanguageModel` protocol. Apple's open source
[Foundation Models utilities](https://github.com/apple/foundation-models-utilities)
include `ChatCompletionsLanguageModel`, which talks to any chat completions
endpoint. Point it at EESI and the same session code runs on Nur: plain
answers, streaming, tool calling, guided generation and pictures.

It needs macOS, iOS, visionOS or watchOS 27, or Linux for server-side Swift.

## Add the package

In Xcode, choose File › Add Package Dependencies and enter
`https://github.com/apple/foundation-models-utilities`. In `Package.swift`:

```swift
.package(url: "https://github.com/apple/foundation-models-utilities", from: "1.0.0")
```

and add `.product(name: "FoundationModelsUtilities", package: "foundation-models-utilities")`
to your target's dependencies.

## Ask Nur

```swift
import FoundationModels
import FoundationModelsUtilities

let nur = ChatCompletionsLanguageModel(
    name: "nur-v1",
    url: URL(string: "https://api.eesi.ai")!,
    additionalHeaders: ["Authorization": "Bearer \(apiKey)"]
)

let session = LanguageModelSession(
    model: nur,
    instructions: "You help people plan their week. Answer in a few sentences."
)
let reply = try await session.respond(to: "What should I do first on Monday?")
print(reply.content)
```

The model appends `/v1/chat/completions` to the URL. Replies stream back
through the session as they are written, so `streamResponse(to:)` works too.

## Guided generation

Ask for a Swift type and Nur answers with exactly that shape:

```swift
@Generable
struct Trip {
    @Guide(description: "A short, memorable name for the trip")
    var name: String
    @Guide(description: "How many days it lasts")
    var days: Int
}

let trip = try await session.respond(
    to: "Plan a short trip to Paris.",
    generating: Trip.self
)
print(trip.content.name, trip.content.days)
```

## Tools

Tools work the way they do with Apple's own models. Nur decides when to call
one, the session runs it, and Nur answers from what it returned:

```swift
struct GetWeather: Tool {
    let name = "getWeather"
    let description = "The current weather in a city."

    @Generable
    struct Arguments {
        @Guide(description: "The city, like Cairo or Lisbon")
        var city: String
    }

    func call(arguments: Arguments) async throws -> String {
        try await weatherService.summary(for: arguments.city)
    }
}

let session = LanguageModelSession(model: nur, tools: [GetWeather()])
let reply = try await session.respond(to: "Do I need an umbrella in Cairo today?")
```

## Keep the key safe

An API key in an app's binary can be read by anyone who has the app. Ship it
only in code you run yourself, such as server-side Swift, a command line tool
or an internal app. For an app in people's hands, keep the key on your server
and have the app talk to your server, or set `url` to your own server and add
the `Authorization` header there.

## Pictures and errors

Nur sees pictures too: an image in the session's transcript reaches her with
the words. Errors come back as the session's errors, with the API's own
message: a `429` is [too many requests or no credits left](/develop/authentication#errors),
and the session can retry after a moment.
