Foundation Models Use Cases: When To Specialize And When To Just Prompt

The on-device model in Foundation Models is not a single thing. Apple ships a default SystemLanguageModel for general prompting and one Apple-managed specialization for content tagging.1 The framework also lets developers train and load their own adapters.2 Three rails, one decision tree, and a documentation page that names exactly two UseCase values.

The earlier post on the Tool protocol covered how to make the default model do useful work. The question this post answers is the next one: when does the default with prompting and tools suffice, and when does Apple’s .contentTagging use case earn its slot? The custom-adapter path is a separate post; the developer-managed lifecycle has too much surface area to share with the decision rubric.

TL;DR

  • SystemLanguageModel.UseCase is a struct with two static properties: .general and .contentTagging.3 No other use cases are documented.
  • .general is the default. Reach for it first. Prompting, instructions, guided generation, and tool calling all live on top of .general; specialization is the last lever to pull.
  • .contentTagging is purpose-built for one job: identify topics, actions, objects, and emotions in input text and return one-to-a-few-word lowercase tags.4 Apple’s own guide tells you when to use .general instead.
  • The third rail (custom adapters, the Adapter type, the entitlement, the toolkit) is where the operational complexity lives. Different post.

What SystemLanguageModel Actually Is

SystemLanguageModel is a final class in the FoundationModels framework, available on iOS 26.0+, iPadOS 26.0+, Mac Catalyst 26.0+, macOS 26.0+, and visionOS 26.0+.1 Apple describes it as “an on-device large language model capable of text generation tasks.”

Two facts shape how to use it. First, SystemLanguageModel.default returns the base version of the model.1 That’s the entry point for everything not specialized. Second, Apple updates the model in OS updates: as of writing, Apple’s documentation lists two model versions, one for iOS, iPadOS, macOS, and visionOS 26.0–26.3 and another for 26.4.1 Apps don’t pin a specific version; the framework returns whichever model the OS is currently running.

Availability is checked at runtime. SystemLanguageModel.availability is an Availability enum with the following cases as documented in Apple’s sample code:1

struct GenerativeView: View {
    private var model = SystemLanguageModel.default

    var body: some View {
        switch model.availability {
        case .available:
            // Show your intelligence UI.
        case .unavailable(.deviceNotEligible):
            // Show an alternative UI.
        case .unavailable(.appleIntelligenceNotEnabled):
            // Ask the person to turn on Apple Intelligence.
        case .unavailable(.modelNotReady):
            // The model isn't ready because it's downloading or because
            // of other system reasons.
        case .unavailable(let other):
            // The model is unavailable for an unknown reason.
        }
    }
}

isAvailable is a convenience getter that returns true only when the system is entirely ready.1 Always check before you call.

The First Rail: Prompt The General Model

Apple frames the default model as the right tool for a wide spread of tasks. The framework’s general guide enumerates capabilities Apple says the on-device model handles well:4

Capability Example prompt
Summarize “Summarize this article.”
Extract entities “List the people and places mentioned in this text.”
Understand text “What happens to the dog in this story?”
Refine or edit text “Change this story to be in second person.”
Classify or judge text “Is this text relevant to the topic ‘Swift’?”
Compose creative writing “Generate a short bedtime story about a fox.”
Generate tags from text “Provide two tags that describe the main topics of this text.”
Generate game dialog “Respond in the voice of a friendly inn keeper.”

Apple is also explicit about what the on-device model is not for:4

Avoid Example
Basic math “How many b’s are there in bagel?”
Code generation “Generate a Swift navigation list.”
Logical reasoning “If I’m at Apple Park facing Canada, what direction is Texas?”

Note that “generate tags from text” appears in the good-at table for the general model. That’s important context for the specialization decision below.

The default rail has the full toolkit available: instructions, prompts, guided generation via Generable, tool calling via the Tool protocol, generation options like temperature. Most apps that adopt Foundation Models will live on this rail and never touch a use case specifier.

The context window is 4,096 tokens for the system model.4 Apple notes that a token corresponds to three or four characters in languages like English, Spanish, or German, and one token per character in languages like Japanese, Chinese, or Korean. The instructions, prompts, and outputs all count toward the limit. When a session exceeds it, the framework throws LanguageModelSession.GenerationError.exceededContextWindowSize(_:).4

The Second Rail: .contentTagging

SystemLanguageModel.UseCase is documented as a struct (not an enum) with two static properties:3

static let general: SystemLanguageModel.UseCase
static let contentTagging: SystemLanguageModel.UseCase

There are no other documented cases. If a writeup names a third use case, the writeup is making it up.

.contentTagging is a different shape from .general. Apple’s guide describes the contentTagging model as one that “identifies topics, actions, objects, and emotions in input text” and produces tags as “one to a few lowercase words.”5 The model is built to evaluate input rather than respond conversationally: “It isn’t a typical language model that responds to a query from a person: instead, it evaluates and groups the input you provide.”5

Loading the model with .contentTagging:

let model = SystemLanguageModel(useCase: .contentTagging)
let session = LanguageModelSession(
    model: model,
    instructions: """
        Provide the two tags that are most significant in the context of topics.
        """
)

The documented convenience initializer is init(useCase:guardrails:).1 Apple’s sample code calls it without the guardrails argument, which suggests guardrails carries a default value at the call site.

The contentTagging model integrates with Generable, so you can define a Swift type that captures the shape of tags you want:

@Generable
struct ContentTaggingResult {
    @Guide(
        description: "Most important actions in the input text.",
        .maximumCount(2)
    )
    let actions: [String]

    @Guide(
        description: "Most important emotions in the input text.",
        .maximumCount(3)
    )
    let emotions: [String]

    @Guide(
        description: "Most important objects in the input text.",
        .maximumCount(5)
    )
    let objects: [String]

    @Guide(
        description: "Most important topics in the input text.",
        .maximumCount(2)
    )
    let topics: [String]
}

let response = try await session.respond(
    to: prompt,
    generating: ContentTaggingResult.self
)

Apple’s guide includes a useful behavioral note: “For very short input queries, topic and emotion tagging instructions provide the best results. Actions or object lists will be too specific, and may repeat the words in the query.”5 The contentTagging model also “respects the output format you want, even in the absence of instructions”, so the Generable shape carries more weight than a verbose system prompt would.

The Decision Tree (Apple’s Own Words)

The interesting part of the use-case API is that Apple’s documentation is explicit about when not to specialize. From the contentTagging guide:5

  1. “If you’re tagging content that’s not an action, object, emotion, or topic, use general instead.”
  2. “Use the general model to generate content like hashtags for social media posts.”
  3. “If you adopt the tool calling API, and want to generate tags, use general and pass the Tool output to the content tagging model.”
  4. “If you have a complex set of constraints on tagging that are more complicated than the maximum count support of the tagging model, use general instead.”

Read those four together. The contentTagging model is narrowly scoped: topics, actions, objects, emotions. Everything else (hashtag generation, tag pipelines that involve tool calls, tag output with constraints richer than maximumCount) belongs on the general model.

The pragmatic decision rubric for an app that thinks it wants tagging:

Default to .general. It handles the broad range of generation tasks Apple’s table describes, including “generate tags from text.” Most apps stop here.

Reach for .contentTagging only when the input is text-shaped, the output is a small set of single-or-few-word tags falling cleanly into Apple’s four categories (topics/actions/objects/emotions), and the constraints fit maximumCount. The example Apple gives is the pattern: a social app that wants per-post tags to drive a topic dashboard, an email client that wants autolabeling, a content store that wants aggregate trend signals.

Defer to a custom adapter only when neither rail fits and the use case is high-value enough to absorb the operational cost of training and shipping an adapter tied to a specific system model version. The custom-adapter path is documented separately; the lifecycle complexity (toolkit version, retraining cycle, distribution) deserves its own treatment.

What Apple Has Not Published

A few things you’ll see speculated about that are not in the documented surface:

  • The mechanism Apple uses to specialize the model for .contentTagging. Apple’s contentTagging guide describes the framework as providing “an adapted on-device system language model that specializes in content tagging.”5 Apple does not publish the specialization mechanism, and the verb “adapted” in that sentence should not be confused with the developer-managed SystemLanguageModel.Adapter type, which is a separate rail.
  • Other use case values. The struct has two static properties as of the current documentation; any third case would need to ship in a future OS update.
  • A guarantee that .general and .contentTagging will always co-exist. Apple says “Apple will periodically update SystemLanguageModel in routine OS updates to improve the on-device model’s abilities and performance.”1 Treat the surface as versioned.
  • Specific quality numbers for .contentTagging versus .general on tagging benchmarks. Apple frames the choice as fit-for-task, not as a quality leaderboard.

If a post (this one or any other) makes a quantitative claim about adapter mechanics that isn’t on developer.apple.com, treat the claim as wrong by default.

What The Two Rails Actually Buy You

The second rail is not “the model gets better.” It’s “the model is built for one job and Apple has documented when to pick it.” That changes the economics:

  1. Lower prompt-engineering surface for tagging tasks. The contentTagging model “respects the output format you want, even in the absence of instructions.”5 You can lean on @Generable and maximumCount instead of a multi-paragraph prompt that the general model would need.
  2. Constrained semantic shape. The model finds similarity across input terms and produces semantically consistent tags (Apple’s example: “greet” emerges as the topic tag for “hi”, “hello”, “yo”).5 That’s exactly what aggregate analytics over user-generated content needs.
  3. A documented decision rubric. Apple tells you when their specialization fits and when to fall back. That rubric is the most valuable part of the use-case API: it’s an opinionated answer to a question app developers would otherwise litigate from first principles.

The cost is also clear: .contentTagging is bound to one task shape. Anything outside that shape goes back to .general and lives or dies on prompt and Generable design.

Takeaways

  1. Two rails today, possibly more later. .general and .contentTagging are the only two UseCase static properties Apple has documented. Don’t write code that assumes others.
  2. Default to .general. Prompting + tools + guided generation handles most use cases the on-device model is designed for. Specialization is the last lever, not the first.
  3. Pick .contentTagging only when Apple’s documented shape fits. Topics, actions, objects, emotions. One-to-a-few-word lowercase tags. maximumCount-level constraints. Anything more, fall back.
  4. Read Apple’s “use general instead” rules. They’re four concrete sentences in the contentTagging guide.5 Each one is a real boundary.
  5. The custom-adapter path is a separate decision. Different surface area, different lifecycle, different post.

The full Apple Ecosystem cluster: the on-device LLM and Tool protocol for the framework’s primitives; the agentic workflow split between in-app and developer-tooling LLMs; App Intents vs MCP for the routing question across all three. The hub is at the Apple Ecosystem Series. For broader iOS-with-AI-agents context, see the iOS Agent Development guide.

FAQ

How many SystemLanguageModel.UseCase values are there?

Two static properties as currently documented: .general and .contentTagging.3 If you see a third value referenced in a tutorial or an LLM-generated answer, verify it against developer.apple.com before adopting it.

When should I use .contentTagging instead of just prompting .general?

Use .contentTagging when the task is identifying topics, actions, objects, or emotions in input text and returning short lowercase tags. Apple’s guide lists four scenarios where .general is the right answer instead: tagging that doesn’t fit those four categories, hashtag generation, tag pipelines that route through tool calls, and tagging constraints richer than maximumCount.5

Does the contentTagging model accept arbitrary instructions like the general model does?

It accepts instructions, but the model’s design is to evaluate input rather than respond to user-style queries. Apple’s guide notes that the contentTagging model “respects the output format you want, even in the absence of instructions”, so a @Generable shape with @Guide annotations carries the constraint, not a long prompt.5

What’s the context window for the on-device model?

4,096 tokens for the system model.4 Token-to-character ratio is roughly three to four characters per token in English/Spanish/German and one token per character in Japanese/Chinese/Korean. The framework throws LanguageModelSession.GenerationError.exceededContextWindowSize(_:) when the session exceeds the limit.

Why does Apple’s sample code call SystemLanguageModel(useCase:) without guardrails:?

The documented convenience initializer is init(useCase:guardrails:).1 Apple’s contentTagging guide calls it without the guardrails argument, which suggests guardrails carries a default value at the call site. The two-argument form is the documented surface; the one-argument form is what Apple’s published sample code shows.

References


  1. Apple Developer, “SystemLanguageModel”. The class declaration, availability annotations, model versions, .default property, Availability enum cases, and the init(useCase:guardrails:) convenience initializer. Retrieved 2026-05-04. 

  2. Apple Developer, “Loading and using a custom adapter with Foundation Models” and the com.apple.developer.foundation-model-adapter entitlement. The custom-adapter rail is covered in a follow-up post on the developer-managed lifecycle. 

  3. Apple Developer, “SystemLanguageModel.UseCase”. The struct’s static properties: static let general and static let contentTagging. Retrieved 2026-05-04. 

  4. Apple Developer, “Generating content and performing tasks with Foundation Models”. Capability tables, context window size, error type. Retrieved 2026-05-04. 

  5. Apple Developer, “Categorizing and organizing data with content tags”. Behavioral description of the contentTagging model, sample code, and the four explicit “use general instead” rules. Retrieved 2026-05-04. 

Related Posts

Foundation Models On-Device LLM: The Tool Protocol

iOS 26's Foundation Models framework puts a 3B-parameter LLM on every Apple Intelligence device. The Tool protocol is th…

15 min read

When The LLM Lives In Your App Vs In Your Tooling

Two LLMs touch a Swift app. The on-device model that ships with the app and the agent that wrote the code. Different sta…

17 min read

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 min read