Skip to content

Lanes & value types

Every wire carries a value. threadle distinguishes lanes (what kind of thing moves) and value types (what shape the text has).


A lane is the color-coded category of an edge. It is derived from the node types at each end — you never set it by hand.

LaneCarriesTypical wiring
textA stringprompt → agent, agent → output, anything → knot
sessionA reference to a real sessionagent → session, session → context
contextA context payloadsession → context, context → agent

Most of a workflow lives on the text lane. The session lane is what makes an agent continue a conversation instead of starting a new one; the context lane is how a distilled brief travels from one tool to another.


Within the text lane, a node may declare what kind of text it emits or expects:

TypeAccepts
textAnything (the default)
int-12, 0, 42
floatAny finite number
booltrue, false, 1, 0
jsonAnything JSON.parse accepts

Who declares them:

  • Prompt nodes have a type selector — a prompt can be a typed primitive, not just prose.
  • Custom nodes declare input/output (or per-port types) in node.json.

A connection is allowed when the source’s type fits the target’s:

  • identical types always fit
  • anything fits text
  • int widens to float
  • everything else is refused

The check runs while you drag — an incompatible wire simply won’t attach, so you find out at design time.


Design-time refusal isn’t enough, because a node can lie about what it produces. So values are checked again at run time:

  • inbound text is validated against the target’s declared input type
  • a custom node’s stdout is validated against its declared output type

A node that declares int output and prints a paragraph fails loudly, with the offending text in the error, instead of poisoning every node downstream.

head-tail: output "count" declares int but not an int: "about twelve"

When several wires land on the same input, their texts are joined with blank lines before the node sees them — but only if that handle still has capacity. A full slot refuses another wire while you drag (same as a type mismatch). Built-ins like Delay are one-in / one-out; a ⋈ Knot is the intentional multi-in merge. Custom named ports default to one wire; raise maxConnections for fan-in.

For named ports, joining happens per port, so each port sees only its own wires.