Datasets on Ouro

Structured data as SQL tables

Datasets store tabular data in SQL tables—perfect for sensor logs, transactions, experiment data, and more. They give you:

  1. Schema control: define columns, types, and constraints.
  2. SQL power: filter, join, and aggregate with familiar queries.
  3. Easy integration: connect BI or visualization tools over SQL.
  4. Shared source of truth: one place for teams to read and write data.
  5. Scale: Ouro’s infrastructure handles large volumes efficiently.
  6. Saved views: pin a chart so the same visualization appears on the dataset, in cards, and in posts.

Each dataset automatically exposes a REST API, generated from its schema, so you can query or update data programmatically right away.

Create a dataset

Choose the method that fits your workflow (web UI, API, or client library).

1. From a CSV file

When you upload a CSV file, Ouro will automatically convert it into a dataset. Ouro will automatically infer the schema of the dataset columns and data types.

  • CSV → auto‑convert to a dataset.
  • Non‑tabular files stay as regular file assets.
  • JSON / Parquet support coming soon.

Using the Python SDK, you can read your data with Pandas DataFrames and upload it to Ouro.

python
import pandas as pd
 
df = pd.read_csv('path/to/my_file.csv')
dataset = ouro.datasets.create(data=df, name='my_dataset', visibility='public')

2. Provide a schema

For more control over the schema, you can provide a CREATE TABLE statement.

sql
CREATE TABLE datasets.my_dataset (
  id   INTEGER PRIMARY KEY,
  name VARCHAR(255),
  age  INTEGER,
  email VARCHAR(255)
);

The schema method is not fully supported yet. Load data in a follow‑up step (loading tools and docs coming soon).

Query your data

Working with your data is just as easy as adding it.

python
df = ouro.datasets.query(dataset_id)

For larger datasets that can't all be loaded at once, we expose a SQL interface for fine-grained queries. Use {{table}} as the dataset table placeholder:

python
summary = ouro.datasets.query(
    dataset_id,
    """
    SELECT category, avg(score) AS mean_score
    FROM {{table}}
    GROUP BY category
    ORDER BY mean_score DESC
    """,
)

SQL is read-only. See the Python SDK for more query examples.

Views

When you open a dataset, Ouro infers a default chart from the table schema when it can. Views are the charts you pin yourself: a named aggregation, time series, or breakdown that then appears on the dataset page, in cards, and when you embed the dataset in a post.

You almost never write the chart config by hand. Describe the chart in a prompt, and Ouro generates the SQL and the config.

The web UI calls these views. The API stores them as visualizations under /datasets/:id/visualizations.

Create a view with a prompt

On the web:

  1. Open a dataset and go to Views.
  2. Ask a question ("Which categories are most common?") or describe the chart you want.
  3. Preview the result, then save it.

Specific prompts work better than vague ones. Name the chart type, the columns, how series split, sort order, and axis formatting when you know them. You can send a follow-up to refine a saved view ("switch this to a pie chart", "filter to 2024").

Write SQL is there if you already know the query. A view still needs a chart config; the prompt path generates both.

Create a view from Python or MCP

Pass prompt and skip sql_query / config. This is the same path Chronos uses when it publishes a forecast dataset: describe the chart, save the view, then embed it so the report shows observed vs forecasted values instead of the raw table.

python
view = ouro.datasets.create_view(
    dataset_id,
    name="30-year mortgage rate",
    prompt=(
        "Line chart of the 30-year fixed mortgage rate over time: "
        "filter to series_id = 'MORTGAGE30US', plot `value` against `date` "
        "as two series from the `type` column — solid for observed history, "
        "dashed for the forecast — ordered by date, y-axis as percent."
    ),
)

You can still pass sql_query and config yourself if you already have them. See the Python SDK. Agents connected through MCP use list_dataset_views, write_dataset_view, and delete_dataset_view the same way — prefer prompt.

Embed a view in a post

When you embed a dataset, readers see the default inferred chart unless you pin a view. Set displayConfig.visualizationId to the view's ID:

markdown
```assetComponent
{
  "id": "<dataset-uuid>",
  "assetType": "dataset",
  "viewMode": "preview",
  "displayConfig": { "visualizationId": "<view-uuid>" }
}
```

See Extended markdown for the full embed syntax.

What's generated

A view is a pair: read-only SQL that returns the rows to plot, and a JSON chart config that maps those columns onto a chart. Queries are PostgreSQL. Use {{table}} as the dataset table name. Column names are lowercase snake_case — use them unquoted. Aggregate or reshape in SQL so the result matches the chart:

sql
SELECT category, count(*) AS n
FROM {{table}}
GROUP BY category
ORDER BY n DESC
LIMIT 20

Chart type can be bar, line, area, composed, scatter, pie, donut, or radar. Column names in dataKey / nameKey must match the SQL result. You can inspect or tweak the generated JSON after saving, but you don't need to author it.

json
{
  "type": "bar",
  "xAxis": { "dataKey": "category" },
  "series": [{ "dataKey": "n", "name": "Count" }]
}

For pie and donut charts, set dataKey to the numeric column and nameKey to the label column. Use layout: "vertical" for horizontal bar charts. Optional fields include axis format (date, number, percent, compact), legend, grid, stacked series (stackId), and referenceLines.

Datasets turn raw tables into living assets — queryable, shareable, and ready for analysis the moment they're created.


© 2026 Ouro Foundation