Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Siri not recognizing the parameter in the phrase

I am trying to create an "OpenShowIntent" that allows the user to open a show from outside the app by either invoking the shortcut and provide a showName and/or by asking Siri "Open (.$showName) in (.applicationName)". Currently the shortcut works and but Siri doesn't recognize the showName and keeps on loading when I say the phrase with a show name. I was wondering where I am going wrong. Here are some of the code below:

OpenShowIntent.swift:
import Foundation
import AppIntents
import Models

@available(iOS 16.0, *)
struct OpenShowIntent: AppIntent {
    static var title: LocalizedStringResource = "Open a Show"
    static var openAppWhenRun = true

    @Parameter(title: "Show", optionsProvider: ShowEntityQuery())
    var show: ShowEntity?

    @Parameter(title: "Show Name")
    var showName: String

    static var parameterSummary: some ParameterSummary {
        Summary("Open \(\.$showName) in (APP NAME)")
    }

    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        
        var showToOpen: ShowEntity

        if let show = show {
            showToOpen = show
        } else {
            let params = ElasticSearchParams(query: showName)
            let searchResults = try await IntentsHelper.getShows(searchParams: params)
            let entities = searchResults.map { show in
                ShowEntity(id: show.id, name: show.displayName, posterUrl: show.posterImageUrl)
            }
            showToOpen = try await $show.requestDisambiguation(
                among: entities,
                dialog: "Choose a show from this list?"
            )
        }
        let deepLink = DeepLink(
            type: .show(
                showId: showToOpen.id,
                showDateStr: nil,
                voucher: nil,
                reviewModalParams: nil
            )
        )
        let url = try deepLink.createURL(source: nil)
        IntentsHelper.openLink(url: url)
        return .result(dialog: "Show '\(showToOpen.name)' opened successfully.")
    }
}
ShowEntity.swift:
import Foundation
import AppIntents
import Models

@available(iOS 16.0, *)
struct ShowEntity: AppEntity {
    typealias DefaultQuery = ShowEntityQuery
    var id: Int
    var name: String
    var posterUrl: URL?

    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Show"

    var displayRepresentation: DisplayRepresentation {
        var image: DisplayRepresentation.Image?
        if let imageUrl = posterUrl {
            image = DisplayRepresentation.Image(url: imageUrl)
        }
        return DisplayRepresentation(
            title: LocalizedStringResource(stringLiteral: name),
            subtitle: nil,
            image: image
        )

    }
    static var defaultQuery = ShowEntityQuery()
    init(id: Int, name: String, posterUrl: URL?) {
        self.id = id
        self.name = name
        self.posterUrl = posterUrl
    }
}
ShowEntityQuery.swift:
import Foundation
import AppIntents
import Models

@available(iOS 16.0, *)
struct ShowEntityQuery: EntityStringQuery {
    func entities(for identifiers: [Int]) async throws -> [ShowEntity] {
        let params = ElasticSearchParams(showIds: identifiers)
        let searchResult = try await IntentsHelper.getShows(searchParams: params)
        return searchResult.map { show in
            ShowEntity(id: show.id, name: show.displayName, posterUrl: show.posterImageUrl)
        }
    }

    func suggestedEntities() async throws -> [ShowEntity] {
        let params = ElasticSearchParams(
            showIds: BookmarksManager.sharedManager.getBookmarkShowIdsAsArray()
        )
        let searchResult = try await IntentsHelper.getShows(searchParams: params)
        return searchResult.map { show in
            ShowEntity(id: show.id, name: show.displayName, posterUrl: show.posterImageUrl)
        }
    }

    func entities(matching query: String) async throws -> [ShowEntity] {
        let params = ElasticSearchParams(query: query)
        print("entities(matching:) called with query: \(query)")
        let searchResult = try await IntentsHelper.getShows(searchParams: params)
        return searchResult.map { show in
            ShowEntity(id: show.id, name: show.displayName, posterUrl: show.posterImageUrl)
        }
    }
}
ShortcutsProvider.swift:
import Foundation
import AppIntents

@available(iOS 16.0, *)
struct TTShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        return [
            AppShortcut(
                intent: OpenShowIntent(),
                phrases: [
                    "View show in \(.applicationName)",
                    "Open \(\.$showName) in \(.applicationName)",
                    "Show \(\.$showName) in \(.applicationName)",
                    "Find \(\.$showName) in \(.applicationName)",
                    "Search for \(\.$showName) in \(.applicationName)"
                ],
                shortTitle: "Open show",
                systemImageName: "pencil.circle"
            )
        ]
    }
    static var shortcutTileColor: ShortcutTileColor = .blue
}

How many shows are return by your suggested entities method? What happens if you limit that to a smaller number?

"Open \(\.$showName) in \(.applicationName)",
"Show \(\.$showName) in \(.applicationName)",
"Find \(\.$showName) in \(.applicationName)",
"Search for \(\.$showName) in \(.applicationName)"

When you update the app shortcuts, the system needs to learn the available values for the parameters so that it can then recognize the spoken phrases when used by the customer. The number of substitutions for the show name parameter can't be unbounded or a huge number. Further, the system needs to learn these phrases for each of the provided phrases, so there's a combinatorial size growth potential between the number of phrases, number of parameters, and number of values for the parameters. Depending on how many values are returned for your bookmarks, there could potentially be a huge number of phrases that exceeds internal system limits once you consider all of those variants.

If your bookmark example here is only a small number — let's say 5 for discussion — and you still aren't having recognized phrases, then I'd like to see a buildable test project with those 5 values hard coded so I can look at this further. If you're not familiar with preparing a test project, take a look at Creating a test project.

— Ed Ford,  DTS Engineer

Thanks for the reply @DTS Engineer . I managed to make it work for now by passing all the shows available in the database (around 200 shows at a given location) to Siri so that Siri can recognize the parameter. This method currently works fine with the expected results but, as you mentioned, it could potentially be problematic.

I was wondering if there is a method to capture the string value that gets applied to the parameter of the phrase when it gets invoked. I could then use this string as a query to search for matching shows. While researching, I read about @AssistantIntent(schema:), but it is only available for iOS 18+. I also saw that YouTube is able to get the string regardless of what the user says and search for that query. If you could point me in the direction of implementing something similar, I would greatly appreciate it. @DTS Engineer

I was wondering if there is a method to capture the string value that gets applied to the parameter of the phrase when it gets invoked.

For an App Shortcut, there's no way to do this in the invocation phase. If you'd like us to consider adding the necessary functionality, please file an enhancement request using Feedback Assistant. Once you file the request, please post the FB number here.

If you're not familiar with how to file enhancement requests, take a look at Bug Reporting: How and Why?

—Ed Ford,  DTS Engineer

Siri not recognizing the parameter in the phrase
 
 
Q