Skip to main content

Natural language to SQL — the dbt companion for AI-powered data workflows

Project description

tabletalk — dbt for agents

Define your data sources once. Deploy an AI agent for every dataset. Redeploy anytime your schema changes — like Terraform for analytics agents.

tabletalk lets you declaratively define which data an AI agent can see, then deploy that agent as a natural-language SQL interface. The workflow mirrors tools you already know:

┌─────────────────────────────────────────────────────────────┐
│  dbt analogy                    terraform analogy            │
│                                                              │
│  contexts/*.yaml  ≈ sources.yml  ≈  resource "agent" {}     │
│  manifest/*.txt   ≈ manifest.json ≈  .tfstate                │
│  tabletalk apply  ≈ dbt compile   ≈  terraform apply         │
│  tabletalk query  ≈ dbt run       ≈  agent is "live"         │
└─────────────────────────────────────────────────────────────┘

The core idea

In dbt, you define models that transform raw tables into analytics-ready datasets. In tabletalk, you define contexts that scope what data an agent can see — then the agent uses an LLM to answer questions about that data.

# contexts/sales.yaml  — defines a "Sales Analyst" agent
name: sales
description: "Order processing, revenue, and product analysis"
datasets:
  - name: public
    tables:
      - name: orders
        description: "Customer orders with status and totals"
      - name: order_items
        description: "Line items  FK to orders and products"
      - name: products
        description: "Product catalogue with pricing"

Run tabletalk apply and the agent is deployed. Ask it anything:

> What is total revenue this month?
→ SELECT SUM(total_amount) FROM orders WHERE ...

> Which products drive the most revenue?
→ SELECT p.name, SUM(oi.unit_price * oi.quantity) AS revenue ...

> Break that down by category
→ (follows up on the previous query using conversation context)

Installation

# Core (includes SQLite — no extra driver needed)
pip install tabletalk

# With your database driver
pip install "tabletalk[duckdb]"     # DuckDB
pip install "tabletalk[postgres]"   # PostgreSQL
pip install "tabletalk[snowflake]"  # Snowflake
pip install "tabletalk[mysql]"      # MySQL
pip install "tabletalk[bigquery]"   # BigQuery
pip install "tabletalk[azuresql]"   # Azure SQL / SQL Server
pip install "tabletalk[all]"        # Everything

Quick start

Option A — no API key (Ollama, runs locally):

# 1. Install Ollama → https://ollama.com, then:
ollama pull qwen2.5-coder:7b

# 2. In tabletalk.yaml, set:
#   llm:
#     provider: ollama
#     api_key: ollama
#     model: qwen2.5-coder:7b
#     base_url: http://localhost:11434/v1

Option B — cloud LLM:

export OPENAI_API_KEY=sk-...      # or ANTHROPIC_API_KEY
# set provider: openai / anthropic in tabletalk.yaml

Then:

# 1. Initialize a new project
tabletalk init

# 2. Configure your database connection
tabletalk connect                      # interactive wizard
# or: tabletalk connect --from-dbt my_dbt_project   (import from dbt)

# 3. Edit contexts/default_context.yaml to match your schema

# 4. Deploy your agents (compile + introspect)
tabletalk apply

# 5. Query with an agent (interactive CLI)
tabletalk query

# 6. Launch the web UI
tabletalk serve

Project structure

my_project/
├── tabletalk.yaml          # Database + LLM config
│
├── contexts/               # Agent definitions — one file = one agent
│   ├── sales.yaml          # "Sales Analyst" — sees orders + products
│   ├── customers.yaml      # "Customer Analyst" — sees customer profiles
│   ├── inventory.yaml      # "Inventory Manager" — sees stock levels
│   └── marketing.yaml      # "Marketing Analyst" — sees campaigns
│
└── manifest/               # Compiled manifests (auto-generated by apply)
    ├── sales.txt
    ├── customers.txt
    ├── inventory.txt
    └── marketing.txt

tabletalk.yaml

# Option A — inline connection
provider:
  type: postgres              # postgres | snowflake | duckdb | azuresql
  host: localhost             #           bigquery  | mysql  | sqlite
  port: 5432
  database: analytics
  user: analyst
  password: ${DB_PASSWORD}   # read from environment variable

# Option B — reference a saved profile (recommended)
# profile: my_prod_snowflake  (run `tabletalk connect` to create profiles)

llm:
  provider: openai            # openai | anthropic | ollama
  api_key: ${OPENAI_API_KEY}
  model: gpt-4o
  max_tokens: 1000
  temperature: 0

contexts: contexts            # directory with agent context definitions
output: manifest              # directory where compiled manifests are written
description: "Production analytics database"

Context definitions

Each .yaml file in contexts/ defines one agent — what data it can see and a human-readable description that becomes part of its system prompt.

# contexts/customers.yaml
name: customers
description: "Customer profiles, acquisition, and lifetime value"
version: "1.0"

datasets:
  - name: public                       # database schema name
    description: "Main schema"
    tables:
      - name: customers
        description: >-
          One row per registered customer.
          lifetime_value tracks cumulative spend.
          Use city/country for geographic segmentation.

      - name: subscriptions
        description: >-
          Active and cancelled subscriptions.
          FK: customer_id → customers.id
          status: active | trialing | cancelled | past_due

The description is the most important field. It tells the LLM what each table is for — not just what it contains. Good descriptions make agents dramatically more accurate.


The deploy lifecycle

# Initial deploy
tabletalk apply

# Schema changed? Redeploy:
vim contexts/sales.yaml        # update table or description
tabletalk apply                # recompiles manifest (like terraform apply)
tabletalk query                # agent now uses updated schema

# Check if redeploy is needed:
tabletalk apply                # tabletalk warns if contexts are stale

Under the hood, tabletalk apply:

  1. Reads every .yaml in contexts/
  2. Introspects the live database (PK/FK detection, column types)
  3. Merges your human descriptions with the introspected schema
  4. Writes manifest/*.txt — compact schema text injected into the LLM prompt

Commands

Command Description
tabletalk init Scaffold a new project
tabletalk apply [dir] Introspect DB + compile manifests
tabletalk query [dir] Interactive agent CLI session
tabletalk serve Web UI at http://localhost:5000
tabletalk connect Save a database connection profile
tabletalk connect --from-dbt PROJECT Import from ~/.dbt/profiles.yml
tabletalk history [dir] View recent queries
tabletalk profiles list List saved profiles
tabletalk profiles delete NAME Remove a profile
tabletalk profiles test NAME Test a saved connection

Query session commands

Inside tabletalk query:

Input Action
Any question Generate SQL (streaming)
change Switch to a different manifest/agent
history Show recent queries for this session
clear Clear conversation context
exit Quit

Options:

tabletalk query --execute          # execute generated SQL and show results
tabletalk query --execute --explain  # also stream a plain-English explanation
tabletalk query --output data.csv  # save results to CSV
tabletalk query --no-context       # disable multi-turn conversation

Web UI

tabletalk serve            # http://localhost:5000
tabletalk serve --port 8080
tabletalk serve --debug

The web UI provides:

  • Manifest/agent selector
  • Streaming SQL generation (token-by-token)
  • Automatic execution with tabular results
  • Plain-English explanation of results
  • Suggested follow-up questions
  • Favorites management
  • Query history

Supported databases

Database Extra Connection
SQLite (none) type: sqlite
DuckDB tabletalk[duckdb] type: duckdb
PostgreSQL tabletalk[postgres] type: postgres
MySQL tabletalk[mysql] type: mysql
Snowflake tabletalk[snowflake] type: snowflake
BigQuery tabletalk[bigquery] type: bigquery
Azure SQL tabletalk[azuresql] type: azuresql

Supported LLMs

Provider Config Models
Ollama (no key) provider: ollama qwen2.5-coder:7b (default), llama3.2, mistral, codellama, phi3
OpenAI provider: openai gpt-4o, gpt-4-turbo, gpt-3.5-turbo
Anthropic provider: anthropic claude-opus-4-6, claude-sonnet-4-6

Ollama config:

llm:
  provider: ollama
  api_key: ollama                      # placeholder — not validated
  model: qwen2.5-coder:7b              # any model you've pulled
  base_url: http://localhost:11434/v1  # default

Safe mode (read-only enforcement)

Set safe_mode: true in tabletalk.yaml to restrict execution to SELECT queries only. Any attempt to run DELETE, UPDATE, DROP, INSERT, etc. raises an error before it reaches the database.

safe_mode: true   # blocks all non-SELECT queries at the session level

This is the recommended setting when the agent is connected to a production database.


Environment variables

Variable Used by Purpose
OPENAI_API_KEY tabletalk.yaml ${OPENAI_API_KEY} OpenAI API key
ANTHROPIC_API_KEY tabletalk.yaml ${ANTHROPIC_API_KEY} Anthropic API key
DB_PASSWORD tabletalk.yaml ${DB_PASSWORD} Database password (any provider)
TABLETALK_SECRET_KEY Flask web UI Session signing key — set in production

Any ${VAR} placeholder in tabletalk.yaml is resolved from the environment at startup. An unset variable raises an error with the variable name.


Health check endpoint

The web UI exposes a /health endpoint suitable for Docker HEALTHCHECK and Kubernetes probes:

GET /health

Returns 200 {"status": "ok"} when manifests are compiled and ready, or 503 {"status": "degraded", "issues": [...]} with a description of what's missing.


Profile management

Profiles store connection credentials in ~/.tabletalk/profiles.yml — the same pattern as ~/.dbt/profiles.yml.

# Create a profile interactively
tabletalk connect

# Import from an existing dbt project
tabletalk connect --from-dbt my_dbt_project --target prod

# Reference in tabletalk.yaml
profile: my_snowflake_prod

Example project

See examples/ecommerce/ for a complete DuckDB-backed ecommerce example with 4 agents, seed data, and pre-generated manifests.

cd examples/ecommerce
pip install "tabletalk[duckdb]"
# Uses Ollama by default — no API key needed.
# Install Ollama → https://ollama.com, then: ollama pull qwen2.5-coder:7b
python seed.py          # create the database
tabletalk apply         # compile manifests
tabletalk query         # start querying (or: tabletalk serve)

Compact schema format

tabletalk uses a compact notation to fit full schema context into the LLM prompt efficiently:

public.orders|Customer orders|id:I[PK]|customer_id:I[FK:customers.id]|status:S|total:N
  • I = Integer, S = String, F = Float, N = Numeric, D = Date, TS = Timestamp, B = Boolean
  • [PK] = primary key
  • [FK:table.column] = foreign key — the LLM uses this to construct JOINs

Running tests

uv run pytest                          # all tests — SQLite + DuckDB, no external services
uv run pytest -k test_sqlite           # SQLite provider tests only
uv run pytest -k test_duckdb           # DuckDB provider tests (requires duckdb)
uv run pytest tabletalk/tests/test_cli.py       # CLI tests
uv run pytest tabletalk/tests/test_app.py       # Flask API tests
uv run pytest tabletalk/tests/test_interfaces.py  # Core session + parser tests

Tests for Postgres, MySQL, Snowflake, BigQuery, and Azure SQL are auto-skipped when the corresponding driver is not installed. Install the driver and set the relevant environment variables to activate those tests:

# PostgreSQL
uv add "tabletalk[postgres]"
# PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD

# Snowflake
uv add "tabletalk[snowflake]"
# SNOWFLAKE_ACCOUNT, SNOWFLAKE_USER, SNOWFLAKE_PASSWORD, SNOWFLAKE_DATABASE, SNOWFLAKE_WAREHOUSE

# BigQuery
uv add "tabletalk[bigquery]"
# BIGQUERY_PROJECT_ID, BIGQUERY_DATASET (+ GOOGLE_APPLICATION_CREDENTIALS or ADC)

# Azure SQL
uv add "tabletalk[azuresql]"
# AZURESQL_SERVER, AZURESQL_DATABASE, AZURESQL_USER, AZURESQL_PASSWORD

License

CC BY-NC 4.0 — free for non-commercial use. For commercial licensing: wtbates99@gmail.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tabletalk-0.2.0.tar.gz (263.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tabletalk-0.2.0-py3-none-any.whl (167.9 kB view details)

Uploaded Python 3

File details

Details for the file tabletalk-0.2.0.tar.gz.

File metadata

  • Download URL: tabletalk-0.2.0.tar.gz
  • Upload date:
  • Size: 263.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for tabletalk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5093e6bdade18c821017baf8bc472e748da13a8cdc29bfd073d9b57d32fb9972
MD5 75a2aa827eabc2264929205f25b94f6d
BLAKE2b-256 c9f6affa9fe6f3af12d00de661a6c053abd5df388f4f508d4fa945e7598411d2

See more details on using hashes here.

File details

Details for the file tabletalk-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: tabletalk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 167.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for tabletalk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dce69a1bb6298c79ff62d37a6b994c767f4a55631611c8466a73b9b5a27cbd77
MD5 fbb844dace98b9c6c7d0638886e1cc03
BLAKE2b-256 088ef7483da838b9df7a6236504d340caee68c65a63aa4a7c46d220bee3d6be5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page