Sandbox — LSD is in active testing. All systems operational·payments are test-mode (no real charges).
Overview Use Cases News Docs Tool Store Support Community Get LSD
All docs
Docs/ Examples/ Example: live node metrics
Examples

Example: live node metrics

Show live row and column counts on a node card with graph_outputs and ctx.set_output, plus progress reporting via StepContext.progress.

TL;DRDeclare graph_outputs={"rows": int, "cols": int} on a step and set them from inside run() with ctx.set_output(...). They render as read-only scalars on the node card, are excluded from the cache key, and StepContext.progress reports a progress bar — all cache-neutral side channels.

A node card can show live numbers — rows processed, a computed score — without those values ever affecting caching. Declare them as graph_outputs, set them with ctx.set_output(...), and report progress with ctx.progress(...).

The code#

Python
# tool.py
from lsdtools import Tool, StepContext, Table

tool = Tool("metrics", label="Metrics")


@tool.load
def demo(n: int = 100) -> Table:
    """A table to measure."""
    return Table({"i": list(range(n)), "sq": [i * i for i in range(n)]})


@tool.shape(graph_outputs={"rows": int, "cols": int})
def summarize(t: Table, ctx: StepContext) -> Table:
    """Pass the table through unchanged, reporting its size to the node card."""
    ctx.progress(0.3, "measuring")
    ctx.set_output("rows", len(t))
    ctx.set_output("cols", len(t.columns))
    ctx.progress(1.0, "done")
    return t

What each line does#

  • graph_outputs={"rows": int, "cols": int} — declares two read-only scalar outputs. They show on the node card, ride along in the step's STEP_FINISHED event, and are excluded from the cache key — setting them never invalidates a cached run.
  • ctx: StepContext — an injected capability object. It is cache-neutral (progress, cancel, scratch dir, set_output) — unlike a full Context, which a step may not read. Injected parameters never appear as form fields.
  • ctx.progress(fraction, message) — reports a [0, 1] progress fraction; the desktop drives a progress bar from it. Best-effort — it never fails the step.
  • ctx.set_output("rows", len(t)) — records a graph-output value. len(t) is the row count; len(t.columns) the column count.
  • The step returns t unchanged — the metrics are a pure side channel.

Run it in Python#

Python
from lsdtools import Engine

s = summarize(demo(n=100))
res = Engine().run(s)
res.output.print() # → the table, unchanged (100 rows)

print(s.rows, s.cols) # → 100 2

After the run, the graph outputs are readable straight off the step instance (s.rows, s.cols) — the same values the desktop paints on the node card.

Try changing it#

  • Add a mean_sq: float graph output: ctx.set_output("mean_sq", ...) from a group_by aggregate.
  • Check ctx.cancelled inside a loop to bail out early on a long run.
  • Write a scratch file under ctx.scratch_dir for intermediate debugging artifacts.

LearnMultiple outputs · Shape steps

APIContext · Table · Engine

ExamplesMulti-output mesh · A dockable panel

By LSD Team · Last updated Jul 17, 2026 Ask on Discord View as Markdown