Blog • Foundation Models
Apple Intelligence 2026: Welches JSON zwischen Foundation Models und App Intents wechselt
2026 hat dieselbe App zwei Eingänge. Eine LanguageModelSession auf dem Gerät dekodiert einen typisierten Wert, das System ruft perform() auf einem App Intent auf. Was Sie speichern, ist keiner der beiden Werte im Rohzustand, sondern ein eigener Umschlag.
Die Produkterzählung steht in warum das iPhone 18 mehr als Hardware ist. Ob Siri ein Agent wird, steht in Wird Siri AI ein KI-Agent. Dieser Artikel ist nur der Umschlag: welche Felder bleiben, und wann die Aktion nicht laufen darf.
- content ist das vom Modell dekodierte Objekt
- parameters ist das Objekt für perform()
- Ist complete false, bleibt parameters null
- Ändert sich schemaVersion, darf ein alter Umschlag nicht direkt erneut laufen
Zuerst dies: Das Framework macht aus einem Generable-Typ ein Schema und dekodiert einen Wert. Das bleibt in der Modellsitzung. Der Umschlag ist, was Sie speichern und abgleichen, bevor die Aktion läuft. Danach: zwei Verträge, die Felder, ein JSON, vier Gründe zum Anhalten.
Zwei Verträge, zwei Aufrufe
Wie das Modell auf dem Gerät einen typisierten Wert füllt, steht unter Generable. Der Typ wird zum Schema, das Modell füllt ihn, das Framework dekodiert einen Wert. Ein statischer Typ nutzt @Generable. Ohne ihn kann die Sitzung GeneratedContent zu einem GenerationSchema liefern. Beides heißt im Umschlag content.
Ein App Intent ist ein anderer Aufruf. Parameter stehen an @Parameter. Siehe Parameter zu einem App Intent hinzufügen. Wenn das System perform() aufruft, gibt es keine LanguageModelSession und kein Generable-content.
- 1Die Sitzung liefert Inhalt
respond(to:generating:) liefert eine Response. Vor dem Ende ist der Wert PartiallyGenerated, Felder können leer sein. Ein ausführbares Parameterobjekt gibt es noch nicht.
- 2Parameter projizieren
Nur Felder, die der Intent annimmt, kommen nach parameters. Eine rationale des Modells bleibt in content. Gleiche Namen, nicht dasselbe Objekt.
- 3Zuerst den Umschlag schreiben
source, sessionId, schemaVersion, complete, content, intent und parameters werden ein JSON. Ist complete nicht true, rufen Sie perform() nicht auf.
Felder im Umschlag
Diese Schlüssel gehören zu Ihrem Umschlag. Sie stehen nicht im dekodierten Wert von Apple.
| Feld | Wer schreibt | Rolle |
|---|---|---|
source | Ihre App | foundation-models oder app-intent. Zeigt, welcher Eingang den Wert geliefert hat. |
sessionId | Ihre App | Nur eine Modellsitzung hat eine, zum Beispiel lm_01. Ein Systemaufruf speichert null. |
schemaVersion | Ihre App | Die Generation Ihrer Generable-Feldliste. Dieses Beispiel nutzt 3. Bei Feldänderungen erhöhen. Einen alten Umschlag nicht in den neuen Intent abspielen. |
generable | Ihre App | Der Typname, zum Beispiel OrderDraft. Ein direkter Systemaufruf speichert null. |
complete | Sie kopieren den Generierungsstand | false heißt: die Generierung läuft, Felder können sich noch ändern. Erst true erlaubt Projektion und einen Ausführungsentscheid. |
content | Dekodierter Modellwert | Das dekodierte Objekt. Es darf mehr Felder haben als die Aktion, etwa rationale. Ein Systemaufruf speichert null. |
intent | Ihre App | Der App Intent, den Sie aufrufen oder den das System aufruft, zum Beispiel PlaceOrderIntent. |
parameters | Ihre Projektion oder die Systemargumente | Das Objekt für perform(). Solange unvollständig, null. Bei einem Systemaufruf sind es die bereits übergebenen Argumente. |
content und parameters dürfen dieselben Feldnamen tragen. Es bleiben zwei Objekte. Geben Sie content direkt an perform(), gelangt eine rationale des Modells in die Aktion.
Ein JSON zum Speichern
Umschlag und Schema unten sind Ihr Vertrag, nicht Apples Leitungsformat. JSON Schema in JSONNote prüft Typen, Enums und Pflichtfelder. Dass perform nur bei complete true laufen darf, drückt dieses Schema nicht aus. Das entscheidet die App.
{
"source": "foundation-models",
"sessionId": "lm_01",
"schemaVersion": 3,
"generable": "OrderDraft",
"complete": true,
"content": {
"itemId": "sku_42",
"quantity": 1,
"fulfillment": "pickup",
"rationale": "User asked for pickup."
},
"intent": "PlaceOrderIntent",
"parameters": {
"itemId": "sku_42",
"quantity": 1,
"fulfillment": "pickup"
}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["source", "sessionId", "schemaVersion", "generable", "complete", "content", "intent", "parameters"],
"properties": {
"source": { "enum": ["foundation-models", "app-intent"] },
"sessionId": { "type": ["string", "null"] },
"schemaVersion": { "type": "integer" },
"generable": { "type": ["string", "null"] },
"complete": { "type": "boolean" },
"content": { "type": ["object", "null"] },
"intent": { "type": "string" },
"parameters": { "type": ["object", "null"] }
}
}
rationale bleibt nur in content. Die Typzuordnung der Aktionsparameter steht in Aktionsfelder der App und JSON Schema. Diese Tabelle wiederholt der Artikel nicht.
Unvollständig: perform nicht aufrufen
{
"source": "foundation-models",
"sessionId": "lm_01",
"schemaVersion": 3,
"generable": "OrderDraft",
"complete": false,
"content": {
"itemId": "sku_42"
},
"intent": "PlaceOrderIntent",
"parameters": null
}
Dieser Umschlag besteht das Schema oben, weil parameters null sein darf. Eine gültige Form ist kein Ausführungsgrund. PartiallyGenerated heißt: spätere Tokens können schon erschienene Felder noch ändern. Warten Sie auf complete true, dann projizieren Sie parameters aus dem vollständigen content. Ein Objekt in parameters bei unfertiger Generierung lässt das Schema ebenfalls durch.
| Umschlag | Warum anhalten |
|---|---|
| complete ist false | Spätere Tokens können schon erschienene Felder noch ändern. |
| schemaVersion ist nicht die aktuelle Feldliste | Alter content passt nicht zum heutigen Intent. |
| Bei foundation-models hat parameters einen Schlüssel, den content nicht hat | Die Projektion darf keinen Wert erfinden, den das Modell nicht geschrieben hat. |
| Bei app-intent ist content nicht null | Systemargumente sind keine Modellausgabe. Schreiben Sie sie nicht nach content zurück und tun Sie nicht so, als hätte das Modell sie erzeugt. |
Einen zusätzlichen Schlüssel sehen Sie im JSON-Vergleich. Diese Prüfung gilt nur, wenn source foundation-models ist. Bei einem Systemaufruf ist content null. Sie können nicht verlangen, dass jeder Schlüssel von parameters in content stand.
Wie Tool und App Intent übergeben
Ihre Sitzung ruft ein Tool von Foundation Models auf. Siehe Generierung mit Tool Calling erweitern. Die Arguments von call(arguments:) sind ebenfalls Generable. Schreiben Sie sie zuerst nach content. Erst nach der Projektion auf parameters steht perform() zur Debatte.
Ruft das System den Intent direkt auf, setzen Sie source auf app-intent und sessionId, generable sowie content auf null. parameters sind die bereits übergebenen Werte. Erfinden Sie keine sessionId, um den Aufruf als Modellausgabe auszugeben.
| Foundation Models Tool | App Intent | |
|---|---|---|
| Wer ruft auf | Ihre LanguageModelSession | Siri, Kurzbefehle, Spotlight |
| Eingabe | Generable Arguments | Werte an @Parameter |
| Methode, die Sie implementieren | call(arguments:) | perform() |
| source im Umschlag | foundation-models | app-intent |
Abgrenzung zu den anderen Artikeln
| Produkt- und Siri-Artikel | Artikel über Aktionsfelder | Dieser Artikel | |
|---|---|---|---|
| Antwort | Warum es mehr als Hardware ist, und ob Siri ein Agent wird | Welche Felder in die Aktion dürfen | Welches JSON zwischen Modellwert und Aktionsparametern liegt |
| Hier nicht suchen | Noch eine Ankündigung | Die Typzuordnung von AppEnum und Entitäts-Id | content unverändert als Eingabe von perform() zu verwenden |
Den Umschlag in JSONNote prüfen
- 1Die richtige Operation wählen
Öffnen Sie JSON Schema. Stellen Sie Betrieb auf Überprüfen Sie mit Schema. Umschlag ins erste Feld, das Schema oben ins zweite. source ist foundation-models oder app-intent. complete ist ein Boolean. parameters ist ein Objekt oder null.
- 2Drei ungültige Dokumente prüfen
Setzen Sie source auf siri, complete auf die Zeichenkette true, oder löschen Sie parameters. Alle drei scheitern. Der unfertige Umschlag mit complete false und parameters null besteht. Bestehen heißt nicht, perform() aufzurufen.
- 3Die zwei Objekte vergleichen
Öffnen Sie JSON Vergleiche Diff. content ins erste Feld, parameters ins zweite. rationale darf nur im ersten stehen. Ein Schlüssel nur im zweiten stammt aus der Projektion, nicht vom Modell. Dieser Vergleich gilt nur, wenn source foundation-models ist.
Häufige Fragen
Kann die Generable-Ausgabe direkt an perform() gehen?
Nein. Die Ausgabe steht in content. perform() erhält nur die projizierten parameters. Der Umschlag behält beide zum Abgleich.
Darf die Aktion laufen, wenn das Schema besteht?
Noch nicht. Dieses Schema prüft nur Typen, Enums und Pflichtfelder. complete false mit parameters null ist eine gültige Form. Vor der Ausführung muss complete true sein, und am Modelleingang darf parameters keinen Schlüssel haben, der in content fehlt.
Sind Tool und App Intent derselbe Aufruf?
Nein. Die LanguageModelSession ruft ein Tool auf. Einen App Intent rufen Siri, Kurzbefehle oder Spotlight auf. Dieselbe Aufgabe kann auf beiden Seiten liegen. Beide Eingaben landen zuerst in diesem Umschlag.
Kann ein altes Log erneut laufen, wenn schemaVersion sich ändert?
Nicht unverändert. Die Version ist die Generation Ihrer Generable-Feldliste. Nach einer Feldänderung passt alter content nicht zum heutigen Intent. Anhalten, eine ausdrückliche Abbildung schreiben, dann über die Ausführung entscheiden.
Ist das derselbe Artikel wie der über Aktionsfelder und JSON Schema?
Nein. Jener Artikel richtet Parametertypen zu einer Feldliste aus. Dieser beschreibt den Umschlag zwischen Modellwert und dieser Liste: Eingang, Abschluss, Version, und content getrennt von parameters.
Fazit
Foundation Models und App Intents sind zwei Eingänge. Der Umschlag legt Eingang, Abschluss, Schema-Version, content und parameters in ein JSON, damit Sie vor perform() anhalten können.
Die Entscheidung: content bleibt im Umschlag; perform() erhält nur parameters; bei complete false nicht ausführen; eine abweichende schemaVersion nicht abspielen; parameters darf keinen Schlüssel enthalten, den content nicht hat.
Als Nächstes: dieses JSON durch das Schema bringen, dann content mit parameters vergleichen.