> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thinkplatform.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Choose User guide for browser tasks, Developers for CLI, SDK and external agents, and Administration for organization management.
> Confirm identity and organization/project context before operations. Documentation access does not grant ThinkPlatform permissions.
> Review side effects, verify changes with a read, and do not blindly retry an operation with an uncertain outcome.
> Use documented UI steps for the web app and documented public CLI or SDK interfaces for automation. Follow each page’s prerequisites and authentication requirements.

# Canvas commands

> Create and update pages, build dashboards, and embed interactive interfaces.

These examples assume an authenticated active saved profile with the intended organization and project. Confirm it with `tp context show` before running commands. Add root `--json` before the command when machine parsing needs JSON output; use root `--profile <name>` only to override the active profile.

## Check context and available resources

```bash theme={"system"}
tp auth whoami
tp context show
tp home pages list
tp canvas pages list
tp dynamic-ui list
tp db tables list
tp flows list
```

## Home and Canvas pages

Prefer idempotent apply by title for repeatable page creation:

```bash theme={"system"}
tp home pages apply --spec @page.json --create-if-missing --dry-run
tp home pages apply --spec @page.json --create-if-missing
tp home pages get <page_id>
tp home pages get <page_id> --markdown
```

Use this path for recurring agent-created reports so reruns update the same titled page instead of creating duplicate pages. Use direct `canvas pages create` only for one-off pages, experiments, or exact REST payload checks.

Canvas renders the page `title` as the visible page heading. Do not duplicate that title as the first body H1. For document pages, begin body content with an introductory paragraph or a second-level section heading. For example, use:

```json theme={"system"}
{
  "title": "Operations Review",
  "surface": "document",
  "contentWidth": "default",
  "blocks": [
    {
      "type": "markdown",
      "content": "This page summarizes the latest run.\n\n## Current status\n\n- Waiting for first run."
    }
  ]
}
```

Do not use:

```json theme={"system"}
{
  "title": "Operations Review",
  "surface": "document",
  "blocks": [
    {
      "type": "markdown",
      "content": "# Operations Review\n\nThis page summarizes the latest run."
    }
  ]
}
```

Use direct Canvas create/update when exact REST behavior is needed:

```bash theme={"system"}
tp canvas pages create --body @page.json --dry-run
tp canvas pages create --body @page.json
tp canvas pages update <page_id> --body @page.json --dry-run
tp canvas pages update <page_id> --body @page.json
tp canvas pages reorder --page-id <new_page_id> --page-id <existing_page_id>
```

## Minimal page specification

```json theme={"system"}
{
  "title": "Operations Review",
  "surface": "document",
  "contentWidth": "default",
  "blocks": [
    {
      "id": "summary",
      "type": "markdown",
      "content": "This page summarizes the latest run.\n\n## Current status\n\n- Waiting for first run."
    }
  ]
}
```

Use `contentWidth: "wide"` or `"full"` only when the user asks for it or the page needs more horizontal room, such as dense dashboards, large tables, or embedded apps. Dashboard pages commonly use `"full"`:

```json theme={"system"}
{
  "title": "Operations Dashboard",
  "surface": "dashboard",
  "contentWidth": "full",
  "dashboardSettings": { "showOnDashboard": true, "tabLabel": "Ops" },
  "blocks": [
    {
      "type": "raw",
      "block": {
        "id": "ops-summary",
        "type": "widget",
        "widgetKind": "markdown",
        "title": "Summary",
        "frame": { "x": 0, "y": 0, "w": 6, "h": 4, "minW": 4, "minH": 3 },
        "config": { "markdown": "## Current status\n\n- Waiting for first run." }
      }
    }
  ]
}
```

## Dashboard widgets

```json theme={"system"}
{ "widgetKind": "system-summary", "config": { "preset": "overview" } }
{ "widgetKind": "resource-list", "config": { "source": "agents", "limit": 6 } }
{ "widgetKind": "notification-list", "config": { "mode": "active", "limit": 8 } }
{ "widgetKind": "quick-actions", "config": { "actions": ["create-agent", "new-job", "open-data-lake"] } }
{ "widgetKind": "lakehouse-query", "config": { "query": "SELECT ...", "visualization": "table", "limit": 100, "refreshSeconds": 0 } }
```

Lakehouse-backed analysis dashboards should keep visualizations live with `lakehouse-query` widgets. Common configs:

Discover the backend-supported visualization catalog before choosing a config:

```bash theme={"system"}
tp canvas visualizations list
tp canvas visualizations describe bubble
```

Use the explicit field roles below. The backend retains legacy column-order and
`yFields` fallbacks for compatibility, but newly generated dashboards should not
depend on them.

| Visualization | Use | Required roles | Main optional roles/options |
| - | - | - | - |
| `table` | Detailed records | none | `tooltipFields` |
| `stat` | Single current value | `valueField` | `yFields` |
| `kpi` | Value versus comparison/target | `valueField` | `comparisonField`, `targetField` |
| `line` | Trend over an ordered axis | `xField`, `yFields` | `seriesField` |
| `bar` | Category comparison | `xField`, `yFields` | `seriesField` |
| `area` | Trend and magnitude | `xField`, `yFields` | `seriesField` |
| `pie` | Part-to-whole composition | `xField`, `yFields` | `seriesField` |
| `combo` | Measures with separate scales | `xField`, `yFields`, `secondaryYFields` | `seriesField` |
| `scatter` | Relationship between two measures | `xField`, `valueField` | `seriesField` |
| `bubble` | Relationship plus a third magnitude | `xField`, `valueField`, `sizeField` | `seriesField` |
| `histogram` | Numeric distribution | `valueField` | `histogramBins` |
| `heatmap` | Intensity across two dimensions | `xField`, `seriesField`, `valueField` | `aggregation` |
| `pivot` | Cross-tab aggregation | `rowFields`, `columnField`, `valueField` | `aggregation` |
| `box` | Distribution and outliers by group | `xField`, `valueField` | none |
| `gantt` | Activities across time | `xField`, `startField`, `endField` | `seriesField` |

Standard agent procedure:

1. Run `tp canvas visualizations list`.
2. Run `tp canvas visualizations describe <id>` when details are needed.
3. Inspect the Lakehouse schema and preview the SQL.
4. Create or apply the dashboard JSON using the documented camelCase roles.
5. Run `tp canvas dashboard lint`, `schema`, `query`, and `validate-page`.

```json theme={"system"}
{
  "widgetKind": "lakehouse-query",
  "title": "Total trips",
  "config": {
    "query": "SELECT SUM(trip_count) AS trips FROM <project_catalog>.gold.daily_trip_metrics",
    "visualization": "stat",
    "yFields": ["trips"],
    "limit": 1,
    "refreshSeconds": 0
  }
}
```

```json theme={"system"}
{
  "widgetKind": "lakehouse-query",
  "title": "Daily trend",
  "config": {
    "query": "SELECT pickup_date, trip_count, gross_revenue FROM <project_catalog>.gold.daily_trip_metrics ORDER BY pickup_date",
    "visualization": "line",
    "xField": "pickup_date",
    "yFields": ["trip_count", "gross_revenue"],
    "limit": 100,
    "refreshSeconds": 0
  }
}
```

```json theme={"system"}
{
  "widgetKind": "lakehouse-query",
  "title": "Revenue by segment",
  "config": {
    "query": "SELECT segment, gross_revenue FROM <project_catalog>.gold.segment_metrics ORDER BY gross_revenue DESC",
    "visualization": "bar",
    "xField": "segment",
    "yFields": ["gross_revenue"],
    "limit": 20,
    "refreshSeconds": 0
  }
}
```

```json theme={"system"}
{
  "widgetKind": "lakehouse-query",
  "title": "Top records",
  "config": {
    "query": "SELECT * FROM <project_catalog>.gold.top_records ORDER BY score DESC LIMIT 20",
    "visualization": "table",
    "limit": 20,
    "refreshSeconds": 0
  }
}
```

Validate Lakehouse SQL before creating a widget:

```bash theme={"system"}
tp lakehouse catalog show
tp lakehouse tables list --schema gold
tp lakehouse sql preview --query "SELECT * FROM ${TP_DATABRICKS_CATALOG}.gold.metrics LIMIT 100"
```

Preview is cached by default. Use `--fresh` only to verify a newly written Gold table. During layout changes, reuse the schema and preview result rather than reissuing SQL.

For dashboards with global filters, prefer `dashboardDefinition` datasets and bindings. Generate or validate the spec before creating the page:

```bash theme={"system"}
tp canvas dashboard scaffold \
  --title "Operations Metrics" \
  --dataset-id daily_metrics \
  --query @daily_metrics.sql \
  --filter dateRange:period:event_date \
  --dry-run
tp canvas dashboard lint --definition @page.json
tp canvas dashboard schema daily_metrics --definition @page.json
tp canvas dashboard query daily_metrics --definition @page.json --filters @filters.json --limit 100
tp canvas pages create --body @page.json --dry-run
tp canvas pages create --body @page.json
tp canvas dashboard validate-page <page_id>
```

Minimal filtered Lakehouse dashboard pattern:

```json theme={"system"}
{
  "title": "Operations Metrics",
  "surface": "dashboard",
  "contentWidth": "full",
  "dashboardDefinition": {
    "version": 1,
    "datasets": [
      {
        "id": "daily_metrics",
        "name": "Daily metrics",
        "source": "lakehouse",
        "query": "SELECT event_date, SUM(value) AS value FROM <project_catalog>.gold.metrics WHERE event_date >= :event_date_start AND event_date <= :event_date_end GROUP BY event_date ORDER BY event_date",
        "limit": 100,
        "parameters": [],
        "columns": []
      }
    ],
    "filters": [
      {
        "id": "period",
        "label": "Period",
        "type": "dateRange",
        "defaultValue": { "start": "2026-01-01", "end": "2026-01-31" },
        "options": []
      }
    ],
    "bindings": [
      { "datasetId": "daily_metrics", "filterId": "period", "mode": "parameter", "target": "event_date", "operator": "between" }
    ]
  },
  "blocks": [
    {
      "id": "daily-line",
      "type": "widget",
      "widgetKind": "lakehouse-query",
      "title": "Daily metrics",
      "frame": { "x": 0, "y": 0, "w": 12, "h": 6, "minW": 6, "minH": 4 },
      "config": {
        "datasetId": "daily_metrics",
        "visualization": "line",
        "xField": "event_date",
        "yFields": ["value"],
        "limit": 100,
        "refreshSeconds": 0
      }
    }
  ]
}
```

For project-scope validation, fully qualify tables with the project catalog. This also applies to metadata queries such as `${TP_DATABRICKS_CATALOG}.information_schema.tables`; unqualified `information_schema.tables` can be rejected by the project catalog guard.

If the current local agent environment has working Databricks CLI auth, direct Databricks commands are acceptable for inspection or troubleshooting, but keep Canvas widget validation anchored to `tp lakehouse` so the query is checked through ThinkPlatform's project-scoped API:

```bash theme={"system"}
databricks current-user me
databricks tables list "$TP_DATABRICKS_CATALOG" gold
```

## Cost-aware execution routes

* Local Agent/Codex: use `tp canvas ...` and `tp lakehouse ...`; keep preview cached.
* ThinkPlatform Agent: use Canvas MCP tools and the Databricks SQL preview system tool with `fresh=false`.
* Set `refreshSeconds: 0`. Use 900 seconds or longer only when the user explicitly requires automatic refresh.
* Prefer one dashboard dataset for widgets sharing source SQL or filters. Use a precomputed Gold table when the same expensive aggregation is viewed frequently.
* Run `lint`, `schema`, and a bounded query while authoring; run `validate-page` once after the full page is ready.

## Dynamic UI

```bash theme={"system"}
tp dynamic-ui create --body @ui.json --dry-run
tp dynamic-ui create --body @ui.json
tp dynamic-ui create-html --html-file ./app.html --title "Operator Panel" --dry-run
tp dynamic-ui get <ui_id>
tp dynamic-ui update <ui_id> --body @patch.json --dry-run
tp dynamic-ui delete <ui_id> --dry-run
```

Embed a persisted Dynamic UI in Canvas with a `dynamic-ui` widget and the created `uiId`.

## Verification checklist

* Read back the page/app by ID.
* Confirm `layout.surface`, block count, widget kinds, and resource references.
* For Mermaid or Dynamic UI, browser-check rendering when available.
* For action surfaces, verify the action target exists and is discoverable.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.