Record Foundation Models requests
Trace native responses, structured generation, and multi-turn sessions.
Wrap your existing LanguageModelSession with LedgeLanguageModelSession.
The wrapper returns Apple's original response and records one invocation around
each request. Run the availability check shown in the quickstart
before using the model.
Text response
import FoundationModels
import LedgeKit
@available(iOS 26.0, macOS 26.0, *)
func summarize(_ text: String, client: LedgeClient) async throws -> String {
let session = LedgeLanguageModelSession(
LanguageModelSession(instructions: "Summarize the text in one sentence."),
recordingTo: client,
traceName: "summarize",
agent: .init(name: "summarizer", version: 1)
)
let response = try await session.respond(to: "Summarize: \(text)")
return response.content
}The console records the original request and response. Trimming or parsing the returned string in application code does not change that captured result.
Structured response
@available(iOS 26.0, macOS 26.0, *)
@Generable
struct Summary {
@Guide(description: "A one-sentence summary of the supplied text")
var sentence: String
}
// `session` is the recording adapter created above.
let response = try await session.respond(
to: "Summarize: \(text)",
generating: Summary.self
)
let summary: Summary = response.contentIf the schema changes, increase the agent version used by that implementation.
Other native request forms
The adapter has six respond overloads: String or Prompt input, each with
text output, a Generable type, or a GenerationSchema. Generation options pass
through to the native session. For schema-based requests, includeSchemaInPrompt
defaults to true.
let response = try await session.respond(
to: prompt,
schema: responseSchema,
includeSchemaInPrompt: true,
options: GenerationOptions(temperature: 0.2)
)Here prompt and responseSchema are the native Prompt/String and
GenerationSchema your application constructs. The returned content is native
GeneratedContent.
Multi-turn sessions and tools
Reuse the adapter and native session for subsequent turns. Each call gets a separate invocation while retaining the same captured session ID and increasing call index. Its input includes the prior native history.
Tools configured on the native session remain native tools. Tool calls and their outputs appear in capture. When a tool makes another model request, use explicit child invocation recording.
The wrapper exposes transcript and an async latestInvocationID. It currently
supports respond; it does not expose a traced streaming method.
See the session API reference for initializer choices and request metadata.