Agent tools
Every tool SCMotif offers an agent you have connected, with the description and inputs the agent itself reads. You do not call these yourself: your agent chooses them from what you ask.
Tools that read¶
Every connection is shown these.
List saved objects¶
list
List objects of one kind: the projects you may reach, each with a summary (oldest first; start here, a workspace grant has no implicit project), or one project's data sources, workflows, scenarios, executions or dashboards. Rows carry the ids other tools take and a url for a person. Scenarios and executions answer a page of items with total, limit and offset: scenarios oldest first, executions newest first with status, timings and finding counts per severity; the other kinds answer the whole list. Scenarios narrow by execution_id, workflow_id or name_contains, and include_profile adds each row's horizon, currency and row counts; executions narrow by workflow_id, status and since. Data sources, named sets of files, come with their latest file and unfinishedUploads, names unread uploads hold; dashboards narrow by workflow_id to those showing its results and carry tileHealth, tiles that stopped drawing.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
project or data_source or workflow or scenario or execution or dashboard |
yes | Which kind of object this call is about. |
include_counts |
boolean | no | Applies to kind project. Default: False. |
content |
tabular or document |
no | Narrow data sources to 'tabular' or 'document'; omit for all. Applies to kind data_source. |
project_id |
string (uuid) | no | The project this call acts in. Required for every kind but kind project. |
execution_id |
string (uuid) | no | Narrow to the scenarios one run published. Applies to kind scenario. |
include_history |
boolean | no | Include retained historical versions alongside current scenarios. Applies to kind scenario. Default: False. |
include_profile |
boolean | no | Also answer each row's horizon, currency and row counts. One scenario's are in get (kind scenario). Applies to kind scenario. Default: False. |
limit |
integer | no | Page size. Applies to kinds scenario, execution. At most 25 for kind scenario; at most 500 for kind execution. Default: 25. |
name_contains |
string or null | no | Narrow to names containing this text, ignoring case. Applies to kind scenario. |
offset |
integer | no | Rows to skip; the next page starts at offset plus the last page's row count. Applies to kinds scenario, execution. Default: 0. |
workflow_id |
string (uuid) or null | no | Narrow to one workflow: the scenarios its runs produced, its own runs, or the dashboards showing its results. Applies to kinds scenario, execution, dashboard. |
since |
string (date-time) or null | no | Executions started at or after this moment, ISO 8601. Applies to kind execution. |
status |
pending or running or completed or failed or cancelled or null |
no | Executions in this state. Applies to kind execution. |
Get saved object¶
get
Get one object by kind and id. project: name, brief (description, briefVersion) and counts. data_source: latest file's kind, columns, row count and sha256, never rows. workflow: nodes, edges with named ports, diagnostics and the version apply_workflow takes as baseVersion. scenario: labels, units, horizon, producing run, availableTables and provenance; for a number, inspect_scenario then query_scenario. execution: status, waiting.explanation while pending, phase while running, what it published with each url, dashboardRefresh, the failing node, firstFinding and findingCounts, and storage; list_execution_diagnostics has the rest. dashboard: selection, link, tile ids and resultSources (versions shown, their runs, newer available); include_health resolves each tile (hasData, needsRebuild, invalidReason) and names commentaryNeedsReview; do that before handing over the link. upload_session: progress, ready with the new dataSourceId, or ingestion's diagnostics.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
project or data_source or workflow or scenario or execution or dashboard or upload_session |
yes | Which kind of object this call is about. |
id |
string (uuid) | yes | The object's id, as list or the call that created it answered it. |
project_id |
string (uuid) | no | The project this call acts in. Required for every kind but kind project. |
include_table_counts |
boolean | no | Include tableRowCounts for browsing stored tables. Omitted by default to keep the identity summary compact. Applies to kind scenario. Default: False. |
include_provenance |
boolean | no | Also answer workflowSnapshot and reproductionManifest. Both are fixed at acceptance, so ask once, not on every poll. Applies to kind execution. Default: False. |
include_health |
boolean | no | Resolve every tile and report whether it answered, as hasData, needsRebuild and invalidReason beside the stored tile. Off by default because resolving runs each tile's query; on, it is the only way to learn that a tile draws nothing. It reports — it never returns the rows themselves. Applies to kind dashboard. Default: False. |
Check analysis readiness¶
check_analysis_readiness
Readiness check for one saved scenario, selected analysis and configuration, without starting a run. ready means declared requirements passed (warnings may still need review); not_ready means fix the returned errors first; unknown means the installed analysis declares neither required tables nor a readiness check. An uninstalled analysis type is refused with the installed node types. Required tables are checked for nonempty presence, then the analysis package can return deeper pre-run findings about fields and configuration. Use it before spending solver time, not as a substitute for validate_workflow, which checks a stored graph.
| Input | Type | Required | Meaning |
|---|---|---|---|
analysis_type |
string | yes | The installed analysis node type to assess, from list_node_types. |
config |
object | no | The selected analysis configuration. Its fields are package-owned, so the core passes this object to the package unchanged. |
project_id |
string (uuid) | yes | The project this call acts in. |
scenario_id |
string (uuid) | yes | UUID of the saved scenario to assess. |
Get storage usage¶
get_storage_usage
Read account storage usage, upload reservations and limit. Workspace grants only. Check before large uploads or after nearLimit and tell the user. Full storage refuses new writes, not reads or deletions. list_history_cleanup reviews unused older versions of scenarios and workflow-saved files to free space.
Preview history cleanup¶
list_history_cleanup
Review what cleanup could free, by kind, across every project you may reach, largest reclaimable storage first: the unused earlier versions of scenarios, or earlier files of data sources (kind data_source). Current versions, latest files and what a workflow, a saved result or an unfinished run reads stay protected. Page with cursor; confirm the selection with the person before cleanup_history.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
scenario or data_source |
yes | Which kind of object this call is about. |
limit |
integer | no | Default: 25. |
cursor |
string | no | Continue from the page before: its nextCursor. |
Preview data source¶
preview_data_source
Preview a data source's file: a table's header and a bounded sample of rows (limit), to orient before mapping columns; a Markdown or text document's complete text, headings and blank lines kept, with no columns or rows. For built scenario data, aggregate through query_scenario.
| Input | Type | Required | Meaning |
|---|---|---|---|
data_source_id |
string (uuid) | yes | |
limit |
integer | no | Default: 20. |
project_id |
string (uuid) | yes | The project this call acts in. |
file_id |
string (uuid) | no | Else its latest file. |
List saved versions¶
list_versions
List an object's versions by kind and id, newest first; page on with before_version set to the last version.number. scenario: each with the exact result's id and input evidence, without changing workflows or comparisons; include_table_counts adds each version's table sizes, and unversioned results have no inferred history. data_source: its files, newest first.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
scenario or data_source |
yes | Which kind of object this call is about. |
before_version |
integer | no | The last number the page before answered. |
include_table_counts |
boolean | no | Include tableRowCounts for browsing stored tables. Omitted by default to keep the identity summary compact. Applies to kind scenario. Default: False. |
limit |
integer | no | Default: 20. |
project_id |
string (uuid) | yes | |
id |
string (uuid) | yes | The object whose versions to list; for a scenario, any version's id. |
Export saved object¶
export
Export one object by kind and id as its portable artifact. workflow: the scmotif.workflow/1 JSON inline (graph, settings and code, no data), with references naming every data source or scenario it reads; pass artifact unchanged to import. scenario: a scmotif.scenario/1 ZIP prepared server-side and answered as a short-lived download_url plus an export id that import copies into another project without handling the file; an unchanged scenario reuses its prepared export. data_source: a short-lived link to a file, never its contents; copy_data_source moves one between projects. If fetching download_url cannot connect, your environment blocks its host: tell the person that host and guide_url, which says how to allow it.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
workflow or scenario or data_source |
yes | Which kind of object this call is about. |
project_id |
string (uuid) | yes | The project this call acts in. |
id |
string (uuid) | yes | The object's id, as list or the call that created it answered it. |
file_id |
string (uuid) | no | Else its latest file. Applies to kind data_source. |
List node types¶
list_node_types
List every node type this instance can run, by category, with what each is for and the data it needs present. The catalogue is what the installed packages supply, so it is this instance's answer and not a remembered one — read it before authoring a workflow rather than assuming a node type exists. Choose from it, then call describe (kind node_type) for each type you use: its ports, parameters and documentation. detail: 'full' returns every type's whole description at once. typeCompatibility declares which port types connect; unknown is untyped and accepts every served type.
| Input | Type | Required | Meaning |
|---|---|---|---|
detail |
summary or full |
no | 'summary' (default) lists each type's name, label, category, purpose and data requirements; 'full' adds every type's ports, parameters and documentation. Default: summary. |
Describe capabilities¶
describe
Describe what the product builds with, by kind. node_type with name: what one node type does, its input ports (an edge's target handle must match one; a Script's ports are its entry function's parameters), what it emits, its parameters, dataRequirements and its documentation page, whose headings sections lists; where documentationComplete is false ask again with section. tile_kind: every tile kind a dashboard can display, with the schema add_tile validates against and authoring guidance, read before the first tile. renderer: the map capability, basemaps, output formats, the columns a points query must supply, the point cap and the privacy posture, read once before the first render_visualization or map tile.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
node_type or tile_kind or renderer |
yes | Which kind of object this call is about. |
name |
string | no | The node type to describe, as list_node_types names it, bare or namespaced. Required for kind node_type; not taken by other kinds. |
section |
string | no | A heading from sections, as written; answers only that part of the page. Applies to kind node_type. |
Validate workflow¶
validate_workflow
Cheap pre-execution check on a stored workflow, without running anything. Returns its structural diagnostics — a scenario-producing node with no create-scenario node after it, an unbound required port, two connections into a port that takes one — and the data-dependent ones no write reports: a data_input node naming a data source this project does not hold, and each join checked against the data it joins (a key column missing from the file, key values that match nothing, an inner join with no matches). valid is false while any error stands. nodeColumns lists the columns each node hands on — a Filter's or Join's by the run's rules, a Script's from its last run, outOfDate once it changed. Use it before run_workflow, which is the expensive way to learn the same thing.
| Input | Type | Required | Meaning |
|---|---|---|---|
project_id |
string (uuid) | yes | The project this call acts in. |
workflow_id |
string (uuid) | yes | UUID of the deployed workflow to validate. |
List execution diagnostics¶
list_execution_diagnostics
Fetch a run's persisted diagnostics in batches. Every finding says what happened, why, and what to do about it, and names the subject it is about. get (kind execution) already carries the first error and the counts per severity; this is where the rest are, a page at a time.
| Input | Type | Required | Meaning |
|---|---|---|---|
execution_id |
string (uuid) | yes | The execution id run_workflow answered as executionId. |
limit |
integer | no | Page size (default 25, max 100). Default: 25. |
offset |
integer | no | Page offset for the next batch. Default: 0. |
project_id |
string (uuid) | yes | The project this call acts in. |
severity |
error or warning or info |
no | Return only findings of this severity; omit for all. |
Get scenario topology¶
get_scenario_topology
Read a scenario's topology: its network as nodes and links, grouped and unit-folded server-side — what it looks like, not what it cost. At most location_limit locations and link_limit links come back; when more match, the network's endpoints (demand points, places that only receive) are cut first, so what serves them stays whole: the biggest receivers kept, the rest folded into one location with groupSize. Narrowing precedes that cut, so every location is reachable: filters narrows the link rows (e.g. one product) and node_filters narrows to named locations or location types with every link touching them. isAggregated reports a cut; matchingLocations counts what the narrowing selected, totalLocations and totalLinks the whole scenario, and omittedLinkRows links naming a location the scenario lacks. Null coordinates mean unplaced locations; when coordinatesDeclared is false, the domain has no coordinate fields. Null measures with mixedUnits cannot be added across units.
| Input | Type | Required | Meaning |
|---|---|---|---|
filters |
object | no | Optional per-axis narrowing of the link rows, applied server-side, before aggregation and before the location cap. A link is grouped by (source, target) only, so its quantity, cost and emissions are totalled across every other column; narrowing here is what keeps each surviving link at the magnitude of the values named, and the answer's locations are the ones those rows reach. Keys are the link axes the installed package declares beyond the two endpoints — to narrow to a location, use node_filters. Each value is a scalar or a list of them — {"<column>": <value>} or {"<column>": [<value>, …]}, equality and membership only. An undeclared key is refused with invalid_constraint_params, never dropped. |
link_limit |
integer | no | How many links this answer may carry. When more connect the kept locations, links between two non-endpoint locations rank first, then the largest by quantity; isAggregated says it cut. A value above the most one answer carries is read as that ceiling. Default: 2000. |
location_limit |
integer | no | How many locations this answer may carry, not counting the one group a cut adds. When more match, the cut takes the network's endpoints first — places the domain records demand at, and places that receive links and send none — keeping every other place in file order and the endpoints that receive the most, and groups the endpoints it did not keep into one location with groupSize; isAggregated says it cut and matchingLocations how many matched. A value above the most one answer carries is read as that ceiling. Raise it with link_limit to see a whole network. Default: 500. |
node_filters |
object | no | Optional narrowing to locations, applied server-side and before the location cap, so any location of the scenario can be reached however large it is. Keys are the location identity and type columns the installed package declares; a location matching every key is kept with every link (still under filters) that has either end at it, and each link's other end. Same value shapes as filters — {"id": "C1999 Madrid"}, {"type": ["Distribution Center"]}. An undeclared key is refused with invalid_constraint_params, never dropped. |
project_id |
string (uuid) | yes | The project this call acts in. |
scenario_id |
string (uuid) | yes |
Inspect scenario¶
inspect_scenario
Inspect a scenario before querying it: by default, a compact overview of stored tables, row counts and column names/types. Select table for column meanings, units and sample rows; optionally select columns. Follow next_offset with the same selection to read more tables (overview) or columns (table detail). Then use query_scenario for read-only SQL.
| Input | Type | Required | Meaning |
|---|---|---|---|
project_id |
string (uuid) | yes | The project this call acts in. |
sample_size |
integer | no | Sample rows for a selected table (default 5, max 20); requires table. Large samples may be reduced with sample_truncated. |
scenario_id |
string (uuid) | yes | UUID of the scenario to inspect. |
columns |
list of string | no | Selected column names; requires table. |
offset |
integer | no | Continue at next_offset from the preceding page, with the same selection. |
table |
string | no | Stored table name from the overview; omit for the catalogue. |
Query scenario¶
query_scenario
Read one or compare several scenarios after inspect_scenario. For totals or grouped aggregates over one table, use table and measures: units are handled automatically, and scope scenario_comparison returns each scenario in scenario_ids in one call. For joins, CTEs, windows, calculated expressions or raw rows, use source_sql, the same read-only DuckDB SQL as dashboard tiles; never combine it with structured query fields. Aggregate each table before joining totals: joining detail rows across tables multiplies sums. SQL tables include scenario_id; scenarios supplies names. Bind :name values with params. SQL does not infer units or convert quantities: inspect source units and make conversions explicit. limit and offset page SQL results; next_offset continues them. Use ORDER BY with unique tie-breakers for repeatable pages. profile requests the shared query plan; slow reads also report it.
| Input | Type | Required | Meaning |
|---|---|---|---|
dimensions |
list of string | no | Stored column names to group by, taken from the selected table's inspect_scenario columns. Omit or send an empty array for one aggregate row across the whole filtered table (one per scenario in a comparison, which always groups by scenario_id and scenario_name before these; naming either here changes nothing). |
filters |
list of object | no | Predicates applied before grouping, combined with AND. Each field is a stored column named by inspect_scenario; use in with an array and between with a two-value array. |
filters[].field |
string | yes | Stored column to test, in the spelling returned by inspect_scenario. |
filters[].op |
eq or ne or lt or lte or gt or gte or in or between |
yes | Comparison to apply to the stored column. in expects an array and between expects a two-value array; the other operators compare one value. |
filters[].value |
any value | yes | Value to compare with the stored column; its type should match the sampled values from inspect_scenario. |
limit |
integer | no | Maximum result rows per response. SQL may return fewer to fit the reply budget; continue using next_offset. Structured aggregation reports truncated when this cap applies. Default: 200. |
measures |
list of object | no | Structured-query aggregate measures, used only without source_sql. |
measures[].agg |
sum or avg or min or max or count or count_distinct |
yes | Aggregate applied to field within each dimension group. |
measures[].as |
string | no | Optional output-column name for this measure. Without it the column is named after field, or <field>_<agg> when another output column would share that name (for example quantity_sum beside quantity_count). Output names must be unique: a collision that remains, such as the same measure twice or an as repeated or naming a dimension, is refused with invalid_constraint_params. |
measures[].field |
string | yes | Stored column to aggregate, in the spelling returned by inspect_scenario. |
order_by |
list of object | no | Output columns to sort by after aggregation. Name a dimension or a measure's as value, in priority order. |
order_by[].dir |
asc or desc |
no | Sort direction; defaults to ascending when omitted. |
order_by[].field |
string | yes | Output dimension or measure column to sort by. |
profile |
boolean | no | Return the shared query profile. Slow SQL reads also include it without this flag; the same timeout and diagnostics apply to dashboard SQL. Default: False. |
project_id |
string (uuid) | yes | The project this call acts in. |
scenario_id |
string (uuid) | no | Single-scenario shorthand; prefer scenario_ids. It is folded into scenario_ids when that is empty, and a value not among a non-empty scenario_ids is refused with invalid_constraint_params. On HTTP it is the path's {id}. |
scenario_ids |
list of string (uuid) | no | Scenario UUIDs to read. For scope: scenario, name exactly one (or use the HTTP path's scenario_id); for scenario_comparison, name at least two. |
scope |
scenario or scenario_comparison |
yes | Required scenario scope: scenario reads one, scenario_comparison reads at least two. SQL reads exactly these scenarios and chooses grouping itself; structured comparisons group by scenario first. |
table |
string | no | Exact stored table name to query, taken from inspect_scenario for every scenario in scope. |
offset |
integer | no | SQL result offset; continue with next_offset. Use stable ORDER BY in source_sql. Structured queries do not accept a nonzero offset. Default: 0. |
params |
map of text to string or number or boolean or null | no | Values for :name SQL parameters. Only valid with source_sql. |
source_sql |
string | no | One read-only SELECT or WITH statement in the dashboard DuckDB dialect. Stored table names are SQL relations, quoted when necessary; each includes scenario_id. Join scenarios by id for names, and filter by scenario_id, never by scenario name. Only explicitly scoped scenarios exist in this read. No file/network access or mutations. |
Render visualization¶
render_visualization
Render a map visualization from scenario results, returning its mapView and requested HTML or PNG exports. Read describe (kind renderer) for formats and category limits. points.source_sql selects longitude, latitude and encoding columns from scenario tables under scenario_scope. The core frames the map and fetches only generic basemap tiles; scenario coordinates never leave. Iterate here, then publish with add_tile using the same map intent. Creates no durable object; a map that cannot be built is refused with each reason named.
| Input | Type | Required | Meaning |
|---|---|---|---|
basemap |
dark or light |
no | The basemap the points sit on: 'dark' (default, the product's own) or 'light' (for export surfaces). Both are keyless. |
bounds |
list of number | no | Optional frame as [minLon, minLat, maxLon, maxLat] (WGS84 degrees). Omit and the map frames itself to its points; set it when sibling maps tell one story (all markets beside only the changed ones) so they share a frame — take the widest map's answered bounds and pass it to the others. |
color_by |
string | no | A column whose distinct values colour the points, one colour per value across facets; the legend follows the query's row order: ORDER BY to read bands in sequence. Omit for a single-colour map. |
color_scale |
categorical or sequential |
no | 'sequential' paints ordered bands light to dark down the brand ramp; default 'categorical'. |
comparison_scenario_id |
string (uuid) | no | Optional second scenario, resolved as the 'comparison' scope; with it, 'both' runs the points query across the two — join scenarios and carry scenarios.name as a column so a point can be told apart by the run it came from. |
facet_by |
string | no | A column whose distinct values split the map into small multiples — one panel each, same basemap and frame. Omit for a single panel. |
dashboard_id |
string (uuid) | no | Colour categories as this dashboard does, so the export matches its tile. |
formats |
list of html or png |
no | Which exports to return: 'html' (interactive, to embed in an artifact) and/or 'png' (static, for decks). Defaults to both. |
label_by |
string | no | A column whose value is written as each point's label; nulls are omitted. |
points |
object | yes | The query that yields the points, one row per point. |
points.source_sql |
string | yes | SELECT over the scenario's stored tables. Must yield longitude and latitude columns (WGS84 degrees); every other column is carried onto the point. |
project_id |
string (uuid) | yes | The project this call acts in. |
scenario_id |
string (uuid) | yes | The scenario whose results bind as the 'primary' scope. |
scenario_scope |
primary or comparison or both |
no | Which scenario(s) the points query runs against: 'primary' (default), 'comparison', or 'both'. |
title |
string | no | Optional working title; a published tile's title is the intent's. |
Get user preferences¶
get_user_preferences
Read the authenticated account number presentation preferences across projects and devices. Defaults: decimal_places 2, number_format en-US. Numerical API values remain unchanged.
Tools that write¶
Only a connection you gave Read and write is shown these.
Create project¶
create_project
Create a new project — the container a workspace grant's data sources, workflows, scenarios and dashboards all live in. Returns the same object get (kind project) returns, including the id every project-scoped call then names. Create one per question the user wants a durable, re-runnable answer to, not one per conversation. A name this user already holds — compared case-insensitively — is refused with a diagnostic naming the collision: reuse the existing project or pick a name that says what is different about this one. A blank name is refused too: a project must be called something. A connection granted only some projects reaches the one it creates: the new project joins its grant at once.
| Input | Type | Required | Meaning |
|---|---|---|---|
description |
string or null | no | |
name |
string | yes |
Update saved object¶
update
Can replace or delete what it acts on.
Update one object by kind and id; omitted fields stay. project: name or brief, the brief sent as description with the baseBriefVersion it was edited from (a stale one is refused); the brief is the standing context loaded each turn; record lasting decisions there. scenario: name and description of the current result; currency and horizon never change. data_source: name only; contents arrive as a new file by upload. dashboard: name, description, the selection within its fixed mode (scenario_ids, or scenario_id with comparison_scenario_id, replaces it; baseline_scenario_id or comparison_scenario_id alone moves that role), refresh_from_execution_id (moves that run's workflow outputs together; refused when one has no single replacement) and layout, every grid tile once with order and span in twelve columns, else refused naming the ids; a moved selection answers stoppedDrawing. Tiles: add_tile, replace_tile, remove_tile.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
project or scenario or data_source or dashboard |
yes | Which kind of object this call is about. |
baseBriefVersion |
integer | no | The briefVersion of the brief this description was edited from. Required with every brief: a brief changed since is refused rather than overwritten. Applies to kind project. |
description |
string or null | no | The new description; for a project, the brief as markdown, replacing the current one in full. Applies to kinds project, scenario, dashboard. At most 100000 characters for kind project; at most 600 characters for kinds scenario, dashboard. Default: None. |
name |
string or null | no | The new name. Default: None. |
id |
string (uuid) | yes | The object's id, as list or the call that created it answered it. |
project_id |
string (uuid) | no | The project this call acts in. Required for every kind but kind project. |
rowCount |
integer or null | no | Not writable: read from the uploaded file on every request. Upload a corrected file with upload (kind data_source) instead. Applies to kind data_source. |
sizeBytes |
integer or null | no | Not writable: read from the uploaded file on every request. Upload a corrected file with upload (kind data_source) instead. Applies to kind data_source. |
type |
csv or xlsx or xls or md or txt or null |
no | Not writable: read from the uploaded file on every request. Upload a corrected file with upload (kind data_source) instead. Applies to kind data_source. |
baseline_scenario_id |
string (uuid) | no | The scenario every widget falls back to and deltas are measured against. Defaults to scenario_id. It must be one of the dashboard's scenarios: naming one outside scenario_ids adds it to the selection rather than binding a scenario the dashboard is not about. Applies to kind dashboard. |
comparison_scenario_id |
string (uuid) | no | The other side of an 'a_vs_b' dashboard. Naming it alone moves that role and leaves the rest of the selection as it is. Applies to kind dashboard. |
layout |
object | no | The whole arrangement, as get (kind dashboard) reports layout: every grid tile once, with its order and its span in twelve columns. Omit it and the core keeps what is stored, or derives one from the tiles for a dashboard nobody has arranged. Applies to kind dashboard. |
layout.tiles |
list of object | yes | |
layout.tiles[].i |
string | yes | |
layout.tiles[].order |
integer | yes | |
layout.tiles[].span |
integer | yes | How many of the row's twelve columns the tile takes: 12 is the whole row, 6 a half, 4 a third, 3 a quarter. |
mode |
single or a_vs_b or across |
no | The existing dashboard mode. Repeating it is accepted; changing it is refused because the mode is fixed at creation. Deploy a new dashboard to use a different mode. Applies to kind dashboard. |
scenario_id |
string (uuid) | no | The single scenario this dashboard is about. Replaces the whole selection, and becomes the baseline unless baseline_scenario_id names another member. Applies to kind dashboard. |
scenario_ids |
list of string | no | Every scenario this dashboard is about, in display order. Replaces the whole selection: a scenario left out stops being one of the dashboard's, and a role whose member is left out is cleared with it. Send it to reorder, to add or to remove; omit every scenario field to leave the selection untouched. Applies to kind dashboard. |
refresh_from_execution_id |
string (uuid) | no | Refresh selected outputs of this run's workflow together, preserving order and roles; other workflows stay fixed. The run must be completed and contain an unambiguous replacement for every selected output of its workflow. Cannot be combined with scenario selection fields. Uses output identities, never names. The link stays the same; inspect stoppedDrawing, tileHealth and commentaryNeedsReview before handing it over. Applies to kind dashboard. |
Delete saved history¶
cleanup_history
Can replace or delete what it acts on.
Delete reviewed unused history permanently, by kind, after the person has confirmed it: send each selection's outputId and previewToken from list_history_cleanup. The review is rechecked under locks and a changed one refuses the whole call: refresh and reconfirm. Current and protected versions remain; storage is reclaimed asynchronously.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
scenario or data_source |
yes | Which kind of object this call is about. |
selections |
list of object | yes | |
selections[].outputId |
string (uuid) | yes | |
selections[].previewToken |
string | yes |
Upload data source¶
upload
Upload a file by declaring it; its bytes never travel here. kind data_source: a .csv, .xlsx, .md or .txt file. scenario_bundle: a scmotif.scenario/1 ZIP, followed by import. Both start or resume a multipart session bound to project, name, exact size and SHA-256 and answer short-lived PUT targets: send each exact slice with the returned headers (a 403 with Cloudflare error 1010 means the User-Agent was missing), then call complete_upload and poll get until ready or rejected. The same name, size and hash resumes; a changed size or hash is refused while the name is held. If a PUT cannot reach the target host, tell the person to allow it (guideUrl) or to upload the file at url. If you cannot hash or send a file at all, start no session and never copy its rows into a workflow: hand the person the project's uploadUrl (create the project first if needed) and continue once list shows the file. Never construct or keep target URLs.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
data_source or scenario_bundle |
yes | Which kind of object this call is about. |
name |
string | yes | The filename with its extension, unused by the project's other files; a bundle's is recorded in provenance. 1 to 200 characters for kind data_source. |
project_id |
string (uuid) | yes | The project this call acts in. |
sha256 |
string | yes | Lowercase hex SHA-256 over the exact whole file. Required independently of storage multipart ETags; ingestion rejects the session if the stored bytes differ. |
size_bytes |
integer | yes | The exact file size in bytes. It reserves account capacity and determines the fixed multipart slices before bytes travel. |
data_source_id |
string (uuid) | no | Joins this data source as its latest file. Applies to kind data_source. |
data_source_name |
string | no | Or starts a data source of this name. Applies to kind data_source. |
Resume upload¶
resume_upload
Resume an upload by reconciling multipart state from object storage and returning fresh short-lived targets for missing parts. Safe to repeat after a timeout, process restart or lost response; an already stored part is not requested again. Send the returned target headers with every PUT; non-browser clients, including Python urllib, must use the supplied User-Agent. Browsers retain their own User-Agent. HTTP 403 with Cloudflare error 1010 means the object edge refused the client identity: retry with the target headers, and contact the service operator if it persists; changing file bytes will not repair that refusal. Retrying a PUT safely replaces its part. Never construct or persist target URLs. Targets are a bounded batch: resume again after sending the batch until no parts are missing.
| Input | Type | Required | Meaning |
|---|---|---|---|
project_id |
string (uuid) | yes | The project this call acts in. |
upload_session_id |
string (uuid) | yes |
Cancel work¶
cancel
Can replace or delete what it acts on.
Cancel something in flight by kind and id. execution: a pending or running run is asked to stop; a finished one refuses, naming its final status; whatever it persisted stays, and a cancelled run publishes no scenario, so poll get to see it take effect. upload_session: an upload that has not finished is discarded, freeing the name it holds and the storage it reserves; starting again is a new upload. An upload whose file has arrived is being read and cannot be cancelled: wait for get to report it, then delete the data source if it is not wanted.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
execution or upload_session |
yes | Which kind of object this call is about. |
id |
string (uuid) | yes | The object's id, as list or the call that created it answered it. |
project_id |
string (uuid) | yes | The project this call acts in. |
Complete upload¶
complete_upload
Complete an upload after every exact-sized part is present, finalizing the multipart object and enqueueing strict ingestion. Safe to repeat: it never creates a second DataSource or a second immutable object. Poll get (kind upload_session); only ready makes the data source visible.
| Input | Type | Required | Meaning |
|---|---|---|---|
project_id |
string (uuid) | yes | The project this call acts in. |
upload_session_id |
string (uuid) | yes |
Delete saved object¶
delete
Can replace or delete what it acts on.
Delete one object by kind and id, permanently. data_source: with all its files; scenarios built from it keep their rows, a workflow reading it stops being runnable; refused, naming them, while an unfinished run reads one. file: one file; the newest left becomes the latest. workflow: archived, so it leaves the overview and can no longer be edited or run, while its runs, snapshots, scenarios and results remain. scenario: every version's tables go; refused while an unfinished run or a dashboard reads it, both named in the answer, and also_delete_dashboards removes those dashboards with it. dashboard: its link stops resolving for everyone it was handed to, so confirm before deleting one you did not just create; the scenarios behind it are untouched. A project is deleted by a person in the app.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
data_source or workflow or scenario or dashboard or file |
yes | Which kind of object this call is about. |
id |
string (uuid) | yes | The object's id, as list or the call that created it answered it. |
project_id |
string (uuid) | yes | The project this call acts in. |
also_delete_dashboards |
boolean | no | Delete dashboards referring to any version together with the entire scenario history. Otherwise refuse and name them. Ask the user before true: it destroys their pages. Applies to kind scenario. Default: False. |
Restore saved version¶
restore_version
Can replace or delete what it acts on.
Restore a historical version as a new current version of the same object, by kind and the version's own id; future downstream runs use it, existing results and queued runs stay pinned. scenario: data, inputs and computation provenance are preserved and nothing is recomputed; comparisons stay pinned, inactive outputs stay inactive, and restoring the current version is refused. data_source: an earlier file, by its id, is copied as the latest.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
scenario or data_source |
yes | Which kind of object this call is about. |
project_id |
string (uuid) | yes | |
id |
string (uuid) | yes | The id of the version to restore, as list_versions answered it. |
Copy data source¶
copy_data_source
Copy a data source's file into project_id as a new data source of the same name; both projects must be in your grant. Its id reconnects a workflow on import (kind workflow).
| Input | Type | Required | Meaning |
|---|---|---|---|
data_source_id |
string (uuid) | yes | |
name |
string | no | Else the original's; same file kind. |
project_id |
string (uuid) | yes | The project this call acts in. |
source_project_id |
string (uuid) | yes | |
file_id |
string (uuid) | no | Else its latest file. |
Create workflow¶
create_workflow
Create a named workflow from nodes and edges. Unfinished graphs are stored with diagnostics identifying missing inputs, configuration and scenario-producing connections. Malformed graphs are refused: invalid node references, unknown ports or incompatible connections. Call list_node_types and describe (kind node_type) before wiring nodes; validate_workflow checks data-dependent rules, and run_workflow refuses outstanding diagnostics. Names are unique within a project, compared case-insensitively. An existing name receives a numeric suffix such as Plan (2), shortening the base to fit the name limit; use the assigned name in the response.
| Input | Type | Required | Meaning |
|---|---|---|---|
description |
string | no | |
edges |
list of object | yes | |
edges[].id |
string | yes | |
edges[].source |
string | yes | |
edges[].sourceHandle |
string or null | no | the output port name; binding is by name, never by edge order; null, or left out, when the source has one output |
edges[].target |
string | yes | |
edges[].targetHandle |
string | no | the input port name; binding is by name, never by edge order |
name |
string | yes | |
nodes |
list of object | yes | |
nodes[].data |
object | yes | The node's configuration: the parameters describe (kind node_type) lists for this type, keyed by parameter name. Every node takes label, its name on the canvas, saying what the step does, and description, saying how and with which assumptions. |
nodes[].id |
string | yes | |
nodes[].position |
object | no | |
nodes[].position.x |
number | no | |
nodes[].position.y |
number | no | |
nodes[].type |
string | yes | a node type the registry declares |
project_id |
string (uuid) | yes | The project this call acts in. |
Apply workflow¶
apply_workflow
Can replace or delete what it acts on.
Replace the whole workflow read with get (kind workflow); send its version as baseVersion. Stale copies are refused. Return all fields, including description: omitted fields become empty and omitted nodes/edges are removed. Use patch_workflow for targeted edits. The create gate applies: malformed definitions are rejected; incomplete definitions are stored with diagnostics. Names must be unique within the project, case-insensitively; retaining this workflow's name or changing its case is allowed.
| Input | Type | Required | Meaning |
|---|---|---|---|
baseVersion |
integer | yes | The version of the get (kind workflow) copy this definition was made from. Required: if the workflow has changed since, the apply is refused with changed_since_read instead of undoing that change — read it again, redo your change on that copy and send it with the new version. |
description |
string | no | |
edges |
list of object | yes | |
edges[].id |
string | yes | |
edges[].source |
string | yes | |
edges[].sourceHandle |
string or null | no | the output port name; binding is by name, never by edge order; null, or left out, when the source has one output |
edges[].target |
string | yes | |
edges[].targetHandle |
string | no | the input port name; binding is by name, never by edge order |
name |
string | yes | |
nodes |
list of object | yes | |
nodes[].data |
object | yes | The node's configuration: the parameters describe (kind node_type) lists for this type, keyed by parameter name. Every node takes label, its name on the canvas, saying what the step does, and description, saying how and with which assumptions. |
nodes[].id |
string | yes | |
nodes[].position |
object | no | |
nodes[].position.x |
number | no | |
nodes[].position.y |
number | no | |
nodes[].type |
string | yes | a node type the registry declares |
project_id |
string (uuid) | yes | The project this call acts in. |
workflow_id |
string (uuid) | yes | Id of the stored workflow this definition replaces, from list (kind workflow) or the get (kind workflow) copy you are sending back. |
Patch workflow¶
patch_workflow
Can replace or delete what it acts on.
Edit a workflow with a merge patch. Call get (kind workflow) first; omitted nodes and fields retain their current values, including concurrent edits. patch.nodes maps node ids to fragments: null deletes a node and its edges; a new id with type and data adds one. Use apply_workflow to replace the whole definition. Malformed results are refused atomically; incomplete graphs are stored with diagnostics. Renames must be unique in the project, case-insensitively; retaining this workflow's name or changing its case is allowed.
| Input | Type | Required | Meaning |
|---|---|---|---|
patch |
object | yes | Merge patch over the workflow document. Include ONLY what changes — everything not named is preserved exactly. Shape: {"name"?, "description"?, "nodes"?: {" |
patch.description |
string or null | no | |
patch.edges |
object | no | |
patch.name |
string | no | |
patch.nodes |
object | no | |
project_id |
string (uuid) | yes | The project this call acts in. |
workflow_id |
string (uuid) | yes | Id of the stored workflow to edit, from list (kind workflow) or the answer of create_workflow or import (kind workflow). |
Run workflow¶
run_workflow
Can replace or delete what it acts on.
Execute a stored workflow asynchronously. Structural errors or no compatible live worker refuse submission without creating an execution; repair the graph or ask the operator to restore workers via /health. Poll executionId with get (kind execution) for status, current storage and outputs; read failures with list_execution_diagnostics. This answer’s storage precedes compute. Inputs use the current saved scenario and file versions at acceptance, fixed for the run, without recomputing upstream workflows. Producing steps add versions; existing dashboards retain exact results.
| Input | Type | Required | Meaning |
|---|---|---|---|
project_id |
string (uuid) | yes | The project this call acts in. |
workflow_id |
string (uuid) | yes | UUID of the deployed workflow. |
Deploy dashboard¶
deploy_dashboard
Create a dashboard about one or more scenarios and get the link that opens it on its own; mode is fixed for its life. The core resolves every tile at view time, so numbers stay live and attributed. Add tiles with add_tile, verify with get (kind dashboard), and hand the user the link. Tiles show numbers: give the recommendation, its reasoning and open points in your answer, not on a tile.
| Input | Type | Required | Meaning |
|---|---|---|---|
baseline_scenario_id |
string (uuid) | no | The scenario every widget falls back to and deltas are measured against. Defaults to scenario_id. It must be one of the dashboard's scenarios: naming one outside scenario_ids adds it to the selection rather than binding a scenario the dashboard is not about. |
comparison_scenario_id |
string (uuid) | no | The scenario compared against the baseline in an 'a_vs_b' dashboard. It does not set the mode: send mode 'a_vs_b' with it, because a dashboard sent without a mode is 'single', and a 'single' dashboard cannot hold a comparison. |
description |
string | no | Optional dashboard description. |
mode |
single or a_vs_b or across |
no | What the dashboard is about, fixed for its whole life: 'single' (one scenario), 'a_vs_b' (one against another, with deltas) or 'across' (many at once). Choose from the question asked, not from how many scenarios exist — two scenarios in 'across' is two of many, not a comparison, and gets no deltas. It cannot be changed afterwards; a dashboard of a different shape is a new dashboard. |
name |
string | yes | Dashboard name. |
project_id |
string (uuid) | yes | The project this call acts in. |
scenario_id |
string (uuid) | no | The scenario this dashboard is about; it becomes the baseline unless baseline_scenario_id names another. Name the selection with this (plus comparison_scenario_id for 'a_vs_b') or with scenario_ids. A dashboard may be created before its scenario exists. |
scenario_ids |
list of string | no | Every scenario a mode='across' dashboard compares, in display order. Use instead of scenario_id when the answer spans more than two scenarios. |
Add tile¶
add_tile
Add a tile to a dashboard. Pass an intent — the kind of tile and what it should show — and the core runs the query and assembles the widget. Omit position to append, use top for the beginning, or after:<widget_id> to insert after a tile whose widgetId get (kind dashboard) reports in widgets; an id the dashboard does not carry is refused and the refusal names the ids it does. describe (kind tile_kind) gives every kind's shape and rules; read it once before authoring the first tile. Do NOT pass rows, chart JavaScript or HTML: a dashboard is a recipe the core resolves at view time, which is what keeps its numbers live. The core assigns the tile's id and answers with it; an id inside the intent is ignored, because two tiles sharing one id is a replace_tile that edits the wrong one. Check the result with get (kind dashboard) before handing anyone the link — include_health is what tells you the tile came back with something.
| Input | Type | Required | Meaning |
|---|---|---|---|
dashboard_id |
string (uuid) | yes | UUID of the dashboard. |
intent |
object | yes | Kind-discriminated tile intent — must include kind. describe (kind tile_kind) gives every kind's schema and authoring rules. |
position |
string | no | Where to insert the tile. 'top' inserts at the beginning, 'after: |
project_id |
string (uuid) | yes | The project this call acts in. |
profile |
boolean | no | Also answer what the tile's slowest statement cost, step by step (profile), however quickly it ran. A statement slow enough to be worth rewriting is answered with it unasked. Default: False. |
Replace tile¶
replace_tile
Can replace or delete what it acts on.
Overwrite one tile with a new intent, keeping its id and therefore its position. This is the repair for a tile get (kind dashboard) reports as empty or unresolvable: send the corrected intent rather than removing and re-adding, which would move it to the end. describe (kind tile_kind) gives the shape and rules of the kind you are correcting. An id this dashboard does not carry is refused — and the refusal lists the ids it does.
| Input | Type | Required | Meaning |
|---|---|---|---|
dashboard_id |
string (uuid) | yes | UUID of the dashboard. |
intent |
object | yes | Kind-discriminated tile intent — must include kind. describe (kind tile_kind) gives every kind's schema and authoring rules. |
project_id |
string (uuid) | yes | The project this call acts in. |
widget_id |
string | yes | The widgetId of the tile to replace, exactly as get (kind dashboard) reports it in widgets. A tile id is assigned by the core and is recipe-local (w1, w2, ...), NOT a UUID. The replacement keeps this id and therefore its position. |
profile |
boolean | no | Also answer what the tile's slowest statement cost, step by step (profile), however quickly it ran. A statement slow enough to be worth rewriting is answered with it unasked. Default: False. |
Remove tile¶
remove_tile
Can replace or delete what it acts on.
Remove one tile from a dashboard by its id, and read the dashboard back without it. The remaining tiles keep their positions and their ids. get (kind dashboard) is where a tile's id comes from, and replace_tile is what to use when the tile belongs there and its contents are wrong. An id this dashboard does not carry is refused — and the refusal lists the ids it does, so a stale id costs one call and not a redeploy.
| Input | Type | Required | Meaning |
|---|---|---|---|
dashboard_id |
string (uuid) | yes | UUID of the dashboard. |
project_id |
string (uuid) | yes | The project this call acts in. |
widget_id |
string | yes | The widgetId of the tile to remove, exactly as get (kind dashboard) reports it in widgets. A tile id is assigned by the core and is recipe-local (w1, w2, ...), NOT a UUID. |
Update user preferences¶
update_user_preferences
Can replace or delete what it acts on.
Save account number presentation preferences across projects and devices. Supply decimal_places (0 through 6), number_format (en-US or de-DE), or both. Omitted settings keep their saved values. Changes separators and precision for display only; stored values, currency placement, calculations and raw exports remain unchanged.
| Input | Type | Required | Meaning |
|---|---|---|---|
decimal_places |
integer | no | Decimal places used for numerical display throughout the app. Defaults to 2. |
number_format |
en-US or de-DE |
no | Number separators for numerical display: en-US (1,234.56) or de-DE (1.234,56). Defaults to en-US; currency placement and precision are unchanged. |
Import saved object¶
import
Import one object of a kind into this project. workflow: an artifact from export or a downloaded file, validated like create_workflow with its code parsed and not run; reconnect maps exported references to this project's data sources and scenarios, and what stays unmapped comes back as unresolved_inputs for patch_workflow. scenario: from exactly one source, the upload_session_id of a bundle sent with upload or the export_id export answered for a scenario in any project you reach. A bundle that fails any check publishes nothing; repeating an upload session's import answers the same scenario.
| Input | Type | Required | Meaning |
|---|---|---|---|
kind |
workflow or scenario |
yes | Which kind of object this call is about. |
artifact |
object | no | Required for kind workflow; not taken by other kinds. |
artifact.name |
string | no | |
project_id |
string (uuid) | yes | The project this call acts in. |
reconnect |
map of text to string (uuid) | no | Exported reference → id of a data source or scenario of this project, of the same kind. Applied before the workflow is stored; a key the artifact does not reference, or a target this project lacks, refuses the import. Applies to kind workflow. |
export_id |
string (uuid) | no | A live export from export (kind scenario). The server copies its bytes. Applies to kind scenario. |
upload_session_id |
string (uuid) | no | The upload (kind scenario_bundle) session the bundle was uploaded through. Applies to kind scenario. |