tabulaflow

agent
Security Audit
Warn
Health Warn
  • License — License: NOASSERTION
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Warn
  • network request — Outbound network request in docs/javascripts/arcs-page.js
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Open-source data agent and Python library for querying, transforming, and visualizing any kinds of data - databases, files, knowledge graphs, Hugging Face datasets, and the web.

README.md

TabulaFlow

PyPI
Python
CI

TabulaFlow is an open-source data agent built on a modular Python library.
See the documentation.

Think of it as Claude Code for data: describe in natural language what you want
to analyze, visualize, or transform. It works with all kinds of data, including
SQL and graph databases, files, Hugging Face datasets, Wikidata, and web pages.

Unlike existing coding-agent harnesses, which are built around files and the
shell, TabulaFlow treats tables as first-class citizens, as its name suggests:

  • Agent ergonomics. The agent writes only queries and visualization
    specifications. TabulaFlow handles data resolution and rendering, so the
    agent never wastes tokens handcrafting data values or HTML to create visual
    artifacts.
  • Human ergonomics. Data provenance is automatically tracked: each
    visualization exposes its underlying data table, and each table exposes the
    query that produced it.
  • Shell-independent. The core harness remains fully functional for data work
    even when shell and filesystem access are disabled (e.g., when building
    hosted applications).

Like a general-purpose coding agent, TabulaFlow can also write code, run shell
commands, and browse the web.

Use the data agent ·
Build a data application ·
Run text-to-query experiments

https://github.com/user-attachments/assets/ac975684-afcc-4702-a325-d015fb89665d

More demos:
Get Precise Data via Interactive Disambiguation ·
Build a Research Paper Database ·
Chat to a Bioinformatics MySQL db ·
Explore a Multimodal Hugging Face Dataset ·
Query and Visualize Graphs

Get started

Install TabulaFlow with uv, set a model provider
key, and launch it:

uv tool install tabulaflow
export OPENAI_API_KEY="your-api-key"
tabulaflow

See Models and providers for
Anthropic, vLLM, and other providers.

We also recommend installing Chromium to enable agent-driven web browsing:

uv tool run --from playwright playwright install chromium

TabulaFlow opens with bundled sample data, so you can start exploring
immediately.

TabulaFlow as a Python Library

At the core of TabulaFlow is a minimalist, async-native Python library for building
and researching data agents. It was the first thing we built when we started this project because existing libraries
lacked the abstractions we needed. Its building blocks allow you to write agent
logic that runs across different database backends and research benchmarks. The same library
powers the TabulaFlow data agent.

You can use any of these building blocks to create
data applications with (e.g. data agents) or without an LLM (e.g., interactive dashboards). Choose the
building blocks you need:

  • Data connectors: inspect schemas and query SQL
    databases, Neo4j, SPARQL endpoints, files, and datasets through a unified
    async interface.
  • Extraction and enrichment: turn documents
    into structured records and enrich DataFrames with new fields.
  • Chat sessions: use ChatSession to converse
    across multiple data sources, run tools, and stream answers and progress,
    with automatic context compaction for long conversations.
  • Structured outputs: let agents produce tables, charts, maps,
    and graphs as structured artifacts by defining declarative specifications, with optional lazy data resolution for
    parameter-driven interaction.
  • Custom agents: combine reusable query, visualization, and
    document tools with your own functions and actions, without adopting ChatSession.
  • Schema and result formatting: turn structured
    schemas and query results into readable text for LLM prompts or human
    inspection.

These building blocks are fully typed and organized into four layers:
core <- data <- output <- agents. See the
API reference for how they fit together.

Quick start

Add TabulaFlow to your Python project:

uv add tabulaflow

With OPENAI_API_KEY set, compare sales and support data from separate
in-memory databases, then inspect the structured chart and table results:

import asyncio

import pandas as pd

from tabulaflow.agents import ChatSession
from tabulaflow.data import DataConnectorRegistry, SQLConnector
from tabulaflow.output.specs import ChartArtifactSpec, TableArtifactSpec


async def load_sample_data(sales: SQLConnector, support: SQLConnector) -> None:
    await sales.write_dataframe_async(
        pd.DataFrame(
            columns=["order_id", "region", "revenue_usd"],
            data=[
                (1001, "West", 1200),
                (1002, "West", 800),
                (1003, "East", 900),
                (1004, "East", 600),
            ],
        ),
        "sales",
    )
    await support.write_dataframe_async(
        pd.DataFrame(
            columns=["ticket_id", "subject", "priority", "status"],
            data=[
                (201, "Checkout payment failures", "high", "open"),
                (202, "Invoice downloads unavailable", "high", "open"),
                (203, "Profile image upload issue", "low", "open"),
                (204, "Password reset emails delayed", "high", "resolved"),
            ],
        ),
        "support",
    )


async def main() -> None:
    async with DataConnectorRegistry() as registry:
        sales = await SQLConnector.from_url_async("sqlite+aiosqlite:///:memory:", read_only=False)
        registry.register("sales", sales)
        support = await SQLConnector.from_url_async("sqlite+aiosqlite:///:memory:", read_only=False)
        registry.register("support", support)
        await load_sample_data(sales, support)

        async with ChatSession(
            registry=registry,
            model="openai:gpt-5.6-sol",
            reasoning="low",
        ) as session:
            result = await session.run(
                "How does revenue compare across regions, and which high-priority "
                "support tickets are still open? Show revenue as a bar chart "
                "and the tickets in a table."
            )
            print("Answer:", result.text)

            for artifact in result.output.artifacts:
                if isinstance(artifact, (TableArtifactSpec, ChartArtifactSpec)):
                    data = await session.output_store.resolve_artifact_source(artifact.source_id)
                    print("Artifact:", artifact.label)
                    print("Source:", data.metadata.connector_alias)
                    print("SQL:", data.metadata.query)
                    print("DataFrame:\n", data.df)


if __name__ == "__main__":
    asyncio.run(main())

result.text contains the answer; result.output contains structured artifact
specifications linked to their source data.

Query data and inspect its structured schema without an API key. This example
creates an in-memory inventory database and finds products to restock:

import asyncio

import pandas as pd

from tabulaflow.data import SQLConnector


async def main() -> None:
    stock = await SQLConnector.from_url_async("sqlite+aiosqlite:///:memory:", read_only=False)
    async with stock:
        await stock.write_dataframe_async(
            pd.DataFrame(
                columns=["product", "on_hand", "reorder_point"],
                data=[
                    ("USB-C dock", 3, 10),
                    ("Laptop stand", 18, 8),
                    ("HDMI cable", 4, 12),
                ],
            ),
            "inventory",
        )
        table = stock.schema.tables[0]
        print("Table:", table.name)
        print("Columns:", [(column.name, column.dtype) for column in table.columns])

        result = await stock.run_query_async(
            "SELECT product, reorder_point - on_hand AS units_to_order "
            "FROM inventory WHERE on_hand < reorder_point ORDER BY product"
        )
        if result.error is not None:
            raise RuntimeError(result.error.message)
        print("DataFrame:\n", result.df)


if __name__ == "__main__":
    asyncio.run(main())

Python library guide

TabulaFlow for Researchers

TabulaFlow Research extends the main Python library for AI and database researchers working
on text-to-SQL and data agents. Its main building blocks include benchmark
loaders, agents, evaluation metrics, and experiment pipelines. It is
designed around principles that enable flexible, rapid, and transparent
experiments:

  • Benchmark-ready. Run BIRD-SQL, Spider 2.0, Beaver, ARCS, AMBROSIA-S, and
    CypherBench with managed setup and official leaderboard metrics.
  • Reusable agent logic. One agent implementation runs on all benchmarks.
  • Transparent and fully typed. Work with typed tasks, schemas, and
    predictions rather than black-box dictionaries or schema strings. Write
    Python instead of YAML.
  • Async-native for large-scale concurrency. Task inference, LLM calls, and
    database queries are async and parallelizable, with configurable concurrency
    controls that can make full use of provider limits.
  • Modular and extensible. Use any building blocks you need, or extend them by
    implementing their public protocols.
  • Built-in tracking. Record trajectories, token usage, and latency for
    analysis, with optional Langfuse and Phoenix tracing.
  • Simple and performant agents. Simple yet state-of-the-art agent
    implementations provide a performant starting point.

Quick start

With the TabulaFlow tool installed and OPENAI_API_KEY set, download BIRD-SQL
and run the bundled research example:

tabulaflow benchmark download bird-sql
tabulaflow examples run research-quick-start

To adapt the workflow in your own project, add TabulaFlow with uv add tabulaflow, then run experiments from Python:

import asyncio

from tabulaflow.research.agents import BasicAgentConfig, FullSchemaAgent
from tabulaflow.research.benchmarks import BirdSQLDatasetLoader
from tabulaflow.research.metrics import BirdSQLEx
from tabulaflow.research.pipelines import evaluate_async, execute_async, predict_async
from tabulaflow.research.types import SimpleNL2QTaskOutput


async def main() -> None:
    dataset = await BirdSQLDatasetLoader().get_split_async(
        "dev",
        databases=["california_schools"],
        subsample_size=3,
    )

    try:
        result = await predict_async(
            FullSchemaAgent,
            BasicAgentConfig(),
            dataset,
            batch_size=3,
        )
        await execute_async(result, dataset, batch_size=3)
        first = result.tasks[0]
        assert isinstance(first, SimpleNL2QTaskOutput)
        assert first.pred_query is not None
        assert first.pred_query.exec_result is not None
        print("Question:", first.question)
        print("Predicted SQL:", first.pred_query.query)
        print("Query result:")
        print(first.pred_query.exec_result.df)

        await evaluate_async(result, dataset, metrics=[BirdSQLEx()], batch_size=3)
        print("Execution accuracy:", result.aggregated_eval_metrics["bird_sql_ex"]["avg"])
    finally:
        await asyncio.gather(*(connector.close_async() for connector in dataset.db_connectors.values()))


if __name__ == "__main__":
    asyncio.run(main())

To keep the predictions, scores, and readable reports together, save the result
after evaluation inside the try block:

result.to_directory("runs/full-schema")

The saved run has this structure:

runs/full-schema/
├── result.json
├── result_summary.csv
└── readable/
    └── <qid>/
        ├── task_readable.md
        └── trajectory/
            └── <trajectory-id>.md

Inspect queries, scores, agent trajectories, token usage, and latency without
rerunning the agent.

Research toolkit guide

Disclosures

This software may include, incorporate, or access open source software (OSS) components,
datasets and other third party components, including those identified below. The license terms
respectively governing the datasets and third-party components continue to govern those
portions, and you agree to those license terms may limit any distribution, use, and copying.
You may use any OSS components under the terms of their respective licenses, which may
include BSD 3, Apache 2.0, and other licenses. In the event of conflicts between Megagon Labs,
Inc. (“Megagon”) license conditions and the OSS license conditions, the applicable OSS
conditions governing the corresponding OSS components shall prevail.
You agree not to, and are not permitted to, distribute actual datasets used with the OSS
components listed below. You agree and are limited to distribute only links to datasets from
known sources by listing them in the datasets overview table below. You agree that any right to
modify datasets originating from parties other than Megagon are governed by the respective
third party’s license conditions.
You agree that Megagon grants no license as to any of its intellectual property and patent rights.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS (INCLUDING
MEGAGON) “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You agree to cease using,
incorporating, and distributing any part of the provided materials if you do not agree with the
terms or the lack of any warranty herein.
While Megagon makes commercially reasonable efforts to ensure that citations in this
document are complete and accurate, errors may occur. If you see any error or omission, please
help us improve this document by sending information to [email protected].

Research benchmark datasets

Benchmark data is downloaded separately unless noted below and remains subject to
the upstream license and access terms.

Benchmark Included Upstream License / terms
BIRD-SQL No BIRD-SQL CC BY-SA 4.0
AMBROSIA No AMBROSIA CC BY 4.0; upstream asks that the dataset not be uploaded to GitHub or Hugging Face.
Spider 2.0 (Lite, Snow, DBT) No Spider 2.0 MIT; hosted database access is subject to provider terms.
BEAVER No BEAVER MIT; separately hosted database dumps are subject to upstream terms.
CypherBench No CypherBench Apache-2.0; graph data is derived from Wikidata (CC0).
Open source software components

TabulaFlow uses the unmodified direct runtime dependencies below. Transitive
Python dependencies and exact resolved versions are recorded in
uv.lock. License notices for JavaScript components bundled with the
application are included alongside those files under
tabulaflow/app/pane/assets/vendor.

Component Modified Upstream License
aiolimiter No mjpieters/aiolimiter MIT
aiosqlite No omnilib/aiosqlite MIT
arize-phoenix-otel No Arize-ai/phoenix Apache-2.0
asyncmy No long2ice/asyncmy Apache-2.0
asyncpg No MagicStack/asyncpg Apache-2.0
datasets No huggingface/datasets Apache-2.0
dbt-duckdb No duckdb/dbt-duckdb Apache-2.0
duckdb No duckdb/duckdb-python MIT
duckdb-sqlalchemy No leonardovida/duckdb-sqlalchemy MIT
filelock No tox-dev/filelock Unlicense
gdown No wkentaro/gdown MIT
genai-prices No pydantic/genai-prices MIT
google-cloud-bigquery-storage No googleapis/python-bigquery-storage Apache-2.0
httpx No encode/httpx BSD-3-Clause
huggingface-hub No huggingface/huggingface_hub Apache-2.0
Jinja2 No pallets/jinja BSD-3-Clause
langfuse No langfuse/langfuse-python MIT
markdown-it-py No executablebooks/markdown-it-py MIT
neo4j No neo4j/neo4j-python-driver Apache-2.0 and Python-2.0
pandas No pandas-dev/pandas BSD-3-Clause
Pillow No python-pillow/Pillow MIT-CMU
playwright No microsoft/playwright-python Apache-2.0
plotext No piccolomo/plotext MIT
pyarrow No apache/arrow Apache-2.0
pydantic No pydantic/pydantic MIT
pydantic-ai-slim No pydantic/pydantic-ai MIT
pydantic-settings No pydantic/pydantic-settings MIT
Pygments No pygments/pygments BSD-2-Clause
PyMySQL No PyMySQL/PyMySQL MIT
pypdf No py-pdf/pypdf BSD-3-Clause
PyYAML No yaml/pyyaml MIT
rich No Textualize/rich MIT
snowflake-connector-python No snowflakedb/snowflake-connector-python Apache-2.0
snowflake-sqlalchemy No snowflakedb/snowflake-sqlalchemy Apache-2.0
SQLAlchemy No sqlalchemy/sqlalchemy MIT
sqlalchemy-bigquery No googleapis/python-bigquery-sqlalchemy Apache-2.0
SQLGlot No tobymao/sqlglot MIT
sqlparse No andialbrecht/sqlparse BSD-3-Clause
tabulate No astanin/python-tabulate MIT
textual No Textualize/textual MIT
tiktoken No openai/tiktoken MIT
tqdm No tqdm/tqdm MPL-2.0 and MIT
typer No fastapi/typer MIT
webbrowser-open No minrk/webbrowser_open BSD-3-Clause

The application also bundles the following unmodified browser-side components:

Component Modified Upstream License
Cytoscape.js No cytoscape/cytoscape.js MIT
cytoscape-dagre No cytoscape/cytoscape.js-dagre MIT
Dagre No dagrejs/dagre MIT
KaTeX No KaTeX/KaTeX MIT
MapLibre GL JS No maplibre/maplibre-gl-js BSD-3-Clause
markdown-it No markdown-it/markdown-it MIT
markdown-it-texmath No goessner/markdown-it-texmath MIT
Tabulator No olifolkerd/tabulator MIT
Vega No vega/vega BSD-3-Clause
Vega-Embed No vega/vega-embed BSD-3-Clause
Vega-Lite No vega/vega-lite BSD-3-Clause

Reviews (0)

No results found