Zum Inhalt springen

Technik

Wir haben Shopify um einen neuen Sidekick-Intent-Typ gebeten. Sie haben ihn ausgeliefert.

By Jahangir Alam · 31. August 2026 · 9 Min. Lesezeit

Wie Sie einen application/*-Intent-Typ für Ihre Kategorie hinzufügen lassen – und was wir beim ersten Anlauf über Intents falsch verstanden hatten.

Wenn Sie eine Shopify-App bauen, deren Kernobjekt kein Produkt, keine Bestellung und kein Kunde ist, sind Sie wahrscheinlich schon gegen diese Wand gelaufen: Sidekick-App-Erweiterungen nutzen ein festes Intent-Vokabular, und Ihr Ding steht nicht drin.

Als wir anfingen, QuotWay in Sidekick zu verdrahten, war die unterstützte Liste application/{ad, campaign, email, faq, loyalty-program, return, review, shipment, ticket} plus shopify/{customer, order, product}. Wir bauen eine B2B-Angebots- und Verhandlungs-App. Ein quote gab es nicht.

Das ist keine weiche Grenze, um die man herumarbeiten kann. shopify app deploy ist atomar und weist einen nicht unterstützten Intent-Typ rundheraus zurück – ein fehlerhafter Intent scheitert also nicht allein, er reißt Ihre gesamte App-Version mit. Wir haben nur lesende Datenwerkzeuge ausgeliefert und den Rest geparkt. (Diese erste Phase ist separat beschrieben in Eine Shopify-Sidekick-App-Erweiterung bauen.)

Dann haben wir gefragt. Shopify hat application/quote zum Ökosystem hinzugefügt – für jede Angebots-App, nicht nur für unsere.

Das haben wir gelernt, einschließlich des Teils, den wir völlig falsch modelliert hatten.

Es gibt eine Vordertür, und sie ist ein öffentliches Repo

Intent-Typen werden offen verwaltet, unter Shopify/app-intent-types. Sie eröffnen eine Diskussion, legen Ihren Fall dar, und ein Plattform-Engineer antwortet.

Was unseren Antrag hat landen lassen, grob nach Gewicht:

Argumentieren Sie für die Kategorie, nicht für Ihre App. Wir haben quote beantragt, weil Angebots- und Verhandlungs-Apps eine erkennbare Klasse von Shopify-Apps mit einem gemeinsamen Objekt sind, nicht weil QuotWay es brauchte. Ein Typ, der für einen Anbieter hinzugefügt wird, ist eine Wartungslast; ein Typ, der einer Kategorie dient, ist ein Plattform-Feature. Schreiben Sie den Antrag so, wie Shopify ihn intern rechtfertigen müsste.

Bringen Sie das echte Objekt mit. Wir haben beschrieben, was ein Angebot tatsächlich ist – eine Käuferanfrage, die bepreist, über mehrere Runden verhandelt und in eine Bestellung umgewandelt wird – und welche Felder über jede App der Kategorie hinweg Bedeutung tragen. Diese Frage („was muss das Schema halten?“) ist die, die vor allem anderen beantwortet werden muss, also nimmt ihre Vorwegnahme den Hauptgrund zum Vertagen.

Schlagen Sie konkrete Aktionen vor. Wir haben open, send_proposal, counter und convert vorgeschlagen. Jede einzelne wurde abgelehnt. Das war trotzdem der nützlichste Teil des RFC, weil die Gründe für die Ablehnung uns das Modell beigebracht haben – siehe unten. Ein falscher konkreter Vorschlag schlägt einen vagen: Er gibt dem Plattform-Team etwas Bestimmtes zum Korrigieren.

Bieten Sie an, die Arbeit zu machen. Wir haben angeboten, den Folge-PR für den types/-Eintrag zu eröffnen. Sie haben abgelehnt und es selbst gemacht, aber das Angebot signalisiert, dass Sie pflegen, worum Sie bitten.

Gesamtdauer: RFC Anfang Juli eingereicht, am 27. August genehmigt. Langsamer als ein Feature, das Sie selbst kontrollieren; weit schneller, als für immer um die Lücke herum zu bauen.

Was wir falsch hatten: Ein Intent ist eine Übergabe, kein Befehl

Hier die Antwort, die alles umgerahmt hat, vom Plattform-Engineer, der den Typ genehmigt hat:

„Wir fügen open, send_proposal, counter und convert nicht hinzu: Jeder application/*-Typ unterstützt genau create und edit. Ein Intent ist eine Übergabe, kein Befehl. Sidekicks Aufgabe endet, wenn der Händler mit dem richtigen Kontext in Ihrer App ist, und Ihre Oberfläche übernimmt den Rest.“

Wir hatten Intents als Fernsteuerungs-API modelliert – ein Intent pro Verb, das unser Produkt kann. Das ist falsch, und sobald man sieht warum, wird die ganze Oberfläche einfacher.

Zwei Konsequenzen, die man verinnerlichen sollte:

open ist bereits das, was edit bedeutet. Es gibt keine separate „zeig es nur“-Aktion, weil edit ein Navigationsvertrag ist, keine Mutation. Sie registrieren edit:application/quote, und Sidekick setzt den Händler auf Ihrer Seite ab. Ob diese Seite ein Editor oder eine reine Ansicht ist, ist Ihre Sache. Shopifys eigene Referenz-Erweiterungen heißen buchstäblich open-email und open-campaign – und beide registrieren action = "edit".

Ihre Verben sind keine Intents, sie sind Werkzeuge in der Seite. send_proposal, counter und convert wurden nicht gestrichen, sie wurden verlagert. Es sind Werkzeuge, die laufen, sobald das Angebot offen ist, und in Ihre eigene Bestätigungsoberfläche einspeisen. Also genau dort, wo der Händler ohnehin den Knopf gedrückt hätte. Wir hatten versucht, unsere gesamte Produktoberfläche in das Intent-Vokabular zu hieven; die Plattform sagt Ihnen, dass Sie das nicht sollen.

Wenn Sie gerade einen RFC für sechs Verben einreichen wollen, sparen Sie sich die Runde: Bitten Sie um den Typ, und entwerfen Sie die Verben als Werkzeuge.

Die Hälfte, die man leicht übersieht

Den Intent zu registrieren tut für sich genommen nichts. Beides muss wahr sein:

  1. Sie registrieren einen Intent für application/quote.
  2. Ihre Suchergebnisse tragen mimeType: "application/quote".

„Dass der mimeType eines Ressourcen-Links zu einem Intent-Typ passt, ist das, was ein Suchergebnis aufrufbar macht.“

Das ist die Verbindung. Ihre Datenerweiterung liefert Ressourcen-Links zurück; ein Link, dessen mimeType zu einem registrierten Intent passt, wird zu etwas, das der Händler öffnen kann, statt zu einer Karte, die er nur lesen kann.

Wir hatten einen Hersteller-Mime ausgegeben – application/vnd.quotway.quote -, was korrekt war, solange kein Standardtyp existierte, und in dem Moment zum Blocker wurde, in dem einer existierte. Der Fix sind zwei Zeichenketten:

-const QUOTE_MIME = "application/vnd.quotway.quote";
+const QUOTE_MIME = "application/quote";

-  uri: `gid://application/quotway.quote/${q.id}`,
+  uri: `gid://application/quote/${q.id}`,

Behalten Sie Hersteller-Mimes für alles ohne Intent-Typ. Unsere Pipeline-Zusammenfassungen und Targeting-Regeln nutzen weiter application/vnd.quotway.*, weil man eine Pipeline-Zusammenfassung nicht öffnen kann. Sie mit einem Standardtyp zu markieren würde dem Händler eine Aktion versprechen, die es nicht gibt.

Die Verdrahtung, konkret

Eine Intent-Erweiterung ist ein admin_link, keine ui_extension:

[[extensions]]
name = "Open quote"
description = "Open a specific QuotWay quote, quote request (RFQ), proposal or counteroffer…"
handle = "quotway-open-quote"
type = "admin_link"

  [[extensions.targeting]]
  target = "admin.app.intent.link"
  url = "/app/quotes/{id}"
  tools = "./tools.json"
  instructions = "./instructions.md"

    [[extensions.targeting.intents]]
    type = "application/quote"
    action = "edit"
    schema = "./intent-schema.json"

Und das Schema, in dem die URL tatsächlich gefüllt wird:

{
  "$schema": "https://extensions.shopifycdn.com/shopifycloud/schemas/v1/intent.json",
  "value": {
    "type": "string",
    "description": "The GID of the quote to open.",
    "mapTo": "param",
    "fieldName": "id"
  },
  "inputSchema": {
    "$ref": "https://extensions.shopifycdn.com/shopifycloud/schemas/v1/application/quote.json",
    "type": "object",
    "properties": {
      "buyer_email": { "type": "string", "description": "…" },
      "company":     { "type": "string", "description": "…" },
      "total":       { "type": "number", "description": "…", "minimum": 0 },
      "message":     { "type": "string", "description": "…" }
    }
  }
}

Vier Dinge, die Ihnen Zeit sparen:

mapTo: "param" plus fieldName füllt das {id} in Ihrer url. Die Namen müssen nicht übereinstimmen – fieldName ist die Umleitung.

GIDs werden für Sie gekürzt. Ist ein auf einen param gemappter Wert eine GID, setzt Sidekick nur das Segment nach dem letzten / ein. Aus gid://application/quote/clx123abc wird also clx123abc. Unsere bestehende Route erwartete diese ID ohnehin, also keine Routenänderung – aber es heißt, dass das Ende Ihrer GID genau das sein muss, was Ihr Router will.

Veröffentlichte Schemas sind bewusst minimal. application/quote veröffentlicht id mit additionalProperties: true. Alles Fachliche – buyer_email, company, total, message – deklarieren Sie selbst unter inputSchema.properties. Der Standardtyp ist ein Handschlag, kein Datenmodell.

Werkzeuge sind Pflicht, nicht optional. Sidekick ruft nur Intents auf, die Werkzeuge haben. Ein Intent-Link-Target ohne tools.json registriert sich sauber und feuert nie.

Zwei Fallen

api_version ist bei einer admin_link-Erweiterung nicht erlaubt. Wir hatten es aus unseren ui_extension-TOMLs kopiert, und die Konfiguration war ungültig. Gefunden von:

shopify app config validate --json

Führen Sie das vor jedem Deployment aus. Das Deployment ist atomar – eine ungültige Erweiterung scheitert nicht für sich, sie lässt die Version scheitern.

Das Budget ist enger, als es aussieht: 5 Intents und 20 Werkzeuge, geteilt über alle Erweiterungen, die Sie ausliefern. Unsere Datenerweiterung hatte bereits 15 Werkzeuge registriert. Drei weitere Werkzeuge in der Seite plus eines für die Vorbefüllung brachten uns auf 19 von 20. Wenn Sie eine reichhaltige Datenerweiterung und Aktionen planen, budgetieren Sie zuerst die Werkzeuge – Ihnen gehen die Werkzeuge lange vor den Intents aus.

Wenn Sie in dieser Lage sind

Wahrscheinlich sind Sie das, wenn das Kernobjekt Ihrer App nicht auf der Liste steht. Ungefähr so:

  1. Prüfen Sie Shopify/app-intent-types – vielleicht hat jemand schon gefragt.
  2. Eröffnen Sie eine Diskussion für Ihre Kategorie, nicht für Ihre App. Beschreiben Sie das Objekt, die Felder, die verallgemeinern, und was Händler laut fragen.
  3. Bitten Sie um den Typ; entwerfen Sie Ihre Verben als Werkzeuge. create und edit sind, was Sie bekommen. Das reicht.
  4. Liefern Sie inzwischen die Datenerweiterung aus. Nur lesende Werkzeuge berühren das Intent-Vokabular nicht, sind also nie blockiert. Wenn Ihr Typ landet, ist der Mime-Wechsel ein Zweizeiler.
  5. Validieren Sie vor dem Deployment.

Das Vokabular sieht aus wie eine Wand. Es ist eine Warteschlange.


QuotWay ist eine B2B-Angebots- und Verhandlungs-App für Shopify. Der Intent-Typ application/quote steht jeder App der Kategorie offen – wenn Sie eine bauen, gehört er auch Ihnen. Wenn Sie Händler statt Entwickler sind, beschreibt die Aufarbeitung für Händler, was das im Adminbereich tatsächlich tut.

Verwandte Artikel

So funktioniert QuotWay in Ihrem Shop.

Wir möchten Analyse-Cookies setzen, um zu verstehen, wie die Website genutzt wird. Sie sind nicht erforderlich – eine Ablehnung ändert nichts an der Funktion der Website, und Sie können Ihre Entscheidung jederzeit ändern auf unserer Datenschutzseite.