LedgeKitDocs
Developer documentation

Record your first request

Add the Swift SDK, trace a Foundation Models response, and inspect it in LedgeKit.

This example records one request to Apple's on-device Foundation Models model. You need an eligible device with Apple Intelligence available, an iOS/macOS 26 destination, and access to a LedgeKit workspace.

1. Add the package

In Xcode, choose File → Add Package Dependencies and enter:

https://github.com/noahtovares/ledgekit-ios

Choose Commit and use 2102e4dd6951d04c2aca7b364f56d0eaac4576f9, the SDK revision these examples target. Link the LedgeKit product to your app target. See installation for Swift Package Manager and repository access.

2. Create an app and test write key

Open the console, choose your workspace, and create an app. Use my-app as its service name for this example. In that app's Test environment, open Keys and create a write key. Copy the token when it is shown; the console does not display the complete token again.

The key chooses the app and environment. serviceName must match that app. Read keys cannot upload traces. Keep the key out of source control and supply it through your local development configuration.

3. Record a summary

FirstTrace.swift
import Foundation
import FoundationModels
import LedgeKit

enum SummaryError: Error { case modelUnavailable }

@available(iOS 26.0, macOS 26.0, *)
func recordSummary(apiKey: String) async throws -> String {
    guard SystemLanguageModel.default.availability == .available else {
        throw SummaryError.modelUnavailable
    }

    let client = LedgeClient(
        configuration: .init(serviceName: "my-app"),
        transport: LedgeHTTPTransport(apiKey: apiKey)
    )
    await client.start()

    let native = LanguageModelSession(
        instructions: "Summarize the supplied text in one sentence."
    )
    let session = LedgeLanguageModelSession(
        native,
        recordingTo: client,
        traceName: "summarize",
        agent: .init(name: "summarizer", version: 1)
    )
    let text = "A durable outbox saves requests locally before uploading them."
    let response = try await session.respond(
        to: "Summarize: \(text)",
        inputData: .object(["text": .string(text)])
    )

    // Useful for this one-shot example; normal uploads run asynchronously.
    await client.flush()
    return response.content
}

Call try await recordSummary(apiKey: testWriteKey) from an async task and handle the returned string or thrown error in your UI. The recordingTo: adapter owns the run and finalizes it when the request succeeds, fails, or is cancelled.

Your app receives Apple's original response. In an app with repeated requests, keep one client at application scope; see configuration.

4. Find the trace

Return to the same app's Test environment and open Traces. Select the summarize trace and its summarizer invocation. You should see the model input, response, agent version, timing, and the original text under Input data.

flush() waits for pending upload attempts; it does not guarantee successful delivery. If the trace is missing, check the app, environment, write-key access, network connectivity, and delivery diagnostics.

Continue

On this page