<!--
{
  "documentType" : "article",
  "framework" : "AppIntents",
  "identifier" : "/documentation/AppIntents/defining-app-entities-for-your-custom-data-types",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Defining app entities for your custom data types"
}
-->

# Defining app entities for your custom data types

Provide the system with information about the types your app uses to model its
data so that your intents can use those types as parameters.

## Overview

People create, manage, and view their data primarily using your app’s interface, but sometimes they might want to
access that data from outside your app. System features like Siri make it possible for people to perform actions
using your app and interact with your app’s data. However, those features interact only with the data you provide
using app entities.

An *app entity* is a type that adopts the [`AppEntity`](/documentation/AppIntents/AppEntity) protocol and reflects a portion of your app’s data. Typically,
you define app entity types only for the subset of data people are likely to use outside your app. For example, an
email app might define an app entity type for email messages and a separate type for mailboxes. Someone interacting
with the app using Siri can instruct it to create emails, read incoming messages, or move them to a particular mailbox.

In your code, include app entities in places where the system can use them. In app intents, include entities as
parameters when an action requires your app’s custom data. In your app’s Spotlight indexes, include entities
alongside the rest of your data so Spotlight has a way to navigate to that data from search results. Indexing
your content also makes your entities discoverable by Apple Intelligence and Siri, which can use the data to process
requests involving your content. You can also suggest entities to the system and make your content more visible in
relevant system interfaces.

### Create the initial code for your app entity type

When defining your app’s entities, you need to determine whether the underlying data is well-known to the system
or specific to your app. The system is already familiar with many types of well-known data, such as photos, mail,
books, files, and more. To promote consistency, the App Intents framework defines schemas that specify the properties
to include in entities for these types. Supporting a schema makes it easier for Apple Intelligence to reason over
your content and provide consistent responses. If your data doesn’t align with a particular schema, you can still
define custom app entities that contain any data you want.

To define an app entity type, create a structure that conforms to the [`AppEntity`](/documentation/AppIntents/AppEntity) or [`IndexedEntity`](/documentation/AppIntents/IndexedEntity) type and
add it to your app. For schema-based entities, precede your type declaration with the `@AppEntity` macro and
specify the schema name as a parameter. In your type, add variables for the data your entity manages. The following
example creates an entity for a photo album and adds the required properties for that schema. You provide the
album type information using an [`AppEnum`](/documentation/AppIntents/AppEnum) that conforms to the [`albumType`](/documentation/AppIntents/AppSchema/PhotosEnum/albumType) schema.

```swift
@AppEntity(schema: .photos.album)
struct PhotoAlbumEntity: AppEntity {

    // Properties from the schema.
    var name: String
    var creationDate: Date?
    var albumType: MyPhotoAlbumType
}
```

> Note: To define a custom app entity, create your structure in the same way as above, but omit the `@AppEntity` macro and
> schema information. Reserve custom entity types for data that doesn’t have a schema-based equivalent.

Although you use entities to reflect your app’s underlying data, you don’t have to reflect all of that data. When
you define an entity, you can choose whether to create a standalone structure or add the [`AppEntity`](/documentation/AppIntents/AppEntity) protocol to
one of your app’s existing data types. A standalone structure provides more flexibility to include only a subset
of the data that makes sense. It also offers a cleaner separation between your app’s data structures and the rest
of the system. The only time it makes sense to integrate the [`AppEntity`](/documentation/AppIntents/AppEntity) protocol into one of your existing types
is when that type is lightweight and you can create new instances of it quickly. For most other types, it’s better
to create a separate entity structure and cache existing data values in it.

The [`IndexedEntity`](/documentation/AppIntents/IndexedEntity) type makes it possible to include your entities in your app’s Spotlight index. Apps use the
<doc://com.apple.documentation/documentation/CoreSpotlight> framework to build a fast, searchable index of their content.
Including entities in your app’s index provides a better experience with system search features. It also makes those
entities available to Apple Intelligence. For more information about adding this support, see [Making app entities available in Spotlight](/documentation/AppIntents/making-app-entities-available-in-spotlight).

### Provide a unique identifier for your type

A requirement for all app entities is that they provide a unique identifier to distinguish one instance from another.
Whether you have only one entity or tens of thousands, a unique identifier helps you differentiate entities of the
same type. When the system needs a specific entity, it provides you with the identifier and expects you to return
the matching entity instance.

The [`AppEntity`](/documentation/AppIntents/AppEntity) already conforms to the <doc://com.apple.documentation/documentation/Swift/Identifiable> protocol,
so you need to implement the <doc://com.apple.documentation/documentation/Swift/Identifiable/id-8t2ws> property from
this protocol to define your unique identifier. Set the type of this property to <doc://com.apple.documentation/documentation/Foundation/UUID>,
<doc://com.apple.documentation/documentation/Swift/String>, or <doc://com.apple.documentation/documentation/Swift/Int>
type whenever possible. The App Intents framework contains built-in support for identifying entities using these types,
so using them is the simplest way to implement your entity. The following example shows an entity that uses a
unique identifier for its `id` property.

```swift
@AppEntity(schema: .photos.album)
struct PhotoAlbumEntity: AppEntity {
    let id: UUID

    // Properties from the schema.
    var name: String
    var creationDate: Date?
    var albumType: MyPhotoAlbumType
}
```

The <doc://com.apple.documentation/documentation/Swift/Identifiable> protocol requires each entity instance to have a
unique identifier value, but enforces that uniqueness only on the current device. If your app runs on multiple devices,
you need to provide an identifier that’s stable across devices. If you store your data in CloudKit or generate UUIDs
from your server, you can use the identifiers from those technologies in your entities. However, if you create a local
identiifer for each entity that’s separate from the one you share with other devices, set the type of your `id` property
to [`SyncableEntityIdentifier`](/documentation/AppIntents/SyncableEntityIdentifier) instead. You can use this type with the [`SyncableEntity`](/documentation/AppIntents/SyncableEntity) protocol to tell the system
that the identifer for each entity is the same on each of the person’s devices.

### Add properties for your key data variables

An entity type contains app-specific data you want to make available to the system. When declaring your type, add
properties to store the relevant information. If your entity types are separate from your app’s data structures, design
your type to store a copy of your app’s actual data. When you need to make changes to your app’s data, continue to
modify your app-specific data structures and copy your changes to any existing entities.

In each entity type, apply property wrappers to the properties you want to make available to the system. The system
doesn’t introspect your entity types automatically. Instead, you use property wrappers to mark the specific properties
you want the system to use. Typically, you apply the `@Property` wrapper to your type, but other wrappers are available
too. The following example, shows an entity with several wrapped properties that provide the system with the name,
description, and length of a trail. The type also contains several unwrapped property with additional information about
the trail from the app’s internal data structures..

```swift
struct TrailEntity: AppEntity {
    var id: Trail.ID
    var imageName: String
    var currentConditions: String
    var trailStartLocation : CLLocationCoordinate2D

    // Wrapped properties.
    @Property var name: String
    @Property var trailLength: Measurement<UnitLength>

    @Property(title: "Region")
    var regionDescription: String

    // Type initializer.
    init(trail: Trail) {
        self.id = trail.id
        self.imageName = trail.featuredImage
        self.currentConditions = trail.currentConditions
        self.name = trail.name
        self.regionDescription = trail.regionDescription
        self.trailLength = trail.trailLength
    }
}
```

> Important: If you implemented your entity using a schema, you don’t need to add property wrappers to the required
> schema properties. The schema automatically implicitly wraps relevant properties.

The App Intents framework supports several different property wrappers, each of which imparts specific behaviors on
that property. The following table lists the supported property wrappers and when to use them.

|Macro              |Description                                                                                                                                                                       |
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|`@Property`        |Apply this wrapper to properties with values you can set directly. See the ``doc://com.apple.AppIntents/documentation/AppIntents/EntityProperty`` type for a list of initializers.|
|`@ComputedProperty`|Apply this wrapper when you need a getter or setter method to compute the property’s value.                                                                                       |
|`@DeferredProperty`|Apply this wrapper if the property stores a large value you want to load lazily. When archiving your entity, the system doesn’t include this property in the archive.             |

Include parameters in a property wrapper when you want to provide a custom title for your property or add other information
like a Spotlight indexing key. For some parameters, the system infers default information from the property declaration.
For example, if you don’t specify a `title` parameter for the macro, the macro uses the name of the property as the
title. For other parameters, the system treats a missing parameter value as a sign you don’t support the feature.

> Important: ``doc://com.apple.AppIntents/documentation/AppIntents/AppEntity`` instances have a total size limit of 10 MB, including all child properties and their values.
> If your entity exceeds this limit, the system throws an exception, and your app might crash.
> To reduce the size of your app entity, use the `@DeferredProperty` property wrapper.

If a property contains an array of entities, use an [`EntityCollection`](/documentation/AppIntents/EntityCollection) as the property’s type to improve performance
in specific situations. An entity collection stores only the unique identifier of each entity in the collection initially.
The collection doesn’t load the rest of the entity unless you specifically request it. If your array includes thousands
of entities, this behavior can save measurable time during critical operations such as parameter resolution of an app
intent. For more information about how to use entity collections, see [`EntityCollection`](/documentation/AppIntents/EntityCollection).

For a list of property wrappers and how to use them, see [Property declarations](/documentation/AppIntents/app-entities#Property-declarations).

### Define properties using only the supported types

For every property you add to your app entity, choose only types that the App Intents framework supports. The
system needs to know how to handle your chosen types because it customizes interactions based on
those types. The following table lists the supported types.

|Category                   |Types                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |Notes                                                                                                                                            |
|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
|Primitive value types      |<doc://com.apple.documentation/documentation/Swift/Bool>, <doc://com.apple.documentation/documentation/Swift/Int>, <doc://com.apple.documentation/documentation/Swift/Double>, <doc://com.apple.documentation/documentation/Swift/String>, <doc://com.apple.documentation/documentation/Foundation/AttributedString>, <doc://com.apple.documentation/documentation/Swift/Duration>, <doc://com.apple.documentation/documentation/Foundation/Date>, <doc://com.apple.documentation/documentation/Foundation/Decimal>, <doc://com.apple.documentation/documentation/Foundation/Measurement>, and <doc://com.apple.documentation/documentation/Foundation/URL>|None                                                                                                                                             |
|Collection types           |<doc://com.apple.documentation/documentation/Swift/Array>, <doc://com.apple.documentation/documentation/Swift/Set>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |Make sure the collection’s elements are of a type that’s compatible with ``doc://com.apple.AppIntents/documentation/AppIntents/IntentParameter``.|
|App Intents framework types|``doc://com.apple.AppIntents/documentation/AppIntents/EntityCollection``, ``doc://com.apple.AppIntents/documentation/AppIntents/IntentPerson``, ``doc://com.apple.AppIntents/documentation/AppIntents/IntentFile``, ``doc://com.apple.AppIntents/documentation/AppIntents/IntentCurrencyAmount``, ``doc://com.apple.AppIntents/documentation/AppIntents/IntentPaymentMethod``, ``doc://com.apple.AppIntents/documentation/AppIntents/SystemShortcut``, ``doc://com.apple.AppIntents/documentation/AppIntents/UnionValue()``                                                                                                                                |For additional information, see <doc://com.apple.AppIntents/documentation/AppIntents/common-data-types>.                                         |
|Other system types         |<doc://com.apple.documentation/documentation/MediaIntents/AudioSearch>, <doc://com.apple.documentation/documentation/Foundation/DateComponents>, <doc://com.apple.documentation/documentation/LinkPresentation/LinkMetadata>, <doc://com.apple.documentation/documentation/Foundation/PersonNameComponents>, <doc://com.apple.documentation/documentation/Photos/PHAsset>, <doc://com.apple.documentation/documentation/GeoToolbox/PlaceDescriptor>, <doc://com.apple.documentation/documentation/Foundation/Calendar/RecurrenceRule>, <doc://com.apple.documentation/documentation/VisualIntelligence/SemanticContentDescriptor>                          |None                                                                                                                                             |
|Custom app data            |``doc://com.apple.AppIntents/documentation/AppIntents/AppEntity``, ``doc://com.apple.AppIntents/documentation/AppIntents/AppEnum``                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |Use these types to store app-specific data.                                                                                                      |

When you want to store app-specific data in a property, create an [`AppEntity`](/documentation/AppIntents/AppEntity) or [`AppEnum`](/documentation/AppIntents/AppEnum) type and use it to specify
your data.

### Create a query type to handle searches

To help the system find your app’s entities, provide a query type for each entity type you define. The system uses your
query type to search your app’s content at relevant times. For example, when an app intent parameter contains an entity,
the parameter resolution process uses your query type to find the right entity. The system also runs your queries at
other times to locate relevant entities in your app.

Implement your query type as a structure that conforms to the [`EntityQuery`](/documentation/AppIntents/EntityQuery) protocol. The minimal implementation of
this protocol requires you to locate or create an entity using only its unique identifier. Use additional protocols to
support text- or property-based searches of your entities. For example, the [`EntityPropertyQuery`](/documentation/AppIntents/EntityPropertyQuery) protocol adds support
for advanced searches using values from one or more properties of your entity type.

> Note: If your app adds entities to its Spotlight index, adopt the ``doc://com.apple.AppIntents/documentation/AppIntents/IndexedEntityQuery`` protocol in your query types
> in addition to any other protocols. For more information about indexing entities, see <doc://com.apple.AppIntents/documentation/AppIntents/making-app-entities-available-in-spotlight>.

The following example shows a query type that searches for hiking trails based on their unique identifier. In this case,
the unique identifier for each entity matches the unique identifier the app assigns to its internal trail data structures.
The [`entities(for:)`](/documentation/AppIntents/EntityQuery/entities(for:)) method uses the app’s internal data manager to find the trails with the requested
identifiers. It then uses the trail information to initialize and return one or more new entity instances.

```swift
struct TrailEntityQuery: EntityQuery {
    
    @Dependency
    var trailManager: TrailDataManager

    func entities(for identifiers: [TrailEntity.ID]) async throws -> [TrailEntity] {
        Logger.entityQueryLogging.debug("[TrailEntityQuery] Query for IDs \(identifiers)")
        
        return trailManager.trails(with: identifiers)
                .map { TrailEntity(trail: $0) }
    }
}
```

To associate your query with your entity, implement the [`defaultQuery`](/documentation/AppIntents/AppEntity/defaultQuery-4khg7) property in your entity and initialize
it with an instance of your query type. The following example shows an updated version of the `TrailEntity` type that
includes an instance of its query type.

```swift
struct TrailEntity: AppEntity {
    var id: Trail.ID
    var imageName: String
    var currentConditions: String
    var trailStartLocation : CLLocationCoordinate2D

    // Wrapped properties.
    @Property var name: String
    @Property var trailLength: Measurement<UnitLength>

    @Property(title: "Region")
    var regionDescription: String

    // Type initializer.
    init(trail: Trail) {
        self.id = trail.id
        self.imageName = trail.featuredImage
        self.currentConditions = trail.currentConditions
        self.name = trail.name
        self.regionDescription = trail.regionDescription
        self.trailLength = trail.trailLength
    }

    // Query type.
    static let defaultQuery = TrailEntityQuery()
}
```

For information about performing additional types of searches, see [`EntityStringQuery`](/documentation/AppIntents/EntityStringQuery) and [`EntityPropertyQuery`](/documentation/AppIntents/EntityPropertyQuery).

### Provide alternate representations of your content

The system occasionally needs to incorporate your entities into conversations with people or other apps. During a Siri
conversation, the system might describe the contents of the entity verbally to someone. During a multi-step operation,
Apple Intelligence or Shortcuts might transfer well-known information from your entity to another app to process. For example,
if your entity represents a geographical location, the system might send that location to Maps to generate directions.
When implementing your entity types, describe your content to the system using specific types:

- [`DisplayRepresentation`](/documentation/AppIntents/DisplayRepresentation): Provides the displayable version of your entity, and offers a title, subtitle, and image
  the system can incorporate into dialogs. Assign this type to the [`displayRepresentation`](/documentation/AppIntents/InstanceDisplayRepresentable/displayRepresentation)
  property of your entity.
- [`TypeDisplayRepresentation`](/documentation/AppIntents/TypeDisplayRepresentation): Describes the type of content your entity contains. Assign this type to the
  [`typeDisplayRepresentation`](/documentation/AppIntents/TypeDisplayRepresentable/typeDisplayRepresentation) property of your entity.
- [`IntentValueRepresentation`](/documentation/AppIntents/IntentValueRepresentation): Bridges the value of your entity to common types like [`IntentPerson`](/documentation/AppIntents/IntentPerson) or
  <doc://com.apple.documentation/documentation/GeoToolbox/PlaceDescriptor>. If you can express your entity as one of these
  types, add support for the <doc://com.apple.documentation/documentation/CoreTransferable/Transferable> protocol and
  include an [`IntentValueRepresentation`](/documentation/AppIntents/IntentValueRepresentation) as one of the representations.

The following example shows the representations for the `TrailEntity` type, which describes a hiking trail. The display
representation incorporates data from the entity into the description, whereas the type representation specifies the
type of information in the entity. The transfer representation uses the trail coordinates to create a <doc://com.apple.documentation/documentation/GeoToolbox/PlaceDescriptor> type, allowing someone to locate the
trail on a map.

```swift
extension TrailEntity {
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(name)",
                              subtitle: "\(regionDescription)",
                              image: DisplayRepresentation.Image(named: imageName))
    }

    static var typeDisplayRepresentation: TypeDisplayRepresentation {
        TypeDisplayRepresentation(
            name: LocalizedStringResource("Trail", table: "AppIntents"),
            numericFormat: LocalizedStringResource("\(placeholder: .int) trails", table: "AppIntents")
        )
    }

    // This representation makes use of a coordinate value stored in the entity.
    static var transferRepresentation: some TransferRepresentation {
        IntentValueRepresentation(
            exporting: { trail in
                PlaceDescriptor(
                    representations: [.coordinate(trail.trailStartLocation)],
                    commonName: trail.name)
            }
        )
    }
}
```

---

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)