Skip to content

Dataset Tools — MCP Tool Reference

Dataset tools implement the Bundle-scoped medallion data pipeline: a Bundle binds a Project, Questionnaire, and Campaign subset to one linear Bronze → Silver → Gold chain (see Bundle Tools for lifecycle operations). These tools extract survey responses into a Bundle's Bronze, derive its Silver (open-end coding, then post-stratification weighting on the coded case base), refine into Gold, and export in multiple formats. Quality is a Bundle concern, not a dataset one — see the quality tools in the Bundle Tools Reference.

Every dataset tool is Bundle-scoped

create_bronze_dataset and create_gold_dataset take a bundle_id, not a free-form questionnaire/campaign/source selection — the Bundle already carries that selection. Weighting a dataset other than a Bundle's own Bronze isn't offered by any tool.

Running the whole chain in one call

create_bronze_dataset → code_open_ends → create_gold_dataset is also available as a single run_bundle_pipeline call, which runs those same three tools and hands back a task_id to poll with get_task_status. Call the stages individually when you want to inspect the Bronze or review the coded dimensions before deriving further.

list_datasets

List datasets with optional filters.

Parameter Type Required Default Description
stage string No — Filter by stage: "bronze", "silver", or "gold"
source_type string No — Filter: "campaign", "project", "upload", "weighted", or "refined"
campaign_id string No — Filter by campaign ID
limit integer No 100 Maximum results to return

Returns: { items: [...], count, limit }


get_dataset

Get a dataset's identity, lineage, metrics and status. This is the tool every pipeline step says to poll, so it is bounded — the response does not grow with the questionnaire.

Parameter Type Required Default Description
dataset_id string Yes — Dataset UUID

Returns: id, name, description, stage, source_type, source_dataset_ids, bundle_id, campaign_id, questionnaire_id, strategy_id, row_count, column_count, has_weights, weight_column, weighted_at, weighting_method, weighting_config, quality_score, processing_status, processing_error, data_path, created_at, invalid_cells.

processing_error is the reason a stage ended in error — the derive's own coding_produced_no_columns: refusal, for example. It is null on every other status. Read it whenever processing_status is error: without it a poll can see that a stage failed and not why.

processing_error always carries the failure kind before the colon. A reason that names only identifiers, units, columns or a threshold comes back whole. A weighting refusal keeps the factor and column it names, but not the column values it quotes, because those can be respondent data. The Silver stage page in Balansor shows that reason in full. get_bundle_quality reports a failed stage's reason the same way, and so does get_task_status for a run_bundle_pipeline run that stopped at Silver.

weighting_config is the derive's record of what it did:

  • the factors it weighted on, with their targets and adjustments;
  • the convergence figures;
  • how many rows the completeness threshold and the volunteer exclusion removed;
  • which open-ended units it attempted, coded and lost, with the kind of each loss.

The column schema is not here — read it with get_dataset_schema. It is the one unbounded field a dataset carries (89 KB of a 90 KB response on a 192-column Silver), so a poll spent tens of thousands of tokens re-reading an unchanging schema to see a 7-byte status string.

invalid_cells is {column: count} for the cells the extraction could not read as the type their column stores and therefore stored as blank — a Radio item holding prose, say. {} means the extraction checked and found none; null means the dataset predates the check. A blank written this way is otherwise indistinguishable from a respondent's skip, so read it before drawing conclusions about missingness.


get_dataset_schema

Get a dataset's column schema: per column its dtype, the item_id, item_title and control_type it came from, its labels map (code → caption), and its roster/indicator provenance.

Parameter Type Required Default Description
dataset_id string Yes — Dataset UUID
columns string[] No — Column names to return; omit for every column
detail boolean No true false returns column_index — each column's name and control_type — instead of column_schema

Returns: { dataset_id, stage, column_count, column_schema, returned, unknown_columns }, with column_index ({ name: control_type }, null for row metadata) in place of column_schema when detail is false.

Two row-metadata columns describe how far each Survey got: _reached counts the items the respondent was shown (the one on screen included), and _completeness is the share of those they answered (answered ÷ reached). The Bundle's completeness threshold reads _completeness.

A Bronze also returns custom_attribute_keys: the respondent custom attributes it was extracted with, each one a column of the dataset (_custom_<key>). Only attributes that a Sampling Strategy factor or a Calibration Target of the Bundle names are extracted, so read this list before targeting an attribute: a key outside it is not in the dataset until a re-extract (create_bronze_dataset). An empty list means nothing was named. The field is absent for Silver and Gold, and for a Bronze extracted before keys were recorded; re-extract that one before weighting on an attribute.

column_count is the dataset's own, so with a columns filter it is larger than returned and the gap tells you how much of the schema you have not seen. A name you pass that the dataset does not have comes back in unknown_columns rather than being dropped, so a typo is distinguishable from a column the stage genuinely lacks.

On a real instrument, read it in two steps. A 293-column schema is ~134 KB, larger than most agent tool-result budgets. Call with detail: false first — the same 293 columns come back as a ~7 KB index — then pass the few names you need as columns for their full entries. Two moments need this tool at all: choosing Calibration Targets (which column, and what its labels map calls each code) and composing a Gold operations catalog (which columns exist to rename, remove or reorder). GET /api/v1/datasets/<id> is the other door and carries the whole schema — REST is the lane for large results.


create_bronze_dataset

Extract a Bundle's Bronze dataset. The Bundle already carries the questionnaire and its campaign subset — there is no free-form questionnaire/campaign selection at this tool. Previews are refused unconditionally, so no argument can fold a design-time test walk into the base. Re-running attaches the fresh Bronze to the Bundle chain and cascade-invalidates a downstream Silver/Gold (they become stale, not deleted — their recipes survive for a one-click re-derive).

Parameter Type Required Default Description
bundle_id string Yes — The Bundle whose Bronze to (re)extract
include_demographics boolean No true Include respondent demographic columns and the custom attributes the Bundle names

Returns: { dataset_id, bundle_id, stage: "bronze", ... } with the extraction report, including invalid_cells (see get_dataset, which is where to read it on any later turn), custom_attribute_keys (the custom attributes written as columns) and empty_custom_attribute_keys (those among them no surveyed respondent carries, which is how a misspelt attribute name shows up).

Which respondent attributes are extracted. Age, gender and location are written for every row. A custom attribute is written only when a Sampling Strategy factor or a Calibration Target of the Bundle names it; every other key on the respondent record stays out of the dataset. A named attribute no respondent carries still gets a column, left empty. Naming a new attribute after an extraction therefore needs another create_bronze_dataset before a derive can weight on it.

include_demographics: false is refused when the Bundle names a custom attribute, with {"error": "named_attributes_require_enrichment", "detail": "..."} naming the attributes. A named attribute is written only together with the demographic columns, and a Bronze without it could never be weighted on it. Extract with the default instead.


code_open_ends (alias: derive_silver)

Derive a Bundle's Silver: code open-ended text into one labelled categorical column per selected dimension, then rake (post-stratification weighting) over the coded case base. This is the only tool that produces a Silver dataset, and it always sources the Bundle's own ready Bronze — weighting any other dataset is not offered by any tool.

Parameter Type Required Default Description
bundle_id string Yes — The Bundle whose Bronze to derive into Silver

Returns: { silver_dataset_id, status: "processing", job_id } — the derive runs in the background. Poll get_dataset(dataset_id=silver_dataset_id) until processing_status is ready or error.

Coding runs over the units the Bundle's coding selection names — set it with set_coding_selection (see Bundle tools) — and, within each, over the dimensions a researcher selected in Balansor; a unit the analyst classified nominal is coded by exact value instead, with no model call and no dimension review. A selected unit that is unclassified or classified identifier stops the derive with coding_selection_unresolvable naming it. When nothing is selected, coding is skipped and weighting runs directly on the Bronze data; that is an ordinary outcome, not an error. A selected unit whose dimensions nobody has reviewed produces no coded column and the derive still succeeds — check awaiting_review on get_bundle_coding before treating the result as complete. A derive is refused when a Calibration Target names a coded column whose dimension (weighting_factor_dimension_deselected) or whose whole unit (weighting_factor_deselected) the Bundle no longer selects — re-select it or drop the factor. A derive is also refused with weighting_attributes_not_extracted when it would weight on a respondent custom attribute the Bronze was not extracted with (see below). derive_silver is registered as a second tool name for the same operation — agent prose that says "derive silver" and prose that says "code open ends" both resolve to it.

A derive that codes nothing ends error, not ready. One unit that cannot be coded is left uncoded and the rest still code, but if every unit the derive attempted produced no column, the Silver reaches processing_status: "error" with processing_error reading coding_produced_no_columns: followed by each unit key and why it yielded nothing. Treat it as terminal — a re-run meets the same units and produces the same nothing, so fix the cause (re-extract a Bronze whose text columns are missing, or repair the codebook in Balansor) before deriving again. This is distinct from an unreachable embedding backend, which the job retries on its own before any error is written.

Weighting on a custom attribute the Bronze does not hold is refused, by name. The code is weighting_attributes_not_extracted and the detail names each attribute and its column. It arrives one of two ways, depending on the Calibration Targets:

  • When the targets are the whole weighting set (use_strategy_factors is false, which is the case after set_calibration_targets(factors=[...]) or once a researcher has opened the Silver page), the tool itself answers {"error": "weighting_attributes_not_extracted", "detail": "..."} and no job starts.
  • When the targets still follow the Sampling Strategy, the tool returns processing and the Silver ends error before any coding, with processing_error opening weighting_attributes_not_extracted:.

Either way the fix is the same: run create_bronze_dataset again, then derive. If no respondent of the Bundle carries an attribute by that name, the name is wrong; correct it in the Calibration Targets or the Sampling Strategy, since a re-extract would only add an empty column. Compare the Bronze's custom_attribute_keys (get_dataset_schema) with the attributes you intend to weight on to see this coming. An attribute the Strategy names without weighting on it never blocks a derive; its factor reads as not measurable in get_bundle_quality until a re-extract.

Coding before weighting

Askalot codes open-ended answers into labelled categorical columns first, then weights once over the finished coded case base — this deliberately differs from a "weight first" workflow. A coded dimension becomes available as a weighting variable in the same derive.


create_gold_dataset

Refine a Bundle's ready Silver into its Gold. Always sources the Bundle's own Silver; replaces any prior Gold in the chain.

Parameter Type Required Default Description
bundle_id string Yes — The Bundle whose Silver to refine
name string No — Name for Gold dataset. Defaults to "{bundle_name} — Gold"
operations object[] No — The Gold recipe for this call. Omit it to build from the Bundle's stored recipe (the layout saved on the Gold page; read it with get_bundle). Passing it overrides the stored recipe for this call only; nothing is stored

With no operations (none passed and none stored) the Gold is a copy of the Silver. With operations, the Gold differs from the Silver only by what they say: every column not removed is kept, in the Silver file's order, with its full schema entry (question text, value labels).

The operations recipe

An ordered list of rows. A row names columns of the Silver file — never a name a rename introduces. The one exception is a reorder entry, which may also name a column the recipe adds. get_dataset_schema lists the columns the Silver's schema names: answers, coded dimensions and weights. The Silver file also holds columns it does not list: row-metadata columns (such as _survey_id and _response_timing) and enrichment columns, the respondent attributes extraction added (_demographic_*, _custom_*). They are kept in the Gold like any other column, and a recipe may address them by name too.

op Fields Effect
rename column, to Serve column under the name to. The last rename of one column wins
remove column Leave column out of the Gold
alias column, to Serve column once more, under the name to. One row per extra name; a column may have several. column must itself be served
reorder order (list of names) The named columns come first, in this order; every column order omits follows in its default position. An entry is a Silver column, an alias's to or a computed name, each at most once. It never drops a column. Only the last reorder row takes effect
compute name, kind, plus the kind's fields Add a column called name

Default positions, for every column order does not name: the Silver columns in the Silver file's order, then the aliases in recipe order, then the computed columns in recipe order. To put an alias or a computed column between two Silver columns, name it in order together with the columns before it.

compute kinds:

kind Fields Effect
arithmetic left, operator ("+", "-", "*", "/"), right An operation between two columns, each cell read as a number. A cell that is not a number, and a division by zero, give an empty value
recode column, buckets (list of [min, max, label]) Each bucket maps the values from min to max, inclusive, to label; each cell is read as a number. A cell that is not a number, or that no bucket holds, gives an empty value. min and max are finite numbers with min not above max; label is non-empty text
concat columns (list), separator (text) Join the columns in order

formula is reserved for a future release and is refused by name, both as an op and as a kind.

Rules the recipe must satisfy:

  • What a compute reads. Computes run on the whole Silver, before any column is renamed or removed. An input is a Silver column (served, renamed or removed alike) or the name of a compute row earlier in the list, never an alias. Where a computed column sits in the file does not change what it may read.
  • Alias and computed names. An alias's to and a computed name must differ from every Silver column name, removed ones included.
  • An alias needs its column. An alias of a column the recipe removes is refused: to serve a column under one new name only, rename it.
  • New names. A name the recipe makes (a rename target, an alias or a computed name) may not be blank and may not start or end with whitespace.
  • Output names. The names the Gold ends up with are each served column under its final name, plus every alias and every computed name. A name the recipe makes must differ from every other output name ignoring letter case: Score and score collide. Two Silver columns the recipe leaves under their own names are never refused, even when they differ only by letter case; that is the Silver's own naming.
  • At least one column. A recipe that removes every Silver column and computes none is refused.
  • The weight column. The Gold's weights are the Silver's weight column: renamed, it stays the weight column under its new name; removed, the Gold carries no weights, even when another column is renamed to its old name. An alias of the weight column is a second copy of its values and is never the Gold's weight column.
  • rename, remove, alias and reorder rows may come in any order among themselves. Order matters among compute rows, and among alias rows only for their default position.
[
  {"op": "rename", "column": "age", "to": "Age"},
  {"op": "remove", "column": "_response_timing"},
  {"op": "alias", "column": "age", "to": "age_at_interview"},
  {"op": "reorder", "order": ["_survey_id", "age", "age_band"]},
  {"op": "compute", "name": "age_band", "kind": "recode", "column": "age",
   "buckets": [[18, 34, "18-34"], [35, 54, "35-54"], [55, 120, "55+"]]}
]

Returns: { gold_dataset_id, name, stage: "gold", bundle_id, row_count, column_count, skipped }

skipped lists the recipe entries the build set aside because the Silver does not have their column, each as { "op": "remove" | "reorder", "column": "<name>" }. A recipe can outlive the Silver it was written for: a remove or a reorder entry naming a column the Silver no longer has is skipped and reported here rather than refused. It is an empty list when nothing was skipped.

Refusals (each { "error": "<code>", "detail": "..." }; no Gold is published):

error When
silver_not_ready The Bundle has no ready Silver, its file cannot be read, or the Silver changed while the Gold was building. Derive the Silver, then call again
invalid_operations The recipe breaks a rule above, checked before any build: an unknown or reserved op or kind, a missing field, a blank or padded new name, a malformed bucket (a bound that is not a finite number, or min above max), a name listed twice in one reorder, a rename or an alias of a column the Silver lacks, an alias of a removed column, a compute input that is neither a Silver column nor an earlier computed name, an alias or computed name equal to a Silver column, a name the recipe makes that differs from another output name only by letter case, or a recipe that leaves no column. detail names each column involved
build_failed The recipe passed the checks and a computation could not be carried out on the data. detail carries the reason
layout_changed Only when building from the stored recipe: the recipe was saved again (on the Gold page) while this Gold was building. The built Gold is discarded and the Bundle's earlier Gold, built from the recipe before that save, is no longer ready; call again
gold_superseded A concurrent build replaced this Gold; call again

Stage validation: The Bundle's Silver must be ready; a missing or non-ready Silver returns an error rather than falling back to Bronze.


export_dataset

Export a dataset in the specified format.

Parameter Type Required Default Description
dataset_id string Yes — Dataset UUID
format string No "csv" Export format: "csv", "xlsx", "spss", "parquet", "rds", or "json"

Returns: { dataset_id, format, download_url, rows, columns, file_size_bytes }. The exported file is never returned inline — download_url is a short-lived link (expires a few minutes after minting) that lets you fetch the file directly over HTTPS with no further authentication; it can be reused any number of times until it expires. Request a fresh export if the link has expired.

Export Formats

Format Extension Description
csv .csv Universal format for most tools
xlsx .xlsx Excel with summary and schema sheets
spss .sav SPSS with variable and value labels
parquet .parquet Columnar format with full metadata (Snappy compression)
rds .rds R — categoricals arrive as factors, value labels as factor levels
json .json One document: {dataset, column_schema, rows}. Rows keep the stored answer codes; each column's value labels are in column_schema. Missing values are null

delete_dataset

Delete a dataset and optionally its data file.

Parameter Type Required Default Description
dataset_id string Yes — Dataset UUID
delete_file boolean No false Also delete the Parquet data file

Returns: { deleted: true, dataset_id, dataset_info: { name, stage, row_count, data_path }, file_deleted }


Error Handling

Stage Validation

The Bundle pipeline enforces stage progression and readiness — a stage can't be skipped or exported while stale:

Operation Requirement Error
code_open_ends / derive_silver Bundle's Bronze must be ready {"error": "bronze_not_ready", "detail": "Extract a ready Bronze first"}
code_open_ends / derive_silver The Bronze must be of the current extraction schema version {"error": "bronze_schema_stale", "detail": "..."}. Re-extract Bronze (create_bronze_dataset), then derive
code_open_ends / derive_silver Every custom attribute the derive weights on must have been extracted into the Bronze {"error": "weighting_attributes_not_extracted", "detail": "..."}, naming the attributes. Re-extract Bronze, then derive
create_bronze_dataset include_demographics must stay true when the Bundle names a custom attribute {"error": "named_attributes_require_enrichment", "detail": "..."}, naming the attributes
create_gold_dataset Bundle's Silver must be ready {"error": "silver_not_ready", "detail": "Derive a ready Silver first"}
create_gold_dataset The recipe must be valid for the Silver's columns {"error": "invalid_operations", "detail": "..."}, naming the rows and columns. See create_gold_dataset
export_dataset Dataset must be ready (not processing/invalidated/error) {"error": "not_ready", "detail": "Dataset is '{status}', not ready — re-derive the stage before exporting."}
export_dataset A Silver's coded questions must all be reviewed: a question awaiting dimension review has no coded column yet {"error": "coding_awaiting_review", "detail": "..."}, naming the questions. Review the dimensions in Balansor, re-derive, then export
export_dataset The dataset's data file must exist {"error": "file_missing", "detail": "The dataset's data file is missing — re-derive the stage."}

Common Errors

Scenario Response
Dataset not found {"error": "Dataset {id} not found"}
Bundle not found {"error": "not_found", "detail": "Bundle {id} not found"}
Strategy not found {"error": "Sampling strategy {id} not found"}
No data file {"error": "Dataset {id} has no data file"}
Invalid export format {"error": "Invalid format. Allowed: csv, xlsx, spss, parquet, rds, json"}
No completed surveys {"error": "no_completed_surveys", "detail": "..."} — widen the campaign selection or wait for more completions
Bundle selects no campaign {"error": "no_campaigns_selected", "detail": "..."} — a Bundle's measurement base is the surveys of the campaigns it selects; assign at least one
Extraction could not write the dataset {"error": "extraction_failed", "column": "q_x", "detail": "..."} — one column holds values that cannot be unified into a single type. The offending value is deliberately omitted (it is a respondent's answer); inspect that column's raw values, correct the source responses, and re-extract