What an artifact stores
Queries and presentation. Never rows. That one decision produces everything else worth knowing:- The dashboard is current every time it opens, because the queries run then.
- It runs them as the person opening it, so each viewer sees only what they’re allowed to see.
- Withdraw an exposure rule and the column stops appearing — immediately, with no rebuild.
- Deleting an artifact touches no data, because there was never any data in it.
Publishing one
Ask an agent to build a dashboard. It callsget_artifact_template for a scaffold, writes
the HTML, and calls publish_artifact with a manifest:
window.SAMPLE_DATA — mrr_by_month is read as
SAMPLE_DATA.mrr_by_month. The HTML declares a small sample with
window.SAMPLE_DATA ||= {...} so it renders while being built; TeamDuo assigns the real
rows before the page’s own code runs.
Every query in a manifest is checked against your exposure rules before anything is
stored. If one is refused, the agent is told which and why.
MongoDB queries use collection with filter or pipeline in place of sql.
Drafts and visibility
Two independent fields, because collapsing them into one would mean you couldn’t keep a finished dashboard to yourself, or widen who sees one without also declaring it done.
Artifacts open at
https://app.teamduo.ai/a/<teamId>/<artifactId>.
How it renders
Artifact HTML is written by a model, so it runs in an<iframe sandbox="allow-scripts">
with no allow-same-origin. The framed document gets an opaque origin: no cookies, no
access to the parent page, no storage. The injected CSP sets connect-src 'none', so a
dashboard cannot send your rows anywhere — the rows arrive inlined and it has no
legitimate reason to open a socket.
Scripts are limited to an allowlist of CDN hosts rather than of libraries, so an agent can
pick whichever charting library suits the dashboard.