Substrata turns SQL Server into the workflow engine for AI. You register a Thread as a row — its Data carries the SPName to run when the answer lands. A fleet of polling workers takes it to the model under a strict JSON schema, and on completion AI.SetRun executes that stored procedure to continue the work — inside the database, where the data already lives. The API only exists so external apps can register the Thread and poll the result.
-- The AI answer just landed as a row. Now, inside the DB: -- 1 · read the procedure the caller armed in Thread.Data DECLARE @SPName NVARCHAR(500) = (SELECT SPName FROM AI.SPRun WHERE ID_Run = @pID_Run AND State = 1); -- 2 · continue the pipeline where the data already lives EXEC @SPName @pID_Run; -- ← your business SP runs on the AI result
The database runs your stored procedure on the AI result — completion is a database event, not an app event.
The business logic that consumes an AI answer lives in SQL Server — campaigns, customer intentions, the rules that fire next. Bolting a separate AI service on top means ETL round-trips, a second state store, and brittle glue: the model answers in one place, the pipeline advances in another, and nothing is transactional or auditable end to end.
Substrata inverts it. The database stays the source of truth and the orchestrator; the model call is the only thing that leaves the data tier — and it leaves asynchronously, so a slow external call never blocks a database connection.
The API enqueues, the database orchestrates, the workers execute. Follow a request as it moves through the system.
A thin .NET 8 facade. Token auth, Swagger, and Dapper calls to API.* stored procedures — each returns a single JSON string. No AI SDK lives here.
The orchestrator. Tables model the AI object graph and a callback registry; AI.Set* procedures write results and dynamically execute the armed business procedure.
Four BackgroundService "virtual processes" poll every 1–5 s, call the model with the schema and key handed to them by the poll, and write back. The only tier that touches the model.
The queue, state machine, and callbacks are SQL rows and procedures — not a separate broker.
When the model answers, the write-back procedure executes the next business procedure in the same scope.
Every response is contracted with a strict JSON schema, so answers are safe to persist and drive SQL.
Every assistant, thread, and run is a row. Restart a worker and it resumes from Complete = 0.
Model and provider key are resolved per row and handed to the worker — swap providers without redeploying.
The slow model call runs in the worker, so it never holds a database connection open.
Real endpoint shapes; illustrative values. Every call needs Authorization: Bearer <token>.
Register a thread with an SPName in its Data; when the AI resolves, that stored procedure runs to continue processing — all inside the database. Step through it.
EXEC @SPName @pID_Run;the pipeline advances inside the database.Honest version: the model call runs in a worker, but the database is the engine that orchestrates it.
CREATE PROCEDURE AI.SetRun @pID_Run INT, @pResponse NVARCHAR(MAX) = NULL, @pMessageResponse NVARCHAR(MAX) = NULL, @pError NVARCHAR(MAX) = NULL AS BEGIN UPDATE AI.Run SET Complete = 1 WHERE ID_Run = @pID_Run; IF @pError IS NULL BEGIN UPDATE AI.Run SET Response = @pResponse, Response_at = GETDATE(), MessageResponse = @pMessageResponse WHERE ID_Run = @pID_Run; BEGIN TRY DECLARE @SPName NVARCHAR(500) = (SELECT TOP 1 SPName FROM AI.SPRun WHERE State = 1 AND ID_Run = @pID_Run); IF @SPName IS NOT NULL BEGIN DECLARE @StartRun_at DATETIME = GETDATE(); EXEC @SPName @pID_Run; -- ← pipeline advances UPDATE AI.SPRun SET State = 0, StartRun_at = @StartRun_at, EndRun_at = GETDATE() WHERE ID_Run = @pID_Run; END END TRY BEGIN CATCH INSERT INTO logs.General (Source, LogType, LogMessage) VALUES ('AI.SetRun', 'Error', ERROR_MESSAGE()); END CATCH END END
Every AI interaction is a durable, auditable row; the model call is delegated so nothing blocks; and the business logic runs the instant the answer lands — from inside a stored procedure, transactional with the data it acts on. The API stays thin, the workers stay stateless, and the database stays the single source of truth.
Everything above is clickable — try the API explorer, step the Run → SP flow, and watch the console.