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 → merge
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.
  • ◇ Data nodes hold a typed value on the card, or coerce an inbound wire to that type at run time.
  • Custom nodes declare input/output (or per-port types) in node.json.
  • Output is 1-in / multi-out on the text lane (fan-out after a result).

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 and ◇ Data are one-in / one-out. ⇤ Output allows fan-out. A ⋈ Merge 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.