· 2 min read · ← All posts
Ardan Labs Go SQL Agents Security

Field notes from working through example 15 of Ardan Labs’ Ultimate AI course by Bill Kennedy and Florin Pățan (Apache 2.0). My fork: PratikDhanave/ai-training. Thank you Bill and Florin for teaching this material — the patterns in this post are derived from the course; the production reflections at the end are mine.

What the example teaches

The minimum-viable NL→SQL tool that doesn’t drop your tables.

What it looks like

func runSQL(ctx context.Context, query string) (Rows, error) {
    // Parse — refuse anything that isn't a single SELECT.
    parsed, err := pgparser.Parse(query)
    if err != nil {
        return nil, fmt.Errorf("invalid SQL: %w", err)
    }
    if len(parsed.Stmts) != 1 {
        return nil, ErrMultipleStatements
    }
    if !isSelectStmt(parsed.Stmts[0]) {
        return nil, ErrNotSelect
    }

    // Allow-listed table check
    for _, table := range tablesIn(parsed.Stmts[0]) {
        if !allowedTables[table] {
            return nil, fmt.Errorf("table %s not in allow-list", table)
        }
    }

    // Strict timeout
    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()

    return db.QueryContext(ctx, query)
}

What I learned

SQL parsing in the tool is more robust than prompt-instructing the LLM. Telling the LLM “only generate SELECT” works most of the time. Refusing non-SELECT after parsing works all of the time.

Table allow-list is the second line. Even with SELECT-only, an LLM might join against the users table when you don’t want it touching PII. Allow-listing tables to a domain-appropriate subset narrows the blast radius.

Production connection

For one Searce client we built a “chat with your sales data” feature. The SQL tool was 90% of the safety story. The other 10% was per-user RLS at the database — a user’s chat agent could only see rows for that user’s territory. Pattern from Ardan; production layering from Genie.


Credit & reference. This post is field notes on example 15 from Ardan Labs’ Ultimate AI by Bill Kennedy + Florin Pățan, licensed Apache 2.0. The original example: cmd/examples/example15-sql-tool/. My fork with notes: PratikDhanave/ai-training. Highly recommend the course for anyone building AI applications in Go — the material is rigorous and the Kronk + yzma + llama.cpp pipeline gives you hardware-accelerated local inference end-to-end. Thank you, Bill and Florin.

← Back to all posts