<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ricardo Morais</title>
    <description>The latest articles on DEV Community by Ricardo Morais (@moraispgsi).</description>
    <link>https://dev.to/moraispgsi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3864140%2Fd608a461-8237-4505-a1fa-36450194b387.png</url>
      <title>DEV Community: Ricardo Morais</title>
      <link>https://dev.to/moraispgsi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moraispgsi"/>
    <language>en</language>
    <item>
      <title>Developers don't hate visual workflows. They hate the magic.</title>
      <dc:creator>Ricardo Morais</dc:creator>
      <pubDate>Wed, 08 Apr 2026 19:24:52 +0000</pubDate>
      <link>https://dev.to/moraispgsi/developers-dont-hate-visual-workflows-they-hate-the-magic-2nh6</link>
      <guid>https://dev.to/moraispgsi/developers-dont-hate-visual-workflows-they-hate-the-magic-2nh6</guid>
      <description>&lt;p&gt;Hey, I'm Ricardo. I've been building &lt;a href="https://flowweaver.ai" rel="noopener noreferrer"&gt;Flow Weaver&lt;/a&gt;, a TypeScript workflow compiler. I've been working on it solo for nearly two years as a side project, and I'm finally sharing it.&lt;/p&gt;

&lt;p&gt;Every workflow tool I've come across has asked me to leave my code behind. Use their editor, their format, their runtime. I never actually used them. I'd see the demo, think about what I'd lose, and close the tab.&lt;/p&gt;

&lt;p&gt;The thing is, I don't think developers hate visual workflows. I think they hate what they have to give up to get them. Your types, your linter, your version control, your ability to just read the code and understand what's happening.&lt;/p&gt;

&lt;p&gt;What if your code was the workflow, and the visual was just a view on top?&lt;/p&gt;

&lt;h2&gt;
  
  
  The code is the workflow
&lt;/h2&gt;

&lt;p&gt;That's &lt;a href="https://flowweaver.ai" rel="noopener noreferrer"&gt;Flow Weaver&lt;/a&gt;. You write TypeScript functions, add one annotation, and the compiler turns them into workflow nodes. The visual representation is generated from your code, not the other way around.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Write your node functions
&lt;/h3&gt;

&lt;p&gt;These are plain TypeScript functions. The only thing special about them is the annotation. The &lt;code&gt;@expression&lt;/code&gt; shorthand handles &lt;code&gt;execute&lt;/code&gt;/&lt;code&gt;onSuccess&lt;/code&gt;/&lt;code&gt;onFailure&lt;/code&gt; automatically, so you just write the transform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @flowWeaver nodeType @expression */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/** @flowWeaver nodeType @expression */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;!!!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can call these directly, test them with vitest, import them anywhere. They're just functions. The &lt;code&gt;greet&lt;/code&gt; function translates to a node (a box in the graph) type with the following ports (connection points for the node):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Direction&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execute&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;in&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Control signal that starts the node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;in&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;The parameter you defined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onSuccess&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;out&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;You set this to true when the node succeeds. Expression nodes set it automatically: true if the function returns without throwing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onFailure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;out&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;You set this to true when the node fails. Expression nodes set it automatically: true if the function throws&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;greeting&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;out&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;The return property you defined&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 2: Wire them into a workflow
&lt;/h3&gt;

&lt;p&gt;The workflow annotation connects node instances together. &lt;code&gt;@connect&lt;/code&gt; wires ports between nodes. &lt;code&gt;@path&lt;/code&gt; is a shortcut so you don't have to write the step connections one by one. &lt;code&gt;@path Start -&amp;gt; g -&amp;gt; s -&amp;gt; Exit&lt;/code&gt; is equivalent to connecting &lt;code&gt;Start.onSuccess -&amp;gt; g.execute&lt;/code&gt;, &lt;code&gt;g.onSuccess -&amp;gt; s.execute&lt;/code&gt;, &lt;code&gt;s.onSuccess -&amp;gt; Exit.onSuccess&lt;/code&gt; manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @flowWeaver workflow
 * @node g greet
 * @node s shout
 * @path Start -&amp;gt; g -&amp;gt; s -&amp;gt; Exit
 * @connect Start.name -&amp;gt; g.name
 * @connect g.greeting -&amp;gt; s.text
 * @connect s.result -&amp;gt; Exit.message
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;helloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This body is replaced by the compiler. Run: npx flow-weaver compile &amp;lt;file&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Start&lt;/code&gt; and &lt;code&gt;Exit&lt;/code&gt; are virtual nodes. &lt;code&gt;Start&lt;/code&gt; receives the workflow inputs, &lt;code&gt;Exit&lt;/code&gt; collects the outputs. Everything lives in one .ts file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: See what you built
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver diagram hello.ts &lt;span class="nt"&gt;--format&lt;/span&gt; ascii
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56a3ld9bgfcjpjukwdq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56a3ld9bgfcjpjukwdq2.png" alt="ASCII diagram of the helloWorld workflow showing Start, greet, shout, and Exit nodes connected in sequence" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also generate SVG for documentation, Mermaid for GitHub, or open an interactive HTML version in your browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Validate
&lt;/h3&gt;

&lt;p&gt;The compiler checks your workflow graph before generating anything. Port types, missing connections, dead-end branches, all caught at compile time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver validate hello.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;✓ 1 file valid in 248ms
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when something is wrong, it tells you exactly what and where:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✗ [line 11] Unknown Input Port: Port 'wrong_port' doesn't exist on node Exit.
⚠ How to fix: Check the port name in the @connect annotation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are structured diagnostics with error codes, source locations, and fix suggestions. They're also machine-readable, which means your AI assistant can fix issues automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Compile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver compile hello.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;  Compiling Workflows

✓ hello.ts 278ms

  1 file compiled (ESM) in 278ms
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler generates the execution logic inside your workflow function, between &lt;code&gt;@flow-weaver-body-start&lt;/code&gt; and &lt;code&gt;@flow-weaver-body-end&lt;/code&gt; markers. Your node functions are never touched. The compiled output is standalone TypeScript. No imports from Flow Weaver. You could remove the package and the code keeps running.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver run hello.ts &lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="s1"&gt;'{"name":"World"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;✓ Workflow "helloWorld" completed in 1ms

  Result

{
  "onSuccess": true,
  "onFailure": false,
  "message": "HELLO, WORLD!!!!"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Or just tell your AI assistant
&lt;/h2&gt;

&lt;p&gt;Everything above, your AI assistant can do through conversation, you don't have to know the syntax by heart, Flow Weaver was designed to work smoothly with AI. You can ask your assistant to use the CLI directly. It gives you direct expertise through the &lt;code&gt;fw context&lt;/code&gt; and &lt;code&gt;fw docs&lt;/code&gt; command. Or, if you prefer, use the available MCP tools that work with Claude Code, Codex, Copilot, Cursor, Windsurf, and any MCP-compatible editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver mcp-setup &lt;span class="nt"&gt;--tool&lt;/span&gt; claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Personally I use the CLI directly, so it is always up-to-date with the available version, up to you.&lt;/p&gt;

&lt;p&gt;Then you talk to it:&lt;/p&gt;

&lt;p&gt;The first thing you'll want to do is ask your AI to load the Flow Weaver context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Load the Flow Weaver context core"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI calls &lt;code&gt;fw context core&lt;/code&gt; and gets the full annotation syntax, node patterns, CLI commands, and a tutorial. From that point on it knows how to build workflows without guessing. There are other presets to choose based on the context you want to give it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Preset&lt;/th&gt;
&lt;th&gt;What's included&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;concepts, annotation syntax, tutorial&lt;/td&gt;
&lt;td&gt;Getting started&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;authoring&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;core + advanced annotations, built-in nodes, scaffolding, node conversion, patterns&lt;/td&gt;
&lt;td&gt;Building real workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ops&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CLI reference, compilation, deployment, debugging, error codes&lt;/td&gt;
&lt;td&gt;Deploying and debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;full&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;everything (16 topics)&lt;/td&gt;
&lt;td&gt;When you want the AI to know it all&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can then ask about how it works, and what it can do for you. It will have the context and will be able to pull up documentation and try things out on your behalf.&lt;/p&gt;

&lt;p&gt;Then, when you are ready to use it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Build a support agent that classifies customer messages and routes to LLM reply or human escalation"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI scaffolds the workflow, adds nodes, wires connections, validates, and compiles. When the compiler finds issues, the AI reads the structured diagnostics and fixes them in a loop until the workflow is valid.&lt;/p&gt;

&lt;p&gt;If you still don't understand the inner details and want to dig deeper, just visit the source code at &lt;a href="https://github.com/synergenius-fw/flow-weaver" rel="noopener noreferrer"&gt;Flow Weaver's GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Routing
&lt;/h2&gt;

&lt;p&gt;The expression nodes above are great for simple transforms. When you need branching, you use the full node signature. The runtime calls your function when the node receives an execute signal. You return which path fires next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @flowWeaver nodeType
 * @label Validate Input
 * @input data - Data to validate
 * @output validated - Validated data
 * @output errors - Validation errors
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name too short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No routing engine, no config file, just a return value from a function you control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent workflows
&lt;/h2&gt;

&lt;p&gt;The hello world is intentionally simple. For real use cases, Flow Weaver ships with templates for LLM agents, RAG pipelines, conversational memory, human approval gates, and more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver create workflow ai-agent my-agent.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each template generates a complete working workflow with mock providers so you can compile and run immediately without any API keys.&lt;/p&gt;

&lt;p&gt;I'll do a deeper walkthrough of the agent workflow patterns in a future post. For now, run &lt;code&gt;npx flow-weaver templates&lt;/code&gt; to see what's available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packs
&lt;/h2&gt;

&lt;p&gt;Flow Weaver is extensible through npm packages called packs. They add deploy targets, node types, CLI commands, and MCP tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver market search        &lt;span class="c"&gt;# see what's available&lt;/span&gt;
npx flow-weaver market &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;pack&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploy
&lt;/h2&gt;

&lt;p&gt;The compiled output is standalone TypeScript, so it runs anywhere TypeScript runs. For specific platforms, install a deploy pack and export:&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless functions
&lt;/h3&gt;

&lt;p&gt;Workflows can be serverless functions on your provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver &lt;span class="nb"&gt;export &lt;/span&gt;agent.ts &lt;span class="nt"&gt;-t&lt;/span&gt; inngest &lt;span class="nt"&gt;-o&lt;/span&gt; deploy/
npx flow-weaver &lt;span class="nb"&gt;export &lt;/span&gt;agent.ts &lt;span class="nt"&gt;-t&lt;/span&gt; vercel &lt;span class="nt"&gt;-o&lt;/span&gt; deploy/
npx flow-weaver &lt;span class="nb"&gt;export &lt;/span&gt;agent.ts &lt;span class="nt"&gt;-t&lt;/span&gt; lambda &lt;span class="nt"&gt;-o&lt;/span&gt; deploy/
npx flow-weaver &lt;span class="nb"&gt;export &lt;/span&gt;agent.ts &lt;span class="nt"&gt;-t&lt;/span&gt; cloudflare &lt;span class="nt"&gt;-o&lt;/span&gt; deploy/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CI/CD pipelines (experimental)
&lt;/h3&gt;

&lt;p&gt;Workflows can also define CI/CD pipelines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver &lt;span class="nb"&gt;export &lt;/span&gt;pipeline.ts &lt;span class="nt"&gt;-t&lt;/span&gt; gitlab-ci &lt;span class="nt"&gt;-o&lt;/span&gt; deploy/
npx flow-weaver &lt;span class="nb"&gt;export &lt;/span&gt;pipeline.ts &lt;span class="nt"&gt;-t&lt;/span&gt; github-actions &lt;span class="nt"&gt;-o&lt;/span&gt; deploy/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Version control that makes sense
&lt;/h2&gt;

&lt;p&gt;When someone changes a workflow, the PR diff looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- @path Start -&amp;gt; g -&amp;gt; s -&amp;gt; Exit
&lt;/span&gt;&lt;span class="gi"&gt;+ @path Start -&amp;gt; g -&amp;gt; validate -&amp;gt; s -&amp;gt; Exit
+ @connect g.greeting -&amp;gt; validate.input
+ @connect validate.output -&amp;gt; s.text
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a real diff you can review. And for deeper analysis, the semantic diff engine compares workflow versions at the graph level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flow-weaver diff hello-old.ts hello.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;═══════════════════════════════════════════════════════════════
  WORKFLOW DIFF - Impact: BREAKING
═══════════════════════════════════════════════════════════════
&lt;span class="err"&gt;
&lt;/span&gt;  SUMMARY
  ───────────────────────────────────────────────────────────
  Node Types:   +1 added, -0 removed, ~1 modified
  Instances:    +1 added, -0 removed, ~0 modified
  Connections:  +4 added, -2 removed
&lt;span class="err"&gt;
&lt;/span&gt;  INSTANCES
  ───────────────────────────────────────────────────────────
  + v
&lt;span class="err"&gt;
&lt;/span&gt;  CONNECTIONS
  ───────────────────────────────────────────────────────────
  + g.greeting → v.text
  + v.validated → s.text
  + g.onSuccess → v.execute
  + v.onSuccess → s.execute
  - g.greeting → s.text
  - g.onSuccess → s.execute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It classifies the overall impact as critical, breaking, minor, or cosmetic. So you know not just what changed, but whether it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  There is a visual editor
&lt;/h2&gt;

&lt;p&gt;I still believe in the visual side, that's what started all of this. I built a &lt;a href="https://flowweaver.ai/studio" rel="noopener noreferrer"&gt;Studio&lt;/a&gt; where you can see the graph and edit it on a canvas. It's still experimental, but core editing with the canvas, terminal, and diagnostics is live. Edit code and the graph updates. Edit the graph and the code updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tgc0nkg72ko8zf28lg0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tgc0nkg72ko8zf28lg0.png" alt="Flow Weaver Studio showing a workflow graph on the canvas with a code editor and terminal panel below" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy8kcse4i8mq1g4x52no.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy8kcse4i8mq1g4x52no.png" alt="Flow Weaver Studio showing the node type browser panel alongside the visual workflow editor" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But you don't need it. The CLI and your text editor work fine on their own. The visual is there when it helps you reason about what you're building, not as something you're forced to use. That's the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Works inside OpenClaw too
&lt;/h2&gt;

&lt;p&gt;If you use &lt;a href="https://openclaw.ai" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt;, Flow Weaver runs as a native plugin. Tell your assistant what you want automated, and it builds, validates, and compiles the workflow for you. The agent uses AI for individual steps like classification or summarization, but the routing between steps is compiled and deterministic. No skipped steps, no wrong routing, same result every run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw plugins &lt;span class="nb"&gt;install&lt;/span&gt; @synergenius/flow-weaver-openclaw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin is on &lt;a href="https://clawhub.ai/plugins/%40synergenius%2Fflow-weaver-openclaw" rel="noopener noreferrer"&gt;ClawHub&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/@synergenius/flow-weaver-openclaw" rel="noopener noreferrer"&gt;npm&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where things stand
&lt;/h2&gt;

&lt;p&gt;Flow Weaver is in beta and real world usage will make it stronger. Even if you are skeptical, just give it a try. I'd really appreciate it, and negative feedback is just as welcome as positive.&lt;/p&gt;

&lt;p&gt;Breaking changes may still happen during the beta. If you run into issues, the &lt;a href="https://discord.gg/TCn4qntaeT" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; is the best place to reach out. Every message gets read and responded to.&lt;/p&gt;

&lt;p&gt;If you've been looking for a way to build workflows without giving up your code, try it. Two commands, first workflow running in under two minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @synergenius/flow-weaver
npx flow-weaver init hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be one of the first people to use it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/synergenius-fw/flow-weaver" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://flowweaver.ai" rel="noopener noreferrer"&gt;Website&lt;/a&gt; · &lt;a href="https://flowweaver.ai/features" rel="noopener noreferrer"&gt;Features&lt;/a&gt; · &lt;a href="https://flowweaver.ai/studio" rel="noopener noreferrer"&gt;Studio&lt;/a&gt; · &lt;a href="https://discord.gg/TCn4qntaeT" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>ai</category>
      <category>automation</category>
      <category>openclaw</category>
    </item>
  </channel>
</rss>
