एजेंट्स के लिए — नियंत्रित डेटा टूल

AI एजेंट टूल
जो प्रमाण सहित उत्तर देते हैं।

SQAI एक टूल-कॉलिंग मॉडल को तीन नियंत्रित टूल के माध्यम से संरचित डेटा तक रीड-ओनली पहुँच देता है। मॉडल टाइप्ड इंटेंट लिखता है। एक कॉन्ट्रैक्ट और आपकी पॉलिसी उसे जाँचती है। एक निर्धारक इंजन उसे निष्पादित करता है। हर उत्तर एक हैश के साथ लौटता है जो उसे दोबारा चला सकता है।

Iलूप का एक चक्र

अनुरोध प्रवेश करता हैकिस क्षेत्र में कुल राजस्व सर्वाधिक था?
कोई भी टूल-कॉलिंग मॉडलमॉडल

चरण योजना बनाता है। इंटेंट लिखता है। डेटा को कभी नहीं छूता।

टूल कॉल — टाइप्ड इंटेंट, SQL नहीं{ version:"1", kind:"query", spec:{ metric:"revenue", aggregation:"sum", group_by:"region", source:"sales" } }
नियंत्रित टूलSQAI
  1. contractहैश-पिन्ड कैपेबिलिटी कॉन्ट्रैक्ट
  2. policyआपकी अनुमति सूचियाँ, एक्ज़ीक्यूशन से पहले जाँची गईं
  3. engineनिर्धारक, रीड-ओनली एक्ज़ीक्यूशन
टाइप्ड स्टेटस — कभी थ्रो नहींstatus: ok · needs_clarification · rejected · error
उत्तर निकलता है — अपने हैश के साथeast — 2,130.50 · plan_hash f87610d8afeb…
ok

लूप से बाहर। पंक्तियाँ या मान — और वह हैश जो उन्हें दोबारा चला सकता है।

needs_clarification ↺

लूप में पुनः प्रवेश। एक प्रश्न और उसके मिले उम्मीदवार — मॉडल स्पेक परिष्कृत करता है और फिर से कॉल करता है। यह कभी कोई कॉलम अनुमान नहीं लगाता।

रिजेक्टेड और एरर एक ही रिटर्न लेन से आते हैं — टाइप्ड परिणाम जो मॉडल पढ़ सकता है, न कि अपवाद जो रन को बाधित करें।

IIटूलसेट

तीन टूल। एक निष्पादित करता है।

sqai.tools() ठीक तीन टूल लौटाता है — एक जानबूझकर छोटी सतह। डिस्कवरी और ड्राई रन कभी निष्पादित नहीं होते; निष्पादन ठीक एक स्थान पर होता है।

listSources

कभी निष्पादित नहीं होता

डिस्कवरी। टाइप्ड फ़ील्ड वाले कनेक्टेड सोर्स, कैपेबिलिटी मॉड्यूल, फ़ंक्शन सिग्नेचर — एक इनपुट से तीन मोड, ताकि specs सटीक नाम उपयोग करें।

sources · capabilitySearch · module
ops: sum avg count min max eq in gt gte lt lte is_null is_not_null

queryData

जो execute करता है

एक versioned इनपुट — kind पर discriminated union: एक query या computation। चार outcomes, हमेशा typed, कभी throw नहीं।

version "1" · kind: query | computation
ok · needs_clarification · rejected · error

explainQuery

dry run — कभी execute नहीं होता

किसी intent को बिना चलाए resolve और validate करता है। मॉडल इसे clarifications debug करने के लिए उपयोग करता है; आप इसे plan preview करने के लिए।

preview invocation_hash ≠ executed hash

यह सेट सीधे generateText या streamText में जाता है — typed, बिना किसी cast के assignable। Vercel AI SDK सेटअप

IIIएरर कॉन्ट्रैक्ट

Tools कभी throw नहीं करते।

एक exception एजेंट रन को रोक देता है। इसलिए यहाँ कुछ भी throw नहीं होता: अस्पष्टता, अस्वीकृति, और विफलता — सब typed statuses के रूप में वापस आते हैं जिन्हें मॉडल अपने step budget के भीतर पढ़ और सुधार सकता है।

retryable transient वाले चिह्नित करता है — network_error · timeout · rate_limited · service_unavailable

queryData — चार outcomes

okपरिणाम: rows या value, provenance hashes, घोषित truncation।plan_hash · invocation_hash · computation_hash · truncated
needs_clarificationintent अस्पष्ट था। एक प्रश्न और candidates — कभी अनुमान नहीं।question · candidates · explanation
rejectedresolver ने intent अस्वीकार किया। कुछ execute नहीं हुआ।rejection_reason · candidates · explanation
errorएक stable code के साथ structured विफलता — मॉडल इसे पढ़कर समायोजन करता है।code · message · retryable · nearest_matches?

हर branch डेटा है। लूप अपनी बारी बनाए रखता है।

सिद्धांत

मॉडल को मानें
एक अविश्वसनीय client।

नीति कोड में · किसी tool इनपुट में policy फ़ील्ड नहीं · केवल संकुचन

IVसिद्धांत, व्यवहार में

उद्योग ने यह production में सीखा — एक autonomous coding agent ने एक live database कुख्यात रूप से हटा दिया। SQAI का उत्तर structural है, behavioral नहीं: exposed surface निर्माण से ही read-only है। Write और non-deterministic श्रेणियाँ कभी इसमें generate नहीं होतीं, और कोई flag, policy, या मॉडल इनपुट उन्हें वापस चालू नहीं करता।

मॉडल क्या भेजता है
केवल typed intent — एक versioned spec। कोई SQL string नहीं, कोई code नहीं, कोई connection handle नहीं।
वह क्या कभी नहीं भेज सकता
Policy। allowedSources, allowedFields और allowedFunctions createSQAI() config में fixed हैं — किसी tool input schema में policy फ़ील्ड नहीं है, इसलिए एक request surface को संकुचित कर सकती है, पर कभी विस्तृत नहीं।
जब वह फिर भी माँगे
एक structured अस्वीकृति — policy_denied_source, policy_denied_field, policy_denied_function। Non-retryable, मॉडल-readable, और रन जारी रहता है।
पूर्ण policy मॉडल

Vवायरिंग

तीन लाइनें। डिफ़ॉल्ट से bounded।

एक package client को tools में wrap करता है। Sources पहली call पर lazily connect होते हैं; पहला computation runtime एक बार provision करता है, फिर warm रहता है — 0.83 ms मापा गया।

import { generateText } from "ai";
import { createSQAI } from "@thyn-ai/sqai-ai-sdk";

const sqai = createSQAI({
  sources: [{ data: "./data/sales.csv", name: "sales" }],
});

const { text, steps } = await generateText({
  model,                  // any AI SDK model
  tools: sqai.tools(),    // listSources · queryData · explainQuery
  prompt: "Which region had the highest total revenue?",
});
ai ^7.0.0zod ^4.0.0node ≥ 20runtime = "nodejs"

केवल server-side — Next.js पर Node runtime रखें, Edge नहीं।

मॉडल तक क्या पहुँचता है

maxRowsToModel
25मॉडल को दिखने वाली rows, engine द्वारा execute की गई सभी चीज़ों में से
maxCellsToModel
250cell budget — fit करने के लिए पूरी rows हटाई जाती हैं; आधी row कभी नहीं दिखाई जाती
maxBytesToModel
32,000मॉडल-visible value के लिए byte budget
maxExecutionRows
1,000engine द्वारा execute की जाने वाली hard cap — जब spec में limit न हो तो defaultLimit 100

Truncation हमेशा घोषित होती है — truncated: true, returned_rows < total_rows। कभी मौन नहीं। पूर्ण परिणाम application code में result_id द्वारा retrievable रहते हैं।

VIएजेंटिक विश्लेषण

विश्लेषण जिसे एजेंट सिद्ध कर सके।

Agentic analytics ज्ञात तरीकों से विफल होता है: malformed tool calls, मॉडल का स्वयं अंकगणित करना, प्रशंसनीय संख्याएँ जिन्हें कोई सत्यापित नहीं कर सकता। हर एक का उत्तर structural है, बेहतर prompt से नहीं।

01अमान्य tool calls

एक versioned इनपुट, कुछ भी चलने से पहले validated। Malformed या अस्पष्ट intent एक typed status लौटाता है — loop crash होने की बजाय जारी रहता है।

02मॉडल गणित करता है

यहाँ नहीं। engine compute करता है। 16 quantitative प्रश्नों के सेट पर, वही मॉडल 0/16 से 16/16 हो गया जब engine ने computing की।

03असत्यापनीय संख्याएँ

हर उत्तर अपना hash लेकर आता है। उसी intent को उसी data पर replay करें और hash मेल खाता है — TypeScript और Python में byte-identical।

04विलंबता संचय

एक loop latency को गुणित करता है। Query plane in-process sub-millisecond पर चलता है; warm compute 0.83 ms मापा गया।

VIIप्रश्न

एजेंट्स के लिए — प्रश्न

मैं किसी AI एजेंट को database तक read-only access कैसे दूँ?

SQL फ़िल्टर न करें — generate ही न करें। Sources को createSQAI() से connect करें और मॉडल को sqai.tools() दें: वह जिस surface तक पहुँचता है वह निर्माण से ही 4,574 read-only capabilities और आपके sources हैं, कोई write path नहीं। ब्लॉक करने के लिए कोई write category नहीं है, और कोई मॉडल इनपुट नहीं जो उसे पुनः सक्षम करे।

एजेंट का अनुरोध अस्पष्ट हो तो क्या होता है?

queryData, needs_clarification के साथ एक प्रश्न और उसे मिले संभावित फ़ील्ड लौटाता है। यह कभी कोई कॉलम अनुमान नहीं लगाता। मॉडल प्रश्न का उत्तर देता है और पुनः कॉल करता है — लूप का एक और चक्र।

क्या टूल कभी exception फेंकते हैं?

नहीं। हर विफलता एक संरचित परिणाम है — एक स्थिर कोड, एक संदेश, और एक retryable फ़्लैग के साथ। अस्पष्टता, अस्वीकृति, नीति-निषेध, और क्षणिक त्रुटियाँ — सभी डेटा के रूप में लौटती हैं जिसे मॉडल पढ़ सकता है।

क्या मॉडल अपनी अनुमतियाँ स्वयं बढ़ा सकता है?

नहीं। allowedSources, allowedFields और allowedFunctions कोड में रहते हैं — createSQAI() के समय निर्धारित और निष्पादन से पहले जाँचे जाते हैं। किसी भी टूल के input schema में कोई policy फ़ील्ड नहीं है; किसी निषिद्ध क्षमता का नाम लेने पर एक संरचित policy_denied त्रुटि मिलती है।

क्या यह Vercel AI SDK के साथ काम करता है?

हाँ — @thyn-ai/sqai-ai-sdk तीनों टूल को generateText और streamText के लिए एक typed tool set के रूप में प्रदान करता है, जिसमें ai ^7.0.0 और zod ^4.0.0 peer dependencies हैं, Node 20 या उससे नया, server-side। अंतर्निहित क्लाइंट वही SDK है जिसे आप किसी भी एजेंट लूप में जोड़ सकते हैं।