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.
https://github.com/user-attachments/assets/ac975684-afcc-4702-a325-d015fb89665d
More demos: Build a Research Paper Database · Ask Your Database Anything · 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
ChatSessionto 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())
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.
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 contact_oss@megagon.ai.
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 |
Metadata
Release files for tabulaflow 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tabulaflow-0.2.2.tar.gz | 4.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tabulaflow-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 9.4 MB
Release files / tabulaflow-0.2.2.tar.gz
| Download URL | tabulaflow-0.2.2.tar.gz |
|---|---|
| Size | 4.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
856d52a634917e6f98e3c0876c55a6e546196793c119f7a447eb3bd57df94bfa
|
|
BLAKE2b-256 checksum How to use checksums |
79da962bb684d6232041296423a7684a8758614141bde9e29a68732736dbedb5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / tabulaflow-0.2.2-py3-none-any.whl
| Download URL | tabulaflow-0.2.2-py3-none-any.whl |
|---|---|
| Size | 4.8 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e9ec6b74dd8443eac7953d3f3ab07c33f1c0cf16e4d35bb145fc0cc8ec58bbf0
|
|
BLAKE2b-256 checksum How to use checksums |
170adf920ba0527ee852df0c14c1b14f2788da02872e4af4c3bd14ef6b17ebcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log