Foundation Models utilities: 4 context patterns Apple shipped for Swift in 2026

Skills, rolling windows and any-server chat completions, with the KV cache trade-off each one carries.

Read time
17 min
Word count
2.4K
Sections
13
FAQs
8
Share
Swift code panels showing Skills, rolling window and chat completions options in Apple's Foundation Models utilities package
Apple's Foundation Models utilities package adds Skills, history compaction and an any-server chat completions client to Swift.
On this page · 13 sections
  1. What is actually in the package
  2. The problem: transcripts grow, context windows do not
  3. Skills: procedural context loaded only when asked for
  4. ChatCompletionsLanguageModel: one Swift API, any server
  5. Where the utilities sit in the WWDC 2026 model line-up
  6. The error surface you now have to handle
  7. Measure the compaction, do not assume it
  8. The Python SDK closes the evaluation loop
  9. India-specific considerations
  10. An adoption checklist
  11. FAQ
  12. How eCorpIT can help
  13. References

Summary. Apple published apple/foundation-models-utilities under the Apache-2.0 licence, delivering the open-source promise it made at WWDC 2026 on 9 June 2026. The package adds four things the base Foundation Models framework leaves to you: a Skills type that loads task instructions only when the model asks for them, three history-compaction modifiers (rollingWindow, droppingCompletedToolCalls, summarizeHistory), a ChatCompletionsLanguageModel that points a LanguageModelSession at any chat-completions server, and support for Linux distributions such as Ubuntu alongside the Apple platforms. The framework itself now spans 4 model paths in one Swift API: the on-device SystemLanguageModel, PrivateCloudComputeLanguageModel, CoreAILanguageModel for your own weights, and MLXLanguageModel pulling from Hugging Face. Apple made Private Cloud Compute inference free for developers under 2 million first-time App Store downloads, which reframes the build-versus-buy maths against hosted rates such as Claude Opus 5 at $5 and $25 per million input and output tokens as of 24 July 2026. The catch nobody puts on a slide: every one of these compaction tricks can invalidate the key-value cache and add latency, so the pattern you pick is a performance decision, not a tidiness decision.

Session code samples in this article are quoted from Apple's own WWDC 2026 sessions and the package README, not reconstructed.

What is actually in the package

The FoundationModelsUtilities package is a single Swift library target with an Apache-2.0 licence and a Swift Package Manager manifest that resolves from: "1.0.0". Apple describes its scope in the README as "extra utilities for working with LLMs via the Foundation Models framework, such as custom skills, context management helpers, and a chat completions client that connects to a hosted model of your choice."

Three details in that repository matter more than the headline. First, the supported platforms line names "Apple platforms and select Linux distributions like Ubuntu", which puts Apple's session-and-transcript abstractions on a server for the first time. Second, the repository ships a skills/ directory whose stated purpose is to "teach your favorite coding agent how to use this package", so the package documents itself for agentic editors. Third, issue reporting goes to the Apple Developer Forums rather than GitHub issues, which tells you how Apple intends to run it.

Adding it to an existing app is a one-line dependency:


            let package = Package(
    name: "YourApp",
    dependencies: [
        .package(url: "https://github.com/apple/foundation-models-utilities", from: "1.0.0")
    ],
    targets: [
        .target(
            name: "YourApp",
            dependencies: [
                .product(name: "FoundationModelsUtilities", package: "foundation-models-utilities")
            ]
        )
    ]
)
          

The base framework it extends targets .macOS(.v27), .iOS(.v27), .visionOS(.v27) and .watchOS(.v27) in Apple's own model-package template, so this is an iOS 27 era API. Teams still shipping to iOS 26 devices need the fallback path described in our on-device versus cloud AI build guide.

The problem: transcripts grow, context windows do not

A LanguageModelSession keeps a Transcript of entries: instructions, prompts, tool calls, tool outputs and responses. Apple's session 242, "Build agentic app experiences with the Foundation Models framework", spells out what happens next. Transcripts grow past the context limit, stale tool output distracts the model, and private content accumulates in a structure you may not want to keep.

The framework's answer is historyTransform, a stateless per-request transform over the history window. The utilities package turns the common transforms into ready-made modifiers so you stop hand-rolling index arithmetic:


            import FoundationModelsUtilities

struct CraftProfile: LanguageModelSession.DynamicProfile {
    var orchestrator: CraftOrchestrator
    var body: some DynamicProfile {
        switch orchestrator.mode {
        case .reviewing:
            Profile { CraftCoach() }
                // Keep the most recent 10 entries
                // after dropping finished tool calls
                .rollingWindow(size: .entries(10))
                .droppingCompletedToolCalls()
        }
    }
}
          

The README shows all three composed, with summarisation gated behind a token threshold so it only fires when the window is genuinely expensive:


            struct MyProfile: LanguageModelSession.DynamicProfile {
  let status: Status

  var body: some DynamicProfile {
    Profile {
      Instructions("A conversation between a user and a helpful assistant.")
      ToggleDarkModeTool()
    }
    .summarizeHistory(threshold: 5000, model: summarizerModel)
    .rollingWindow(entries: 10)
    .droppingCompletedToolCalls()
  }
}
          

Modifiers apply outside-in: tool calls are dropped first, then the rolling window applies, then summarisation runs only if the 10-entry window still exceeds 5,000 tokens. Apple's guidance is explicit that there is no single correct strategy and that composition is the point.

Compaction strategies compared

Strategy What it removes KV cache impact Best for
droppingCompletedToolCalls() Finished tool call and tool output pairs before the latest response Rewrites earlier entries, so the cached prefix is invalidated Agents that call many tools per turn and never re-read the raw output
rollingWindow(size: .entries(10)) Everything older than the last N entries Invalidates the prefix each time the window slides Long chat sessions with no need for early history
summarizeHistory(threshold: 5000, model:) Old entries, replaced by one generated summary Invalidates the prefix and costs an extra generation call Sessions where early decisions still matter but verbatim text does not
onResponse lifecycle trim Whatever your closure decides, at session boundaries Same invalidation, but you control when it happens Apps that can trim during a natural pause in the UI
Append-only (no compaction) Nothing Cache preserved, latency lowest Short sessions that fit the window comfortably

Apple's own performance chapter in session 242 states the rule plainly: transcript mutations can invalidate key-value caches and raise latency, while appending preserves them. That is the sentence to put in your design review.

Skills: procedural context loaded only when asked for

The second pattern is the one most likely to change how teams structure prompts. A Skill is a named block of instructions that is not in the transcript until the model activates it with a tool call. The README's stated purpose: skills "allow adding extra directions about performing specific tasks into a LanguageModelSession transcript on a just-in-time basis. This prevents context pollution and helps optimize time-to-first-token."


            struct CraftingSkills: LanguageModelSession.DynamicInstructions {
    var activations: SkillActivations
    var body: some DynamicInstructions {
        Skills(activations: activations) {
            Skill(
                name: "origami_folds",
                description: "Details about specific types of folds",
                prompt: """
                    Valley Fold: Paper is folded toward you, creating a V-shaped crease
                    Mountain Fold: Paper is folded away from you, creating an inverted V
                    ...
                    """
            )
            Skill(...)
            Skill(...)
        }
    }
}
          

SkillActivations conforms to Observable and RandomAccessCollection, so the same object that tracks which skills are live can drive a SwiftUI list showing the user what the assistant just pulled in. That is a real product affordance, not only plumbing.

The initialiser you choose changes the cost. A skill created with prompt: lands in the transcript as a matching tool output, which does not invalidate the key-value cache. A skill created with instructions: is inserted at the end of the first instructions entry, where models weight it more heavily, at the cost of a cache invalidation. Instructions-based skills can also be deactivated later if you pass allowsDeactivation: true, which pairs well with droppingCompletedToolCalls() to clear both the content and the activation record.

Skill initialiser Where content lands Model adherence Cache cost Deactivation
prompt: Tool output entry matching the activation call Normal prompt weighting No prefix invalidation Not applicable
instructions: End of the first instructions entry Higher, models are trained to obey instructions Prefix invalidated on activation Optional with allowsDeactivation: true
@PromptBuilder trailing closure Same as prompt: Normal prompt weighting No prefix invalidation Not applicable
No skill, everything in base instructions Always present Highest Paid once at session start None
No skill, injected per prompt Every prompt Normal Grows the prompt every turn None

The engineering judgement here is simple. If a body of guidance applies to one task in twenty, a prompt: skill costs nothing until it is needed. If it applies to every turn, putting it in a skill buys you nothing and adds a tool call.

ChatCompletionsLanguageModel: one Swift API, any server

The third piece is the one that turns Apple's API into a general client. ChatCompletionsLanguageModel talks to any server that implements the chat completions REST API, so a locally served open-weight model and Apple's own on-device model sit behind the same LanguageModelSession:


            let model = ChatCompletionsLanguageModel(
  name: "minimax-m2.5",
  url: URL(string: "http://localhost/v1:8000")!,
)

let session = LanguageModelSession(model: model)

let response = try await session.respond(to: "How many folds does it take to make a paper crane?")

print(response.content)
          

Capabilities are declared, not assumed. Some local servers do not implement guided generation, and you say so at init time:


            let model = ChatCompletionsLanguageModel(
  name: "minimax-m2.5",
  url: URL(string: "http://localhost/v1:8000")!,
  supportsGuidedGeneration: false
)
          

That flag matters because guided generation is how Swift developers get typed output out of the framework, and a server that silently ignores a schema produces a runtime failure that looks like a model quality problem. For the deeper provider story, including how to write your own executor rather than reuse this client, see our walkthrough of the Foundation Models any-LLM provider API.

Where the utilities sit in the WWDC 2026 model line-up

Session 339, "Bring an LLM provider to the Foundation Models framework", shows the swap surface: one line changes which model a session runs against.


            import FoundationModels
import MLXFoundationModels

// On-device Apple Foundation Model
let model = SystemLanguageModel()

// Private Cloud Compute model
// let model = PrivateCloudComputeLanguageModel()

// Custom Core AI model
// let model = try await CoreAILanguageModel(resourcesAt: modelURL)

// Open-source MLX model from HuggingFace
// let model = MLXLanguageModel(modelID: "mlx-community/my-model")

let session = LanguageModelSession(model: model)
let response = try await session.respond(to: "...")
print(response.content)
          

Apple also lists Anthropic and Google partner integrations as upcoming in the same session's introduction chapter. Mike Grabowski, CEO and founder at Callstack, drew the boundary well in his 8 June 2026 write-up of the announcements: "Foundation Models is Apple's model. Core AI is for your model." He added that for app teams "this changes the boundary conditions. A feature can now be evaluated against device class, model availability, latency budget, privacy requirement, and acceptable error rate before it ever becomes a cloud decision."

Model path Where inference runs Marginal token cost Typical use
SystemLanguageModel On device None beyond battery and thermal budget Short generation, extraction, guided output, tool calling
PrivateCloudComputeLanguageModel Apple's Private Cloud Compute Free below 2 million first-time App Store downloads per Apple's WWDC 2026 announcement Longer context and heavier reasoning without a vendor contract
CoreAILanguageModel On device, your weights None beyond device resources Domain classifiers, embeddings, specialised vision models
MLXLanguageModel On device via MLX None beyond device resources Open-weight models pulled from Hugging Face
ChatCompletionsLanguageModel Any chat completions server Whatever the host charges, for example $5 and $25 per million tokens for Claude Opus 5 at its 24 July 2026 launch Frontier models, shared server-side context, existing inference stacks

Our comparison of Claude Opus 5 and GPT-5.6 Sol for coding agents has the wider hosted-price picture if the last row is where your traffic will land.

The error surface you now have to handle

Opening the API to arbitrary providers forced Apple to standardise failures. Session 339 lists 9 built-in cases that any model can throw:


            public enum LanguageModelError: LocalizedError, CustomDebugStringConvertible {
    case contextSizeExceeded(     )
    case rateLimited(     )
    case refusal(     )
    case guardrailViolation(     )
    case unsupportedCapability(     )
    case unsupportedTranscriptContent(     )
    case unsupportedGenerationGuide(     )
    case unsupportedLanguageOrLocale(     )
    case timeout(     )
}
          

contextSizeExceeded is the one this article is about: Apple's own guidance for it is to trim entries and retry, which is exactly what the compaction modifiers automate. rateLimited and timeout only appear once you point a session at a server, so an app that was on-device-only until now needs new UI states before it ships a ChatCompletionsLanguageModel path.

There is a second failure mode worth wiring up at the same time. By default a thrown tool error reverts the transcript. Session 242 introduces transcriptErrorHandlingPolicy with .revertTranscript and .preserveTranscript, and makes Transcript settable so you can repair it, but only while isResponding is false.

Measure the compaction, do not assume it

Compaction has two costs that do not show up in a code review. Latency rises when the cached prefix is thrown away, and accuracy can fall when rewritten history confuses the model about what was already decided. Apple's answer is instrumentation rather than intuition: session 242 points teams at the Foundation Models Instrument in Xcode for latency and the Evaluations framework for quantifying an accuracy change.

A workable measurement plan before you ship any compaction strategy:

  1. Record time-to-first-token and tokens-per-second for a fixed 30-turn scripted session with no compaction, as the baseline.
  1. Re-run the same script with each modifier alone, then in the composed order, and keep the traces.
  1. Score output quality on the same transcripts with the Evaluations framework so a latency win that costs accuracy is visible.
  1. Repeat on the lowest-end supported device, because the on-device path is where cache invalidation hurts most.

Custom executors can help here. Session 339 shows how a provider attaches tokensPerSecond and timeToFirstToken as response metadata, so if you write your own executor the numbers arrive with every response rather than only under a profiler.

The Python SDK closes the evaluation loop

Apple ships a second, separate package for the workflow around all this. apple/python-apple-fm-sdk provides Python bindings to the on-device model on macOS, released under Apache-2.0, with 3 releases published and version 0.1.1 dated 8 March 2026 as the latest at the time of writing. It requires macOS 26.0 or later, Xcode 26.0 or later, Python 3.10 or later, and Apple Intelligence enabled on a compatible Mac. Installation is pip install apple-fm-sdk.

Its first listed capability is the useful one for teams: evaluate Swift Foundation Models app features by running batch inference and analysing results from Python, including transcripts exported from Swift apps. Guided generation carries across with a decorator:


            import apple_fm_sdk as fm

@fm.generable # This decorator signals this type be generated by a model
class Cat:
    name: str
    age:int = fm.guide("Age in years", range=(0, 20))
          

The pairing is deliberate: build the feature in Swift, export the transcript, then run the regression suite in Python where your existing evaluation tooling already lives. WWDC 2026 session 334 covers the same ground alongside an fm command-line tool.

India-specific considerations

Two constraints change the calculus for Indian product teams.

The first is data protection. Under India's Digital Personal Data Protection Act 2023, the safest transcript is the one that never leaves the device. droppingCompletedToolCalls() and rollingWindow are minimisation controls as much as performance controls: tool output containing personal data stops being resident in the session once the modifier drops it. Teams that must keep a server path should treat the summarisation model in summarizeHistory(threshold:model:) as a processor in its own right, because that call sends the old history somewhere to be condensed.

The second is unit economics. On-device and Core AI inference carry no marginal token cost, while a hosted frontier model bills per million tokens, for example the $5 and $25 input and output rates Claude Opus 5 launched with on 24 July 2026. For a price-sensitive consumer app, a chatty feature that runs many short generations per user per day is free on SystemLanguageModel and a recurring line item on a hosted API, and that gap widens with every retained user. The honest counterpoint: the on-device model is small, so quality gating has to happen before the cost saving is real, and Apple's own framing puts Private Cloud Compute in the path when the task needs more capacity or longer context.

Device coverage is the third constraint and it is not solved by any of this. Apple limits its more capable on-device model to higher-end iPhone, iPad and Mac systems, so an Indian user base weighted towards older hardware will exercise the server fallback more often than a US one. Our iOS 27 enterprise fleet readiness guide covers how to work out that split before committing to an architecture.

An adoption checklist

  • Pin the dependency at from: "1.0.0" and read the skills/ directory, since Apple wrote it to brief coding agents on the package.
  • Start with droppingCompletedToolCalls() alone. It is the cheapest win in tool-heavy agents and the easiest to reason about.
  • Add rollingWindow only after you have a measured context-size failure, not in anticipation of one.
  • Treat summarizeHistory as the last resort. It costs a generation call and it is where subtle behaviour regressions appear.
  • Prefer prompt:-based skills unless the model is ignoring the guidance, then move that one skill to instructions: and re-measure.
  • Set transcriptErrorHandlingPolicy explicitly rather than relying on the revert default once tools can fail.
  • If you ship a ChatCompletionsLanguageModel path, handle rateLimited and timeout in the UI before you handle anything else.
  • Declare supportsGuidedGeneration: false for any local server you have not verified, and fail loudly rather than silently.

The real cost is usually the evaluation harness, not the modifiers. The modifiers are three lines.

FAQ

How eCorpIT can help

eCorpIT builds iOS and macOS applications with on-device and hybrid AI features, including transcript design, evaluation harnesses and the device-coverage analysis that decides whether a feature runs locally or falls back to a server path. Our senior engineering teams work under CMMI Level 5 and ISO 27001:2022 practices, and we design applications aligned with DPDP requirements for Indian deployments. If you are planning a Foundation Models feature for iOS 27 and want the latency and accuracy numbers before you commit to an architecture, talk to our iOS engineering team.

References

  1. apple/foundation-models-utilities on GitHub — package README, Apache-2.0 licence, Skills, history modifiers and ChatCompletionsLanguageModel.
  1. Build agentic app experiences with the Foundation Models framework, WWDC26 session 242 — dynamic profiles, history transforms, key-value cache guidance.
  1. Bring an LLM provider to the Foundation Models framework, WWDC26 session 339 — LanguageModel and LanguageModelExecutor protocols, error cases, custom metadata.
  1. What's new in the Foundation Models framework, WWDC26 session 241 — framework changes announced at WWDC 2026.
  1. Build AI-powered scripts with the fm CLI and Python SDK, WWDC26 session 334 — command-line and Python workflow.
  1. Build with the new Apple Foundation Model on Private Cloud Compute, WWDC26 session 319 — the Private Cloud Compute model path.
  1. Composing dynamic sessions with instructions and profiles — Apple documentation for dynamic profiles.
  1. apple/python-apple-fm-sdk on GitHub — Python bindings, requirements, releases and guided generation decorator.
  1. Apple outlines major AI and developer tool updates at 2026 Platforms State of the Union, MacRumors, 9 June 2026 — free Private Cloud Compute access below two million first-time downloads.
  1. On-device AI after WWDC 2026: what's new, Callstack, 8 June 2026 — Mike Grabowski on the Foundation Models and Core AI boundary.
  1. apple/coreai-models on GitHub — Core AI model resources referenced by session 339.
  1. ml-explore/mlx-swift-lm on GitHub — MLX Swift language model package referenced by session 339.
  1. Foundation Models framework documentation — the base API these utilities extend.
  1. Anthropic prices Claude Opus 5 at half of Fable 5, Quartz, 24 July 2026 — hosted token pricing used in the cost comparison.

Last updated: 4 August 2026.

Frequently asked

Quick answers.

01 What is the Foundation Models framework utilities package?
It is an open-source Swift package from Apple, licensed Apache-2.0, that adds context-management helpers, a Skills type for just-in-time instructions, and a chat completions client to the Foundation Models framework. Apple published it after committing at WWDC 2026 to open-source the framework and its companion utilities.
02 Which platforms does the utilities package support?
The README names Apple platforms and select Linux distributions such as Ubuntu. The base framework's own package template targets macOS 27, iOS 27, visionOS 27 and watchOS 27, so in practice this is an iOS 27 era API with a server-side Swift path that did not exist before this package shipped.
03 Does compacting the transcript slow the model down?
Yes, and Apple says so directly. Session 242 states that transcript mutations can invalidate key-value caches and raise latency, while appending preserves them. Every rolling window, dropped tool call and summary rewrite pays that cost, which is why Apple points developers at the Foundation Models Instrument to measure it.
04 What is the difference between a prompt skill and an instructions skill?
A skill built with prompt: is added as a tool output, so it does not invalidate the key-value cache. A skill built with instructions: is inserted into the first instructions entry, where models weight it more heavily but the cache is invalidated. Instructions-based skills can also be deactivated by the model.
05 Can a Swift app call a self-hosted model through Apple's API?
Yes. ChatCompletionsLanguageModel connects a LanguageModelSession to any server implementing the chat completions REST API, with a supportsGuidedGeneration flag for servers that lack structured output. Apple's session 339 also documents writing a full LanguageModelExecutor when you need control over streaming, metadata and caching.
06 How much does Private Cloud Compute inference cost developers?
Apple announced at its 2026 Platforms State of the Union that Foundation Models running on Private Cloud Compute are free for developers with fewer than two million first-time App Store downloads. Hosted alternatives bill per token instead, for example Claude Opus 5 at five dollars and twenty-five dollars per million tokens at launch.
07 Is there a Python route to the on-device model?
Yes. Apple's python-apple-fm-sdk package provides Python bindings for the on-device model on macOS under Apache-2.0. It needs macOS 26 or later, Xcode 26 or later and Python 3.10 or later, and its stated purpose includes batch inference and analysing transcripts exported from Swift apps.
08 Which compaction strategy should a team adopt first?
Start with dropping completed tool calls, because tool output is usually the largest and least reusable part of an agent transcript. Add a rolling window only after a measured context-size failure. Treat history summarisation last, since it costs an extra generation call and is where behaviour regressions surface.

About the author

Manu Shukla

Founder & Director

Founder of eCorpIT. Hands-on engineer leading senior-only delivery for AI apps, custom software, and cloud systems for global clients.

Subscribe

One engineering note a week. No fluff, no spam.

Senior-architect playbooks on AI agents, mobile apps, cloud, security, data, and marketing — delivered every Wednesday.

Past the reading

Read enough. Let's build something.

A senior architect responds in 24 working hours with scope, indicative cost, and a timeline. NDA before any technical conversation.