Skip to content

Output representations

An output representation is the stored form of one published notebook result. It determines which applications, agents, Python tools, and browser clients can interpret that output.

Notebook resultOutputSpec form or exporterPython accessBrowser loaderAgent use
JSON-compatible valueOutputSpec.json()json()jsonLoader()Summaries, records, and arrays
Native scalarOutputSpec.native()scalar()scalarLoader()Metrics, labels, statuses, and identifiers
Native NumPy arrayOutputSpec.native()asset_bytes()numpyLoader()Numeric arrays with NPY tooling
Native Apache Arrow tableOutputSpec.native()asset_bytes()arrowTableLoader()Columnar data with Arrow tooling
Native BlobAssetOutputSpec.native()blob_asset()Matching blob loaderMedia-typed application data
JSON BlobAssetblob.jsonblob_asset()Matching blob loaderVersioned JSON in a media-typed envelope
Rendered marimo outputOutputSpec.output()asset_bytes()marimoOutputLoader()Inert output and replay records
Complete marimo cellOutputSpec.cell()asset_bytes()marimoCellLoader()Output, console, and cell provenance
Textblob.textblob_asset()textLoader()Reports, labels, and source text
HTMLblob.htmlblob_asset()htmlLoader()Authored document fragments
Table rowsparquet.tableblob_asset()parquetRowsLoader()Tables, filtering, and aggregation
Altair chartaltair.vegaliteblob_asset()vegaLiteLoader()Chart specification and companion view
Chart imagealtair.pngblob_asset()imageLoader()Visual companion
AnyWidgetanywidget.bundleblob_asset()anyWidgetLoader()Saved state and browser-local interaction
Custom valueOutputSpec.export() and callableblob_asset()Custom loaderDepends on its media type and schema

The codec identifies the stable native envelope. A BlobAsset media type identifies the representation inside that envelope. Browser applications select one codec-aware loader explicitly.

Every descriptor records the stored value's python_type. Exporter-backed outputs record marimo_export.outputs.BlobAsset. Producer-local marimo cache paths are outside the portable representation contract.

When an exported state needs execution, a custom exporter runs for that state. Declared dependency modules contribute to exporter source identity and drift checks. anywidget.bundle also captures current model state. Reusing a prepared state reuses its representation bytes.

Choose representations for agents

For agent-oriented publication, combine:

  • one concise scalar or versioned JSON summary
  • one inspectable Parquet, Arrow, or NumPy output
  • one chart, image, or widget when visual review is part of the task

An image or interactive widget supports human review, while a paired table or JSON record supplies machine-readable evidence. Use notebook exports with agents defines the grounding workflow and evidence identity.

Browser loader dependencies

NumPy defines the NPY array-file format. Apache Arrow defines the columnar interprocess communication format used by Arrow assets. Parquet defines a columnar file format for table data. Vega-Lite defines a declarative chart specification. AnyWidget defines a browser widget model and view lifecycle.

Install the dependency used by each imported loader:

LoaderDependencyRole
JSON, scalar, text, HTML, imageNoneBrowser-native values and DOM APIs
marimo output and marimo cellNoneInert replay records
NumPyNoneBuilt-in NPY decoder
Arrow@uwdata/flechette and lz4jsArrow table API and LZ4 decompression
ParquethyparquetParquet row decoding
Vega-Litevega-embedChart rendering and disposal
AnyWidget@anywidget/typesTypeScript model, host, and lifecycle types
bash
pnpm add @marimo-team/marimo-export hyparquet vega-embed

Import each loader from its public subpath. Output loaders defines every result type, option, default, cancellation point, and disposal contract.

Exporter options

ExporterOptions
altair.vegaliteNone
altair.pngscale
anywidget.bundleNone
parquet.tablecompression, filename
blob.jsonmedia_type, filename, metadata
blob.textmedia_type, filename, metadata
blob.htmlfilename, metadata

Typed exporter factories live under marimo_export.exporters.

Define a custom representation

A Python exporter converts one notebook result into a BlobAsset:

python
import json

from marimo_export.outputs import BlobAsset


def encode_summary(value: list[object]) -> BlobAsset:
    payload = {
        "schema": "example.summary.v1",
        "rows": len(value),
    }
    return BlobAsset(
        data=json.dumps(payload, separators=(",", ":")).encode("utf-8"),
        media_type="application/vnd.example.summary.v1+json",
        filename="summary.json",
    )

An ExportSpec selects that callable:

yaml
outputs:
  summary:
    source: { kind: export, selector: report }
    exporter:
      name: summary_exporter:encode_summary
      options: {}
      dependencies:
        - json

The browser loader validates the same media type and payload:

ts
import { defineBlobAssetLoader } from "@marimo-team/marimo-export";
import { parsePortableJson, portableJsonObject } from "@marimo-team/portable-json";

interface Summary {
  readonly rows: number;
}

export const summaryLoader = defineBlobAssetLoader<Summary>({
  mediaTypes: "application/vnd.example.summary.v1+json",
  load({ payload, signal }) {
    signal?.throwIfAborted();
    const text = new TextDecoder("utf-8", { fatal: true }).decode(payload.data);
    const value = portableJsonObject(parsePortableJson(text), "summary");
    if (
      value.schema !== "example.summary.v1" ||
      typeof value.rows !== "number" ||
      !Number.isSafeInteger(value.rows) ||
      value.rows < 0
    ) {
      throw new TypeError("Summary payload is invalid.");
    }
    signal?.throwIfAborted();
    return Object.freeze({ rows: value.rows });
  },
});

Install the companion parser when the custom loader uses it:

bash
pnpm add @marimo-team/marimo-export @marimo-team/portable-json

Use a versioned media type for a representation shared with agents or another client. A loader can return data or a value with a browser mount() method. A mount returns an idempotent disposable view and owns every node, listener, object URL, model, and renderer resource that it creates.

Portable JSON defines the cross-language value contract. Errors and limits defines the integrity and execution boundaries for custom loaders.

Released under the Apache 2.0 License.