Connections
How data moves between nodes.
A connection (or edge) wires an output port of one node to an input port of another. Every connection is a line of code with an assignment:
Read it like a variable assignment: "the analyzer's prompt input gets its value from input_text's value output." Data flows right to left.
Shape
Every connection is <target_node>.<input_port> = <source_node>.<output_port>. Both sides are required, including the port name. There is no shorthand for "connect node A to node B", because nodes have multiple ports and the compiler needs to know which one.
You can also connect into a group's interface from inside the group using self:
See Groups for the full story on self.
Type checking
Every edge is type-checked. The source output type must fit the target input type. String into Number is a compile error. String into String | Number is fine. List[String] into String is not a mismatch, it is a parallel split (see parallel processing).
You do not write any cast syntax. The compiler figures out whether two types are compatible and how they relate.
Required vs optional targets
When you connect to a required input and the source produces null at runtime, the target node skips. This is null propagation: the null cascades downstream until it hits something that can handle it.
When you connect to an optional input (declared with ?), the target node runs even if the source is null. The input is available as null inside the node's code, which means you must handle the null case explicitly.
This is how branching works: the router outputs null on inactive branches, and each branch's downstream nodes have required inputs that skip on null.
Fan-out and fan-in
An output port can feed multiple inputs. You just write several connections from the same source:
All three downstream nodes receive the same value. No copying, no special syntax. Think of each output port as a value that any number of inputs can read.
An input port can only have one connection. If you need to combine data from multiple sources into one input, use a Template or a Pack node upstream.
Port wiring inside a config block
Instead of writing a separate connection line, you can wire a port from inside the node's config block when the key matches an input port name:
Here template and name are input ports on the Template node, and the right side is a port reference, so the parser creates real edges instead of storing strings. This keeps one-off wiring compact.
The rule: the key must be an actual input port on the parent node, not a pure config field. If you try to port-wire into a config-only field, the compiler errors out and tells you to use a separate connection line.
A common mistake
The most common mistake in Weft is connecting the wrong output. Nodes do not forward their inputs to their outputs. If you need processed data, connect from the node that did the processing, not from the raw source.
Example. This does not do what the author intended:
The fix is to connect output.data to llm.response, the output port of the node that actually produced the value you want to see.
Before each connection, ask: does this output actually contain the data this input needs?
What's next
- Types: the type system that makes connections safe.
- Null propagation: what happens when a source produces null.
- Parallel processing: when a List connects to a single-item input.