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/ Building Tools/ Load steps
Building Tools

Load steps

A @tool.load node produces a Table from parameters or a Source the user picks — the entry point of every pipeline. Learn its signature and Source injection.

TL;DRDecorate a function with @tool.load to make a node that produces data. It takes no Table ports (it is the source of data). Add a Source parameter to let the user pick files or a database; add outputs=[...] to emit several tables at once.

A load step is where data enters a pipeline. It produces a Table and takes no Table input ports — it is the source, so there is nothing upstream to read.

Usage#

The smallest load step builds a table from its parameters:

Python
from lsdtools import Tool, Table

tool = Tool("demo")

@tool.load
def rows(n: int = 3) -> Table:
    """Emit a tiny table of n rows."""
    return Table({"i": list(range(n)), "sq": [i * i for i in range(n)]})

n: int becomes a number field on the node. Run it → a 2-column table. # → i:[0,1,2] sq:[0,1,4]

Reading files with Source#

To let the user pick real data, add a parameter annotated Source. LSD injects a reader bound to whatever the user selects (a file, a folder + glob, or a SQL query); call source.read() to get a Table:

Python
from lsdtools import Tool, Source, Table

tool = Tool("io")

@tool.load(source_kinds=("file", "sql"))
def load_data(src: Source) -> Table:
    """Load a CSV/Parquet file or a SQL query the user picks."""
    return src.read()

source_kinds narrows the picker (default is file). A Source parameter is only valid on @tool.load — using it on a shape/deliver step raises at import time.

Emitting several tables#

Pass outputs=[...] to produce named output ports; return a dict. Downstream nodes wire to a specific port with step.output("name"):

Python
@tool.load(outputs=["nodes", "edges"])
def load_graph(src: Source) -> dict:
    tbl = src.read()
    return {"nodes": nodes_of(tbl), "edges": edges_of(tbl)}

Parameters vs ports — the rule#

Inside any step signature:

  • a Table annotation → an input port (load steps may not have these);
  • a Source annotation → an injected reader (load only);
  • a Context / StepContext annotation → injected capabilities, excluded from the cache key;
  • anything else → a typed parameter (a form field; no default ⇒ required).

These are checked at import time, so mistakes surface when you load the package, never mid-click.

LearnShape steps · Deliver steps · Params vs ports

APITool · Source · Table

ExamplesFile loader · Multi-output mesh

Frequently asked questions

Why can't a load step take a Table input?

A load step is the START of a pipeline — it produces the first Table, so it has nothing upstream to read. Passing a Table parameter to @tool.load raises an error at import time, not at click time.

How do I let the user choose a file?

Add a parameter annotated Source. LSD injects a reader bound to the file/folder/query the user picks in the node's form, and source.read() gives you a Table.

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