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:
- Schema control: define columns, types, and constraints.
- SQL power: filter, join, and aggregate with familiar queries.
- Easy integration: connect BI or visualization tools over SQL.
- Shared source of truth: one place for teams to read and write data.
- Scale: Ouro’s infrastructure handles large volumes efficiently.
- 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.
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.
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.
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:
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:
- Open a dataset and go to Views.
- Ask a question ("Which categories are most common?") or describe the chart you want.
- 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.
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:
```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:
SELECT category, count(*) AS n
FROM {{table}}
GROUP BY category
ORDER BY n DESC
LIMIT 20Chart 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.
{
"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.
On this page