Custom Database Connectors

📋 Planned

Documentation Under Construction

This guide will show you how to implement a custom database connector by implementing the SqlRunner interface, allowing Vanna to connect to any SQL database.

Planned Content

  • The SqlRunner interface explained
  • Complete example implementation (e.g., for DuckDB or ClickHouse)
  • Handling connection management and pooling
  • Error handling and retries
  • Testing your custom runner
  • Row-level security considerations
  • Registering your custom runner with the agent

Want to contribute or suggest improvements? Open an issue on GitHub

The SqlRunner Interface

When complete, this will show:

from vanna.core.tool import SqlRunner, RunSqlToolArgs, ToolContext
import pandas as pd

class MyCustomDatabaseRunner(SqlRunner):
    """Connect to YourDatabase"""

    def __init__(self, connection_string: str):
        self.connection_string = connection_string
        # Initialize your database client

    async def run_sql(
        self,
        args: RunSqlToolArgs,
        context: ToolContext
    ) -> pd.DataFrame:
        """Execute SQL query and return results as DataFrame"""
        # 1. Get user context for row-level security
        user = context.user

        # 2. Apply any filters based on user permissions
        filtered_query = self.apply_user_filters(args.query, user)

        # 3. Execute query with your database client
        results = await self.execute_query(filtered_query)

        # 4. Return as pandas DataFrame
        return pd.DataFrame(results)

Use Cases

This guide will be useful for:

  • Uncommon databases: DuckDB, ClickHouse, TimescaleDB, etc.
  • Custom data sources: APIs, data warehouses with special auth
  • Enhanced security: Custom row-level filtering logic
  • Special requirements: Connection pooling, query rewriting, logging