博客 • App Intents

iOS 27 AI Agent 如何調用第三方 App?App Intents、App Actions、API 與 JSON 參數驗證完整教程

系統調用第三方 App 時,入口是你聲明的 AppIntent。參數進 perform() 之後、API 之前,先落成一份 JSON。類型、枚舉或必填對不上,就返回失敗記錄,這次調用停在 App 裏。

一條指令怎麼走到 API,見 App Actions 的 JSON 路徑。Siri 會不會變成 Agent,見 Siri AI 會成爲 AI Agent 嗎。本篇只寫 App 側:聲明哪些參數、用 Schema 擋住什麼、失敗時返回哪一份 JSON。

先記住這一點:系統把調用交到你的 App,不代表參數已經能用。下面按「聲明合同 → 一份 Schema → 三條失敗 → 形狀通過仍停 → 失敗怎麼回」拆開。

先聲明參數合同

第三方 App 對外的入口寫在 AppIntent 上。你給出標題,並實現 perform()。系統能發現這個動作,是因爲你聲明瞭它。聲明本身不證明這次參數可以打 API。

每個參數用 @Parameter 標出。說明見 爲 App Intent 添加參數。這份示例只收三樣:商品 id、數量、履約方式。名稱、說明文字和模型多寫的鍵都不在合同裏。

  1. 1
    釘住 Intent 名

    候選 JSON 裏的 intent 只能是 PlaceOrderIntent。別的名字表示這次調用找錯了動作。

  2. 2
    列出三個參數

    itemId 是字符串,quantity 是整數,fulfillment 只能是 pickup 或 delivery。缺任何一項,這份候選就不完整。

  3. 3
    perform() 裏先校驗

    校驗失敗就返回下面的失敗記錄。通過,並且 id 能解析、數量至少爲 1,才進入 API。

同一組字段寫成 Schema

下面的候選和 Schema 是你的契約,不是 Apple 的線上格式。JSONNote 的 JSON Schema 會檢查類型、枚舉和必填。數量至少爲 1、id 必須存在,這層 Schema 表達不了,要在 App 裏再判斷。

能進入下一步的候選。fulfillment 必須是 pickup 或 delivery。
{
  "intent": "PlaceOrderIntent",
  "parameters": {
    "itemId": "sku_42",
    "quantity": 1,
    "fulfillment": "pickup"
  }
}
第一欄貼候選,第二欄貼這份 Schema。操作改成用 Schema 校驗。
{
  "$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"] }
      }
    }
  }
}

參數類型怎麼對齊,見 App 動作字段與 JSON Schema。本篇不重複那張表,只寫校驗失敗時 App 返回什麼。

三條會失敗的候選

候選裏改了什麼爲什麼失敗
fulfillment 寫成 ship不在 pickup 和 delivery 裏。
quantity 寫成字符串 1合同要的是整數。
刪掉 itemId必填缺了,候選不完整。

把 quantity 改成 0,類型仍是整數,這份 Schema 會通過。通過不等於可以下單。0 件商品要在 App 裏拒絕。

形狀通過仍要停

數量小於 1 時留下的失敗記錄。dialog 是說給用戶的那一句。
{
  "intent": "PlaceOrderIntent",
  "status": "rejected",
  "reason": "invalid_parameter",
  "field": "quantity",
  "dialog": "Quantity must be at least 1."
}

itemId 是非空字符串時,Schema 也通過。接着要在你的數據裏解析這個 id。解析不到,就再寫一份 rejected,field 寫成 itemId。不要用商品名造一個 id,也不要打 API。

失敗怎麼回

缺必填時,用參數上的 requestValue 再問一次,不要拿空值去打 API。值非法時,讓 perform() 停住,並用 IntentDialog 寫出用戶能看懂的那一句。上面的 JSON 是你爲這次決定留下的記錄。

情況記錄裏的 statusAPI
缺 fulfillmentneeds_value再問一次,不打 API
fulfillment 是 shiprejected說明只能是 pickup 或 delivery
quantity 是 0rejected形狀合法也停
itemId 解析不到rejected不用商品名頂替 id

needs_value 表示還要問。rejected 表示這次候選不能執行。兩條都不進入 API。用戶看見的是 dialog 那一句,日誌裏留下整份 JSON,之後才能對上是哪一個字段被擋住。

和另外幾篇怎麼分工

指令路徑那篇交換信封那篇本篇
回答短語怎麼走到 API模型值和參數之間落哪一份 JSONApp 如何聲明、校驗、把失敗回回去
不要在這裏找再走一遍語音到 API 的步驟content 和 parameters 兩份對象用商品名頂替實體 id

在 JSONNote 裏擋住這次調用

  1. 1
    選對操作

    打開 JSON Schema。操作選「用 Schema 校驗」。第一欄貼候選,第二欄貼上面的 Schema。intent 只能是 PlaceOrderIntent。fulfillment 只能是 pickup 或 delivery。quantity 必須是整數。

  2. 2
    撞三條壞數據

    fulfillment 寫成 ship,或 quantity 寫成字符串 1,或刪掉 itemId。這三條都會失敗。quantity 改成 0 會通過。通過之後仍要寫 rejected,不打 API。

  3. 3
    對比 1 和 0

    打開 JSON 對比 Diff。第一欄貼 quantity 爲 1 的 parameters,第二欄把 quantity 改成 0。差的是這個數。0 仍能通過 Schema,所以擋住 API 的是失敗記錄,不是這次形狀檢查。

常見問題

系統已經把參數交給 App,還要再校驗嗎?

要。系統交來的是一次調用,不是已經校驗過的 API 請求。perform() 開頭先看這份 JSON。不過就不繼續。

Schema 通過就可以打 API 嗎?

還不行。這份 Schema 只看類型、枚舉和必填。quantity 爲 0 會通過。itemId 是字符串也會通過。數量至少爲 1,並且 id 能解析,纔打 API。

缺參數時應該返回錯誤還是再問一次?

再問一次。status 寫成 needs_value,用 requestValue 向用戶要這個值。問到合法值之前不打 API。值到了但非法,才寫成 rejected。

和「一條指令的 JSON 路徑」是同一篇嗎?

不是。那篇跟着一條指令從短語走到 API。本篇停在 App 裏面:參數合同、Schema,以及失敗時返回的 JSON。API 只有在 rejected 和 needs_value 都沒有出現時才發生。

失敗記錄是 Apple 的返回格式嗎?

不是。Apple 用 requestValue 和 IntentDialog 把結果交給系統和用戶。這份 JSON 是你自己的日誌:status、reason、field、dialog。留下它,才能在 JSONNote 裏複覈這次爲什麼沒有打 API。

總結

第三方 App 被調用時,先有一份參數合同,再有一份能失敗的 JSON。失敗記錄把這次調用停在 API 之前,並留下用戶能看懂的一句 dialog。

直接結論:先聲明 Intent 參數;用 Schema 卡住類型、枚舉和必填;缺值返回 needs_value;非法值返回 rejected;這兩種都不打 API;數量小於 1 或 id 不存在,形狀通過也要停。

下一步:先讓候選參數通過 Schema,再決定這次調用是繼續還是返回失敗。

返回博客