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 der SQAI runtime, 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 SQAI-Bereitstellung, bevor jede Prüfung bestanden ist.
01Typisierte Anfrage
Eine Anfrage, die die SQAI-Bereitstellung 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
04SQAI runtime
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 SQAI runtime, 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 SQAI-Bereitstellung. Die SQAI 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