Блог • App Intents
Как агент iOS 27 вызывает стороннее приложение: проверка JSON App Intent до API
Когда система вызывает стороннее приложение, вход — объявленный вами AppIntent. После того как параметры попали в perform() и до API, запишите их как JSON. Если тип, enum или обязательный ключ не совпали, верните запись об отказе и остановите вызов внутри приложения.
Как один запрос доходит до API — в статье JSON-путь App Action. Станет ли Siri агентом — в статье Станет ли Siri AI агентом. Здесь только сторона приложения: какие параметры объявить, что останавливает схема и какой JSON вернуть при отказе.
- Параметры Intent — собственный контракт приложения
- Схема проверяет тип, enum и обязательные ключи
- Отказ записывают как needs_value или rejected
- Ни одна из этих записей не доходит до API
Сначала это: Вызов, дошедший до приложения, ещё не значит, что параметры готовы. Дальше: объявленный контракт, одна схема, три отказа, верная форма, которую всё равно надо остановить, и как отказ возвращается.
Сначала объявить контракт параметров
Вход стороннего приложения — это AppIntent. Вы задаёте заголовок и реализуете perform(). Система находит действие, потому что вы его объявили. Объявление не доказывает, что эти параметры можно отправлять в API.
Каждый параметр помечайте @Parameter. См. Добавление параметров в App Intent. Этот пример принимает только три вещи: id товара, количество и способ получения. Имена, пояснения и лишние ключи модели в контракт не входят.
- 1Зафиксировать имя Intent
Поле intent в JSON кандидата может быть только PlaceOrderIntent. Другое имя значит, что вызов попал не в то действие.
- 2Перечислить три параметра
itemId — строка, quantity — целое, fulfillment — только pickup или delivery. Если нет любого из них, кандидат неполон.
- 3Проверять в начале perform()
Если проверка не прошла, верните запись об отказе ниже. К API переходите только после успеха, разрешения id и количества не меньше 1.
Те же поля записать схемой
Кандидат и схема ниже — ваш контракт, не сетевой формат Apple. JSON Schema в JSONNote проверяет типы, enum и обязательные ключи. Правило «количество не меньше 1, id должен существовать» эта схема не выражает. Это решает приложение.
{
"intent": "PlaceOrderIntent",
"parameters": {
"itemId": "sku_42",
"quantity": 1,
"fulfillment": "pickup"
}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["intent", "parameters"],
"properties": {
"intent": { "enum": ["PlaceOrderIntent"] },
"parameters": {
"type": "object",
"required": ["itemId", "quantity", "fulfillment"],
"properties": {
"itemId": { "type": "string" },
"quantity": { "type": "integer" },
"fulfillment": { "enum": ["pickup", "delivery"] }
}
}
}
}
Как типы параметров совпадают — в статье поля действия приложения и JSON Schema. Эту таблицу статья не повторяет. Здесь только то, что приложение возвращает, когда проверка не прошла.
Три кандидата, которые не проходят
| Что изменили в кандидате | Почему не проходит |
|---|---|
| fulfillment равен ship | Это не pickup и не delivery. |
| quantity — строка 1 | Контракт требует целое число. |
| itemId удалён | Нет обязательного ключа, кандидат неполон. |
Поставьте quantity равным 0: тип остаётся целым, схема проходит. Прохождение — ещё не заказ. Количество 0 приложение должно отклонить.
Верная форма всё равно может остановить
{
"intent": "PlaceOrderIntent",
"status": "rejected",
"reason": "invalid_parameter",
"field": "quantity",
"dialog": "Quantity must be at least 1."
}
Непустой itemId тоже проходит схему. Затем разрешите этот id в своих данных. Если не разрешился, запишите ещё один rejected с field равным itemId. Не выдумывайте id из названия товара и не вызывайте API.
Как отказ возвращается
Если нет обязательного значения, спросите ещё раз через requestValue у этого параметра. Не вызывайте API с пустым значением. Если значение недопустимо, остановите perform() и используйте IntentDialog, чтобы написать фразу, которую человек может прочитать. JSON выше — запись, которую вы храните для этого решения.
| Случай | status в записи | API |
|---|---|---|
| нет fulfillment | needs_value | Спросить ещё раз, API не вызывать |
| fulfillment равен ship | rejected | Сообщить, что допустимы только pickup и delivery |
| quantity равен 0 | rejected | Остановить, хотя форма верна |
| itemId не разрешается | rejected | Не подменять id названием товара |
needs_value значит, что ещё нужно спросить. rejected значит, что этот кандидат нельзя выполнять. Оба не доходят до API. Человек видит фразу dialog. В журнале остаётся весь JSON, чтобы позже было видно, какое поле остановило вызов.
Чем эта статья отличается от других
| Статья о пути запроса | Статья о конверте обмена | Эта статья | |
|---|---|---|---|
| Отвечает | Как фраза доходит до API | Какой JSON лежит между значением модели и параметрами | Как приложение объявляет, проверяет и возвращает отказ |
| Здесь не ищите | Ещё один проход от речи до API | Два объекта content и parameters | Подмену id сущности названием товара |
Остановить вызов в JSONNote
- 1Выбрать нужную операцию
Откройте JSON Schema. Переключите действовать на Проверьте с помощью Schema. Кандидат — в первое поле, схему выше — во второе. intent может быть только PlaceOrderIntent. fulfillment — только pickup или delivery. quantity — целое.
- 2Прогнать три плохих документа
Поставьте fulfillment равным ship, quantity — строке 1, или удалите itemId. Все три не проходят. quantity 0 проходит. После этого всё равно запишите rejected и не вызывайте API.
- 3Сравнить 1 и 0
Откройте JSON Сравнить Diff. В первое поле — parameters с quantity 1, во второе — тот же объект с quantity 0. Разница в этом числе. 0 по-прежнему проходит схему. API останавливает запись об отказе, а не эта проверка формы.
Вопросы
Если система уже передала приложению параметры, их всё равно проверять?
Да. Система передала вызов, а не уже проверенный запрос API. В начале perform() смотрите этот JSON. Если он не прошёл, не продолжайте.
Можно ли вызывать API, как только схема прошла?
Ещё нет. Эта схема смотрит только тип, enum и обязательные ключи. quantity 0 проходит. Строковый itemId тоже проходит. Вызывайте API только когда количество не меньше 1 и id разрешается.
Если параметра нет, вернуть ошибку или спросить ещё раз?
Спросите ещё раз. status равен needs_value, а requestValue просит это значение у человека. Не вызывайте API, пока нет допустимого значения. Если значение пришло и оно недопустимо, запишите rejected.
Это та же статья, что про JSON-путь одного запроса?
Нет. Та статья ведёт один запрос от фразы до API. Эта остаётся внутри приложения: контракт параметров, схема и JSON, который возвращают при отказе. API выполняется только если не записаны ни rejected, ни needs_value.
Запись об отказе — это формат ответа Apple?
Нет. Apple передаёт результат системе и человеку через requestValue и IntentDialog. Этот JSON — ваш собственный журнал: status, reason, field, dialog. Храните его, чтобы в JSONNote проверить, почему API не вызывался.
Итог
Когда вызывают стороннее приложение, сначала есть контракт параметров, затем JSON, которому разрешено не пройти. Запись об отказе останавливает вызов до API и сохраняет одну читаемую фразу dialog.
Решение: сначала объявить параметры Intent; схема останавливает неверные типы, enum и пропущенные обязательные ключи; needs_value, если значения нет; rejected, если значение недопустимо; оба не вызывают API; количество меньше 1 или отсутствующий id останавливают вызов и при верной форме.
Дальше: прогоните параметры кандидата через схему, затем решите, продолжать вызов или вернуть отказ.