So funktioniert es
Das Modell schlägt vor.
SQAI entscheidet.
Ein Agent schreibt weder SQL noch ausführbaren Code. Er formuliert eine typisierte Anfrage — und jede Anfrage durchläuft dieselbe Strecke: Validierung gegen einen versionierten Vertrag, Prüfung gegen Ihre Richtlinie, Ausführung auf einer deterministischen Engine, Rückgabe mit den Hashes, die sie reproduzierbar machen.
Jede Anfrage — ask(), compute() oder ein AI SDK Tool Call — durchläuft dieselbe Strecke. Nichts erreicht die Engine, bevor jede Prüfung bestanden ist.
01Typisierte Anfrage
Eine Anfrage, die die Engine parsen kann. Kein String, dem sie vertrauen muss.
Das Modell gibt ein typisiertes Objekt aus — niemals SQL, niemals Code. Eine Abfrageabsicht ist ein QuerySpec: eine Metrik, die über eine benannte Quelle aggregiert wird. Eine Berechnungsabsicht ist ein ComputationSpec: eine benannte Funktion aus dem Vertrag, mit Argumenten und Bindungen. Eine diskriminierte Union, zwei Formen — und in keiner davon Platz für einen ausführbaren String.
Das ist die gesamte Authoring-Oberfläche. Was die Form nicht ausdrücken kann, kann das Modell nicht anfordern.
QuerySpecAufbau{"kind": "query",der Union-Tag — Abfrage oder Berechnung"version": "1",die Spec-Version, fixiert"source_name": "sales",eine verbundene Quelle, beim genauen Namen"metric": "revenue",die zu aggregierende Spalte"aggregation": "sum",eines von sum · avg · count · min · max"group_by": "region"optional — Ergebnis nach einem Feld aufteilen}ebenfalls optionalfilter · limit · order
die Berechnungsformmodule · function · args · kwargs · bindings · seed?
02Vertragsvalidierung
Ein Vertrag, hash-fixiert. Das Unbekannte wird mit Hinweisen abgewiesen.
Die Spec wird gegen den Capability-Vertrag validiert — eine generierte, hash-fixierte Datei, die jede Operation, ihre genaue Signatur und ihre Determinismus-Flags auflistet. Eine Capability ist nur erreichbar, wenn sie lesend und deterministisch ist oder deterministisch bei gesetztem Seed. Schreibende und nicht-deterministische Operationen werden nicht zur Laufzeit blockiert; sie wurden erst gar nicht in die Oberfläche generiert.
Eine unbekannte Funktion schlägt als unsupported_operation fehl und antwortet mit nearest_matches aus demselben Index — das Modell korrigiert sich selbst, anstatt in eine Schleife zu geraten.
contract_hashsha256:79f1c5a6c7164e7e9e1750e70a5c03292fa87eb52d8148a740c06695924be9a1
- 4,778
- im Vertrag aufgeführte Operationen
- 4,574
- den SDKs zugänglich, lesend
- 4,564
- vollständig deterministisch
- 10
- seed-pflichtige Simulationen
- 204
- von der Oberfläche ausgeschlossen
Zulässigkeitread_only && (deterministic || deterministic_when_seeded)
bei unbekanntem Namenunsupported_operation + nearest_matches
03Richtlinienprüfung
Ihre Positivliste entscheidet, ob — und wie — es ausgeführt wird.
Die Richtlinie wird beim Konstruieren der Instanz durch createSQAI() festgelegt und prozessintern durchgesetzt, bevor irgendetwas ausgeführt wird — auf der Quelle, auf jeder Metrik, Gruppe, jedem Filter und jeder gebundenen Spalte sowie auf dem Funktionsnamen. Sie kann den Vertrag nur einschränken: Eine Capability außerhalb der zulässigen Oberfläche zu benennen, löst weiterhin unsupported_operation aus.
Die Tool-Eingabe des Modells enthält kein allowed*-Feld. Nichts in der Anfrage kann den Zugriff erweitern — es gibt also nichts, das eine Prompt-Injection ausweiten könnte.
allowedSourcesQuellen, die das Modell benennen darf
- "sales"
allowedFieldsSpalten, die es lesen darf, je Quelle
- sales.region
- sales.revenue
- sales.order_date
allowedFunctionsder Standard — jede lesende Capability, nicht mehr
- "all-readonly"
eine Ablehnung ist präzise, zugeordnet, endgültig
- policy_denied_source
- policy_denied_field
- policy_denied_function
source: "sqai" · nicht wiederholbar
04Deterministische Engine
Fixiert vor der Ausführung: float64, ein Thread, eine Runtime.
Zuerst werden Bindungen aufgelöst. Das Modell hat eine Quelle und ein Feld benannt; SQAI zieht die tatsächlichen Werte über das zeilenausgerichtete extractColumns-Primitiv der Engine, Nullwerte paarweise behandelt. SQAI zippt Arrays nie selbst — der gehashte Input ist damit exakt der Input, der ausgeführt wurde.
Erst jetzt erreicht die Anfrage die Engine. Die Runtime ist signiert, versioniert und fixiert: float64-Präzision, ein einzelner Thread. Das erste compute() provisioniert sie einmalig in etwa 110 Sekunden; danach bleibt sie resident — finance.npv misst 0,83–0,93 ms im Warmzustand.
0.1.04d64142e4c1ff63d299cfc8b172fdf97cb59169b545e1e02978e678a632ce6e1darwinarm64float641—2ea5ede72acd2912fe9e1230cef34afad4c9436bfa8a709bac2da02b478e3212Mit jedem Ergebnis aufgezeichnet — der Envelope benennt den Geltungsbereich der Garantie, ohne ihn zu überdehnen.
05Antwort + Herkunft
Zwei Hashes. Einer davor, einer danach.
invocation_hash wird vor der Ausführung gestempelt — über Modul, Funktion, Argumente, aufgelöste Bindungen, Seed, Vertrag und Scope. computation_hash wird danach gestempelt: der Invocation-Hash gefaltet mit dem kanonischen Ergebnis. Replay bedeutet: erneut ausführen und Bytes vergleichen.
Beide SDKs teilen einen kanonischen Serializer, sodass dieselbe Berechnung byte-identische Hashes in TypeScript und Python liefert. Abfrageantworten unterliegen derselben Disziplin: ein plan_hash über den kanonisch aufgelösten Plan, ergänzt um den Entscheidungspfad und den genauen Scope, in dem er ausgeführt wurde.
3188.1687606249325finance.npv · an eine Live-Spalte gebunden · 0,83 ms warm
vor der Ausführung gestempelt
invocation_hash
8223a694250fc751fcf8a7777b8e1f524c44ff1f0e7e83451467f554a6123950
Modul · Funktion · Argumente · aufgelöste Bindungen · Seed · Vertrag · Geltungsbereich
gestempelt nach der Ausführung
computation_hash
ff5280ea128113f528dd1e9a28b9bc4a81469075ed7c981c7176fb172d98085d
der Aufruf-Hash, gefaltet mit dem kanonischen Ergebnis
Byteidentisch in TypeScript und Python — ein in einer Sprache berechnetes Ergebnis lässt sich in der anderen wiedergeben und verifizieren.
beide berechnet gegencontract_hash sha256:79f1c5a6…
auf der Query-Ebeneplan_hash f87610d8afeb…decision_path "exact_spec"deterministic_scope "local_registered_source"
06Der Discovery-Loop
Nie raten. Entdecken, trocken laufen lassen, dann ausführen.
Feldnamen und Funktionssignaturen werden entdeckt, nicht halluziniert. Das AI SDK stellt genau drei Tools bereit — und nur eines davon führt aus.
- 01
listSources()Was kann ich anfassen?
Verbundene Quellen mit exakten Feldnamen, Typen und den erlaubten Operationen je Feld. Führt nie aus.
- 02
listSources({ capabilitySearch: "npv" })Was kann ich berechnen?
Dasselbe Tool, das den deterministischen Katalog durchsucht — passende Module, exakte Signaturen und ob ein Seed erforderlich ist.
- 03
explainQuery({ … })Wird es laufen?
Ein Trockenlauf. Gibt den aufgelösten Plan, die Konfidenz und einen vorläufigen invocation_hash zurück — eine Vorschau, kein ausgeführter Hash.
- 04
queryData({ … })Ausführen.
Das einzige Tool, das ausführt. Gibt das Ergebnis samt vollständiger Herkunft zurück; zu große Ergebnisse bleiben per result_id abrufbar.
Die Tools werfen nie — jedes Ergebnis ist typisiertok · needs_clarification · rejected · error
Die Mechanik, Feld für Feld.
Dokumentation lesen →- Deterministisches AIder Envelope und die drei Hashes, Feld für Feld
- AI-Daten-GovernanceAllow-Listen und die Narrow-only-Regel, in der Tiefe
- Daten verbindenjede Quelle landet in derselben typisierten Form