Assets¶
The Assets page displays interactive dashboards, reports, and visualizations generated by AI agents during sessions. Assets are saved via the save_asset tool and support multiple content types. A file you wrote yourself and want the agent to use as-is is a resource, not an asset; the empty state says so.


Features:
- Search — Full-text search by name or description
- Filters — Content type dropdown (HTML, JSX, SVG, Markdown, CSV) and tag filter
- Sort — Column dropdown (updated, created, name, size) and a direction toggle. The list opens on most recently updated, so an asset revised today sits above one created yesterday and never touched since; the date shown on each card and row is the one the list is ordered by, so the visible dates always run in the order the rows do. Sorting is server-side over the whole library, not just the page already loaded. The date moves when someone changes the asset — new content, a rename, a description or tag edit. A thumbnail capture is not a change to the asset, so a pass that refreshes a library's previews leaves the order and the dates where they were. A relevance search is ranked rather than sorted, and the control reads as inert while one is running.
- View toggle — Switch between grid (card thumbnails) and table view; preference persisted to localStorage
- Grid cards — 4:3 thumbnail previews with content type icon, tags, collection badges, file size, and sharing indicators
- Theme-aware thumbnails — Markdown, CSV, JSON and NDJSON previews are captured in both light and dark variants, and the grid shows the one matching your active theme. The same preview follows the asset everywhere you meet it while signed in: the collection viewer, an administrator's view of a collection someone else owns, and the picker you add assets from. Self-themed content (HTML, JSX, SVG) carries its own colors, so a single preview is used in both modes. Public shares always use the light variant.
- When a preview is captured — A preview is produced in your browser, by rendering the asset off-screen and rasterizing it. That is a long piece of work on the same thread the page runs on, so it waits: it starts only once the browser has gone idle with the tab in front, runs one asset at a time, stops after eight assets per batch, and skips any asset over 1 MB, which keeps its placeholder icon. The work is not tied to this page — any portal tab you have open asks the server which of your assets need a preview and captures them, so an asset a managed script rewrites on a schedule gets a current one without you opening anything.
- A preview after the asset changes — Rewriting an asset does not take its preview away. The card keeps showing the last one captured, which is an image of an earlier version of the document, until a capture catches up; the asset records which version its preview came from, and that is what puts it on the queue above. An asset that has never been captured shows the placeholder icon for its content type.
- A preview of an artifact that references a file — An asset whose content names a managed resource or another asset is captured with those references resolved, exactly as it renders in the viewer, so the tile shows the artifact rather than the branch it draws when a file is missing. A capture in which a referenced file did not load is discarded rather than stored, and the asset stays on the queue for another try.
- Asking for a preview again — The Thumbnail panel in an asset's metadata sidebar shows the stored image and offers Recapture, which discards it and puts the asset back on the queue. It is the owner's action, and an administrator has it on every asset. Use it when a tile shows something the asset no longer looks like without the asset itself having changed.
![]()
![]()
- Table rows — Columns for name, type, tags, collections, size, sharing, and the ordering date. Name, size, and the date header sort the list; clicking the active column reverses it.
Asset Viewer¶
Click any asset to open the full-screen viewer. The viewer renders content natively based on type: HTML and JSX as interactive components, SVG as vector graphics, Markdown with full formatting, CSV and TSV as sortable tables, JSON as a searchable collapsible tree, images with zoom and pan, audio and video with working seek, and PDFs in an embedded viewer. Anything with no viewer shows a metadata card and a download action rather than raw bytes. See Content Types and Viewers for the full family list and for how a mislabeled content type is detected and corrected at write time.


The viewer provides:
- Preview / Source toggle — Switch between rendered output and raw source code
- Actions — Delete, Download, and Share buttons
- Owner display — Shows the asset owner's email address
- Metadata sidebar — Type, size, created and updated timestamps, tags, version history, and the calls this asset was built from
The Provenance panel groups those calls by capture — one per time the asset was written, so a revised asset shows what fed each of its versions. Each call names its kind (a SQL statement, an API request, or another data call), the connection it ran against, the purpose the agent stated for it, how long it took, and whether it failed; a failed call is shown, not hidden, because it is part of how the answer was reached. Opening a call shows the full statement or request with a copy action and the mcp:call: reference that names it in the audit log. A capture marked Cited is one where the agent named its sources itself rather than the platform taking the session's recent calls. See Provenance.
The newest capture is shown expanded and every earlier one sits behind a disclosure naming how many there are, each opening on its own. An asset a scheduled script refreshes accumulates a capture per run, and the panel leads with the write that produced what is on screen rather than making you scroll past a year of them. The call count in the panel header still covers every capture.


References¶
An asset's content can name a managed resource by its mcp:// URI rather than carrying the file's bytes — a logo, a photograph, a design element — or another asset by its mcp:asset:<id> reference, which resolves to that asset's current content every time the page is read. The References panel in the metadata sidebar lists what this asset depends on: each one's name and type, a scope for a file and an owner for an asset, a thumbnail where it is an image, a link to it where you can open it on your own, and the reference with a copy control.


The owner, an editor on a shared asset, and an administrator can add a reference through a picker with a tab for each kind — the resources they can read, and the assets they can open — and remove one. A reference carries the asset's audience — anyone who can open the asset can load the target through it, including anyone holding a public link — so the picker names what this asset is currently shared with before anything is added.


The Assets tab is what makes a refreshing dashboard possible: reference the data asset a scheduled job rewrites, write the reference into your markup where the data belongs, and the report reads the current numbers on every open without being saved again.


Used by below it answers the reverse question about this asset: which reports read its content. An asset carrying a public link is flagged, because that is the reference that widens this asset's audience furthest, and referencing assets you cannot open are counted rather than named. Deleting an asset something references leaves those reports rendering without it.


Adding a reference does not change the asset's content. The markup has to name the URI for the picture to render, which is why every row carries it with a copy control; the panel also reports which lines of the stored content already write each URI, and removing a reference the content still names warns with those lines first.
Reading an older version¶
The version picker beside the Preview / Source toggle lists every version the asset keeps, each with the time it was written. A number alone does not identify a version of an asset written on a schedule, where two entries can be an hour apart. Selecting an older version shows its content read-only and offers a revert to it.


Version retention¶
Every write to an asset records a version, and until a cap applies that history grows without end. A dashboard a scheduled script refreshes hourly writes twenty-four versions a day, each with its own stored content, for as long as the schedule runs.
An asset keeps its most recent 100 versions by default. The deployment sets that default with portal.max_versions, and the asset's owner (or an administrator) can override it from the metadata sidebar's edit mode, under Version history:
- Deployment default — the asset has no opinion and follows whatever the deployment is set to. This is where every asset starts.
- Keep the newest N — the asset keeps N versions, however many the deployment keeps.
- Keep every version — nothing is ever pruned from this asset.


A version pushed past the cap is deleted along with its stored content and its thumbnails, so the cap bounds storage and not only the list. The version the asset currently points at is never pruned, whatever the cap, so the content stays readable and the newest entry stays revertible-to.
Retention applies when a version is written, not on a schedule. An asset that already carries more history than the cap is left alone until it is next written, and is trimmed to the cap then. Changing the setting never deletes anything by itself.


The Version history control is the one field on this form an editor share does not carry; here it is left where every asset starts.
Retention is the owner's to set. An editor share carries every other field on that form — name, description, tags, the content itself — but not this one: lowering the cap deletes the owner's history and its stored content at the next write, and nothing brings it back. The control is not shown to an editor, and the API refuses the field from one.
Agents set the same thing through manage_asset action update with max_versions (owner or administrator, as with every other update through that tool), and administrators through the admin asset route; all three write the same value.
The sidebar's Session row and the Open session action beneath the captured calls both open the session that made this asset: the panel shows only the calls captured at the moment the asset was saved, while the session holds every call that session made, before and after. Both appear only on your own assets — a session opens for the person who ran it, so on an asset shared with you there is nothing to link to. Administrators get the same walk on the admin asset viewer, into the admin sessions surface.
The Share action opens a dialog to mint a link or a user-scoped share, with a copy-once token and a per-link access count. A public link takes an expiration, and must have one; every other share is now minted without one and grants access until the owner revokes it. Shares created before that rule keep the expiry they were given, whatever their mode, so an older link may still show a countdown. Every share carries an access mode that decides who the link opens for:
| Mode | Who can open the link |
|---|---|
restricted |
Only the named recipient (and the person who created the share) |
authenticated |
Any signed-in platform user |
public |
Anyone with the link, without signing in |
Sharing with a person makes the share restricted: the link resolves only for that recipient, signed in, so forwarding the email or the URL grants nothing. The Share by Link section mints a link for any signed-in user by default, with no lifetime control, because such a link resolves against who the viewer is and ends on revocation. Choosing Anyone with the link makes it public, shows a warning that the link opens without sign-in, and reveals the lifetime control: possession of a public URL is the whole of its access check, so it expires on a clock as well. A signed-in user who is not the recipient of a restricted share sees a branded page naming the account they are signed in as, with a sign-out-and-switch action, rather than a generic not-found.


The same dialog with the link switched to Anyone with the link:


Naming a recipient reveals two more controls. Notify by email is checked by default and can be cleared to share quietly — the share is created either way, only the email is suppressed. With notification on, an optional Message box attaches a short plain-text note to that email, quoted and attributed to the sharer; it travels only in the notification and is stored nowhere. The note takes text, not markup or links: a link inside a trusted platform email is a phishing vector, so one is refused rather than delivered. Addresses pasted in the Example User <[email protected]> form mail clients copy are reduced to the bare address as the field loses focus, so what is stored and mailed is what the sharer sees. See Email Notifications for what the recipient receives and how they control it.


A signed-in platform user who opens a share link lands on the item in their own portal rather than on the page built for people who have no account. That is where the version history, the feedback threads, the collections the asset belongs to, and editing where the share permits it all are, and the item is in their asset list from then on. The Shared page action in the viewer's toolbar opens the shared page as its recipient sees it, which is what someone who sent a link needs in order to check what arrived. An anonymous visitor, and a guest holding a one-time link, get the shared page unchanged.
A recipient who opens a non-public share while signed out lands on a branded page with a Sign in action that returns them to the shared item after authenticating. When the share names an email address, the same page also offers Email me a one-time view link for recipients who have no platform account: a single-use link is emailed to the address the share names (never to an address the visitor types), expires in 15 minutes, and opens a view-only guest session scoped to that one share for the current browsing visit. Guests see the shared item (and, for collection shares, its items) with a "Viewing as guest" indicator; they can download but not edit, even when the share grants Editor, and they never gain portal access. A forwarded or replayed link is dead after its first use, and revoking the share cuts off existing guest sessions immediately. The recipient can request a fresh link for each viewing session, which keeps an email share strictly safer than a public URL. When the address the share names has opted out of notification emails, the same landing page shows a notice with a Resume notification emails action, so an opted-out recipient has a way back in without asking the sharer; opting back in takes one deliberate click and restores immediate delivery.
All content types are rendered inline:
Interactive dashboards with KPI cards, charts, and tables rendered as live HTML.


React components rendered with live state and interactivity (tabbed views, filters).


Vector graphics — charts, diagrams, and data visualizations rendered at full resolution.


Formatted text with headings, tables, lists, code blocks, and mermaid diagrams.


Tabular data rendered as a sortable, searchable table.


Querying a CSV asset as a table¶
A CSV asset can be registered as a table and joined to warehouse tables from then on. The viewer's Query as a table panel offers the connections you can register onto, and lists what is already registered with the columns each table has.


Nothing is copied. The table reads the file where it already sits, so re-running the export that produced the asset changes what the table returns. Every column comes back as text, so a join to a typed warehouse column needs a CAST — the panel shows the table's name to copy into a query, and the platform's search results carry a sample statement.
The Register control stays available after the first registration, because one file is not limited to one table. Registering under a different name, or onto a different connection, adds a second table over the same file and leaves the first alone. Registering the same name on the same connection replaces that registration, which is how a table is moved forward after the asset changes: editing an asset writes a new version, the table keeps serving the version it was registered against, and the panel says so and asks you to register again. Overwriting the file at the same key is different — the table returns the new contents on the next query with nothing to do.
The trash control beside a table unregisters it. That drops the table and leaves the asset completely alone: the file is not deleted, not moved, and not changed. Deleting the asset itself is what drops every table over it.
The panel is absent unless the asset is a CSV and an administrator has given a Trino connection a scratch catalog and schema. Registering is the owner's call: it puts the file's contents in a schema everyone with that connection can read. An agent can do it for you without the portal step, with manage_table. See Registered Tables.