Wato Docs
Artifacts & Dashboards

Live Dashboards

Build HTML artifacts that load fresh data at runtime through Wato-approved connectors, with credentials kept server-side.

A live dashboard is a hosted HTML artifact that loads fresh data at runtime through Wato. The page stays a normal web page; Wato handles authentication, connector access, team policy, and traceability server-side. The browser never sees connector secrets, OAuth tokens, or MCP credentials.

Use a live dashboard when you want a report or operational view that refreshes from approved systems (Linear, Notion, your CRM, …) instead of showing static exported data.

How it works

The model has three parts:

  1. You declare the connector calls a page wants, as static attributes in the HTML (data-wato-call, data-wato-id).
  2. Wato classifies and approves those calls against your team's server-side connector/tool registry and stores an approved view policy. Read calls are approved automatically; write or destructive calls become actions that need review.
  3. At runtime, the browser SDK exchanges a short-lived session token and may call only the tools in the stored policy. Wato runs the actual connector call server-side and returns the result.

The agent never labels calls

You declare what the page wants to call. Wato decides whether each call is a read or an action using its own tool registry — not labels in your HTML.

Authoring workflow

  1. Call wato_get_usage_guide, then wato_get_live_artifact_primitives for the current contract.
  2. Find exact connector and tool names with mesh_search_tools (includeSchema: true).
  3. Declare each call in HTML with data-wato-id and data-wato-call (plus data-wato-defaults / form fields for inputs).
  4. Add the config block and the SDK script.
  5. Bind the page with wato_bind_dashboard_view, passing the final HTML, a stable viewSlug, a title, and every non-hosted origin the page will run on.
  6. Test the unauthenticated, sign-in callback, authenticated, and partial-failure states.

Declaring calls

Mark each section that needs data with a stable data-wato-id and the connector.tool to call. Use form fields for values the viewer can change, and data-wato-defaults only for safe, fixed defaults.

<form data-wato-form="recentDocs">
  <input name="query" value="project updates" />
</form>

<section
  data-wato-id="recentDocs"
  data-wato-call="notion.notion-search"
  data-wato-defaults='{"page_size": 10}'
></section>
AttributeRequiredPurpose
data-wato-callYesThe connector.tool to call, e.g. notion.notion-search. Must be statically written in the HTML.
data-wato-idRecommendedStable id for this call, referenced by the SDK and in results.
data-wato-defaultsNoJSON object of safe fixed defaults. Wato still validates keys and bounds server-side.

Rules:

  • Connector and tool names must be statically visible in data-wato-call. Dynamically constructed calls require an explicit reviewed binding.
  • Do not hardcode org or team in portable HTML — Wato binds those from the hosted URL, share link, localhost bootstrap, or launch params.
  • Do not embed connector secrets, OAuth tokens, dashboard tokens, or API keys in the HTML.
  • Use form fields for viewer-provided input; use data-wato-defaults only for fixed defaults.

Adding the SDK

Include a static config block and load the Wato dashboard SDK:

<script id="wato-dashboard-config" type="application/json">
  { "apiBaseUrl": "https://mesh.watolabs.com", "viewId": "default" }
</script>
<script src="https://mesh.watolabs.com/api/dashboard/sdk.js"></script>

Then initialize the SDK and make calls:

const wato = await window.WatoDashboard.init();

// Preferred: call by the data-wato-id you declared
const docs = await wato.call("recentDocs", { query });

// Or call a connector tool directly
await wato.callTool("notion", "notion-search", { query });

// Run an approved action (write/destructive calls)
await wato.callAction("archive-issue", { issueId });

init() returns the resolved config, plus call, callTool, callAction, and refreshSession. For hosted Wato artifacts, keep viewId: "default" and omit org/team; Wato derives them from the URL.

Live dashboards never run from file://

A live dashboard must run from an allowed http(s) origin. On localhost it must resolve an explicit org, team, and view slug; file:// is never valid.

Binding the view

After the HTML is final, bind it so Wato can build the server-side policy before runtime auth works:

wato_bind_dashboard_view({
  "viewSlug": "brightcart-renewal-risk",
  "title": "BrightCart Renewal Risk",
  "html": "<!doctype html>...",
  "allowedOrigins": ["http://localhost:5173"]
})
ParameterPurpose
viewSlugStable, URL-safe id for the view, e.g. brightcart-renewal-risk.
titleHuman-readable dashboard title.
htmlThe full HTML containing the static data-wato-call declarations.
allowedOriginsBrowser origins allowed to bootstrap the view, e.g. http://localhost:5173. Hosted artifacts are handled automatically.

Wato scans the data-wato-call declarations, verifies them against the team's approved tool catalog, activates read-only safe calls, and returns review_required for write, destructive, or unknown calls.

The result tells you what happened:

ResultMeaning
status: "active"The view is bound and read calls are approved.
status: "review_required"The binding includes actions or unknown/blocked calls that need approval.
allowedCallsThe calls that were approved into the policy.
blockedCallsCalls that were not allowed (unknown tools, not in the catalog).

Permission required

Creating or updating a durable binding requires team admin, org admin, teams:manage, or tools:manage access.

Reads vs. actions

Wato classifies each declared call using its tool registry:

  • Reads (search/list/get/fetch…) are approved automatically and stored as the view's reads.
  • Writes and destructive calls (create/update/send/delete…) become actions that require confirmation and review before they can run. Until then the binding is review_required.

Origins and context

  • Hosted Wato artifacts: Wato derives org, team, and the view from the hosted URL. Keep viewId: "default".
  • Share links: Wato maps a share id to org, team, and view server-side.
  • Localhost / custom hosts: include the exact origins in allowedOrigins, and resolve an explicit org, team, and view slug (via config or query params).

Note that bootstrap origins (where the page is allowed to load — allowedOrigins) are not the same as the dashboard view itself.

Runtime states to handle

A live dashboard should treat these as normal UI states, not crashes:

StateWhat to do
login_requiredShow a real sign-in button that redirects the viewer to Wato auth.
connector_auth_requiredPrompt the viewer to authenticate the connector in Wato.
token_expiredRefresh the dashboard session and retry once.
origin_not_allowedOpen from an allowed origin, or update the view's allowedOrigins.
tool_not_allowedOnly call tools approved into the server-side policy.
connector_call_failedShow a fallback for that section; keep the rest of the page live.

Rendering rules:

  • Load each data-wato-id independently — one failed call must not blank the page.
  • Show partial live data when some calls succeed, with a fallback only for the sections whose source failed.
  • Surface failed data-wato-id names, not raw stack traces.

Reading results

Connector results may be wrapped. Normalize before rendering:

  • Prefer structuredContent when present.
  • Otherwise, if result.content contains a text block with JSON, parse content[0].text, then read keys such as issues, projects, or teams.

Done check

Before declaring a live dashboard finished:

  • wato_bind_dashboard_view returned status: "active".
  • allowedCalls are exactly what you expect; blockedCalls is empty (or explained).
  • Hosted resolves viewId: "default"; localhost resolves explicit org/team/view slug.
  • The page is not opened from file://.
  • The unauthenticated state shows a working sign-in button.
  • The sign-in callback exchanges the code, removes it from the URL, and caches the session.
  • Partial failures keep the working sections visible.

Reference

The MCP tools used here are documented in the Reference: wato_get_live_artifact_primitives, mesh_search_tools, and wato_bind_dashboard_view.

On this page