Lookups
Lesen Sie aktuelle Kundendatensätze über signierte Anfragen an Ihr Geschäftssystem aus.
Lesen Sie aktuelle Kundendatensätze über signierte Anfragen an Ihr Geschäftssystem aus.
Wann Sie einen Lookup verwenden#
Verwenden Sie einen Lookup für den aktuellen Bestellstatus, eine bestehende Buchung oder den Kontodatensatz eines Kunden. Stabile Richtlinien und Produktinformationen gehören in die Wissensquellen. Ein Lookup liest Ihr System aus; er darf einen Datensatz weder belasten, stornieren, reservieren noch anderweitig ändern. Allgemeine Auswahl- und Bestätigungskarten senden lediglich eine Nachricht des Besuchers. Für bestätigte Schreibvorgänge verwenden Sie Änderungsaktionen; für Kalenderreservierungen nutzen Sie Buchung mit Cal.com. Nur Bestätigungskarten, die an einen Ausführungslauf gebunden sind, autorisieren diese Vorgänge.
Aktion konfigurieren#
Öffnen Sie Agent → Aktionen. Erstellen Sie das Secret unter Angemeldete Kunden, speichern Sie es auf Ihrem Server und implementieren Sie die Kundenidentifikation. Fügen Sie unter Lookups einen Namen wie order_status hinzu, beschreiben Sie, wann der Agent ihn verwenden soll, und geben Sie Ihren öffentlichen HTTPS-Endpunkt ein. Deklarieren Sie nur die Eingaben, die Sie benötigen, zum Beispiel einen String order_id. Der Agent sieht das Tool als lookup_order_status.
Lassen Sie Angemeldeter Kunde erforderlich für private Datensätze aktiviert (Standardeinstellung). Ist die Option deaktiviert, können Anfragen customer: null enthalten; geben Sie dann nur Informationen zurück, die für einen anonymen Besucher geeignet sind. Eine im Chat genannte oder aus einem Foto extrahierte ID ist eine Eingabe, keine authentifizierte Identität.
Bestehende Felder werden automatisch gespeichert; warten Sie vor dem Testen auf die Speicheranzeige. Sie können einen Lookup aktivieren/deaktivieren, bearbeiten oder löschen. Das Panel setzt ein konfiguriertes Secret voraus. Diese Aktionen werden im Dashboard konfiguriert; Wave 1 bietet keine Verwaltung von Lookups über die öffentliche API.
Die Anfrage, die Sie erhalten#
Make Agent Fast sendet einen JSON-POST an Ihre konfigurierte URL. Die folgenden Beispiele verwenden Platzhalterwerte für die Signatur:
POST /agent/order-status HTTP/1.1
Content-Type: application/json
x-maf-timestamp: <unix-seconds>
x-maf-signature: v1=<64-lowercase-hex-characters>{
"version": 1,
"action": "order_status",
"requestId": "c5c1d94b-e88f-4bf6-8023-2dcd1e7ac67b",
"siteId": "YOUR_SITE_ID",
"input": { "order_id": "A128" },
"customer": { "id": "customer_123", "email": "customer@example.com" }
}action ist der konfigurierte Name ohne das Präfix lookup_. requestId identifiziert diesen Versuch; siteId identifiziert Ihre Website. input enthält nur deklarierte String-Parameter. customer ist entweder null oder das vom Server verifizierte Objekt { id, email?, name? }; Eingaben des Besuchers oder des Modells können es nicht ersetzen. Der Test im Dashboard verwendet bewusst den Beispielkunden, den ein autorisierter Owner eingegeben hat.
Signatur verifizieren#
Die Signatur ist ein hexadezimaler HMAC-SHA256 in Kleinbuchstaben, berechnet mit Ihrem Agent-Secret und mit dem Präfix v1=. Signiert wird exakt "maf-webhook-v1:" + timestamp + "." + rawBody. Bewahren Sie die empfangenen Bytes unverändert auf; Parsen und erneutes Serialisieren von JSON vor der Signaturprüfung kann sie verändern. Diese Hilfsfunktion akzeptiert eine standardmäßige serverseitige Request, wendet ein Aktualitätsfenster von fünf Minuten an und prüft die Website-ID:
import { createHmac, timingSafeEqual } from "node:crypto";
export async function verifyLookupRequest(request, expectedSiteId) {
const secret = process.env.MAF_SECRET_KEY;
if (!secret) throw new Error("MAF_SECRET_KEY is required");
const timestamp = request.headers.get("x-maf-timestamp");
const signature = request.headers.get("x-maf-signature");
const now = Math.floor(Date.now() / 1000);
if (!timestamp || !/^\d+$/.test(timestamp) ||
!Number.isSafeInteger(Number(timestamp)) ||
Math.abs(now - Number(timestamp)) > 300) {
throw new Error("Invalid timestamp");
}
if (!signature || !/^v1=[a-f0-9]{64}$/.test(signature)) {
throw new Error("Invalid signature");
}
const rawBody = Buffer.from(await request.arrayBuffer());
const expected = createHmac("sha256", secret)
.update(`maf-webhook-v1:${timestamp}.`)
.update(rawBody)
.digest();
const actual = Buffer.from(signature.slice(3), "hex");
if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {
throw new Error("Invalid signature");
}
const body = JSON.parse(rawBody.toString("utf8"));
if (body?.version !== 1 || body.siteId !== expectedSiteId) {
throw new Error("Invalid lookup scope");
}
return body;
}Rufen Sie die Funktion auf, bevor Ihr Body-Parser die Anfrage verarbeitet. Ihr Handler sollte Verifizierungsfehler ablehnen, die erwartete Aktion und die Struktur der Eingaben validieren und die Zugehörigkeit des Datensatzes anhand von body.customer.id prüfen, bevor er private Daten zurückgibt. Wählen Sie beispielsweise Bestellung A128 aus den Bestellungen dieses Kunden aus, nicht allein anhand der Bestell-ID. Verwenden Sie niemals input.customer_id, eine im Chat angegebene E-Mail-Adresse oder ein Foto als Autorisierung. Verlangen Sie für private Endpunkte einen Kunden, der nicht null ist. Begrenzen Sie die Größe eingehender Bodys auf Ihrem Server und protokollieren Sie requestId innerhalb des Aktualitätsfensters, wenn Sie Replay-Angriffe abweisen möchten; die Zeitstempelprüfung allein weist einen Replay innerhalb dieses Fensters nicht ab.
Verwenden Sie HTTPS und halten Sie diesen Endpunkt schreibgeschützt, auch wenn der Transport per POST erfolgt. Aktualisieren Sie nach einer Rotation des Agent-Secrets sowohl Ihren Server zur Identitätssignierung als auch Ihren Lookup-Verifizierer.
Antwort zurückgeben#
Antworten Sie mit einem erfolgreichen 2xx-Status und JSON, das diesem Vertrag entspricht. Das erste Beispiel zeigt einen gefundenen Datensatz, das zweite ein normales Ergebnis ohne Treffer:
{
"found": true,
"card": {
"title": "Order #A128",
"status": { "label": "Shipped", "tone": "success" },
"fields": [{ "label": "Carrier", "value": "DHL" }],
"reference": "A128",
"asOf": "2026-10-12T09:00:00Z",
"link": { "label": "Track", "url": "https://shop.example.com/orders/A128" }
},
"facts": { "order_id": "A128", "status": "shipped", "carrier": "DHL" }
}{ "found": false }found ist erforderlich. Bei found: true geben Sie card, facts oder beides an. Eine Karte benötigt title und fields (ein leeres Array ist zulässig). Optionale Felder sind status, reference, asOf und link. Fügen Sie der Antwortkarte kein kind hinzu. Die Status-Tonalitäten sind neutral, success, warning und danger. Verwenden Sie für asOf einen ISO-Zeitstempel und für den Link eine HTTPS-URL ohne eingebettete Zugangsdaten. Ungültige optionale Links werden weggelassen.
facts ist ein flaches Objekt, dessen Werte Strings, endliche Zahlen, Booleans oder null sind; verschachtelte Objekte und Arrays werden abgelehnt. Unbekannte Felder im Antwort- bzw. Kartenschema werden abgelehnt. Geben Sie nur die Informationen zurück, die zur Beantwortung nötig sind: Das Modell erhält maskierte, begrenzte Daten, die als nicht vertrauenswürdig gekennzeichnet sind und keine Anweisungen darstellen. Karteninhalt ist reiner Text, kein HTML.
Limits und Verhalten bei Fehlern#
| Element | Limit |
|---|---|
| Lookups pro Agent | 5; eindeutige Namen und IDs |
| Name | ^[a-z][a-z0-9_]{2,39}$; reservierte Aktionsnamen sind nicht verfügbar |
| Beschreibung | 300 Zeichen |
| Deklarierte Eingaben | 3; eindeutige Namen gemäß ^[a-z][a-z0-9_]{1,31}$ |
| Beschreibungen / Werte der Eingaben | 300 / 200 Zeichen; Werte werden getrimmt |
| Endpunkt | Öffentliches HTTPS, bis zu 500 Zeichen, keine Zugangsdaten; private/interne Adressen werden blockiert; Weiterleitungen werden nicht verfolgt |
| Timeout / Antwort-Body | 8 Sekunden / 32 KiB (32.768 Bytes) |
| Modelldaten | 2.000 Zeichen, getrennt von der Karte für den Besucher |
| Kartentitel / Labels / Feldwerte | 80 / 40 / 200 Zeichen |
| Kartenfelder | 8; höchstens 3 Karten pro Agent-Zug |
Fehlt die Kundenidentität, wird eine Anmeldewarnung angezeigt, ohne dass Ihr Endpunkt aufgerufen wird. Fehlen erforderliche Eingaben, fordert der Agent den Besucher dazu auf. found: false zeigt eine neutrale Karte ohne Treffer an. Timeouts, Nicht-2xx-Status, ungültiges JSON bzw. Schema oder zu große Antworten zeigen einen Fehlerstatus an und weisen das Modell an, nicht zu raten. Geben Sie für einen gewöhnlich fehlenden Datensatz found: false mit 2xx zurück, statt HTTP 404. Halten Sie wichtige Fakten knapp: Überlange Kartenstrings und Modelldaten werden gekürzt.
Im Dashboard testen#
- Speichern Sie den Lookup und öffnen Sie Test. Geben Sie eine Beispiel-Kunden-ID, optional eine E-Mail-Adresse und alle erforderlichen Eingaben ein. Verwenden Sie ein Konto, das Sie kontrollieren.
- Führen Sie den Test aus. Dabei wird eine echte signierte Anfrage gesendet, auch wenn der Lookup für Besucher deaktiviert ist; der gewöhnliche Probechat ruft den Endpunkt nie auf. Das Dashboard begrenzt Testversuche pro Owner.
- Prüfen Sie die validierte Karte bzw. Zusammenfassung oder den Fehler, die Anfrage-ID, die Dauer und gegebenenfalls den HTTP-Status. Kontrollieren Sie die Logs Ihres Endpunkts, ohne Secrets oder Kunden-Tokens aufzuzeichnen.
- Testen Sie die Fälle „gefunden“, „nicht gefunden“, „falsches Konto“, „fehlende Eingabe“ und „Timeout“. Testen Sie anschließend das echte Embed mit zwei authentifizierten Kunden; ein Beispiel im Dashboard belegt weder die Isolation der Browser-Identität noch die tatsächliche Tool-Auswahl durch das Modell.
Das Widget zeigt Statuskarten an; allgemeine Auswahl-/Bestätigungsantippen senden ihre Beschriftungen als Nachrichten. Bestätigungen für Änderungen und Buchungen, die an einen Ausführungslauf gebunden sind, nutzen stattdessen den geschützten Ausführungsablauf. Connectors passen Karten an native Text-/Kartenformate und Schaltflächen, Schnellantworten oder Listen an, mit Text-Fallback gemäß den Limits des jeweiligen Channels. Testen Sie jeden vorgesehenen Channel, bevor Sie sich auf die Zustellung verlassen.