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: your first tool
Examples

Example: your first tool

A complete, runnable package with one load step and one shape step — the smallest tool that shows up on the LSD canvas. Copy, run, and adapt.

TL;DRA full tool.py with a load step (emit rows) and a shape step (keep the top N). Drop it in a project folder next to your .lsd file and LSD hot-loads it — both nodes appear in the palette with generated forms.

The smallest real tool: one node that makes data, one that transforms it. Save this as tool.py in a folder, point LSD at it ("Add local package…"), and both nodes appear in the add-node palette with generated forms.

The code#

Python
# tool.py
from lsdtools import Tool, Table

tool = Tool("hello", label="Hello")


@tool.load
def numbers(count: int = 5) -> Table:
    """Emit a table of the first `count` integers and their squares."""
    xs = list(range(count))
    return Table({"n": xs, "square": [x * x for x in xs]})


@tool.shape
def top(t: Table, limit: int = 3) -> Table:
    """Keep the `limit` rows with the largest square."""
    return t.sort("square", descending=True).head(limit)

What each line does#

  • tool = Tool("hello") — one Tool per package, created at module scope. Its name namespaces the nodes (hello.numbers, hello.top).
  • @tool.load — makes a node that produces data. count: int = 5 has a default, so it is an optional parameter and renders as a number field.
  • Table({...}) — builds a Table from a dict of columns.
  • @tool.shape — makes a transform node. t: Table is an input port (wire it from the load node); limit: int is another parameter.
  • Every function returns a step, never data at import time — LSD runs it when the node runs.

Run it in Python#

You don't need the desktop to try it — wire the steps and run with an Engine:

Python
from lsdtools import Engine

n = numbers(count=6)
result = Engine().run(top(n, limit=3))
result.output.print()
# → n:[5,4,3] square:[25,16,9]

top(n, ...) wires the shape node's input port to the load node n. Engine().run(...) executes the chain and caches each step; result.output is the final Table.

Try changing it#

  • Add a @tool.deliver node that calls t.write_csv("out.csv").
  • Give numbers a Source parameter to load a real file instead — see File loader.
  • Add a second output with outputs=["evens", "odds"] — see Multi-output.

LearnLoad steps · Shape steps · Develop a package

APITool · Table · Engine

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