MCP tool reference
Every capability in Semanticus, exposed as a typed operation your AI assistant can call.
Semanticus has two doors onto one live model: the Studio UI you drive, and an MCP server your AI Assistant drives. This page lists every operation on that second door. All 304 are typed operations any compatible MCP client can call. A change made through either door lands on the same model, undo timeline and live broadcast, so you and your assistant always see the same state.
Use the filter to find an operation by name or by what it does. Each entry shows a lead line; open "more" for the full description as the engine reports it. Operations are grouped into families below. The engine itself runs no inference and holds no AI credentials: the intelligence is your assistant, on your account.
No operations match that filter.
#Orientation & reading 13
Start here. These read-only operations let your assistant get its bearings on a model it has never seen: a cheap summary first, then the objects, expressions and dependencies underneath. Nothing in this family changes the model.
model_overview
Summarize the open semantic model: name, source, table/measure counts, and whether there are unsaved changes.
more
Call this first.
get_model_summary
CALL THIS FIRST: the blessed session-start orientation for a fresh session, post-compaction or handoff.
more
ONE round-trip, token-budgeted (≤~2k tokens), giving connection state · entitlement · model overview · a compact excerpt from the model's declared Primer · AI-readiness · structural graph · in-flight work · recent activity · deterministic next actions. Drill down with get_model_primer, connection_status, get_entitlement, ai_readiness_scan, get_model_graph, get_workflow_run, get_plan, get_spec and list_calendars. It omits full findings, object detail and DAX bodies.
model_graph_summary
CHEAP structural overview – START HERE on a large model before get_model_graph.
more
Table/relationship counts, tables by type (date/calculated/hidden), relationship breakdown (many-to-many, bidirectional, inactive counts), and the names of DISCONNECTED visible tables (in no relationship – the key star-schema smell) – without the full per-table/per-relationship detail. Call get_model_graph for the full graph when you need it.
get_model_graph
Get the model's structure as a graph for relationship/ER analysis: every table (with column/measure counts, key columns, date-table & hidden flags) and every relationship (endpoints, cardinality, cross-filter direction, active/inactive).
more
Use it to reason about the star schema, find isolated tables, or audit bidirectional/inactive relationships. On a LARGE model, model_graph_summary is the cheaper first call.
get_object
Get an object's properties by ref (e.g. 'measure:Sales/Total Sales', 'column:Sales/Amount', 'table:Sales').
get_properties
List an object's editable properties (the property grid surface).
more
Each: name, displayName, category, kind (string/bool/number/enum), current value, enum options, read-only. Pass 'model:' for model-level settings, or any table/column/measure/relationship/function ref. Pair with set_property.
get_dax
Get the DAX expression of a measure or calculated column/table by ref (e.g. 'measure:Sales/Total Sales').
list_objects
List child objects of a node.
more
Pass an empty/null parentRef to list tables; pass a table ref (e.g. 'table:Sales') to list its measures and columns.
list_columns
List every column (excluding the internal RowNumber) with the metadata that drives column AI-readiness/authoring: ref, name, table, data type, display folder, format string, summarize-by, data category, and flags for key / hidden / calculated / has-description (+ description, + DAX expression for calculated columns).
more
One call to audit smells like a visible key column, a key with SummarizeBy != None, or a missing description/format.
list_measures
List every measure in the model with the metadata that drives AI-readiness and authoring: ref, name, owning table, display folder, format string, hidden flag, whether it has a description (+ the description), and its DAX expression.
more
One call to audit naming/folders/formats/descriptions across all measures (e.g. find measures missing a description or a format string).
list_functions
List the model's DAX user-defined functions (UDFs).
more
Each has a ref like 'function:MyFunc' – read its body with get_dax, edit with update_measure, rename with rename_object.
get_model_objects
One-call browser dataset: every table + its measures, columns, and hierarchies (with the level names, in order) – each with its display folder, data type, and hidden/key flags.
more
Backs the Advanced-Modelling object browser (perspective/field-parameter/RLS pickers). Prefer this over separate list_measures + list_columns when you need the WHOLE object surface at once (it also carries hierarchies, which those omit). Read-only metadata; works offline.
search_model
Detailed model-wide search.
more
Default (no filters): case-insensitive substring over object names, descriptions, and DAX expressions – the classic behaviour. Optional modes: caseSensitive, wholeWord, regex (validated, with a timeout guard). Optional filters: kinds[] (measure/column/table/hierarchy/calcitem/function/role/perspective/partition), fields[] (name, description, expression, displayFolder, formatString, rlsFilter, mExpression, synonyms – pass fields to widen BEYOND the default name+description+expression), and scope ('table:Name' or 'folder:Name'). Each hit carries ref, kind, table, the field matched, a snippet, raw-offset spans[], and – key for replace – a matchClass (ObjectName | PlainText | DaxReference | DaxLiteral | DaxComment | DaxCode | MExpression) with replaceable + replaceHint. matchClass tells you how to change it safely: ObjectName → rename_object (references auto-update); DaxReference/DaxCode → NOT text-replaceable (rename the object); DaxLiteral/DaxComment/PlainText/MExpression → replace_in_object. Results carry byField/byMatchClass/byKind facet counts and paging (offset). An invalid regex is reported in .Error (not thrown).
#Connections & sessions 19
Open a model from a PBIP or TMDL folder, snapshot a running Power BI Desktop instance, or load a deployed Power BI, Fabric or Azure Analysis Services model over XMLA. One model drives the tree, the Studio and the assistant at the same time. The product also remembers every source you connect to, each with the environment label (local, dev, uat, prod) the agent-permissions matrix gates on.
open_model
Open a semantic model from a Power BI PBIP (point at the .pbip file, the project folder, or the .SemanticModel folder), a TMDL folder, or a .bim file path.
more
Returns basic counts.
open_local
UNIFIED open of a running local Power BI Desktop model: makes the SAME instance both editable in the tree (its metadata is snapshotted into the session) AND queryable live (DAX/DMV).
more
Localhost uses integrated Windows auth – no token. Leave dataSource empty to auto-pick the running instance, or pass 'localhost:51234' (see list_local_instances).
open_live
LOAD the full editable model from a Power BI / Fabric / Azure AS XMLA endpoint into the session, so the WHOLE workbench – AI-readiness scan, BPA, the change-plan, and every edit – operates on the LIVE deployed model.
more
Unlike connect_xmla (which only enables read-only DAX/DMV), this loads the model's metadata via TOM, exactly as Tabular Editor attaches to a deployed model. Edits stay IN-MEMORY and undoable; push them back with deploy_live (the write half – dry-run by default) or persist to a TMDL folder with save_model for review/deployment. endpoint e.g. 'powerbi://api.powerbi.com/v1.0/myorg/<Workspace>'. Leave database empty to load the workspace's only/first dataset. authMode: interactive (browser/MFA via Azure.Identity) | serviceprincipal (AZURE_*/FABRIC_* env – most reliable for Fabric) | azcli (default) | devicecode. tenantId optional – target a specific Entra tenant when your `az login` is a different tenant than the model's.
create_model
Create a brand-new, EMPTY semantic model from scratch and make it the current session (replaces any open model).
more
Default compatibility level 1604 (Direct-Lake-capable, Power BI mode). The model is UNSAVED – the first save_model MUST be given a path. Build it with create_data_source / create_named_expression / create_import_table / create_directlake_table / create_column / create_measure / create_relationship, etc. Returns the new session.
save_model
Persist the model.
more
Pass a target folder path (TMDL) or null to overwrite the source. format defaults to TMDL.
connect_local
Connect (read-only) to a local Analysis Services instance (an open Power BI Desktop).
more
Pass a Data Source like 'localhost:51234', or leave it empty to auto-pick the running Power BI Desktop instance.
connect_xmla
Connect (read-only) to a Power BI / Fabric / Azure AS XMLA endpoint to run DAX/DMV against the LIVE deployed model while you edit files offline.
more
endpoint e.g. 'powerbi://api.powerbi.com/v1.0/myorg/<Workspace>'. authMode: azcli (default, uses your `az login`), interactive (browser), or devicecode. tenantId optional – target a specific Entra tenant when your `az login` is a different tenant than the model's (same as open_live). The result's account field names the identity signed in, when known.
connection_status
Report the current live connection (connected, kind, data source).
disconnect
Close the live connection.
list_local_instances
List running local Power BI Desktop Analysis Services instances (port + workspace).
more
Use one with connect_local.
list_connections
Every live model source this machine has connected to (XMLA endpoints and local running models), newest first.
more
Use this INSTEAD of asking the user to retype an endpoint. Each record carries endpoint, dataset, auth mode, model name, last-used, and the user's target label. Holds NO secrets: authMode is a mode NAME, never a token. 'label' is what the USER declared the environment to be (local | dev | uat | prod); an EMPTY label means the target is treated as PRODUCTION, the strictest reading and the only inference ever made. NEVER guess a label from an endpoint's name. 'workingFolder' is a durable local copy made from that source. 'publishConnectionId' is the separate final XMLA destination when one is linked; a local source does not become a published destination by implication. Existing user-owned local files remain valid sources even though they are not live-connection records. Read-only and free. Next: connection_context for the active edit/query/publish identities, or prepare_working_copy to preview a local workflow.
label_connection
Declare what a target IS: local | dev | uat | prod.
more
REFUSED FROM THIS DOOR. A label is a governance statement and the agent's own permissions are gated on it, so an agent that could relabel prod as dev would have defeated the matrix that restrains it. This tool exists so you can EXPLAIN the refusal, not work around it: when an operation is blocked because a target is unlabelled (and therefore treated as production), name the endpoint that needs labelling and ask the user to set it. Read current labels with list_connections.
forget_connection
Remove a connection from the remembered list (see list_connections).
more
Does not disconnect anything and does not touch the model – it only forgets the endpoint, its auth mode, its target label and its working folder. Re-connecting to the same endpoint records it again, UNLABELLED, which means it will be treated as production until the user labels it.
connection_context
Explain the model identity currently being EDITED and the model identity currently answering QUERIES.
more
They may deliberately be two copies: for example, a safe local working copy for edits while the published model answers real-data queries. Returns relationship=sameInstance only when that is proven; workingCopyAndPublished and twoModels explicitly mean two model contexts are in play. Read this before comparing, testing, or deploying so you never assume the query target is the write target. Holds no credentials. Read-only and free. Next: list_connections to choose a remembered model, connect_xmla/connect_local to change only the query model, or open_live/open_local to edit and query one live model.
prepare_working_copy
Preview or confirm the safe local-edit workflow from a remembered SOURCE connection.
more
The source may be XMLA or a local running model. Default commit=false is read-only: it names the local folder, explains which model will answer tests/queries, names the separate XMLA publish destination when one is selected, and refuses any non-empty folder not proven to belong to that source. commit=true creates or opens the durable local model, then attaches the optional queryConnectionId. Omit queryConnectionId to query the source. For a local source, publishConnectionId is optional and must name an XMLA connection; for an XMLA source it defaults to the source. Local files alone cannot execute DAX. Reopening NEVER refreshes or overwrites local edits, and this operation NEVER pushes changes. Use list_connections for the ids. Next: read connection_context, edit and test locally, then review changes before an explicit push to the linked published model.
remember_xmla_connection
Remember an XMLA endpoint in the shared connection registry without connecting to it.
more
Stores endpoint, optional model name and auth MODE only; never a token or secret. New records are unlabelled and therefore treated as production until the human labels them. Use this only when the endpoint is already known, then list_connections to retrieve its id. This does not open, query, edit, or publish a model.
set_publish_destination
Link the OPEN editable model to a remembered XMLA connection as its explicit final publish destination.
more
Works for Semanticus-created working copies and existing user-owned local files, including files in source control. Writes only machine-local connection metadata: it never edits model/repository files and never deploys. Use list_connections for the XMLA connection id. The actual push remains a separate preview + confirmation through apply_model_diff. Next: connection_context to verify Editing and Publish to before reviewing changes.
list_connection_history
The device-local connection TIMELINE (connects, opens, account switches and sign-ins), newest first – the same log the Connections drawer shows.
more
Optionally filter to ONE connection id (from list_connections). Each event carries the WHERE (endpoint/dataset), the account UPN in play when known, the outcome (ok – a failed open that changed nothing is still recorded), a short detail note, and a UTC timestamp. Holds NO credentials – never a token or secret. Use it to see who last connected where, or to confirm an account switch actually took effect. Read-only and free. Next: probe_connection_accounts for who the NEXT open will sign in as; list_connections for the target list.
probe_connection_accounts
For each remembered XMLA target, the account (UPN) the NEXT open will actually sign in AS – a cheap SILENT probe (a local disk read of the saved sign-in, no network, no prompt).
more
A sign-in is remembered per tenant and credential family (interactive / device-code), so 'account' is that identity, which may differ from a target's own last-used one. 'account' is null when it is genuinely UNKNOWN – no saved MSAL record for that tenant and family (for example azcli / service-principal keep none); a null account is unknown, never signed-out. 'previousAccount' surfaces the target's last-used account as provenance ('was' / 'last opened as') – both when a different current account supersedes it AND when the current account is unknown, so a prediction is never invented from the last-used hint. Holds no credential. Use it to show 'as <account>' before connecting, or to confirm which identity a switch left in place. Read-only and free. Next: list_connections for the full target list; list_connection_history for the timeline.
#Authoring: tables, columns, measures & scripts 27
The typed create, edit, rename and delete primitives for the model’s core objects, plus safe in-field replace, a curated format-string library, and the script-and-apply route for editing many objects as text. Every write is change-tracked and undoable.
create_table
Create a new (empty) table.
more
Add columns with create_column/create_calculated_column; it needs a partition before it can be deployed/refreshed. Returns the new ref ('table:Name'). Undoable.
create_column
Add a DATA column (a physical/source column) to a table.
more
dataType: String|Int64|Decimal|Double|DateTime|Boolean (default String). sourceColumn is the underlying physical column name (defaults to the column name). Returns the new ref ('column:Table/Name'). Undoable.
create_calculated_column
Add a DAX calculated column to a table.
more
Returns the new ref ('column:Table/Name'). Undoable.
create_calculated_table
Create a DAX calculated table (its single partition is a DAX expression, e.g. a date dimension or bridge).
more
Returns the table ref ('table:Name'). Undoable.
create_measure
Create a new measure on a table.
more
Returns the new object ref. Undoable. Pass displayFolder to create it already filed ('Parent\Child' nests) – create + folder is ONE undo step.
create_function
Create a DAX user-defined function (UDF).
more
The expression is a lambda, e.g. '(x: INT64, y: INT64) => x + y'. Names cannot contain spaces. Requires model compatibility level >= 1702 (call set_compatibility_level first if needed). Returns the new ref ('function:Name'). Undoable.
duplicate_object
Duplicate a measure, calculated/data column, hierarchy, calculation item, table (incl.
more
calculated tables / field parameters), or calculation group (a deep clone). newName optional (collision-safe auto-name if omitted). targetRef optional: a 'table:' ref to clone a MEASURE onto another table, or a calc group's 'table:' ref to clone a CALCULATION ITEM onto another group – columns/hierarchies stay on their own table; tables duplicate at model scope. Returns the new ref. Undoable.
delete_object
Delete any model object by ref (measure/column/table/hierarchy/relationship/calculation-group/calculation-item/role…).
more
Deleting an absent ref is a net-zero no-op. DAX references to a deleted object are NOT auto-rewritten – they will error; check dependents first. Undoable.
rename_object
Rename a measure/column/table.
more
ALL DAX references to it are automatically rewritten (safe rename). Returns the new ref. Undoable. (Report-layer bindings outside the model can't be updated – review for renames used in reports.)
replace_in_object
Safely replace matched text in ONE object field, routed by the field's matchClass (from search_model).
more
name → a reference-aware RENAME (FormulaFixup rewrites every DAX/RLS reference); description/displayFolder/formatString → plain-text set; expression → replaces text INSIDE a DAX string-literal or comment only (validated for syntax); mExpression → literal M edit (with a warning – M is not reference-fixed); synonyms → updates the linguistic terms. HARD-BLOCKED: a match on a DAX identifier/reference or on DAX code – it returns the 'rename the object instead' hint rather than corrupting the formula. RLS filters are rename-only. This is a single, free, undoable edit. Pass spanStart/spanLen (from a hit's spans[]) to change ONLY that one occurrence; omit them to replace every occurrence in the field. preview=true rehearses: returns the same before/after + warnings (+ .references blast radius for a rename) WITHOUT mutating, and reports a safety refusal in .blocked instead of throwing. Returns before/after, the (possibly new) ref, and any warnings (e.g. M references the old name). For MANY matches at once, use propose_replace + apply_plan instead.
update_measure
Set the DAX expression of a measure (or calculated column/table).
more
The change is applied to the live shared session, appears immediately in the VS Code UI, and is a single undoable step.
set_measure_format
Set a measure's STATIC format string (e.g. '0.0%', '\$#,0', '#,0').
more
Deterministic, undoable. For a DYNAMIC (per-filter-context) format that switches by magnitude/sign/currency, use set_measure_format_expression. Browse curated strings with list_format_templates.
set_measure_format_expression
Set (or clear) a measure's DYNAMIC format-string expression – the DAX that RETURNS a format string, evaluated per filter context (Power BI's 'Format = Dynamic').
more
This is how magnitude-adaptive scaling (500->'500', 5e6->'5M'), per-currency, per-selected-measure, and duration/bps formats work on a plain measure (a static string can't). Pass an empty string to clear it (the measure falls back to its static/model format). A non-blank expression AUTO-CLEARS any static format string. Requires model compatibility level 1601+. Undoable. (For a static literal use set_measure_format; browse ready-made expressions with list_format_templates.)
list_format_templates
Browse the curated NUMBER-format-string template library (colour is report-side, out of scope): 86 templates across 17 categories (whole numbers, decimals, percentages, currency, scaled K/M/B, signed/variance, Unicode change-indicators, accounting, dates, times, durations, KPI glyphs, ratios, basis points, custom units, blank/zero, scientific).
more
Each has an id, category, name, kind ('static' literal | 'dynamic' DAX expression), the format string, a sampleInput->exampleOutput, a 'common' flag (~20 pinned), and any credit/pack. Apply a STATIC template with set_measure_format (measure) or set_calc_item_format_string (a quoted literal on a calc item); apply a DYNAMIC one with set_measure_format_expression (measure) or set_calc_item_format_string (raw expression on a calc item). Read-only; works with no model open. Use this instead of guessing glyphs / scaling-commas.
set_column_data_type
Set a data (source) column's data type: String|Int64|Decimal|Double|DateTime|Boolean.
more
Only applies to physical/source columns (a calculated column derives its type from its DAX). Undoable.
set_summarize_by
Set a column's default aggregation (None/Sum/Average/Min/Max/Count/DistinctCount).
more
Use None for keys/years/codes. Deterministic, undoable.
set_data_category
Set a column's data category (e.g. 'City','Country','StateOrProvince','PostalCode','WebUrl','ImageUrl').
more
Helps Copilot/maps. Deterministic, undoable.
set_sort_by_column
Set a column's sort-by column (e.g. sort 'Month Name' by 'Month Number').
more
Deterministic, undoable.
set_description
Set an object's description (measure/table/column).
more
Keep it <=200 chars and front-loaded – Copilot truncates. Applies as a reviewable, undoable change tagged as the agent. Use after get_grounding.
set_display_folder
File measures/columns/hierarchies into a display folder in ONE undoable batch (or clear with an empty folder).
more
A display folder is just the DisplayFolder string on each member ('Parent\Child' nests) – it has no existence of its own, so an EMPTY folder cannot persist: create one by moving/creating a member into it. All-or-nothing: any bad ref rolls the whole batch back. For a single object set_property(DisplayFolder) works too; this op keeps a multi-object gesture to one undo step.
rename_display_folder
Rename (or move) a display folder on a table by rewriting the DisplayFolder prefix on EVERY member – measures, columns and hierarchies, nested subfolders included – in ONE undoable batch.
more
toPath may be nested ('Parent\Child') to move the folder; empty toPath removes the folder level (members are promoted). Fails with a teaching message if no member is in fromPath (folders exist only through their members).
set_property
Set one property of an object by name (from get_properties).
more
value is the string form: 'true'/'false' for bool, the enum NAME for enum, the number for numeric. Setting 'Name' renames (DAX refs auto-rewritten). Undoable.
set_properties
Set ONE property to ONE value across MANY objects as a single atomic, undoable change (the multi-select property edit).
more
Same value encoding as set_property. ALL-OR-NOTHING: if any object lacks the property or the value is invalid, NOTHING changes and the error names the object; one undo reverts the whole batch. Use set_property for a single object.
script_objects
Script one or MANY objects to text (read-only – never mutates).
more
format: 'dax' (annotated expressions for measures/calc columns/calc tables/calc items/UDFs), 'tmdl' (per-object TMDL – the model's native, readable on-disk format; the preferred export), or 'tmsl' (createOrReplace JSON; TMSL's unit is the table/role, so a child object scripts its containing table – deduped to containers). Pass several refs to capture a whole batch (e.g. all of a table's measures) in one document. Unresolvable refs are skipped.
apply_dax_script
Apply an edited DAX script (the 'dax' output of script_objects, with '// @object <ref>' headers) back to the model: each block's expression is set on its object in ONE undoable batch.
more
Lets you bulk-edit many measures/calc columns/calc items in one document and commit together. Refs that don't resolve or aren't DAX-expression objects are skipped and reported. Returns {applied[], skipped[]}.
apply_tmdl
Apply edited output from script_objects(format='tmdl') back to the model IN PLACE.
more
Existing table/role documents and individually scripted measures round-trip through TOM's native partial-update path in ONE undoable batch. Measure ownership is pinned by the emitted // @object ref; changing its header/parent is refused (use rename_object/create_measure for structural changes). A brand-new top-level object is skipped (use its typed create op). Returns {applied[], skipped[]}.
#Relationships, hierarchies & model structure 14
The shape of the model: relationships with their cardinality and cross-filter direction, hierarchies, perspectives, calculation groups and their items, and field parameters.
create_relationship
Create a single-column relationship from a foreign-key column (the MANY side) to a lookup column (the ONE side).
more
crossFilter: OneDirection|BothDirections (optional). isActive optional. Returns the new ref ('relationship:Name'). Undoable.
set_relationship_active
Activate or deactivate a relationship.
more
Only ONE active relationship can exist on a given path between two tables – inactive ones are reached on demand via USERELATIONSHIP in DAX (e.g. role-playing date relationships like Order Date vs Ship Date). isActive=true activates it, false deactivates it. Deterministic, undoable.
set_relationship_cardinality
Set a single-column relationship's end cardinalities.
more
fromCardinality is the FK/from side, toCardinality the lookup/to side; each is 'Many' or 'One' (a null/empty end is left unchanged). A normal star-schema relationship is Many→One. Use this to fix a mis-shaped relationship in place instead of deleting and recreating it. Deterministic, undoable.
set_relationship_crossfilter
Set a relationship's cross-filter direction (OneDirection or BothDirections).
more
Prefer OneDirection in a star schema – bidirectional can confuse AI filter context. Undoable.
create_hierarchy
Create a hierarchy on a table from an ordered list of its column names (top level first).
more
Returns the new ref. Undoable.
create_perspective
Create a perspective – a named, curated subset of the model's tables/columns/measures/hierarchies (a focused Q&A or report view).
more
Add members with set_perspective_member; delete with delete_object and rename with rename_object. Returns the new ref ('perspective:Name'). Undoable.
set_perspective_member
Include (or exclude) one object in a perspective.
more
The object ref is a table/column/measure/hierarchy. Including a TABLE cascades to all its columns/measures/hierarchies. Undoable.
get_perspectives
List the model's perspectives and the object refs currently shown in each (the objects×perspectives membership matrix).
more
Read-only.
create_calculation_group
Create a calculation group (a special table).
more
Add calculation items with create_calculation_item. Requires compatibility level >= 1470. Returns the new ref ('table:Name'). Undoable.
create_calculation_item
Add a calculation item to a calculation group.
more
The expression typically uses SELECTEDMEASURE(), e.g. 'CALCULATE(SELECTEDMEASURE(), DATESYTD(...))'. Returns the new ref. Undoable.
list_calculation_groups
List the model's calculation groups with their precedence and ordered items (each item's DAX expression + dynamic format-string).
more
Read-only – author with create_calculation_group / create_calculation_item / set_calc_group_precedence / set_calc_item_format_string.
set_calc_group_precedence
Set a calculation group's precedence (an integer; a HIGHER precedence is applied FIRST when multiple calculation groups combine).
more
Give each calc group a distinct precedence so their combination order is deterministic. Undoable.
set_calc_item_format_string
Set (or clear) a calculation item's DYNAMIC format-string expression – the DAX that overrides the format string of measures evaluated under this item (e.g. a '% of Total' item rendering 0.0%, or a currency item).
more
Pass an empty string to clear it (the item falls back to the base/model format). Undoable.
create_field_parameter
Create a Power BI FIELD PARAMETER: a calculated table of NAMEOF(...) rows that drives a slicer to swap which measures/columns a visual shows.
more
Builds the full Power-BI-Desktop-identical structure (the 3 columns, the ParameterMetadata marker, sort-by, hidden plumbing columns, and the field-switch key). Items are measure/column refs in display order; each label defaults to the object's name. Requires a Power BI-mode model at compatibility level >= 1400. Returns the table ref ('table:Name'). Undoable.
#Data sources, partitions & refresh 18
Where the data comes in: structured data sources, import and Direct Lake tables, partition M source, shared M expressions and parameters, incremental-refresh policy, and the update-schema loop that re-reads a table’s source columns and applies the drift you accept.
create_data_source
Create a structured (M) data source pointing at a Fabric SQL endpoint / Lakehouse-or-Warehouse SQL analytics endpoint (protocol 'tds').
more
Needs compatibility level >= 1400. Referenced by NAME from create_directlake_table or inside an M expression. Returns the data source name. Undoable. (Credentials are supplied out-of-band at refresh – none are stored here.)
create_import_table
Create an IMPORT-mode table whose data is loaded via an M partition – e.g. from a Fabric SQL endpoint via Sql.Database(...).
more
Bundles the table + its M partition (no orphaned placeholder). Add columns with create_column. Returns the table ref ('table:Name'). Undoable.
create_directlake_table
Create a DIRECT LAKE table backed by a Fabric Lakehouse/Warehouse entity (Parquet/Delta, no data copy).
more
Needs compatibility level >= 1604. Bind it to a source created first with create_named_expression (M to the SQL endpoint) OR create_data_source (structured), referenced by name. Returns the table ref ('table:Name'). Undoable.
create_named_expression
Create a shared (model-level) M expression / parameter – the source target for a Direct Lake partition, or reusable M referenced by name (#"Name") inside import partitions.
more
Returns the expression name. Undoable.
update_named_expression
Replace the M of an existing shared expression / parameter (create it first with create_named_expression).
more
Undoable.
get_named_expression
Get one shared M expression / parameter's M text by name (e.g. 'RangeStart').
list_named_expressions
List the model's shared M expressions + parameters (name, kind, M, description).
more
RangeStart/RangeEnd parameters show here. Edit one with update_named_expression, create with create_named_expression.
list_partitions
List a table's partitions (ref, mode, source type, data source).
more
Read a partition's M with get_partition_m, edit it with set_partition_m.
get_partition_m
Get a partition's M source expression.
more
Errors if the partition is not an M source (e.g. a Direct Lake Entity or DAX calculated partition).
set_partition_m
Replace a partition's M source expression (M partitions only).
more
Use to add an incremental-refresh RangeStart/RangeEnd date filter, or to edit the query. Undoable.
refresh_partition
Refresh ('process') a SINGLE partition of the live model.
more
Types: Full (reload + recalc, the default), DataOnly (reload, no recalc), Calculate (recalc only), ClearValues (empty it – destructive), Automatic (refresh only if stale), Add (append rows). LIVE DATA WRITE against the Analysis Services engine – runs as a DRY RUN by default (reports what would run, connects to nothing); pass commit=true to actually execute. Leave endpoint EMPTY to target the live model this session was opened from (open_live/open_local binds it); a file model has nothing to refresh. See list_refresh_types for full explanations.
list_refresh_types
List the partition refresh ('process') options, each with a plain-language explanation: Full (reload + recalc), DataOnly (reload, no recalc), Calculate (recalc only), ClearValues (empty it), Automatic (refresh if stale), Add (append rows), plus the table-level Defragment / Indexes.
more
Read-only – use it to pick a type for refresh_partition.
get_incremental_refresh_policy
Read a table's incremental refresh policy (rolling-window store + incremental window, granularity, mode).
more
Returns enabled=false if no policy is defined. Read-only.
set_incremental_refresh_policy
Define/update a table's incremental refresh policy: store N periods of history and re-import the latest M periods.
more
Set autoWire=true to create or repair RangeStart/RangeEnd and append the required half-open date filter without replacing existing M steps. Leave it false to validate and refuse when prerequisites are missing. Metadata only; it does not refresh data. Deterministic and undoable. Existing-policy fields are preserved when omitted.
remove_incremental_refresh_policy
Remove a table's incremental refresh policy (sets RefreshPolicy = null).
more
Leaves RangeStart/RangeEnd and the partition M intact. Deterministic, undoable.
get_source_schema
Update-Schema step 1 – re-read a table's SOURCE columns (names + data types) schema-only, WITHOUT importing data, by probing the SQL/Fabric endpoint its partition query reads (server/database/schema/table parsed from the partition M, or read off a Direct-Lake entity partition) over TDS.
more
Returns the source columns mapped to TOM types (String|Int64|Decimal|Double|DateTime|Boolean). Needs a reachable source: for an OFFLINE snapshot, a non-SQL source, or a native-query partition it returns Reachable=false with a clear message (never throws). Use diff_schema to compare against the model.
diff_schema
Update-Schema step 2 – diff a table's SOURCE columns against its CURRENT model columns: ADDED at the source, REMOVED from it, or TYPE-CHANGED.
more
Each item carries a stable id for per-item selection. By default it probes the live source (like get_source_schema); pass sourceColumns to diff a SUPPLIED/synthesized schema instead (the offline/manual path – no connection needed). Calculated columns are never flagged (they're DAX-derived, not source-driven). Returns Reachable=false + a message when the live source can't be read. Feed the accepted items to apply_schema_update.
apply_schema_update
Update-Schema step 3 – apply a chosen SUBSET of a schema diff as ONE undoable change: add the source columns you accept, retype the ones whose type drifted, remove the ones the source dropped.
more
Each item: {change: Added|Removed|TypeChanged, column, dataType? (TOM type, for Added/TypeChanged), sourceColumn? (physical name for Added, defaults to column)}. Items that can't apply (a calculated column, a name clash, an unknown column) are SKIPPED with a reason – the accepted changes still commit atomically. Returns per-kind counts + the applied/skipped lists.
#Calendars & time intelligence 8
Calendar-based time intelligence with the modern calendar objects, plus the classic date-table and time-intelligence generators, and marking a table as the model’s date table.
define_calendar
Create a calendar on a table (calendar-based time intelligence, CL 1701+): map its columns to TimeUnit categories (Year, Quarter, Month, Week, Date, MonthOfYear, DayOfWeek, … – absolute units and recurring '…OfYear' variants), with optional associated columns per unit and a 'timeRelated' bucket for untagged time columns (e.g. IsWorkingDay).
more
Enables calendar-aware DAX: TOTALYTD(expr, '<calendar>'). A table can hold several calendars (Gregorian + Fiscal + ISO…) over the same columns. One undoable step; persist with save_model. Requires CL 1701+ (set_compatibility_level).
define_calendar_from_template
One-step calendar setup (the modern replacement for generate_date_table): generate a template's calculated columns (only where absent – existing columns are kept and mapped as-is) AND the calendar with its TimeUnit mappings, as one undoable step.
more
Templates: gregorian (Year/Quarter/Month/Day + name-by-number sort pairing) · fiscal (fiscalStartMonth, FY labeled by ENDING year) · iso (ISO-8601 weeks, Thursday rule) · 445 (4-4-5 retail periods over ISO weeks) · 13period (13 four-week periods). Targets an existing table with a date column (dateColumn, auto-detected when unambiguous), or creates a fresh CALENDAR() calculated table when tableName doesn't exist. The week-based templates (iso/445/13period) share ISO scaffolding columns so they coexist on one table. Requires CL 1701+.
delete_calendar
Delete a calendar from a table (the columns themselves are untouched).
more
Undoable.
list_calendars
List the model's calendars (calendar-based time intelligence, CL 1701+): per table, each calendar's column→TimeUnit mappings (Year/Quarter/Month/Week/Date/…, primary + associated) and its time-related (untagged) bucket.
more
Pure offline metadata read – no connection needed. Also reports whether the model's compatibility level supports calendars at all.
tag_calendar_column
Incrementally edit one column mapping on an existing calendar: tag a column to a TimeUnit (replacing that unit's primary if it has one), add it as an ASSOCIATED column of a unit, put it in the 'timeRelated' bucket, or remove=true to untag it.
more
Undoable.
generate_date_table
CLASSIC approach: create a calculated date table (Date, Year, Quarter, Month Number/Name, Year-Month, Day, Day-of-Week) over a date range and mark it as the model's date table (DataCategory='Time').
more
For calendar-based time intelligence (CL 1701+, the modern approach with calendar-aware DAX like TOTALYTD(expr, 'Fiscal')), prefer define_calendar_from_template. Defaults: name 'Date', range 5 years back to end of this year. Columns materialize on deploy/process. Undoable.
generate_time_intelligence
Generate a suite of time-intelligence measures for a base measure, each correctly written against the given date column, named '<base> <variant>', placed in a 'Time Intelligence' display folder, and inheriting the base format.
more
Default suite: YTD, QTD, MTD, PY (prior year), YoY, YoYPct. Additional opt-in variants (pass in 'variants'): ROLL12/R3M/R6M (rolling 12/3/6-month windows), SPLY (same period last year), PYTD (prior-year YTD), PM (prior month), MoM + MoM% (month-over-month delta and %). Undoable.
mark_date_table
Mark a table as the model's date table (DataCategory='Time').
more
Required for good time-intelligence and Copilot date handling. Deterministic, undoable.
#Security: roles, RLS & OLS 8
Row-level and object-level security: roles and their members, model permissions, per-table row-filter DAX, and table or column visibility per role.
create_role
Create a security role.
more
modelPermission defaults to None (Read is auto-applied once you add an RLS filter). Then use set_table_permission to add per-table row filters and set_role_member to add members. Undoable.
delete_role
Delete a security role (and its RLS filters + members).
more
Undoable.
list_roles
List the model's security roles – each role's name, model permission (None/Read/ReadRefresh/Refresh/Administrator), per-table RLS row-filter DAX, and members.
more
RLS gates what data a Copilot / data-agent persona can see, so it matters for AI grounding.
set_role_member
Add or remove an (Azure AD / external) member of a role, by name (e.g. a UPN or group).
more
add=true adds, add=false removes. NOTE: adding members is blocked on a governed Power BI model (V3Restricted) – members are then managed in the Power BI service; removing/listing always works. Undoable.
set_role_permission
Set a role's model-level permission: None | Read | ReadRefresh | Refresh | Administrator.
more
Undoable.
set_table_permission
Set (or clear) a table's RLS ROW-FILTER DAX for a role – the boolean filter applied to that table's rows for members of the role, e.g. "[Region] = LOOKUPVALUE(...)" or "[Owner] = USERPRINCIPALNAME()".
more
Pass an empty filter to remove it. Setting a filter auto-promotes the role's permission from None to Read – the result echoes the resulting ModelPermission and a Promoted flag so the elevation is explicit. RLS row-filters cannot target a calculation group. The filter is a DAX expression and participates in rename fixup. Undoable.
set_column_ols
Set a column's OBJECT-LEVEL (metadata) security for a role – controls whether the role can SEE the column.
more
'None' hides the column from the role; 'Read' grants it; 'Default' removes the override (visible). Requires model compatibility level >= 1400 (errors clearly below). Surfaced via list_roles → ObjectPermissions[].Columns. Undoable.
set_table_ols
Set a table's OBJECT-LEVEL (metadata) security for a role – controls whether the role can SEE the table at all (distinct from set_table_permission's row filter).
more
'None' hides the table's metadata + data from the role; 'Read' grants it; 'Default' removes the override (visible). Requires model compatibility level >= 1400 (errors clearly below). A calculation group cannot carry OLS. Surfaced via list_roles → ObjectPermissions. Undoable.
#DAX: query, validate, benchmark & profile 14
The DAX lab as operations: run queries and DMVs, validate and lint before you write, benchmark cold and warm, profile the formula-engine and storage-engine split, and read VertiPaq storage.
run_dax
Run a DAX query (EVALUATE / DEFINE...EVALUATE) against the connected live model and return columns + rows (capped).
more
Returns {error} if not connected or the query fails. Read-only. A ROW-returning query (`EVALUATE <table>`, SUMMARIZECOLUMNS, FILTER, VALUES, TOPN, …) reads source rows, so the agent policy's QueryData rule applies to the connected target – an Ask refusal names the approval to request; a Deny means the target's policy forbids it (a human can run it or change the policy). A scalar probe (EVALUATE ROW(...) / EVALUATE { … }) is a calculation and is never gated.
run_dmv
Run a DMV query (e.g. SELECT * FROM $SYSTEM.TMSCHEMA_MEASURES) against the connected live model.
more
Read-only.
preview_table
Preview the first N rows of a table on the connected live model (EVALUATE TOPN(N, 'Table')).
more
Accepts a table name or a 'table:Name' ref. Requires a live connection. Reads DATA rows, so the agent policy's QueryData rule applies to the connected target – an Ask refusal names the approval to request; a Deny means the target's policy forbids it (a human can run it or change the policy).
validate_dax
Validate a DAX expression against the OPEN model BEFORE you write it (create_measure/set_dax).
more
Catches unbalanced brackets (error) and unknown table/column/measure references (warning), with line:column. Offline/read-only – no live engine needed. Valid=false only on a structural error.
lint_dax
Deterministic DAX best-practice lint (SQLBI/DAX-Patterns) – ~15 token-path rules over one DAX expression: IFERROR/ISERROR plus the DIVIDE- and SEARCH/FIND-specific forms, ERROR() as control flow, EARLIER/EARLIEST, extended columns inside SUMMARIZE, comparison-to-BLANK(), hand-rolled zero guards, VAR-as-live-alias inside CALCULATE, unused VARs, the SELECTEDVALUE / DISTINCTCOUNT / REMOVEFILTERS idioms, a measure in a boolean filter predicate, and bare-table CALCULATE filters.
more
With an open session the table-identity rules activate (bare-table filter). Token-based, so comments / strings / [bracketed names] never false-fire. Read-only, free, advisory per-expression – the model-scored layer is the AI-readiness BestPractice category (ai_readiness_scan). Run it on a rewrite before applying.
benchmark_dax
Benchmark a DAX query's wall-clock cost on the connected live model: runs it N times and returns first-run, warm-min and warm-median ms plus each run.
more
Use it to measure a query/measure BEFORE and AFTER an optimization to prove the rewrite is actually faster. Read-only.
benchmark_dax_coldwarm
DAX-Studio 'Run Benchmark': measure a query COLD (the SE cache is cleared before each run) and WARM (no clear), and return Average/StdDev/Min/Max for BOTH total query time and storage-engine time, split by cold vs warm, plus per-run detail.
more
This is the way to prove an optimization helps the worst case. Needs a local Power BI Desktop or admin XMLA endpoint for the cold runs + SE split; on a shared/cloud endpoint pass confirm=true to allow clearing (it affects all users) or it degrades to warm-only. Read-only.
profile_dax
Profile a DAX query's SERVER timings on the connected live model: total ms, the Formula-Engine vs Storage-Engine split, the number of SE scans, SE CPU and parallelism, and the heaviest scans (xmSQL).
more
Use it to understand WHY a query is slow (FE-bound vs SE-bound) when optimizing. Needs a local Power BI Desktop or an admin XMLA endpoint; falls back to wall-clock only otherwise. Read-only.
capture_query_plan
Capture a DAX query's LOGICAL and PHYSICAL query plans (the DAXQueryPlan trace) to understand WHY it's slow – the Formula Engine builds the logical plan, the Storage Engine the physical plan (with #Records per operator).
more
Use it alongside profile_dax when a query is FE-bound (a tall physical plan / huge intermediate records points at the costly operators). Needs a local Power BI Desktop or an admin XMLA endpoint; degrades to 'unavailable' otherwise. Read-only.
clear_cache
Clear the Storage-Engine (VertiPaq) cache for the connected model – the DAX-Studio 'Clear Cache' primitive that makes cold-vs-warm benchmarking meaningful (run it before a query to measure the cold/worst-case cost).
more
NON-DESTRUCTIVE: it only evicts the cache (the engine rebuilds it on the next query); no data or metadata changes. SAFETY: on a SHARED/cloud endpoint this evicts the cache for ALL users (their next queries run cold), so it is REFUSED there unless you pass confirm=true. Needs a local Power BI Desktop or an admin XMLA endpoint.
evaluate_and_log
Debug a DAX query that contains EVALUATEANDLOG(<expr>, "label") calls: runs it and returns the query result PLUS every logged intermediate (label, the sub-expression, and its evaluated rows/values) captured from the engine.
more
Wrap the sub-expressions you want to inspect in EVALUATEANDLOG to see what they actually evaluate to. Needs a local Power BI Desktop or admin XMLA. Read-only. The logged intermediates can include row samples of any table, so the agent policy's QueryData rule applies to EVERY call on the connected target (regardless of the outer query shape) – an Ask refusal names the approval to request; a Deny means the target's policy forbids it (a human can run it or change the policy).
pivot_measure
Test a measure (or any scalar DAX) across a pivot: EVALUATE SUMMARIZECOLUMNS(rowFields..., colField?, filters..., "value", measureExpr).
more
Returns long-form rows the caller pivots into a row x column matrix. Use it to sanity-check a measure's values by category/date before trusting it. Read-only; requires a live connection. Returns rows of source grouping values, so the agent policy's QueryData rule applies to the connected target – an Ask refusal names the approval to request; a Deny means the target's policy forbids it (a human can run it or change the policy).
vpaq_scan
Storage analysis of the connected live query model.
more
Returns observed column and table bytes, component bytes, encoding, an observed-denominator percentage, and an explicit storageMode. Import mode establishes complete model totals, directLake is resident-only, and unknown leaves completeness unconfirmed. Requires a live connection.
export_vpax
Export the open model to a VertiPaq-Analyzer .vpax file (the interchange format for VertiPaq Analyzer, DAX Studio, and the SQLBI ecosystem), using Microsoft/SQLBI's official Dax.Vpax.
more
Writes the model METADATA (tables, columns, measures, relationships) – works offline. Storage statistics (column sizes / cardinality) require a processed/live model and are not included yet. Returns the path, table count, and a note; door-safe (a bad path returns .Error rather than throwing).
#Verified edits & equivalence 9
The deterministic referee. Prove a rewrite is behaviour-preserving, gather evidence for a new measure across many contexts, capture values before a risky edit and compare after, and read the audit trail. See the Pro page for how these become enforced.
capture_baseline
VERIFIED EDITS – value-capture at edit-START (run this BEFORE a risky structural edit: rename, retype, relationship change, delete, M rewrite).
more
Freezes the MEASURED values of the object's blast radius – the lineage-downstream measures, evaluated BY REFERENCE over the SUMMARIZECOLUMNS(groupBy) grid you supply – into a session-held baseline, and returns a captureId. After the edit, compare_baseline re-evaluates the same grid and reports exactly which numbers moved. Pass representative groupBy columns: a grand-total-only baseline is thin evidence (disclosed in the result). Over-cap measures are listed in Skipped, never silently dropped. CERTIFIED TOTALS (month-end close): pass a `label` (the period, e.g. "close FY26 · July") to also PERSIST this capture beside the model as a certified baseline – one control total per call (objRef = the measure, filters = its stated context, includeDependents:false), all under the same label. That certified set survives the session, so a later refresh or edit that moves a signed-off number is caught by compare_baseline(label:…). Free; needs a live connection (a baseline is measured values, not metadata).
compare_baseline
VERIFIED EDITS – the edit-END half of capture_baseline: re-evaluates a captured baseline's grid on the LIVE model and reports per measure whether its numbers are unchanged, MOVED (with the exact contexts and before→after values), or MISSING (the measure no longer resolves – that is an impact, not a skip).
more
Safe=true only when everything is unchanged, nothing is missing/errored, AND coverage wasn't truncated – honesty first. IMPORTANT: it reads the LIVE model, so run it AFTER the edit is deployed (deploy_live) – an undeployed local edit is not validated (the result discloses session edits since capture). CERTIFIED TOTALS (month-end close): pass a `label` instead of a captureId to re-check that period's PERSISTED certified figures – each is re-evaluated at ITS stated context and reported held / moved (old→new) / missing / not-checkable, so drift from what was signed off is named. Detection, not prevention: it cannot stop a refresh or an out-of-tool edit, only report what moved. The verdict is recorded in the Verified Edits audit trail. Free; needs the live connection.
probe_measure
VERIFIED EDITS: run a measure across MANY filter contexts to gather EVIDENCE before you trust it – value/BLANK/ERROR per member, non-blank coverage, additivity – across a scenario matrix.
more
DAX context-dependence bugs (missing time-intel guards, blanks, non-additivity) are INVISIBLE until you run the measure in different contexts. It replicates a real visual (SUMMARIZECOLUMNS with your filter args as the OUTER/slicer context + a group-by axis) so ALLSELECTED / SELECTEDVALUE / ISINSCOPE resolve correctly – a naive one-context test lies about those. Pass a primaryAxis to auto-generate grand/single/multi/empty/boundary scenarios, and/or scenarios[] for cross-filter cases (name columns + members; do NOT hand-write DAX). Reports BEHAVIOR across contexts, NEVER 'correct' – you judge it against intent. Read-only; needs a live connection.
verify_dax_equivalence
PROVE a candidate DAX rewrite is behavior-preserving before applying it: evaluates exprA (original) and exprB (rewrite) side by side across MULTIPLE context shapes built from groupBy – the fully-crossed leaf rows AND each single-column subtotal AND the grand total – and reports whether ALL values match plus any mismatching contexts.
more
The extra shapes matter: SUMMARIZECOLUMNS leaves pin every dimension, so a wrong-SCOPE rewrite (wrong denominator, collapsed context transition, over-broad ALL/ALLEXCEPT) can match at every leaf yet diverge at a subtotal or the grand total – this gate catches that. ALWAYS run it (over a representative group-by matrix) before replacing a measure with an optimized version. Read-only.
optimize_measure
VERIFIED EDITS – an evidence-gated way to optimize a measure.
more
Give >=2 candidate DAX rewrites; the engine validates each, checks each returns identical values to the current body across the SUMMARIZECOLUMNS(verifyGroupBy) matrix YOU supply, benchmarks only the ones that matched (warm wall-clock over that same grid – not a server SE/FE trace), and applies the fastest that beats the current body beyond a measured noise band – recording the proof + benchmark as evidence. Equivalence is only as strong as verifyGroupBy: a grand-total-only match is downgraded to unverified (not accepted), so pass representative group-by columns. REFUSES to finalize without >=2 candidates, without a live connection, or with nothing proven (correctness always gates speed – a faster-but-wrong candidate can never win). Prefer this over update_measure for rewrites/optimization. Auto-apply is Pro; on free it returns the full evidence (paused) so you can apply the winner with update_measure. Needs a live connection (open_live / open_local).
get_verified_mode
Is Verified Mode on? When ON, single-edit DAX ops (set_dax + create measure/calc column/calc table/calc item/function) are strictly validated before they commit – invalid syntax OR an unknown table/column/measure reference is refused (validity only, not an equivalence/drift proof; bulk script/plan paths aren't gated yet).
more
Session-scoped (resets on reconnect). 'available' = whether the tier can turn it on (Pro). Check this so you know whether an edit will be gated.
set_verified_mode
Turn Verified Mode on/off.
more
When ON, single-edit DAX (set_dax + create measure/calc column/calc table/calc item/function) is strictly validated before it commits – invalid syntax or unknown table/column/measure refs refused (validity only, not an equivalence proof). This is the human's guarantee switch – turning it ON is a Pro feature (returns a Pro-required error on free); turning it OFF is always allowed. Prefer the human sets this; if you turn it off, do so deliberately.
list_verified_edits
VERIFIED EDITS: read the append-only, hash-chained audit trail persisted ON the model – every verified op (or accountable override) with its verdict, evidence, and any override reason, in chain order.
more
Each record links the previous by hash, so the trail self-checks: ChainIntact=false (with FirstBrokenSeq) means a record was edited, removed, or reordered after it was written. Read-only, free.
export_verified_edits
VERIFIED EDITS: export the model's audit trail as a shareable report – 'md' (default) for a human-readable markdown summary (boss/auditor) or 'json' for the raw serialized chain (CI/tooling).
more
Read-only. Pro.
#Explain a number & value history 3
Understand one number: a deterministic dossier for a single cell of a single measure, the recorded history of a measure’s value over time, and an honest answer to what moved it. Explaining a value is free; the recorded history is a Pro feature.
explain_value
EXPLAIN THIS NUMBER – a deterministic evidence dossier for ONE cell of ONE measure: the value re-derived in the cell's exact filter context (the same SUMMARIZECOLUMNS shape a real visual runs), the measure's dependency chain (what feeds it), source lineage (where each leaf column's data comes from), TOP CONTRIBUTORS split by a related dimension, and – when the value is BLANK – a why-is-this-blank checklist (filters remove every row / no relationship path / filter flows the wrong way / inactive relationship / blank by design / RLS advisory) with the likely cause named.
more
HONESTY RULES: contributors ship ONLY when the parts provably sum to the total (distinct counts / ratios / min-max / semi-additive measures get an explicit refusal, never a misleading breakdown); RLS is listed as roles that WOULD filter these tables (the engine cannot impersonate a role, so never 'computed under role X'). Describe the cell with filterContext: Filters = column+members (a pivot cell's row/col keys are single-member filters), ExtraPredicates = raw DAX boolean lines (page-filter style). OFFLINE the dossier degrades to chain/lineage/RLS with Evidence.Available=false – connect (open_local / open_live) for the value, blank checks, and breakdown. Next steps: probe_measure to test the measure across MANY contexts; blame_value to ask what CHANGED a number over time. Free, read-only.
blame_value
NUMBER TIME-MACHINE – answer "what moved this number?" deterministically.
more
The engine ambiently snapshots the top measures' values + their whole DAX dependency-cone expressions at checkpoint moments (apply_plan / optimize_measure / deploy_live / save_model – Pro, automatic); this op finds the most recent movement of a measure (or since a given point) and attributes it HONESTLY: verdict 'attributed' when exactly ONE recorded edit sits in the window; 'interval' when several do – candidates come RANKED by dependency overlap (formula-changing edits first) and are a ranking, NEVER a causal claim; 'data-suspected' when every formula is identical but the value moved (data/refresh is the suspect – proving it needs a shadow pre-edit instance, which v1 does not keep); 'inconclusive' when the history can't answer. Formula-caused movement is proven by a deterministic expression diff of the dependency cone between the two points (ExprDiffs). Pro (soft: free tier gets Status='pro' + how to do it by hand for free). Read-only.
list_value_history
NUMBER TIME-MACHINE: the recorded values of one measure across every checkpoint moment (apply_plan / optimize_measure / deploy_live / save_model) – the raw time series behind blame_value, and the UI sparkline's feed.
more
Points with a null value are honest gaps: the formulas were snapshotted but the number wasn't observed there (offline capture, or the edit's impact cone never reached the measure). Truncated=true means retention pruned older points (last 200 checkpoints / 20MB) or unreadable lines were skipped. Pro (soft: free tier gets Status='pro' + the manual free alternative). Read-only.
#AI-Readiness & Best Practice 21
Score the model A to F for AI readiness, run the Best Practice Analyzer, apply deterministic safe fixes, and waive findings honestly (an accepted finding stays visible and counted, never hidden). You can also author your own rules for both analyzers: validate a rule with a live test-run before saving it onto the model.
ai_readiness_scan
Score the open model A-F for AI readiness (Copilot / Q&A / Fabric data agents): overall grade + 0-100, per-category scores, coverage KPIs, gating reasons, and a prioritized findings list.
more
Each finding is tagged SafeFix (deterministic), AiContent (you generate it), or Proposal (human review). On a LARGE model call ai_readiness_summary first, then filter here. Optional filters: category (e.g. 'Naming','Descriptions','DataAgentConfig'), severityMin ('Info'|'Medium'|'High'|'Critical' – keep this severity and above), maxFindings (cap the returned findings; 0 = all, the default – capping is explicit so nothing is hidden silently). Scores/categories/counts are always for the FULL model; only the returned findings list is filtered.
ai_readiness_scan_live
Like ai_readiness_scan, PLUS the live cardinality rules: it reads per-column distinct-value counts (COLUMNSTATISTICS) from the attached connection and applies the Q&A-index rules – SCALE-QNA-INDEX (total indexed unique values vs the Microsoft-documented 5,000,000-value Q&A ceiling, beyond which Copilot/Q&A drop values) and SCALE-HICARD-COLUMN (a single visible column whose cardinality dominates the index).
more
Requires a live connection (connect_xmla / connect_local) – read-only. Use this instead of ai_readiness_scan when connected to grade scale/cardinality too.
ai_readiness_summary
CHEAP overview – START HERE on a large model.
more
Returns the A-F grade + 0-100 overall, per-category score/applicable/violations, coverage KPIs, gating reasons, the total finding count, and counts by severity / fix-kind / top rule – WITHOUT the (potentially large) findings list. Token-light regardless of model size. Then call ai_readiness_scan with a category or severityMin filter to pull only the findings you'll act on.
make_model_ai_ready
The one-shot flow: apply ALL deterministic safe fixes, then return the new scorecard PLUS a prioritized AI-content work queue (each item has the finding + grounding: DAX, table, siblings).
more
Iterate the queue: for each, author a description/name and call set_description (renames need review). Re-scan when done.
apply_fix
Apply the deterministic safe fix for ONE finding (by ruleId + objRef).
more
Supports VIS-FK (hide a foreign-key column), FMT-SUMMARIZE / SUMMARIZE-DIMENSION (SummarizeBy=None), CAT-GEO (geographic data category). For content findings use get_fix_prompt + the matching tool instead. Undoable.
apply_safe_fixes
Apply ALL deterministic, low-risk AI-readiness fixes (hide foreign-key columns, set SummarizeBy=None on key/relationship + non-additive identifier columns, set geographic data categories) in one undoable batch, then return what was applied + the new scorecard.
more
No renames, no generated content.
get_fix_prompt
Get a ready-made remediation instruction (with grounding baked in) for an AI-content finding – which tool to call and what to author (description/name/format/synonyms).
more
Useful when iterating a scorecard's findings.
bpa_scan
Run the Best Practice Analyzer (general modeling best practices: performance, DAX, formatting, naming, layout).
more
Uses the bundled Power BI standard ruleset merged with any rules embedded in the model (load your own with load_bpa_rules / clear them with reset_bpa_rules). Returns violations (rule, category, severity, object, message) flagged CanAutoFix (deterministic) or not. For AI-specific readiness use ai_readiness_scan instead. On a LARGE model call bpa_summary first, then filter here. Optional filters: category, ruleId, autoFixableOnly (true = only deterministically fixable), maxViolations (0 = all, the default; capping is explicit so nothing is hidden silently). RuleCount/ViolationCount/AutoFixable are always for the FULL model; only the returned violations list is filtered.
bpa_summary
CHEAP overview – START HERE on a large model.
more
Rule count, total violation count, auto-fixable count, any rule errors, and violation COUNTS by category / rule / severity – WITHOUT the (potentially large) violations list. Then call bpa_scan with a category / ruleId / autoFixableOnly filter to pull only the violations you'll act on (or bpa_fix_all for all deterministic fixes).
bpa_fix
Apply a BPA rule's deterministic fix to ONE violating object (only for CanAutoFix violations – e.g. bi-directional relationship -> single, key column SummarizeBy -> None).
more
For non-auto-fixable rules use bpa_get_fix_prompt. Undoable.
bpa_fix_all
Apply ALL deterministic BPA auto-fixes in one undoable batch, then return how many were applied + the new scorecard.
more
Does not touch content/naming rules (those need bpa_get_fix_prompt).
bpa_get_fix_prompt
Get a remediation instruction (with the rule + object context) for a NON-auto-fixable BPA violation, so you can fix it with the right tool (set_description / set_measure_format / update_measure / rename_object).
more
This is how Semanticus exceeds Tabular Editor: every rule is fixable – deterministically or by you.
load_bpa_rules
Load Best Practice rules from a file path, an http(s) URL, or inline JSON (standard BPARules.json schema – an array of {ID, Name, Category, Severity, Scope, Expression, FixExpression?, Description}).
more
They layer on TOP of the bundled Power BI standard ruleset and are persisted on the model (so they travel with it and are undoable). replace=false MERGES with any rules already on the model (by id); replace=true sets the model's custom rules to exactly this set. Use reset_bpa_rules to clear them. Returns the new active rule counts.
reset_bpa_rules
Clear all custom/model-embedded BPA rules, reverting bpa_scan to the bundled Power BI standard ruleset only.
more
Undoable.
load_readiness_rules
Load custom AI-READINESS rules from a file path, an http(s) URL, or inline JSON, persisted on the model (they travel with it; undoable).
more
Schema: array of {ID, Name?, Category (an EXISTING readiness category: Naming|Descriptions|Synonyms|Relationships|Visibility|Formatting|CopilotLimits|DataAgentConfig|BestPractice), Severity? (Info|Medium|High|Critical, default Medium), Scope (same vocabulary as BPA rules, e.g. Measure/Column/Table), Expression (violation predicate – same expression language as BPA rules), AppliesTo? (population filter: Applicable = objects matching it; an EMPTY population leaves the rule dormant, never inflating its category), Message?, Description?, FixKind? (None|AiContent|Proposal – advisory; SafeFix is refused)}. Rules are validated strictly against the open model BEFORE anything is written (preview first with validate_rule). Merged by id with the model's existing custom rules (replace=true swaps them); a built-in rule id is refused – custom rules can never override built-ins or register hard gates. Findings from these rules are tagged custom:true; waivers work on them like any finding. reset_readiness_rules clears them.
reset_readiness_rules
Clear all custom AI-readiness rules from the model, reverting ai_readiness_scan to the built-in rule set only.
more
Undoable.
validate_rule
Compile + TEST-RUN a custom rule (or a whole set) against the open model WITHOUT saving – the authoring preview for both rule kinds.
more
kind='bpa' or 'readiness'; rules = inline JSON (one rule object or an array, the same schema the matching load op accepts). Per rule you get: compile errors from the real expression parser (with the failing position), the would-be Applicable population, the violation count, the first few flagged object names, and a dormant flag (empty population = the rule would never move a score). Save with load_bpa_rules / load_readiness_rules once valid.
get_custom_rules
List the custom (user-authored) rules embedded on the model – both kinds: BPA rules (BestPracticeAnalyzer annotation) and AI-readiness rules (Semanticus_ReadinessRules annotation) – plus the valid readiness Category list and the supported Scope vocabulary.
more
Read-only; the manage view behind the Studio 'Custom rules' panels.
waive_finding
WAIVE (accept) a finding so it stops counting against the score – for findings you've consciously decided not to fix (e.g. 'we keep these unused columns').
more
system: 'bpa' or 'air'. objRef set = waive THIS instance (free); objRef empty/'*' = waive the ENTIRE rule, every instance model-wide (the bulk lever – Pro). A reason is REQUIRED: a waiver is an audited decision (stored with who+when on the model), never a silent suppression – the finding is still surfaced (tagged 'waived' with its reason) and the scorecard reports a waived count, so the grade is honest. Hard gates (Q&A scale ceiling, >50% measures undescribed) are NOT lifted by waivers. Persisted on the model (undoable, travels with it); per-instance BPA waivers also write Tabular Editor's BestPracticeAnalyzer_IgnoreRules so TE3 honours them. Re-scan to see the score move.
unwaive_finding
Remove a waiver so the finding counts against the score again (re-instates it).
more
system: 'bpa' or 'air'. objRef set = un-waive that instance; empty/'*' = remove the rule-level waiver. Never gated (it makes the model more compliant). Undoable; also clears Tabular Editor's ignore annotation for a per-instance BPA waiver.
list_waivers
List every accepted (waived) finding on the model – system, rule id, object ref (null = rule-level/model-wide), the reason, who waived it and when.
more
The audit trail behind the scorecard's waived count.
#Model interview 5
Interview the model the way its users will: save natural-language questions with trusted answers, let the engine grade every answer deterministically, and catch the confidently wrong ones before your users do. Ready-made question candidates come from the model’s verified answers and a built-in hard-question pack. Running a one-off question is free; saving a question to the replayable pack is a Pro feature.
list_interview_questions
INTERVIEW: list the OPEN model's saved interview question pack – each question with its tier ('value' = answer vs a trusted number; 'paraphrase' = the same question asked two ways must agree; 'refusal' = the model cannot answer it and the honest outcome is declining), its recorded oracle, and the LAST graded outcome (Correct | Refused | SilentlyWrong | Unverified).
more
Packs are BOUND to the model they were authored against, so `questions` is THIS model's pack only; `otherModelQuestions` and `unattributedQuestions` (legacy, saved before binding, in a shared store) are surfaced separately and are NOT run against the open model. The pack lives in plain JSONL (`.semanticus/interview/questions.jsonl` beside the model; '~/.semanticus/interview/' for scope 'global') – the user's own data. Reports the count of any corrupt lines it skipped (the store never bricks). Free, read-only.
run_interview
INTERVIEW: grade ONE question deterministically – the engine executes the recorded DAX live, compares against the recorded oracle, and returns Correct | Refused | SilentlyWrong | Unverified with plain evidence.
more
HIGH PRECISION by design: offline, an erroring query, a truncated comparison, or a missing oracle all come back Unverified – never a fabricated pass, never a fabricated 'wrong'. Pass `questionId` (from list_interview_questions; the outcome is also recorded on the saved question) OR `inlineJson` (the same fields add_interview_question takes – a one-off, nothing persisted; this is the FREE path). An inline value-tier question MAY omit the oracle: it executes and comes back Unverified with the computed number in the detail – the confirm-and-record flow for seed candidates (confirm the number with the user, then add_interview_question with expectedValue; persistence still REQUIRES the oracle). Refusal tier: pass abstained=true if you (honestly) declined to answer, or attemptDax with the DAX you produced – producing any answer to an unanswerable question is the failure being caught. On SilentlyWrong the result carries fixRuleId + a plain fixHint naming the readiness fix that prevents it. Needs a live connection for the value/paraphrase tiers (open_live/open_local). A saved questionId that belongs to a DIFFERENT model (or is unattributed) is refused – its oracle was authored against another schema, so grading it here would be misleading.
add_interview_question
INTERVIEW (Pro): SAVE a question to the model's interview pack so it replays as a regression check on every future edit (and as the 'interview_replay' workflow verify kind).
more
One-off checks stay FREE – run_interview grades an inline question without saving. Fields by tier – 'value': `query` (a FULL EVALUATE, e.g. EVALUATE ROW("v", CALCULATE([Total Sales], 'Date'[Year]=2024))) + `expectedValue` (the trusted number, confirmed by the user or a verified answer) or `expectedMatrixJson` (rows, order-insensitive); 'paraphrase': `scalarExpr` + `paraphraseExpr` (the SAME question answered two ways as SCALAR expressions – not EVALUATE queries) with optional `groupBy`/`filters` for a per-context proof; 'refusal': just the question – it asserts the model CANNOT answer it, so an assistant that produces a number is confidently wrong. `fixRuleId` maps a failure to the AI-readiness rule that prevents it (a data-table fallback applies when omitted). `seedSource` records where the question came from ('user' | 'claude' | 'verified-answer'). Validation is fail-loud so a saved question is always runnable.
delete_interview_question
INTERVIEW: remove a saved question from the pack (a delta-append tombstone – the JSONL is never rewritten, the history stays).
more
Use it to retire a question whose business definition changed. Free.
list_interview_seeds
INTERVIEW: ready-made question CANDIDATES from two deterministic sources – (1) the model's own VERIFIED ANSWERS (the definition files beside an on-disk model, parsed read-only + fail-soft since the format is observed-not-documented: each usable one yields its trigger question, alternative phrasings, and the fields it references; unusable ones are counted as skipped with the reason) and (2) the BUILT-IN HARD-QUESTION PACK (~a dozen model-agnostic templates from the trap families AI most often answers confidently wrong: rank with ties, year-to-date under a text date attribute, rolling 12-month distinct counts, prior full period, share of total, semi-additive closing balances, same-period-last-year, retention cohorts, weighted averages, inactive-relationship totals, blank-vs-zero, grand-total additivity).
more
Pack templates bind ONLY to objects that exist (a marked date table, a measure to target, related dimensions...); every unbindable template is listed as skipped with the exact missing shape. NO candidate carries a trusted answer and none is fabricated: run the candidate's query, have the user confirm the number, then save it with add_interview_question (expectedValue = the confirmed number; the literal BLANK records a no-value answer; seedSource 'verified-answer' | 'hard-pack'). Free, read-only.
#Grounding & Prep-for-AI content 6
Author the grounding an AI consumer needs: Q&A linguistic schema, synonyms, model instructions and the AI data schema, plus a grounding helper for writing good descriptions.
enable_qna
Enable a Q&A / Copilot linguistic schema (synonyms) on the model by seeding a culture's linguistic metadata.
more
Call once before set_synonyms. Pass null culture for the default (en-US). On an existing schema it self-heals: entities bound to hidden or deleted objects are pruned, and any visible-name collisions Q&A can't distinguish are surfaced as a warning.
set_synonyms
Set the synonyms (alternate words users might say) for a measure/column/table, e.g. Total Sales -> ['revenue','turnover','sales amount'].
more
Auto-enables the linguistic schema if needed. Helps Copilot/Q&A map natural language to the right field. The linguistic schema requires conceptually UNIQUE names: hidden targets are refused, entities bound to hidden or deleted objects are pruned automatically, and a write that would collide two names under Q&A term matching fails with the objects named.
set_ai_instructions
Set the model's Prep-for-AI AI instructions – business context, terminology and analysis rules that guide Copilot/data agents (stored on the model as the LSDL 'CustomInstructions' string).
more
Pass empty/null to clear. Max 10,000 chars (the service ignores anything beyond; the call is rejected if over). Auto-enables the linguistic schema if needed; the write is round-trip verified, live in the shared session, and a single undoable step. CAVEAT: for a DEPLOYED model an LSDL edit syncs to the service only after a model refresh – it is not instant. Persist to disk with save_model.
get_ai_instructions
Read the model's Prep-for-AI AI instructions (the LSDL 'CustomInstructions' string set_ai_instructions writes): the text, its length vs the 10,000-char cap, and the culture read.
more
Read-only. Call BEFORE editing instructions so an append/update doesn't clobber what's already there.
set_ai_data_schema
Include or exclude a field (measure/column/table) from the Prep-for-AI 'AI data schema' – the focused field set Copilot/data agents reason over.
more
included=false EXCLUDES it (marks it Hidden in the LSDL); included=true restores it. Excluding noise (keys, sort/helper columns, intermediate measures) sharpens AI answers without hiding the field from report authors. Auto-enables the linguistic schema if needed; round-trip verified, live, a single undoable step. CAVEAT: for a DEPLOYED model the LSDL edit syncs only after a model refresh. Persist with save_model.
get_grounding
Get grounding context for an object (name, table, DAX expression, format string, existing description, sibling names) so YOU can author a high-quality business description or a clearer name.
more
Call this before set_description.
#Lineage & impact 9
Trace any object end to end, see everything that would break before you change it, find what nothing uses, check safe-to-remove report-aware against local or published reports, and remove the verified-safe set in one undoable sweep.
get_lineage
Read-only LINEAGE GRAPH of the open model (offline, from TOM): every node (data source, table, column, measure) and every directed edge – source→table (resolved from partition M / shared expressions), table→column/measure (contains), dependant→dependency (DAX), and FK→PK (relationship).
more
Use it to trace where a field comes from and what flows from it. NOTE (Phase 1): model-only – published-report field usage is not yet included (see .Caveat).
impact_of
Read-only forward IMPACT analysis: everything that breaks (transitively) if the given object changes or is removed – its DAX dependents (measures/calc columns/calc tables/calc items/KPIs/RLS) plus, for a column, the relationships, hierarchies, and sort-by columns that use it.
more
Returns the impacted set with BFS depth + counts by kind. Call BEFORE editing or deleting a measure/column. NOTE (Phase 1): downstream published reports/visuals are not yet included (see .Caveat).
get_dependencies
DAX dependency edges for an object (measure, calculated column/table, calculation item, UDF, column).
more
direction='dependsOn' (default) lists what its DAX consumes – check before editing; direction='dependents' lists what REFERENCES it – check before delete_object/rename_object to see what would dangle. Returns each ref/name/kind; empty when the object has no DAX edges.
unused_objects
Read-only reverse SAFE-TO-REMOVE sweep (the 'Measure Killer'): every measure/column that NO model object references – a deletion-candidate list.
more
CONSERVATIVE – a column used by a relationship, hierarchy, sort-by, or RLS is never listed. Tri-state verdict per item: 'safe' (nothing references it), 'usedByUnusedOnly' (referenced only by other unused/dead objects – surfaced with BlockedBy), 'caution' (report read failed – Phases 2-3). IMPORTANT (Phase 1): MODEL-ONLY – a field used ONLY by a published report (not by any model object) will still appear here; verify report usage before deleting (see .Caveat).
remove_safe_objects
The safe-to-remove sweep's ACT half: delete the verified-safe objects (unused measures/columns) as ONE undoable transaction.
more
The safe set is RECOMPUTED server-side and each item RE-VERIFIED at apply time – an item whose status changed since your scan (something now references it) is SKIPPED with the reason, never deleted stale. refs (optional) narrows the sweep to those candidates from unused_objects/analyze_reports; omit to remove every currently-safe item. reportPaths (optional, local PBIR – same forms as analyze_reports) makes the verification report-aware, so a field a report displays is never removed. Returns removed[] / skipped[{ref,reason}] / count; writes ONE audit record with the evidence; undo_change reverses the whole sweep in one step. Removing MORE THAN ONE item at once is Pro – each item can be deleted one at a time free (delete_object).
analyze_reports
REPORT-AWARE lineage (the safe-to-remove gap-closer): parse one or more LOCAL Power BI report definitions in PBIR format (a PBIP '<Report>.Report' folder, its 'definition' folder, a .pbip file, or a project root) and return which model fields each report uses, PLUS a safe-to-remove sweep that EXCLUDES anything a report uses.
more
This closes the model-only blind spot where a descriptive column a report displays – but no measure references – wrongly looks unused. Report field references are reconciled to the open model BY NAME (the model must be the one the reports bind to). Offline (local files); the cloud 'Get Report Definition' path will reuse the same parser. Legacy .pbix / RDL are not parsed yet (reported as unreadable → result stays model-only with a caveat).
analyze_cloud_reports
REPORT-AWARE safe-to-remove over CLOUD (published) reports – the Measure-Killer headline against the live service.
more
Fetches each report's PBIR via the Fabric 'Get Report Definition' API, reconciles its field usage to the OPEN model BY NAME, and recomputes safe-to-remove EXCLUDING any field a report uses. reportIds empty = every non-paginated report in the workspace. Behaviour is READ-ONLY (Semanticus never modifies the report), BUT getDefinition requires a WRITE-CAPABLE Fabric scope (Item.ReadWrite.All / Report.ReadWrite.All) + the Contributor role – so you MUST pass consent=true to acknowledge that (tell the user first). Per-report failures (paginated/RDL, a report blocked by an encrypted sensitivity label, a download error) are reported as unreadable with a reason – never silently dropped, so 'safe' is never overstated. A model must be open and must be the one these reports bind to.
list_reports
List the published reports in a Fabric/Power BI workspace (id, name, datasetId, reportType, webUrl) via the non-admin per-workspace path.
more
The datasetId tells you which reports bind to a given semantic model – match it to the open model to find the reports that use it. reportType 'PaginatedReport' = RDL (its field usage can't be parsed). Live read against api.powerbi.com using your Entra identity. Read-only. Pair with analyze_cloud_reports to close the safe-to-remove blind spot using real published-report usage.
impact_assessment
IMPACT: compose the deterministic change assessment before editing, renaming, restructuring or removing one model object.
more
Returns the transitive TOM blast radius, affected supplied PBIR reports/visuals, current-model saved Tests and Interview questions to replay, explicit coverage, unknowns, one five-word verdict, and the exact next op. scope='modelAndReports' is the honest default: without reportPaths it returns Unknown/NeedsReview, never green. scope='model' deliberately proves only model-internal impact. Free and read-only; it deliberately omits report contents and does not apply the change.
#Change plans, diffs & undo 10
The pull request for your model: propose a plan (or build one from a model-wide find and replace), review each item as a before-and-after, and apply the approved subset. Also dry-run any single edit, and step the shared undo timeline. Applying more than one item at once is a Pro feature; see the Pro page.
propose_plan
Analyse the model and assemble a CHANGE PLAN (a 'pull request for your model') WITHOUT mutating anything: deterministic safe fixes + BPA auto-fixes are fully specified; AI-content items (descriptions, formats, names, synonyms) come back as a work queue with grounding for YOU to fill via set_plan_item.
more
Review with get_plan, then apply_plan. scope null = whole model; 'table:Name' = just that table. This is the flagship: fix the whole model in one reviewed, undoable transaction.
propose_replace
Bulk find & replace as a reviewable Change Plan (nothing mutates).
more
Runs the same detailed search as search_model, then turns every replaceable match into the RIGHT KIND of plan item: name matches → 'rename' items (FormulaFixup rewrites every DAX/RLS reference at apply; renames are opt-in 'proposed'); description/displayFolder/formatString/synonyms → plain-text set items (pre-approved, safe); matches INSIDE DAX string literals/comments → 'set_dax' items spliced span-wise so reference spans are NEVER touched (opt-in – they change results; validated for syntax); M bodies → 'set_m' items (opt-in, literal, not reference-fixed). DAX-reference/DAX-code/RLS matches yield NO items – the view's .note reports them honestly (rename the referenced object instead). Items that cannot apply (name collisions, empty results) come back status='skipped' with the reason. REPLACES any current plan. Next: get_plan to review, set_plan_item to approve/reject, then apply_plan – one item is free; applying >1 at once is the Pro bulk primitive (the existing apply_plan gate).
get_plan
Get the current change plan: every proposed item with its before→after, source (deterministic/bpa/ai), risk, status, and a summary.
more
Use it to see what still needs content (status 'needs_content') and what is approved/ready to apply.
add_plan_item
Add a custom change to the plan (an incremental edit, or a DAX rewrite you want verified before applying).
more
kind is the operation: set_dax | set_description | set_measure_format | set_summarize_by | set_column_hidden | set_data_category | rename | set_synonyms | set_relationship_crossfilter | mark_date_table | set_ai_instructions (model-level: objRef is the model, after = the instructions text) | set_ai_data_schema (objRef a measure/column/table, after = 'Excluded' or 'Included') | delete (remove the object) | delete_if_unused (remove ONLY if unused_objects' safe verdict still holds at apply time – recomputed server-side, else the item is skipped with the reason). An identical pending item (same ref+kind+target+after) is deduped: the existing item is returned, not re-added. For a set_dax rewrite, ALWAYS pass verifyGroupBy so apply_plan PROVES equivalence (and skips it if results change). A set_dax item WITHOUT verifyGroupBy is added as 'proposed' (opt-in, like a rename) – it will NOT be applied unless you explicitly approve it via set_plan_item, and if applied it goes in UNVERIFIED. Nothing is mutated until apply_plan.
set_plan_item
Fill an AI-content plan item with your authored value (and/or approve/reject it).
more
Authoring a value moves the item to 'approved' – EXCEPT the opt-in kinds (rename, set_dax without a non-empty verify matrix, set_m), which land on 'proposed' after ANY value revision (even one made after an approval – the consent covered the old value) and need an explicit approve. e.g. set_plan_item('ci-0007', after='Total revenue recognised in the period.'). Use get_plan to see item ids + grounding first.
clear_plan
Discard the current change plan (nothing in the model is affected – the plan never mutated it).
apply_plan
Execute the APPROVED subset of the change plan as ONE undoable transaction.
more
Only approved items are applied – passing approvedIds narrows the approved set (it never applies rejected/proposed/needs_content items). DAX rewrites carrying a verify matrix are proven equivalent first and skipped if they'd change results or can't be proven; renames apply last. Returns a report: applied/skipped/failed counts + before→after BPA violations and AI-readiness grade. A single undo reverts everything; re-run propose_plan to iterate the tail.
dry_run
PLAN MODE for the model: rehearse ANY single model-mutating op through its REAL code path and get back the EXACT change set it would make (the model/didChange deltas) plus the op's own return value – with a hard guarantee of NO mutation, NO undo entry, NO broadcast, and NO audit record (the edit is applied, then rolled back).
more
Preview a create_measure / update_measure / rename_object / set_property / define_calendar before committing, or check whether an op WOULD fail – a rehearsal that finds the failure is still a SUCCESSFUL dry-run (WouldSucceed=false with the op's real teaching error). 'argsJson' is a JSON object of the op's arguments by name, e.g. {"tableRef":"table:Sales","name":"Margin","expression":"[Sales]-[Cost]"}. Entitlement gates stay ACTIVE (a Pro refusal is the real answer you'd get). DENIED (each refusal names the right path): external/system I/O + lifecycle (save_model/open_*/connect_*/refresh_partition/export_vpax/clear_cache/evaluate_and_log/benchmark_*), deploy/cloud/git/fabric/cicd/daxlib/data-agent (already commit-gated – run directly), the undo timeline (undo_change/redo_change), multi-mutate composites whose later steps read earlier writes (apply_plan/apply_safe_fixes/bpa_fix_all/make_model_ai_ready/apply_model_diff/cherry_pick/build_model_from_spec/apply_dax_script/apply_tmdl – use propose_plan / preview paths / apply one typed op), and workflow/knowledge/waiver bookkeeping. After a green rehearsal, run the op itself to apply.
undo_change
Undo the most recent change on the shared session – steps back one entry on the model's SINGLE undo timeline.
more
A whole batch (apply_plan / bpa_fix_all / apply_safe_fixes / a generator) undoes as ONE step. The timeline is shared across both drivers, so this reverts the last change regardless of who made it (your edits or the human's in the VS Code UI). The revert is live – it broadcasts to the UI immediately. Returns CanUndo / CanRedo / AtCheckpoint. Use it to back out a change you just applied.
redo_change
Re-apply the change most recently undone with undo_change – steps forward one entry on the shared undo timeline.
more
Live (broadcasts to the UI). Returns CanUndo / CanRedo / AtCheckpoint. Making a NEW edit after an undo clears the redo stack.
#Multi-model compare & merge 4
Enumerate the model’s authorable objects as a flat reference tree, compare the open model against another version, merge selected changes across models, and copy objects from one model into another.
get_reference_tree
Get the model's object tree as flat nodes – every table (and calculation group) with its measures, calculated columns, and calculation items – each carrying a ref (e.g. 'measure:Sales/Total Sales'), display name, kind, and whether it has children.
more
This is the same reference tree the VS Code compare/cherry-pick picker shows. Use it to enumerate the model's authorable objects in ONE call – to pick refs for model_diff / apply_model_diff / cherry_pick, or as a cheap structural map of what exists. Defaults to the OPEN model; pass sourceFile to read a model on disk instead. Read-only.
model_diff
ALM-Toolkit-grade SEMANTIC compare of the open model against another version – by default the git ref 'HEAD' (i.e. what you changed since the last commit).
more
Returns an object-level diff (per table/column/measure/relationship/role/...: Create/Update/Delete) with each object's before/after text. Pass a different gitRef to compare against a branch/commit, or targetFile to compare against a model on disk, or sourceFile to compare two files. Read-only.
apply_model_diff
Selectively MERGE a source model's changes INTO a target (the ALM-Toolkit 'Update'): makes the target match the source for the chosen objects.
more
TARGET is either a model file on disk (targetFile) OR a PUBLISHED model on an XMLA endpoint (targetEndpoint + targetDatabase). SOURCE defaults to the open model; pass sourceFile or sourceGitRef to merge FROM elsewhere. DRY RUN by default (commit=false reports what WOULD apply – including any DELETES). Pass commit=true to write. selectedRefs limits to specific object refs (e.g. ['measure:Sales/Total']); omit to apply all differences. Preview and single-object commits are free; committing MORE than one object at once is Pro (same rule for every target). Pushing to a published model runs an ALWAYS-ON drift guard: if a target object changed since the diff, the push is REFUSED unless you pass overrideReason (recorded in the audit trail). Every committed push to a published model FIRST writes a restore point (returned as restorePointId) so it can be undone with rollback_push; if a push contains DELETES and the restore point cannot be written, the push is REFUSED. Next: run model_diff first to see the object refs; on a drift refusal, re-run model_diff to see the new state before overriding.
cherry_pick
Copy objects FROM another model INTO the OPEN model (cross-model copy/paste) – e.g. copy a measure from a teammate's model into yours.
more
DRY RUN by default (commit=false reports what would copy, what already exists (would overwrite), and what can't). Pass commit=true to apply as ONE undoable batch. Source is a model on disk (sourceFile) or a git ref of the open model's repo (gitRef). refs are object refs like ['measure:Sales/Margin %']. Supported into the open model: measures, calculated columns, and calculation items (into an existing group). For a whole table or calculation group, use apply_model_diff to a file target instead.
#Workflows 26
Enforced playbooks: read the stock library, start a run, submit or skip a step with a reason, and inspect run state. Curate which workflows are on the menu, show one only when a condition holds, require one for a task, and read the whole policy in one call. Templates are workflows with blanks you fill with your own process, then turn into a runnable workflow. Reading a playbook is free; an enforced run is a Pro feature. See the Pro page.
list_workflows
WORKFLOWS: list the available enforced playbooks – the stock library shipped with the engine plus this project's own `.semanticus/workflows/*.md` (a user file shadows a stock one of the same name; files are re-read on every call, so edits are live).
more
Each entry shows step count, whether it is GATED (starting it needs Pro – enforcement is what's paid, reading is free) and any parse error (a malformed file is surfaced here, never hidden). Free, read-only.
get_workflow
WORKFLOWS: read one workflow's FULL definition – every step's instruction text, gate inputs (the questions you must ask the user), and verify checks.
more
Free: use it to follow a playbook manually, or to preview what start_workflow will enforce. To customise a stock workflow, copy it into `.semanticus/workflows/<name>.md` and edit – the user copy shadows the stock one.
start_workflow
WORKFLOWS: start an ENFORCED run of a workflow.
more
Returns the run id plus step 1's full instructions and its gate questions – ask the USER those questions (do not invent answers), do the step's work with the normal tools, then submit_workflow_step. The engine – not you – evaluates each gate: required inputs must be answered or explicitly declined, and verify checks (probe / equivalence / BPA / readiness) run against the live model. Every transition broadcasts to the Studio UI; the finished run's full record (answers, declines, evidence) is appended to the experience log. Pro when any gate enforces; a workflow whose gates are all 'off' runs free.
get_workflow_run
WORKFLOWS: the live state of a run – per-step status (pending/in_progress/passed/skipped/failed), recorded answers and declines, verify evidence (each verify is one of: passed = proven; failed = evidence produced, gate unmet; unavailable = applicable but no authoritative evidence, blocks a hard step, Missing names what was absent; not_applicable = its when: condition did not hold; skipped = legacy advisory non-blocking skip – with a per-shape equivalence breakdown + engine-reported mismatch cells where present), and any adjudication receipts (witness locks + witness/partition revisions).
more
Plus the CURRENT step's full instructions + unanswered questions. Omit runId for the most recent run. Free, read-only.
submit_workflow_step
WORKFLOWS: submit the run's CURRENT step.
more
answers is a JSON object keyed by gate-input name: a value, or the explicit decline sentinel {"declined": true, "reason": "..."} (answer-or-decline inputs accept a reasoned decline; required ones do not). The ENGINE then runs the step's verify checks against the live model – a hard gate that fails blocks the step with the failure evidence (fix and re-submit, or skip_workflow_step with a reason); a warn gate records it and passes. Answers accumulate run-wide: a later step's probe can reference an input recorded earlier. On success you get the NEXT step's instructions.
skip_workflow_step
WORKFLOWS: skip the run's current step WITH A REASON.
more
The accountable-override shape: never a hard wall, never a silent bypass – the reason is recorded on the run and lands in the experience log with the terminal record. Prefer fixing and re-submitting over skipping a failed hard gate.
abort_workflow
WORKFLOWS: abort a run.
more
The partial record (steps passed, answers, declines, evidence so far) is preserved and appended to the experience log – an abandoned run is data, not a deletion.
save_workflow
WORKFLOWS: author or edit a workflow – write the full markdown (frontmatter + '## Step N:' sections + optional yaml-gate fences with inputs/verify/ops) to this project's `.semanticus/workflows/<name>.md`.
more
The engine PARSE-VALIDATES FIRST: a file the parser refuses is never written and the parse error comes back verbatim – fix and retry. Saving a stock workflow's name creates your project's customised copy (it shadows the stock one). A workflow is a SKILL definition: gate-free = pure instructions (runs free); gates make it Pro-enforced. Free; broadcasts workflow/libraryDidChange so the Studio library updates live.
delete_workflow
WORKFLOWS: delete a USER workflow from `.semanticus/workflows`.
more
Stock workflows are read-only (deleting a customised copy reverts to the stock version). Free.
check_workflow
WORKFLOWS (Learning Loop L4): the admission dry-run for a learned/authored workflow – replay-of-deterministic-steps is a later layer.
more
Parses the file (parse errors surface as usual), then statically resolves it against the live op surface and its own gate inputs: every triggers:/ops: entry must be a real op; every verify when/probe must name an input some gate collects; probe/equivalence (and object-scoped bpa_clean) verifies need a target objectRef input. Returns Ok plus info/warn findings (a distilled workflow's derived_from provenance surfaces as an info). Ok = parses AND no warn. Free, read-only.
replay_check_workflow
WORKFLOWS (Learning Loop L4): the admission layer's EXPENSIVE half – runs check_workflow (parse + op-catalog resolution) THEN a dry_run REHEARSAL of every step op the workflow's exemplar run can drive.
more
Args come from the distilled workflow's `exemplar_answers` frontmatter (the L0 log has no op args; /distill-workflow embeds the exemplar). Each op is REHEARSED (dry_run ran – wouldSucceed + delta count, or the op's own error; the model is untouched, guaranteed rollback), SKIPPED-DENIED (deny-listed/unknown – not a failure), or SKIPPED-UNBINDABLE (a required param the exemplar can't supply – named). Returns Admissible = parses clean AND no rehearsed op would fail. Deliberately does NOT: execute live DAX probes (marked replayable – they need a connection), touch the model, or run sidecar/bookkeeping ops. No exemplar → replay is SKIPPED with an instructive note, never a failure. Free, read-only.
get_op_catalog
WORKFLOWS: the engine's own MCP tool catalog (name + one-line description), reflected from the live tool surface – use it to fill a workflow step's `ops:` action chain or `triggers:` with real op names.
more
Free, read-only.
get_workflow_enforcement
WORKFLOWS: read the model-wide enforcement mode – the user's kill-switch over gate strictness.
more
null mode = no override (each workflow's own strictness applies, engine default hard); 'off' = every gate is skipped (runs record no verified evidence and gated runs start without Pro); 'warn'/'hard' force that strictness everywhere. Free, read-only.
set_workflow_enforcement
WORKFLOWS: set (or clear) the model-wide enforcement mode.
more
mode='off' disables every gate – for quick tasks where the user explicitly doesn't want enforced workflows; mode='default' (or null) restores per-definition strictness; 'hard'/'warn' force that level everywhere. Sits at the TOP of the strictness resolution (above per-gate and per-workflow overrides), is persisted in .semanticus/workflow-settings.json beside the model, and re-broadcasts the library so both doors see gated flags flip. Ask the user before turning enforcement off – it is their accountability lever, not yours.
set_workflow_enabled
WORKFLOWS: turn a workflow ON or OFF for this project – the availability toggle (which workflows are on the menu).
more
Disabled = hidden from the run picker and refused by start_workflow, but STILL listed (marked enabled:false) so it can be re-enabled. Persisted in .semanticus/workflow-settings.json beside the model (git-tracked, so the curation travels with the repo) and re-broadcast to both doors. Orthogonal to strictness (how hard gates bite) and to whether a workflow is required for a task. Free – curating your menu is content.
set_workflow_binding
WORKFLOWS: require an op to route through a workflow – the "Required for…" control (the third axis: availability · REQUIRED · strictness).
more
require is the allowed workflow set (you pick among them by whenToUse); mode 'hard' REFUSES the bare op and steers you to start_workflow, 'warn' allows it but records a compliance advisory, 'off' (or an empty require) CLEARS the binding. The bare op is exempt only while an active run of a required workflow is AT a step that performs it (start-and-freestyle does not satisfy the mandate). Persisted in .semanticus/workflow-settings.json beside the model (git-tracked, so the mandate travels with the repo) and re-broadcast to both doors. Independent of the strictness kill-switch – a mandate is whether you must ENTER a run, not how hard its gates bite. Pro for 'hard'/'warn' (mandatory routing is the enforcement); clearing is free unless the binding is locked team policy. get_workflow_policy shows the current rules.
set_workflow_activation
WORKFLOWS: show a workflow only when a condition holds – the dynamic-activation control (which workflows are on the CURRENT menu).
more
e.g. show 'deploy-freeze-guard' only during the month-end window, or 'prod-checklist' only on the prod workspace. `when` is a plain condition over facts the engine knows – date (date.monthEndOffset >= -3, date.dayOfMonth >= 28), connection (connection.workspace ~ '*prod*', connection.kind == 'xmla'), git (git.branch == 'main'), the model (model.tableCount > 50, model.hasRls == true, model.readinessGrade < 'B'), or the session (session.tier == 'pro') – joined with && / || (no parentheses; split into separate rules for grouping). set='on' shows it only when the condition holds; set='off' hides it then. Passing neither `when` nor `set` CLEARS the rule (it shows normally again). Activation CURATES the menu – it is NOT a lock: a hidden workflow is still startable on demand, and a workflow REQUIRED by a binding is always shown. Persisted in .semanticus/workflow-settings.json (git-tracked) and re-broadcast to both doors. Pro (writing a rule); reading the menu/policy is free. get_workflow_policy shows the current rules + any contradictions.
get_workflow_policy
WORKFLOWS: this project's whole workflow POLICY in one compact read – the model-wide enforcement mode, one row per workflow (on the menu? gated? its whenToUse hint, and the ops that REQUIRE it), and the raw op→workflow bindings (op, required set, mode, whether locked team policy).
more
Token-lean (no step bodies): read it BEFORE authoring so you self-route into a required workflow instead of hitting a mandate by rejection. Free, read-only.
list_workflow_profiles
WORKFLOWS: list the simple project profiles available in Studio, what each changes in plain language, whether it requires Pro, and which profile is selected.
more
A profile is one reviewed bundle of menu, requirement and check-strength settings. Free, read-only. Use activate_workflow_profile to apply one atomically.
activate_workflow_profile
WORKFLOWS: atomically replace the project's simple workflow policy with one named profile from list_workflow_profiles.
more
Solo analyst clears prior menu rules, requirements and automatic visibility rules. Team and Consulting profiles require Pro because they make workflows required. The settings remain source-controlled and any later manual policy edit marks the profile Custom.
export_workflow_evidence
WORKFLOWS: export one terminal run as the shared sealed evidence artifact: canonical JSON plus deterministic self-contained HTML and a SHA-256 content signature.
more
Every step, instruction, declared action, answer or explicit decline, gate result, effective strictness, skip reason and abort reason is preserved. The run is bound to the model that owned it and is refused from a different model. Omit runId for the most recent run. Free, read-only; starting an enforced workflow remains the existing Pro boundary.
list_workflow_templates
TEMPLATES: list the workflow-template shelf – the fill-in-your-own-process recipes (stock shipped with the engine + this project's `.semanticus/workflow-templates/*.md`; a user file shadows a stock one of the same name).
more
A template is NOT a runnable workflow: it has declared SLOTS you fill once (your KPI dictionary, your close checklist, your freeze window) and instantiate into a concrete workflow. Each entry shows the slot count + names and any parse error (surfaced, never hidden). Free, read-only. Next: get_workflow_template to read one, instantiate_workflow_template to fill it in.
get_workflow_template
TEMPLATES: read one template's full definition – its slot declarations (the questions to ask the user, each with an example) plus the raw markdown body with the {{slot}} references intact, so you can see exactly what will render.
more
Free, read-only. To fill it in, collect a value for each slot (ask the user the slot's question verbatim) and call instantiate_workflow_template.
instantiate_workflow_template
TEMPLATES: fill a template into a concrete, runnable workflow.
more
valuesJson is a JSON object keyed by slot name (ask the user each slot's question – do not invent org process). The engine renders by DETERMINISTIC text substitution (no inference), then enforces the STRUCTURE-PRESERVING INVARIANT: it renders once with your values and once with dummy values, parses both, and REFUSES if your values changed anything the engine ENFORCES – a step, a gate, a check, strictness (slot values may change what a step SAYS and what a question ASKS, never what it enforces); the refusal names exactly what changed where. It then runs the same admission check a saved workflow gets, and saves the instance with provenance (template, version, date, slot values) so it can be re-instantiated later. FREE (authoring is content; the paid line is ENFORCING the instance via start_workflow). A missing required slot is refused with the slot's own question. Next: start_workflow(newName) to run it.
save_workflow_template
TEMPLATES: author or edit a USER template – write the full markdown (frontmatter with `kind: template` + a `slots:` block + '## Step N:' sections whose prose/questions reference each slot as {{slotName}}) to `.semanticus/workflow-templates/<name>.md`.
more
PARSE-VALIDATES FIRST (a file the parser refuses is never written; the error returns verbatim), and slot-validates: every {{ref}} must name a declared slot, and every slot needs an example (the trial instantiation renders with it). Saving a stock template's name creates your customised copy (it shadows the stock one). Free – authoring is content. Next: check_workflow(name) to trial-instantiate, then instantiate_workflow_template to fill it in.
delete_workflow_template
TEMPLATES: delete a USER template from `.semanticus/workflow-templates`.
more
Stock templates are read-only (deleting a customised copy reverts to the stock version). Free.
#Tests 8
Save and run model tests, inspect run history, reconcile a changed measure to its test, and export a report. Test execution is engine-graded, so an offline or incomplete result is never turned into a pass.
list_tests
TESTS: the saved test definitions (.semanticus/tests/suite.jsonl beside the model): id, kind ('measureReconcile'), title, target binding and enabled state.
more
Definitions bind by LineageTag when present, or by a stable tests-sidecar identity for a valid tagless object. A vanished or ambiguous target reports MISSING on the next run, never a silent pass. Ambient checks are not listed here because they derive from the model on every run_tests. Unreadable lines are counted, never thrown. FREE, read-only.
save_test
TESTS: create or update a saved test definition (upsert by id; omit id to create).
more
kind='measureReconcile': paramsJson carries the ReconcileRequest (sql, groupBy, required blankPolicy, tolerances; see reconcile_measure, which is the same runner one-off). Pass targetRef; the engine binds by LineageTag when present and otherwise creates a stable tests-sidecar identity so valid tagless measures follow renames. The returned bindingWarning is non-null if a name fallback was unavoidable. GROUND TRUTH IS AI-DRAFTED, HUMAN-ACCEPTED: show the user the SQL and get acceptance before saving. A saved test is the user's suite, not the assistant's guess. Pro; running the ambient suite is free.
delete_test
TESTS: delete a saved test definition by id (list_tests shows ids).
more
Returns false when the id wasn't present. Ambient checks cannot be deleted – they derive from the model; to clear a failing integrity check, fix the data it measured. FREE.
run_tests
TESTS (the Prove intent): run the model's whole test suite and get graded health.
more
ZERO-SETUP AMBIENT CHECKS run on every model: per-relationship integrity (live: six data probes – orphaned foreign keys, duplicate/blank keys, row counts; an invalid relationship reparents orphans onto the hidden blank row so TOTALS STILL TIE while every per-member breakdown is silently wrong – any integrity Fail caps the grade at D) + per-role static security (a tautology filter like 1=1 restricts nothing). Saved definitions (list_tests) run too – measureReconcile defs execute the full SQL-vs-DAX reconciliation. Verdicts: Pass | Fail | Suspect (downstream of a sibling failure, its root cause named – not a second failure) | NotVerifiable (couldn't check: offline, refused, insufficient coverage – NEVER counted as a pass and NEVER graded). READ Health.Grade WITH Health.CoveragePct – the grade scores only what was decided; coverage says how much that was; RootFailures is the number that matters. Offline runs the static checks and reports the rest NotVerifiable – connect_xmla/connect_local for the full run. Agent-origin data probes are governed by the standard QueryData permission gate. FREE including all evidence; persist=true also appends the run to history (Pro). Read-only.
list_test_runs
TESTS: the persisted run history for this model (chronological, fingerprint-filtered) – each run's health only (grade + coverage together, verdict tallies, root-failure count), never per-cell evidence (evidence lives on the live run).
more
The drift-trend substrate: compare health across runs to see a suite degrade before a user does. Pro (run_tests itself is free and shows everything live); free callers get a teaching note, never an error. Read-only.
export_test_report
TESTS: export the latest successful run as portable Markdown plus one sealed evidence artifact in canonical JSON and self-contained HTML.
more
Returns {markdown, json, html, contentHash, note, error}; JSON is the record of truth, HTML is its deterministic human view, and contentHash detects any later change. The report includes model and environment context, grade WITH coverage, hard gates, root causes before detailed evidence, measure reconciliation rows only for failing measures, time-intelligence variant evidence, relationship counts and rates, and static security plus object visibility. It never exports a run from a different model: if no current-model run exists, call run_tests and retry. Pro with a soft gate: free callers receive a teaching note, not an exception. Read-only.
reconcile_measure
Reconcile a DAX measure against an INDEPENDENT SQL ground truth, cell by cell (the Tests-tab correctness spine).
more
The engine runs the DAX side (SUMMARIZECOLUMNS over your groupBy + the measure, plus an independent grand-total query) over the live XMLA connection and runs YOUR supplied SQL over the Fabric SQL endpoint, full-outer-joins them by the composite grouping key, and judges every cell under an explicit tolerance + blank policy. The engine NEVER authors the SQL – you supply the ground truth. The SQL runs against the source endpoint as YOUR OWN identity (the engine holds no elevated credential – it can only read what you already can; the endpoint's nature + your warehouse permissions decide what is possible). Whether you (an agent) may run it is governed by the QueryData permission setting on the SQL target (the permissions tab – Ask/Deny/Allow), exactly like preview_table / run_dax. A human runs ungated. groupBy entries are resolved to real model columns (a 'column:Table/Column' ref or a plain 'Table'[Column]); an unresolved entry is refused (this prevents WRONG RESULTS, not writes). blankPolicy is REQUIRED ("zero"|"null"|"distinct"). Grade on `status` (Reconciled|Mismatch|InsufficientCoverage|NothingVerifiable|InputError), NOT `anyMismatch`; an uncaveated pass is Reconciled AND unverifiable==0 AND complete==true – and even then expected-member coverage is UNKNOWN (coverageKnown=false; it reconciles the members observed, not that none is missing). A total-only run is InsufficientCoverage by design (a matching total can hide the VertiPaq blank-row trap). Requires a live connection; reads source-row aggregates from BOTH the model and the SQL endpoint. Returns the status, summary, worst offender, coverage facts, per-side execution timestamps (independent connections may see different snapshots), snapshotNote, and the mismatching cells (capped).
review_reconcile_mapping
TESTS: inspect how a saved SQL-vs-DAX reconciliation maps its measure to Fabric SQL.
more
Returns the detected endpoint/database plus every candidate model table with schema/entity, and echoes the effective endpoint after optional overrides. Detection follows the measure's dependency tables; multiple reachable SQL sources are reported AMBIGUOUS and never guessed. testConnection=true performs only SELECT 1 against the effective endpoint/database (it does NOT run or change the human-accepted SQL); agent calls use the standard QueryData approval gate. Suggested next action is returned on refusal/failure. FREE, read-only.
#Evidence 3
Store, list and verify evidence from tests, workflows and reviewed changes. Evidence stays beside the model and carries hashes so a later reader can detect tampering.
list_evidence
EVIDENCE: list the sealed Test and Workflow evidence saved with the open model under `.semanticus/evidence/<model-identity>`.
more
Each item includes type, producer, verdict with coverage, content signature, paths, and verification state. A changed or conflicted record remains listed as invalid and is never trusted or hidden. Free, read-only. Next: get_evidence(id) to review one; save_evidence(source) to explicitly retain the latest Test report or a terminal Workflow run.
get_evidence
EVIDENCE: open one current-model record from list_evidence as canonical JSON plus its deterministic self-contained HTML view.
more
The engine re-verifies the signature and HTML pairing before returning it; invalid evidence is refused with the exact reason. Free, read-only.
save_evidence
EVIDENCE: explicitly save an engine-owned artifact with the open model for source control and team review.
more
source='tests' saves the latest current-model Test report and keeps its existing soft Pro boundary; source='workflow' saves a terminal Workflow run (sourceId may be omitted for the latest). The engine regenerates and verifies the artifact itself, then atomically writes canonical JSON plus matching HTML under `.semanticus/evidence/<model-identity>`. Re-saving the same source is idempotent. Nothing is written by export alone.
#Primer 5
Read and edit the concise guide to the model, then review Pro suggestions one at a time. The Primer is plain Markdown beside the project and is never rewritten from an unreviewed suggestion.
get_model_primer
PRIMER: read the open model's single project orientation document.
more
It is plain Markdown in a .semanticus/primers sidecar – beside the model (travels in source control) for a disk model, or in the workspace for a live/local connection – and always uses six fixed sections: Overview, Business context, Gotchas, Patterns, Known issues, History. Read this before model work for the declared business context and known traps. Free, read-only.
set_model_primer
PRIMER: replace the open model's declared orientation document with reviewed Markdown.
more
The document must keep exactly six second-level sections in this order: Overview, Business context, Gotchas, Patterns, Known issues, History. Stored beside the model in .semanticus/primers so it travels in source control without changing the model definition. Manual writing is free. Show the user the proposed edit before writing; automated suggested-edit generation is a separate Pro capability.
list_primer_suggestions
PRIMER (Pro): list reviewed, model-scoped learning as proposed edits to the open model's fixed Primer sections.
more
Each proposal carries the source lesson id, capture time and source-run provenance. This never changes the Primer. Show the proposal to the user, then call accept_primer_suggestion only after explicit approval or reject_primer_suggestion to dismiss it. Free users can still edit the Primer manually.
accept_primer_suggestion
PRIMER (Pro): apply ONE already-reviewed suggestion to its fixed Primer section and preserve its source provenance in the Markdown.
more
Human approval is required before this call. The accepted source id is recorded so it cannot resurface. To write directly without suggestion automation, use set_model_primer (free).
reject_primer_suggestion
PRIMER (Pro): dismiss ONE suggested update for this model without changing the Primer.
more
The source learning remains in the hidden learning store, while this model records the rejection so the same suggestion does not keep resurfacing.
#Knowledge & learning loop 11
The learning loop’s memory: record and curate insights, recall prior experience for a model of this shape, read the model’s fingerprint, and mine the experience log for where tools flail. Capture and recall are free for everyone.
add_insight
KNOWLEDGE (L1): record ONE actionable lesson – a distilled insight or a post-mortem root cause.
more
Insights are the USER'S OWN DATA: plain append-only JSONL (`.semanticus/knowledge/insights.jsonl` for project scope, `~/.semanticus/knowledge/` for global), readable without us, never rewritten. Give deterministic match keys (rule ids, gate signatures, error types, op names, domain tokens) so recall can find it. Write-gated (SSGM): it lands 'pending' until approve_insight, UNLESS the auto-approve setting is on – which DEFAULTS TO TRUE for single-user local mode (set knowledge-settings.json {"autoApprove": false} to force review). fingerprintScoped=true pins it to the CURRENT model's shape (needs an open model); false = a user-level lesson that travels across all models. Free.
edit_insight
KNOWLEDGE (L1): refine an insight's text and/or match keys – a delta append (the store is never rewritten; constraint against context collapse).
more
Provide new text and/or keys; omit one to leave it unchanged. Free.
approve_insight
KNOWLEDGE (L1): approve a 'pending' insight so recall_experience can surface it (the SSGM write-gate release).
more
No-op-safe on an already-approved insight. Free.
upvote_insight
KNOWLEDGE (L1): +1 an insight's importance counter (ExpeL – the engine counts, you judge).
more
An insight that keeps proving useful ranks higher and resists decay. Free.
downvote_insight
KNOWLEDGE (L1): -1 an insight's importance counter.
more
When the score falls to 0 the insight is materialized OUT of the live set (the delta trail is kept – nothing is erased). Use it to retire a lesson that stopped applying. Free.
delete_insight
KNOWLEDGE (L1): tombstone an insight (delta append; the JSONL is not rewritten).
more
It vanishes from the live set and recall. Prefer downvote for a lesson that merely lost relevance. Free.
list_insights
KNOWLEDGE (L1): list the live insight set with counters (score/uses/retrievals) and provenance (who/when/session/source-runs).
more
Filter by scope ('project'|'global'; omit for both) and/or status ('pending'|'approved'). Reports the count of any corrupt JSONL lines it skipped – the store never bricks. Free, read-only.
recall_experience
KNOWLEDGE (L2): before starting work on the open model, recall prior experience for THIS model shape.
more
The engine computes the model's fingerprint, reads BOTH scopes' APPROVED insights, and returns a DETERMINISTICALLY-ranked candidate set (key-term overlap with your query + same-shape fingerprint bonus + importance score + temporal decay) – each with WHY it matched (matchedKeys). This is retrieval, not judgment: YOU do the semantic ranking over the candidates and decide what applies. Returns the fingerprint too, and says so plainly when there is no prior experience for this shape. Needs an open model. Free.
get_model_fingerprint
KNOWLEDGE: the open model's deterministic fingerprint – table/measure/column counts, source types, fact/dim classification, a naming-convention hash, and the top domain-word tokens, plus the stable FingerprintKey used to scope insights to matching model shapes.
more
No inference, no embeddings. Use it to reason about 'have I seen a model like this before'. Needs an open model. Free, read-only.
purge_knowledge
KNOWLEDGE (L1): scoped one-op purge (the MemoryGraft safety valve).
more
DRY RUN by default: confirm=false returns how many live insights WOULD be erased and changes nothing; confirm=true appends a purge marker so everything before it in that scope becomes invisible on replay (the file is not rewritten). Free.
harness_report
Read-only harness-ergonomics report over the L0 experience log (.semanticus/experience.jsonl): per-op counts + error rates, retry clusters (>=2 consecutive same-op failures), the top-N recurring error messages, top flail sites (failures-before-a-success per op), and the four harness KPIs (task success rate, tokens/outcome [not derivable from L0 v1], flail rate per 100 events, human interventions).
more
Use it to find where agents flail so you can fix TOOL ERGONOMICS (better error messages, terser results) – a permanent improvement, cheaper than learning machinery. Fail-soft: a missing/empty/corrupt log returns an empty report with a note, never an error. Does not mutate the model.
#DaxLib packages 6
Install, list, inspect and remove DAX user-defined-function packages from the DaxLib feed as atomic, undoable transactions.
daxlib_search
Search the DaxLib feed (daxlib.org – the 'app store for DAX UDFs') for packages.
more
Anonymous + read-only; no model needs to be open. Omit 'text' to list all. Returns package summaries (id, latest version, description, authors, downloads). Then use daxlib_package_info to preview a package's functions, and daxlib_install to add them.
daxlib_versions
List the published versions of a DaxLib package (newest-first, including -prerelease tags).
more
Anonymous + read-only.
daxlib_package_info
Get a DaxLib package's detail: metadata, dependencies, and the list of UDF names it would install (the blast radius to review before installing).
more
Anonymous + read-only. Omit 'version' for the latest stable.
daxlib_install
Install a DaxLib package's DAX UDFs into the OPEN model as ONE atomic, undoable transaction (raises compatibility level to 1702 if needed; pulls in dependency packages, deps-first).
more
Free. By default existing functions of the same name are left untouched (reported as skipped); pass replaceExisting=true to overwrite. Provenance is recorded so daxlib_list_installed / daxlib_uninstall work. Undoable in one step.
daxlib_uninstall
Remove a DaxLib package previously installed by Semanticus – deletes the UDFs it owns (per provenance) in one undoable batch and clears its provenance record.
more
Free.
daxlib_list_installed
List the DaxLib packages installed in the open model (from the Semanticus_DaxLibInstalled provenance annotation): id, version, and the UDF names each owns.
more
Offline – no network.
#Documentation & model spec 12
Author and read the model’s documentation narrative, and work with the declarative model spec you can build a model from or generate from an existing model or a Fabric SQL endpoint.
get_doc_model
Get the complete documentation snapshot of the model that the exporter renders: header (name, compatibility level, culture, counts), the relationship graph, every table's detail (description, hierarchies, partitions with their source – M/SQL/DAX or, for Direct Lake, the Entity binding – calc-group items), all measures & columns (with DAX), KPIs, roles/RLS, data sources, shared expressions, the Prep-for-AI surface, the AI-readiness + BPA scorecards, and (when live-connected) VertiPaq storage stats – PLUS any authored Documentation narrative.
more
Read-only. Use it to understand the whole model at once or to see what the built docs will contain.
get_doc_outline
List the model objects that can carry Documentation NARRATIVE (the model, every table, every measure) and which narrative sections each already has.
more
Use this to discover WHERE to add business context for the exported documentation. The narrative is ADDITIONAL context for the docs – separate from each object's first-class Description (which you set with set_description).
get_doc_section
Read one Documentation narrative section (Markdown) for an object.
more
objRef is 'model' for the model-wide narrative, or 'table:Name' / 'measure:Table/Name' (narrative is supported on the model, tables and measures). Common sectionKeys: 'overview', 'businessContext', 'notes' (per object); 'overview', 'glossary', 'methodology' (model). Returns null if empty.
set_doc_section
Author/insert a Documentation narrative section (Markdown) for an object – ADDITIONAL business context that merges into the exported documentation, SEPARATE from the model's Descriptions.
more
objRef is 'model' or 'table:Name' / 'measure:Table/Name' (narrative is supported on the model, tables and measures; other refs are rejected). Common sectionKeys: 'overview', 'businessContext', 'notes' (per object); 'overview', 'glossary', 'methodology' (model). Set markdown to empty/null to clear the section. This is the collaborate-on-the-docs path: it's stored as a model annotation, broadcasts live to the human's Documentation tab, and is undoable.
get_spec
Get the current MODEL SPEC – the structured plan for the model to build (storage mode + Fabric source, tables with columns/types/role, relationships, core measures, time-intelligence).
more
The spec is an authoring artifact (NOT the model itself); build_model_from_spec materialises it. Returns { version, source, spec } (spec is null if none is loaded). Read-only.
set_spec
Replace the current model spec with the supplied JSON (the whole ModelSpec document).
more
Use this to author or refine the spec; it broadcasts live to the Spec tab. Shape: { name, compatibilityLevel, storageMode: 'import'|'directLake', source: { kind:'fabric-sql', server, database, schema }, tables: [{ name, role:'fact'|'dimension'|'date'|'calculated'|'isolated', entity, schema, mExpression, calculatedExpression, sourceName, columns: [{ name, dataType, sourceColumn, isKey, hidden, summarizeBy }] }], relationships: [{ fromTable, fromColumn, toTable, toColumn, cardinality:'manyToOne'(default)|'oneToOne'|'oneToMany'|'manyToMany', crossFilter, isActive }], measures: [{ table, name, dax, formatString, displayFolder }], timeIntelligence: ['YTD','PY',...], timeIntelligenceBaseMeasures: [...], dateTable: { name, startExpr, endExpr, markAsDate } }. Does NOT touch the model. Returns the new spec view.
save_spec
Save the current model spec to a JSON file (for version control / sharing).
more
Pass an absolute path, e.g. '.../model.spec.json'. Returns the spec view.
load_spec
Load a model spec from a JSON file (written by save_spec) and make it the current spec.
more
Broadcasts live to the Spec tab. Returns the loaded spec view.
clear_spec
Discard the current model spec (nothing in the model is affected – the spec never mutated it).
more
Returns the empty spec view.
autogenerate_spec_from_model
Auto-generate a starter model SPEC from the currently OPEN model (read-only – does not change the model): classifies each table fact/dimension/date/calculated by its relationship roles, captures columns + data types + keys + relationships + existing measures, PROPOSES additive 'Total <col>' measures for numeric fact columns, and suggests a time-intelligence set + date table.
more
The autogen is a FIRST DRAFT – refine it (set_spec / the Spec tab), then build_model_from_spec. Returns the spec view.
autogenerate_spec_from_fabric
Auto-generate a starter model SPEC by introspecting a FABRIC SQL ENDPOINT (Warehouse / Lakehouse SQL analytics endpoint) over TDS – reads INFORMATION_SCHEMA (tables, columns + types, declared PK/FK) using your Entra identity (a deterministic, read-only schema read; no data is copied).
more
Classifies fact/dimension from FK topology, maps SQL types to TOM types, hides key columns, and proposes additive measures + a time-intelligence set. storageMode 'import' (M) or 'directLake'. authMode: azcli (default) | serviceprincipal | interactive | devicecode. If the endpoint rejects the sign-in with an authentication error, the workspace is usually in a DIFFERENT tenant than your az login – pass tenantId. The result is a FIRST DRAFT – refine it, then create_model + build_model_from_spec. (Fabric often declares no enforced keys, so relationships may be empty – add them in the spec.) Returns the spec view.
build_model_from_spec
Materialise the current model spec INTO the open model as ONE undoable transaction (a single undo reverts the whole build).
more
Composes the authoring primitives in dependency order: data source + shared M -> tables (import/Direct Lake/calculated, with columns + data types + keys) -> relationships (FK->PK) -> date table -> measures -> time-intelligence. Existing objects are skipped (re-run safe); per-row failures are reported without aborting. Build INTO the current session – call create_model first for a from-scratch build. Returns a report (created/skipped/errors + before->after counts).
#Data agents 7
Create, read, update, publish and delete Fabric data-agent items, and generate a data-agent configuration from the open model. Writes are dry-run by default.
create_data_agent
PRO (all data-agent writes are Pro; list/get stay free).
more
Create a new (empty draft) Fabric data agent – data_agent.json + a minimal draft stage_config with aiInstructions. DRY RUN by default: commit=false returns the exact request and changes NOTHING; commit=true creates it. aiInstructions capped at 15000 chars.
get_data_agent
Get one data agent's decoded configuration: the draft (and published, if any) stage – aiInstructions, each data source (type, ids, descriptions, the raw elements tree, few-shots), and the publish description.
more
Live read; read-only.
list_data_agents
List the Fabric data agents in a workspace (id, name, description, type).
more
Live read against api.fabric.microsoft.com with your Entra identity; read-only. [verify-at-build]: the item type string isn't documented yet, so this filters items whose type CONTAINS 'dataagent' (case-insensitive) – if none match, ObservedItemTypes lists every item type in the workspace so you can confirm the real one.
update_data_agent
PRO (all data-agent writes are Pro; list/get stay free).
more
Update a data agent's DRAFT – replace only the parts you pass (null = keep). Read-modify-write: fetches the current definition and re-emits ALL existing parts plus your changes (never drops unknown parts). aiInstructions capped at 15000 chars. datasourceJson/fewshotsJson go under the draft/{datasourceFolder}/ folder (folder = 'semantic_model-<name>'). DRY RUN by default: commit=false returns the exact request and changes NOTHING.
publish_data_agent
PRO (all data-agent writes are Pro; list/get stay free).
more
Publish a data agent: copy every draft/* part to published/* and write publish_info.json with a description ([verify-at-build] – v1 publishes via the documented definition-write path). DRY RUN by default: commit=false returns the exact request and changes NOTHING; commit=true publishes.
delete_data_agent
PRO (all data-agent writes are Pro; list/get stay free).
more
Delete a Fabric data agent item. DRY RUN by default: commit=false returns the exact request and changes NOTHING; commit=true deletes it (irreversible).
generate_data_agent_config
PRO.
more
Build a complete semantic_model datasource config FROM the open model in one shot – an element tree of every table/column/measure with model descriptions carried and is_selected honoring hidden objects + the Prep-for-AI AI-data-schema exclusions; aiInstructions seeded from the model's LSDL instructions. Returns the JSON for review (feed it to update_data_agent) – writes NOTHING. artifactId/workspaceId come back as placeholders (resolve the real Fabric ids first – see the Note). Like every data-agent write, Pro; list/get stay free.
#Deploy, pipelines, ALM & Fabric 17
Ship the model: the deploy gate, live metadata deploy, Fabric deployment pipelines, Fabric Git sync, and a CI/CD scaffold. Cloud writes are dry-run by default and gated.
deploy_gate
The deploy-readiness gate: runs the BPA + AI-readiness scans (and, if a target is given, the pending-change count) and returns pass/block + the blockers.
more
This is the guardrail the deploy/publish actions check before a live write. Read-only. WAIVED BPA findings never block (they're audited acceptances – bpaWaivedBlocking counts them); readiness hard-gates ignore waivers by design.
deploy_live
DEPLOY the session's metadata edits back to the live Power BI / Fabric / Azure AS model over XMLA (the write half of open_live).
more
Metadata only – names/descriptions/visibility/categories/format strings/folders/summarize-by, measure + calc-column DAX, partition sources (M / calc-table DAX / legacy), shared expressions, and the linguistic schema – via Model.SaveChanges(), matched by LineageTag so renames land on the right object. NO data refresh and NO deletes. A NEW CALCULATED table IS created (and Calculate-recalced on commit); other structural changes (new DATA/import tables, new data columns, new partitions, source-type or Direct Lake rebinds, incremental-refresh policy) are reported in Unmatched/LiveOnly, never silently dropped. Empty endpoint = deploy back to the model this session opened (the round-trip); or pass endpoint + database. DRY RUN by default – commit=true writes. Needs a Read-Write XMLA endpoint and a write principal (authMode=serviceprincipal is the reliable one).
preview_deploy
Preview what promoting a model between pipeline stages WOULD change (New vs Update per item, by source→target pairing) + the readiness gate.
more
Read-only – deploys nothing. ('Update' items may be identical; Different-vs-NoDifference is only known after a real deploy.)
deploy_stage
Promote items between Fabric deployment-pipeline stages.
more
DRY RUN by default (the New/Update preview + the readiness gate); commit=true deploys. An agent may deploy to NON-production stages only – promoting to PRODUCTION needs a human confirming from the Deploy tab with the confirmToken their own dry-run shows. A failing gate blocks unless forceOverride=true. items = source item ids (empty = all supported).
deployment_history
List a deployment pipeline's recent deployments (status, source→target stages, item counts, who deployed).
more
Read-only.
get_pipeline_stages
List a deployment pipeline's stages in order (Dev=0, Test=1, Prod=2…) with each stage's assigned workspace.
more
Needs an Admin role on the pipeline. Live read; read-only.
get_stage_items
List the items in a pipeline stage (itemType e.g. SemanticModel/Report, with source/target item ids + last deployment time) – use it to resolve the SemanticModel itemId to deploy.
more
Needs Contributor on the stage workspace. Live read; read-only.
list_deployment_pipelines
List the Fabric deployment pipelines you can access (id, displayName, description).
more
Use get_pipeline_stages then get_stage_items to drill into a pipeline's Dev/Test/Prod stages. Live read; read-only.
list_workspaces
List the Fabric workspaces you can access (id, displayName, type, capacity).
more
Live read against api.fabric.microsoft.com using your Entra identity. Read-only.
cicd_generate
Generate a ready-to-run fabric-cicd CI scaffold (parameter.yml + a GitHub Actions or Azure DevOps workflow + deploy.py) running the real publish_all_items in CI.
more
Pure file authoring – no Fabric call. Returns the contents; write=true also writes them into the repo.
cicd_publish
Publish the OPEN model's on-disk definition (PBIP/TMDL) to a Fabric workspace via updateDefinition – a FULL OVERWRITE of the target semantic model.
more
DRY RUN by default (enumerates parts + target, writes nothing); the live publish (commit=true) is human-only from the Deploy tab – an agent's commit is refused, previewing is allowed.
fabric_git_connect
Connect a workspace to a git repo (Azure DevOps or GitHub).
more
DRY RUN by default (commit=false). Pass commit=true to connect. Needs workspace Admin. After connecting, initialize + fabric_git_update/commit to sync.
fabric_git_connection
The workspace's Fabric Git connection: provider (Azure DevOps / GitHub), repo/branch/directory, connection state, last-synced commit.
more
Read-only.
fabric_git_status
The workspace ⇄ git diff: each changed item (workspace change vs remote change vs conflict), plus the workspace + remote commit hashes.
more
Read-only.
fabric_git_update
Update the WORKSPACE from git (git→workspace) – OVERWRITES workspace items with the git version.
more
DRY RUN by default (commit=false reports the incoming change count + any conflicts). Pass commit=true to apply. conflictPolicy = PreferRemote (default) | PreferWorkspace; allowOverride=true permits overwriting items that have workspace changes.
fabric_git_commit
Commit the WORKSPACE's changes to git (workspace→git).
more
DRY RUN by default (commit=false reports the pending change count; writes nothing). Pass commit=true to commit. items = item objectIds for a selective commit (empty = all).
fabric_git_disconnect
Disconnect a workspace from git.
more
DRY RUN by default (commit=false). Pass commit=true to disconnect. Needs workspace Admin.
#Restore points & agent permissions 5
The safety and governance layer around a live push. Every committed push to a published model writes a restore point first, so list the restore points a target can be rolled back to, preview and run a rollback (it reports what it would restore and remove), and prune old snapshots. And read the agent-permissions policy: the global switch, the active preset, and the capability-by-environment matrix your assistant checks before it acts, plus the queue of actions waiting for your approval. Reading is free, rolling a push back is free at both tiers, and changing a policy or a target label is a human-only action.
list_restore_points
List the pre-push snapshots a published model can be rolled back to.
more
Every committed apply_model_diff push to an XMLA endpoint writes one FIRST, so the push can be undone – this is the only way back from a live DELETE (a deploy re-creates measures, calculated columns, calculated tables and named expressions, but a relationship, role, perspective, hierarchy, partition, culture, datasource or data table removed from a published model is otherwise gone for good). Newest first. Only the newest 10 per target are kept. Filter by endpoint + database, or omit both for every target. Snapshots live in ~/.semanticus/restore and hold the target's full model METADATA (measures, M queries, role filters, connection strings – never row data) in clear text; purge_restore_points removes them. An integrityError means rollback is refused, while purge remains available through its validated storage path. Read-only and free. Next: rollback_push(id) to preview a restore.
rollback_push
Undo a push to a PUBLISHED model by restoring it to a pre-push snapshot (see list_restore_points).
more
DRY RUN by default: commit=false reports exactly what would be restored and – critically – what would be REMOVED, i.e. every object that exists on the target now but not in the snapshot. That includes anything the push added AND anything anyone else added since, so READ RemovedRefs before committing. Pass commit=true to write. Restores the object kinds a redeploy cannot: relationships, roles (RLS), perspectives, hierarchies, partitions, cultures, datasources and data tables. Resolution is by lineage identity, so an object republished under you is refused rather than overwritten. Recorded in the audit trail. FREE at both tiers – the undo for an irreversible write is never gated. Next: run list_restore_points to find the id; run rollback_push(id) to preview; then rollback_push(id, commit=true).
purge_restore_points
Permanently delete pre-push snapshots from ~/.semanticus/restore using a review-then-confirm flow.
more
Choose exactly one selector: id removes one restore point, or olderThanDays selects every snapshot older than that non-negative age. DRY RUN by default: confirm=false returns the exact candidates and a token without deleting. After reviewing them, pass confirm=true with that exact confirmToken; a stale or changed candidate set is refused. Reports partial file-delete failures honestly. Use this to clear model metadata from disk only when you accept that the guarded live push can no longer be undone.
get_agent_policy
Read the agent-permissions policy – what YOU (the agent) are allowed to do to a live target, by environment.
more
Returns the global on/off switch, the active preset, and the capability×label matrix. Labels are local | dev | uat | prod; an UNLABELLED target is treated as prod (the strictest). Actions are allow | ask | deny: 'ask' means a human must approve the specific action in the UI before you can do it (see list_pending_approvals – you request approval simply by attempting the action). Reading, and running a calculation, are never gated. Use this to know BEFORE you try: if pushing to a target is 'deny' or 'ask', tell the user rather than failing repeatedly. Only a human can change this policy or the labels it reads. Read-only and free.
list_pending_approvals
The 'waiting for you' queue – actions you attempted that the policy said need a human's approval (an 'ask').
more
Each entry is bound to the EXACT action (capability + target + intent); the human approves it in the UI, then you retry the SAME action and it proceeds once (a grant is one-shot and expires). Use this to see what you're waiting on. You cannot approve your own actions – that asymmetry is the point. Read-only and free.
#Git (model source control) 12
Source control for the model’s files: clone, status, diff, log, branch, checkout, pull, commit and push. Outward writes are dry-run or confirm-gated.
git_clone
Clone a git repository and locate the semantic model inside it.
more
A relative target stays inside the current workspace, and the target must not already exist. Returns the model path to open with open_model. Uses the user's git credential helper.
git_status
Source control status of the OPEN model's git repository: current branch, ahead/behind, and the changed TMDL files (staged/worktree).
more
Also flags whether the open model has unsaved in-memory edits (git_commit saves them to disk first). Read-only.
git_diff
The unified text diff of the open model's git working tree (the on-disk TMDL diff).
more
Pass a file path to scope it; staged=true for the staged diff. Read-only.
git_log
Recent commits on the open model's repository (hash, author, date, subject).
more
Read-only.
git_branch
List branches with no name or flags.
more
To change state, pass a branch name and set create=true, checkout=true, or both. If switching changes the on-disk model, the result names the model path to reopen and flags modelReloadNeeded.
git_checkout
Switch to a git ref (branch, tag, or commit).
more
Refuses while the open model has unsaved edits. If the on-disk model changes, the result names the model path to reopen and flags modelReloadNeeded.
git_pull
Fast-forward pull the current branch from its upstream.
more
Refuses while the open model has unsaved edits. If the on-disk model changes, the result names the model path to reopen and flags modelReloadNeeded.
git_commit
Commit the open model to git.
more
DRY RUN by default (commit=false returns the file set that WOULD be committed and whether the model needs saving first; nothing changes). Pass commit=true to actually commit – it SAVES the open model's unsaved edits to disk first, stages the model folder, then commits. Returns the commit hash + files.
git_push
Push commits to the remote.
more
DRY RUN by default (confirm=false reports what would push). Pass confirm=true to push. Uses the user's git credential helper – the engine never handles git credentials.
create_history_checkpoint
EDIT HISTORY (Free): create a durable, model-scoped git checkpoint without committing unrelated repository files.
more
DRY RUN by default: commit=false reports the owned paths, changed files and whether the model will be saved. Pass commit=true after review. Refuses a detached branch, conflicts, or unrelated staged files instead of sweeping them into the commit. The result names the exact checkpoint hash; use restore_history_checkpoint to preview a restore.
list_history_checkpoints
EDIT HISTORY (Free): list durable checkpoints for the open model on the current git branch.
more
Checkpoints are ordinary model-scoped commits, so they survive closing the session and cloning the repository. Returns supported=false for a model outside git; session undo remains the short-term alternative. Read-only.
restore_history_checkpoint
EDIT HISTORY (Free): restore the open FILE model to one of its durable checkpoints without resetting the branch or unrelated files.
more
DRY RUN by default: restore=false names the model paths and safety sequence. Pass restore=true only after review. The engine first commits the current model as a rescue checkpoint, restores the selected model paths, reopens the model, and commits the restored state. Returns all three hashes so the action stays reversible. Live published models use rollback_push and its restore points instead.
#Utilities 4
The odds and ends: the current entitlement tier, saved diagram positions, and the one-way compatibility-level upgrade.
get_entitlement
Get the current Semanticus tier (free | pro).
more
The free tier is fully usable one edit at a time; Pro unlocks the one-click BULK apply (apply_plan with >1 item, bpa_fix_all, apply_safe_fixes). Check this before attempting a bulk apply so you can fall back to applying items individually on free.
get_layout
Get the saved diagram positions for the model's tables (x/y, and width/height when set).
more
Returns only tables that HAVE a stored position – tables not listed are unplaced (auto-laid-out by the UI). Positions are engine-owned (a .semanticus/layout.json sidecar beside the model), keyed by a stable LineageTag so a position survives a table RENAME, and excluded from the model diff. Read it to render or reason about the table layout the human sees.
save_layout
Persist diagram positions for tables (x/y, optional width/height).
more
Identify each table by its `ref` (preferred) or `name`. MERGES with existing positions (tables you omit keep theirs; deleted tables are pruned) and the engine re-keys each by its stable LineageTag, so the layout survives renames. Writes the .semanticus/layout.json sidecar beside the model – this is NOT a model edit (it does not touch the model definition or its diff). The model must be saved on disk first; otherwise returns an Error.
set_compatibility_level
Raise the model's compatibility level (a ONE-WAY upgrade).
more
Needed for newer features – DAX user-defined functions require 1702+. Refuses to lower it. Undoable within the session, but re-deploying an upgraded model to an older runtime may fail.
Semanticus