# Workflows docs

> Install @texuli/workflows, build a typed graph, edit or view it. In development. Not a workflow runner.

Language: en
Canonical: https://texuli.com/guides/solutions/workflows/
Markdown: https://texuli.com/guides/solutions/workflows.md (this page). Every texuli.com page has a Markdown twin at its URL plus `.md` (the home page is https://texuli.com/index.md), and any page URL answers `Accept: text/markdown` with its twin instead of HTML.
Last Updated: 2026-11-13

---

Guides

Install @texuli/workflows, build a typed graph, edit or view it. In development. Not a workflow runner.

[Back to overview](https://texuli.com/solutions/workflows/)

## What Workflows is

Workflows is an embeddable graph system: `@texuli/workflows` holds a typed model of nodes, ports and edges, a deterministic layout, an editor, an inspector, an accessible outline and a read-only viewer. The package is published as `0.18.0` and is **in development** (pre-1.0). Pin the exact version or use `^0.17.0`.

It authors and views workflow diagrams. It does not run automations, persist graphs, or host a workflow service. The host app stores the graph and owns any runner.

The JSON live preview on this site stays at `/workflows-page/json/`. The technical docs you are reading live at `/guides/solutions/workflows/`.

## What you get

- Closed node types, validated operations, cycle policy and hard limits.
- Layered auto-layout, left-to-right or top-to-bottom.
- `WorkflowEditor`, `WorkflowViewer` and `WorkflowInspector`.
- Canonical JSON (`parseWorkflow` / `stringifyWorkflow`) and a spec adapter for `workflow-graph` blueprints.

There is no hosted persistence. The host keeps the data.

## Install

Svelte 5 (`^5.57.2`) is a peer of `@texuli/workflows`. Import `@texuli/tokens/base.css` once; each view imports its own CSS.

```
npm install @texuli/workflows
```

## Build a graph and edit it

Declare node types, apply operations (each one is validated), lay the graph out, then pass it to `WorkflowEditor`.

```
<script lang="ts">
  import { WorkflowEditor } from '@texuli/workflows/editor';
  import { layoutMoves, layoutWorkflow } from '@texuli/workflows/layout';
  import {
    applyWorkflowOps,
    createWorkflow,
    defineNodeTypes,
    type WorkflowGraph,
  } from '@texuli/workflows/model';

  const registry = defineNodeTypes([
    {
      type: 'request',
      label: 'Request',
      category: 'Start',
      ports: [{ id: 'out', direction: 'out', dataType: 'any' }],
    },
    {
      type: 'end',
      label: 'End',
      category: 'Done',
      ports: [{ id: 'in', direction: 'in', dataType: 'any' }],
    },
  ]);

  const at = { x: 0, y: 0 };
  const built = applyWorkflowOps(
    createWorkflow(),
    [
      { op: 'addNode', node: { id: 'ask', type: 'request', label: 'Expense submitted', position: at } },
      { op: 'addNode', node: { id: 'paid', type: 'end', label: 'Paid', position: at } },
      {
        op: 'connect',
        edge: { id: 'e1', from: { node: 'ask', port: 'out' }, to: { node: 'paid', port: 'in' } },
      },
    ],
    { registry }
  );
  if (!built.ok) throw new Error(built.error.message);

  const moves = layoutMoves(layoutWorkflow(built.graph, { direction: 'LR' }));
  const laid = applyWorkflowOps(built.graph, [{ op: 'moveNodes', moves }], { registry });
  let graph = $state.raw<WorkflowGraph>(laid.ok ? laid.graph : built.graph);
</script>

<WorkflowEditor {graph} {registry} onchange={(next) => (graph = next)} />
```

For a read-only figure, use `WorkflowViewer` from `@texuli/workflows/viewer` with the same `graph` and `registry` and a `label`.

## Graph model

Everything in `@texuli/workflows/model` is a pure function. `defineNodeTypes` declares the closed vocabulary. `createWorkflow` starts empty. `applyWorkflowOps` applies add, connect, move, group and remove operations; a refused operation changes nothing.

```
import {
  applyWorkflowOps,
  createWorkflow,
  createWorkflowHistory,
  defineNodeTypes,
  parseWorkflow,
  stringifyWorkflow,
} from '@texuli/workflows/model';
```

Every operation checks ports, directions, data types, cardinality, duplicates, the cycle policy and hard limits (500 nodes, 2,000 edges, 5,000 operations per batch). Labels are text; control and bidirectional override characters are refused. Link and image props pass the URL policy at the `untrusted` tier.

`parseWorkflow` and `stringifyWorkflow` round-trip canonical JSON. `createWorkflowHistory` is undo and redo for the host to keep.

## Layout

`layoutWorkflow` and `layoutMoves` in `@texuli/workflows/layout` place nodes with a deterministic layered auto-layout, left-to-right or top-to-bottom, right-to-left aware. Apply the moves with `applyWorkflowOps`.

## Spec adapter

`fromSpecWorkflow` and `toSpecWorkflow` in `@texuli/workflows/spec-adapter` convert the `@texuli/spec` `workflowGraph` JSON used by blueprint `workflow-graph` nodes.

## Editor

`WorkflowEditor` from `@texuli/workflows/editor` is the Svelte 5 authoring surface: toolbar, palette, canvas with minimap, inspector and a treegrid outline. Parts also import on their own (`WorkflowCanvas`, `WorkflowToolbar`, `WorkflowPalette`, `WorkflowMinimap`, `WorkflowOutline`, `WorkflowNodeBody`).

The editor reports each change with `onchange(graph, event)`. Undo and redo run on `createWorkflowHistory`. The host stores the graph.

## Viewer and inspector

`WorkflowViewer` from `@texuli/workflows/viewer` is a read-only figure whose nodes are a list that says where each one leads. Pass a `label`. `WorkflowInspector` from `@texuli/workflows/inspector` edits the selected node's typed props.

## Player

`@texuli/player` paints a `workflow-graph` node with this package: the viewer in `view` mode, the editor in `edit` mode, through the spec adapter. An agent can send a workflow as JSON. That painter is in development with the rest of Workflows.

The JSON live preview on this site is `/workflows-page/json/`.

## Keyboard first

On the canvas, arrows move focus to the nearest node in that direction, Alt+Arrow nudges one grid step, Space toggles selection, Enter on a port starts connect mode (arrows cycle compatible ports, Enter connects, Escape cancels), Delete removes, and Ctrl or Cmd with Z / Y undoes and redoes. `=` / `-` zoom, and `0` fits the view.

The outline is a WAI-ARIA treegrid that reads and edits the whole graph without the canvas. The palette adds a node with a button press as well as a drag (WCAG 2.5.7).

## Drag contract

The shared drag contract applies: localized announcements, 24 px targets, reduced motion and forced colors. Nothing renders as HTML.

## Status

Workflows is **in development**. `@texuli/workflows` is on npm as `0.18.0`. Under 0.x a new minor may break. Native rendering is planned, not built.

## Not built

- A live automation or workflow runner
- Hosted persistence or multiplayer
- A visual schema builder outside the typed graph
- Native Compose, Android or iOS painting of the editor

Texuli draws and edits the graph. The host app stores it and owns any execution. Hard limits are 500 nodes and 2,000 edges.

## Untrusted graphs

A graph from an agent, a paste or a share link is untrusted data. Use `parseWorkflow` or `applyWorkflowOps` so every operation is checked. Labels are text. There is no HTML sink.

## Catalog and skill

Agents can emit a `workflow-graph` catalog node (view or edit). `@texuli/player` paints it with `@texuli/workflows`. The Texuli skill covers the editor, viewer, inspector, model and layout under `skills/texuli/build-ui/SKILL.md`.

Do not invent a hosted runner or an MCP operation that is not in `@texuli/tools`. Convert blueprint JSON with `fromSpecWorkflow` / `toSpecWorkflow`.
