Groups
Collapse a set of nodes into one. This is how Weft stays readable at scale.
A group is a bundle of nodes wrapped as a single unit with its own typed inputs and outputs. From outside, a group looks like one node. From inside, it is a small project of its own. Groups contain groups, arbitrarily deep.
Groups are the single most important structural feature of the language. Without them, a graph-based system becomes a plate of spaghetti by the time it has 30 nodes. With them, a 100-node system still looks like 5 boxes at the top level.
Loading playground...
Try collapsing and expanding the groups to see how complexity compresses.
Anatomy of a group
A group declaration has four parts:
- ID:
data_processing. - Interface:
Group(raw: String) -> (result: String). The typed inputs and outputs that the outside world sees. - Description: the first
#comment inside the body. Always include one. - Body: the child nodes and their connections.
self
Inside a group, self refers to the group's own interface. You use it to connect child nodes to the group's inputs and outputs.
self.raw on the right side means "the data coming into this group through the raw input". self.result on the left side means "send this data out of the group through the result output".
Encapsulation
Child nodes inside a group can only talk to each other and to self. They cannot reference nodes outside the group, and nothing outside the group can reference a child by name. Data crosses the boundary only through the interface ports.
This gives you real encapsulation:
- No hidden coupling. A group is self-contained. If it works in one place, it works in another.
- No name conflicts. Two different groups can both have a
workerchild. They do not collide. - Scoped reasoning. When you debug a group, you only need to think about what goes in and what comes out. Everything else is the group's problem.
Nesting
Groups inside groups work exactly the way you would expect. Each level has its own scope, its own self, and its own interface:
To pass data through nested groups, chain the interface ports at each level. Data does not leak across group boundaries on its own.
When to use a group
A group is worth creating when any of the following are true:
- Three or more nodes work together on a single task.
- You find yourself copy-pasting the same small pattern more than once.
- You want to reason about "the piece that does X" separately from "the piece that does Y".
- The project has more than 5 top-level nodes.
Short version: if the graph is starting to feel noisy, it is time for a group.
Collapsed view
Every group has a collapse/expand toggle button on its header in the graph. Collapsed, the group renders as a single labeled box with its input ports on the left and its output ports on the right, just like any other node. Expanded, the group shows its whole body inside a bordered container. Click the toggle to switch between the two.
This is how you navigate a large project: stay collapsed at the top level, zoom into the one group you care about, everything else stays out of your way.
What's next
- Parallel processing: groups are the natural unit for parallel work.
- Mock nodes and test configs: replace a group with canned outputs while you work on other parts.
- Branching: conditional flow across and inside groups.