<!--
{
  "availability" : [
    "iOS: 27.0.0 -",
    "iPadOS: 27.0.0 -",
    "macCatalyst: 27.0.0 -",
    "macOS: 27.0.0 -",
    "visionOS: 27.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "CoreSpotlight",
  "identifier" : "/documentation/CoreSpotlight/CustomStage",
  "metadataVersion" : "0.1.0",
  "role" : "Protocol",
  "symbol" : {
    "kind" : "Protocol",
    "modules" : [
      "Core Spotlight",
      "FoundationModels"
    ],
    "preciseIdentifier" : "s:31_CoreSpotlight_FoundationModels11CustomStageP"
  },
  "title" : "CustomStage"
}
-->

# CustomStage

A custom processing stage the Spotlight search tool uses to identify search results.

```
protocol CustomStage : Generable, Decodable, Encodable, Sendable
```

## Overview

A custom stage is a generable type that implements app-specific data transformations for queries. When using
Foundation Models, you can use the Spotlight search tool to find app-specific content related to a prompt. The
model uses the Spotlight search tool to create queries, each of which might involve require several steps to deliver
the final results. For example, a query might fetch items from your app’s Spotlight index, count the number of items
it fetched, and assign relevance scores to each item. Each of these steps is a *stage* in the query pipeline, and
a custom stage lets you integrate your app’s custom transformations.

Define custom stages as a generable type, and implement your stage’s behavior using the properties and methods
of this protocol. A custom stage includes static properties that the model uses to assess how to apply the stage
to queries. It also includes `execute` methods to perform the actual data transformations. Each execute method
takes one of the input types your stage supports and delivers the specified output type.

The following example shows an implementation of this type that accepts Spotlight searchable items as input and
produces scored items as output. The `execute` method in the implementation uses a custom `SentimentAnalyzer`
type to calculate the score for each item, based on whether its content conveys a positive, negative, or neutral tone.
The example also includes an extension with a static `sentiment` function, which simplifies the creation of the custom stage later.

```swift
@Generable
struct SentimentStage: CustomStage {
    static var name: String { "sentiment" }
    static var description: String { "Scores search results by sentiment.” }
    static var inputTypes: [SearchPipelineDataType] { [.items] }
    static var outputType: SearchPipelineDataType { .scoredItems }

    @Guide(description: “The sentiment to consider when scoring the text of a search result.”)
    var mode: String

    func execute(items: [SearchableItem]) async throws -> SearchPipelineData {
        let scored = items.map { item in
            ScoredSearchableItem(item: item,
                                   score: SentimentAnalyzer.score(item, mode: mode))
        }
        return .scoredItems(scored)
    }
}

extension CustomStage where Self == SentimentStage {
     static func sentiment(mode: String = "all") -> Self {
         SentimentStage(mode: mode)
     }
}
```

To make your custom stage available to a model, include it in the configuration of the Spotlight search tool you associate with
your Foundation model’s session. The following example configures the Spotlight search tool with two separate instances of
the sentiment stage from the previous example. The first instance scores items across all sentiments while the second instance
scores items only on the positivity scale.

```
let tool = SpotlightSearchTool(configuration: .init(
      customStages: [.sentiment(), .sentiment(mode: "positive")]
))
```

The model builds tool pipelines dynamically, and can run multiple stages in parallel, so implement custom stage types to run
independently. Treat the input data your stage receives as immutable, and don’t consider the state or contents of other stages
when making decisions. If you do require additional data to generate results, make sure you access the data in a deterministic way.

## Topics

### Getting the stage metadata

[`static var name: String`](/documentation/CoreSpotlight/CustomStage/name)

The name of the stage as you want it to appear in the pipeline.

[`static var description: String`](/documentation/CoreSpotlight/CustomStage/description)

A human-readable description of what this stage does.

[`static var inputTypes: [SearchPipelineDataType]`](/documentation/CoreSpotlight/CustomStage/inputTypes)

The data types this stage accepts as input.

[`static var outputType: SearchPipelineDataType`](/documentation/CoreSpotlight/CustomStage/outputType)

The data type this stage produces as output.

### Performing the stage behavior

[`func execute(items: [SearchableItem]) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(items:))

Generates output data from an array of searchable items from the app’s Spotlight index.

[`func execute(scoredItems: [ScoredSearchableItem]) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(scoredItems:))

Generates output data from an array of scored searchable items.

[`func execute(text: String) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(text:))

Generates output data from the specified input string.

[`func execute(count: Int) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(count:))

Generates output data from the specified count value.

[`func execute(groupedItems: [SearchableItemAttribute : [SearchableItem]]) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(groupedItems:))

Generates output data from the specified dictionary of attributes and searchable items.

[`func execute(table: SearchResultsTable) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(table:))

Generates output data from the specified tabular data.

### Instance Methods

[`func execute(statistic: String, value: Double) async throws -> SearchPipelineData`](/documentation/CoreSpotlight/CustomStage/execute(statistic:value:))

Generates output data from the specified statistical value.

## Relationships

### Inherits From

[`Decodable`](/documentation/Swift/Decodable)

[`Encodable`](/documentation/Swift/Encodable)

[`ConvertibleFromGeneratedContent`](/documentation/FoundationModels/ConvertibleFromGeneratedContent)

[`InstructionsRepresentable`](/documentation/FoundationModels/InstructionsRepresentable)

[`Sendable`](/documentation/Swift/Sendable)

[`ConvertibleToGeneratedContent`](/documentation/FoundationModels/ConvertibleToGeneratedContent)

[`Generable`](/documentation/FoundationModels/Generable)

[`PromptRepresentable`](/documentation/FoundationModels/PromptRepresentable)

[`SendableMetatype`](/documentation/Swift/SendableMetatype)

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)