A node is one step in a flow. You register it withDocumentation Index
Fetch the complete documentation index at: https://docs.waniwani.ai/llms.txt
Use this file to discover all available pages before exploring further.
.addNode({ id, run, label?, hideFromFunnel? }). The run handler receives a context object and returns one of three things:
- A plain state update (action node).
- An interrupt signal (pause and ask).
- A widget signal (pause and delegate to a display tool).
Node context
Every handler receives a single argument with this shape:Current flow state. Partial because earlier nodes may not have filled every field yet.
The MCP request
_meta for this tool call. Rarely needed directly. Use waniwani for tracking.Helper to build an interrupt signal. Field keys are typed against the state schema. See Interrupts.
Helper to build a widget signal. Accepts a
RegisteredTool (from createTool()) or its id as a string.A session-scoped tracking client. Present when the MCP server is wrapped with
withWaniwani(). Undefined otherwise.Action nodes
An action node returns a plain state update. The engine deep-merges the update into state and advances along the node’s outgoing edge without pausing.Interrupt nodes
An interrupt node returnsinterrupt(...). The engine stores the graph step, returns status: "interrupt" to the model, and waits for a continue call. When the user answers, the node’s validators run (if any) and the engine advances.
Widget nodes
A widget node returnsshowWidget(tool, config). The engine returns status: "widget" pointing at a display tool (created with createTool()) and the flow pauses. When the user interacts, the host calls the flow back with action: "continue" and whatever values you want stored in stateUpdates.
field enables the same auto-skip behavior as interrupts: if selectedPlan is already filled when the flow reaches this node, the widget is skipped. Setting interactive: false makes the widget display-only and auto-advances after it renders.
The flow itself is a data-only tool. It never returns
structuredContent. The display tool referenced by showWidget is the one that renders the widget. Register the display tool with Skybridge’s server.registerWidget(name, meta, schema, handler) and the flow with flow.register(server) — Skybridge handles all the widget-binding metadata for you. See the Pet insurance example for the full pattern.Async handlers
Handlers can be sync or async. Most real handlers are async because they touch external services:Naming and uniqueness
Node names are internal identifiers. They appear in Mermaid diagrams (flow.graph()), compile-time validation errors, and error messages at runtime. Use snake_case, keep them short, prefer verbs for actions and ask_* for interrupts.
Node names must be unique within a flow. Adding the same name twice throws at build time. START and END are reserved and cannot be used as node names.