<?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: ByteChef</title>
    <description>The latest articles on DEV Community by ByteChef (@bytechef).</description>
    <link>https://dev.to/bytechef</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3622449%2F5f75e94d-42ad-41ff-9035-22082f2f8fc9.png</url>
      <title>DEV Community: ByteChef</title>
      <link>https://dev.to/bytechef</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bytechef"/>
    <language>en</language>
    <item>
      <title>One Workflow, Many Lanes: Completing ByteChef's Flow Controls</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Fri, 14 Aug 2026 18:36:57 +0000</pubDate>
      <link>https://dev.to/bytechef/one-workflow-many-lanes-completing-bytechefs-flow-controls-4k0f</link>
      <guid>https://dev.to/bytechef/one-workflow-many-lanes-completing-bytechefs-flow-controls-4k0f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; ByteChef's workflow editor now exposes the &lt;strong&gt;full set of flow controls&lt;/strong&gt;: alongside the familiar &lt;strong&gt;Condition&lt;/strong&gt;, &lt;strong&gt;Branch&lt;/strong&gt;, and &lt;strong&gt;Loop&lt;/strong&gt;, you can drop &lt;strong&gt;Parallel&lt;/strong&gt;, &lt;strong&gt;Fork/Join&lt;/strong&gt;, &lt;strong&gt;Each&lt;/strong&gt;, &lt;strong&gt;Map&lt;/strong&gt;, and &lt;strong&gt;Subflow&lt;/strong&gt; onto the canvas. That means workflows that fan out over lists, run independent steps concurrently, and call other workflows as reusable building blocks - all visually, no custom code. This closes out &lt;a href="https://github.com/bytechefhq/bytechef/issues/1057" rel="noopener noreferrer"&gt;issue #1057&lt;/a&gt;, one of the longest-running feature checklists in the ByteChef repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some GitHub issues are essays. &lt;a href="https://github.com/bytechefhq/bytechef/issues/1057" rel="noopener noreferrer"&gt;Issue #1057&lt;/a&gt; is a checklist:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;[x] condition&lt;/li&gt;
&lt;li&gt;[x] loop&lt;/li&gt;
&lt;li&gt;[x] each&lt;/li&gt;
&lt;li&gt;[x] branch&lt;/li&gt;
&lt;li&gt;[x] map&lt;/li&gt;
&lt;li&gt;[x] parallel&lt;/li&gt;
&lt;li&gt;[x] fork-join&lt;/li&gt;
&lt;li&gt;[x] subflow&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each of those checkboxes is a &lt;strong&gt;flow control&lt;/strong&gt; - what the workflow engine internally calls a &lt;em&gt;task dispatcher&lt;/em&gt;. A regular component does work: it sends the email, queries the database, calls the API. A task dispatcher never does work itself. It decides &lt;strong&gt;which tasks run, when, how many times, and with what data&lt;/strong&gt; - it directs traffic.&lt;/p&gt;

&lt;p&gt;We wrote about the first half of that checklist in &lt;a href="https://blog.bytechef.io/blogs/guide-to-flow-controls" rel="noopener noreferrer"&gt;our guide to flow controls&lt;/a&gt;: &lt;strong&gt;Condition&lt;/strong&gt; routes on true/false, &lt;strong&gt;Branch&lt;/strong&gt; picks one of several paths based on an expression, and &lt;strong&gt;Loop&lt;/strong&gt; repeats steps over a list. Those cover &lt;em&gt;decisions&lt;/em&gt; and &lt;em&gt;repetition&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This post is about the second half - the controls that cover &lt;strong&gt;concurrency&lt;/strong&gt; and &lt;strong&gt;composition&lt;/strong&gt;. They've been running behind a feature flag while we hardened them one checkbox at a time; with the list complete, the flag is going away and the full set is available to everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Sequential Isn't Always Enough
&lt;/h2&gt;

&lt;p&gt;Every workflow starts as a straight line: trigger, then step one, then step two. That's the right default - it's easy to reason about, and each step can use the output of the one before it.&lt;/p&gt;

&lt;p&gt;But real processes aren't always lines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Onboarding a customer means creating a CRM record, provisioning an account, &lt;em&gt;and&lt;/em&gt; notifying the sales channel - three things that don't depend on each other, so why wait?&lt;/li&gt;
&lt;li&gt;Enriching 200 leads one at a time takes 200× as long as enriching them all at once.&lt;/li&gt;
&lt;li&gt;Five different workflows all end with the same "notify the team" sequence, and you're tired of rebuilding it five times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two are concurrency problems. The third is a composition problem. Here's the control for each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallel: Independent Steps, All at Once
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Parallel&lt;/strong&gt; is the simplest of the new controls: give it a collection of tasks, and it runs them all concurrently without waiting for any of them to finish first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"parallel_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"parallel/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"createCrmRecord"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pipedrive/v1/createOrganization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"notifySales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"slack/v2/sendMessage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it when you have a &lt;em&gt;fixed set of different steps&lt;/em&gt; that don't depend on each other. The three-things-at-customer-onboarding case is exactly this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork/Join: Parallel Branches, Sequential Inside
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fork/Join&lt;/strong&gt; is Parallel's bigger sibling. Instead of a flat set of tasks, you define &lt;em&gt;branches&lt;/em&gt; - each branch is a sequence of tasks that runs in order, but the branches themselves run in parallel to each other, each as its own isolated sub-flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"forkJoin_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fork-join/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"branches"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fetchInvoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"summarizeInvoices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fetchTickets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"summarizeTickets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule of thumb: reach for &lt;strong&gt;Parallel&lt;/strong&gt; when each concurrent piece is a single step, and for &lt;strong&gt;Fork/Join&lt;/strong&gt; when each concurrent piece is itself a &lt;em&gt;pipeline&lt;/em&gt;. The "join" part means the workflow waits for every branch to finish before moving on, so the step after a Fork/Join can safely use results from all branches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Each and Map: Fan Out Over a List
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Loop&lt;/strong&gt; already iterates over a list - but sequentially, one item at a time, in order. &lt;strong&gt;Each&lt;/strong&gt; and &lt;strong&gt;Map&lt;/strong&gt; iterate over a list &lt;em&gt;in parallel&lt;/em&gt;: every item gets its own execution of the inner task at the same time.&lt;/p&gt;

&lt;p&gt;The difference between the two is what you get back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Each&lt;/strong&gt; is for side effects. It runs the task for every item and returns nothing. Order of completion isn't guaranteed - and for firing off 200 notification emails, it doesn't need to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"each_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"each/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"=leads"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"iteratee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sendFollowUp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gmail/v1/sendEmail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"=each_1.item.email"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Map&lt;/strong&gt; is for transformations. It also runs in parallel, but it &lt;em&gt;collects&lt;/em&gt; each item's result and returns them as a list - in an order that matches the source list, no matter which items finished first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"map_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"map/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"=range(1, 10)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"iteratee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enrich"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"=map_1.item"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the iteration, the current element is available as a data pill on the dispatcher itself - &lt;code&gt;each_1.item&lt;/code&gt;, &lt;code&gt;map_1.item&lt;/code&gt; - so inner steps can reference it like any other output.&lt;/p&gt;

&lt;p&gt;So the lead-enrichment case from earlier: 200 leads, enriched concurrently, results back in the original order, ready for the next step. That's Map.&lt;/p&gt;

&lt;p&gt;One honest footnote on the checklist: the &lt;em&gt;infinite loop&lt;/em&gt; variant (loop until a break condition, with no list at all) is the one box still open on #1057. Loop already supports a &lt;strong&gt;Loop Break&lt;/strong&gt; statement; the fully unbounded mode is still on the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subflow: Workflows Calling Workflows
&lt;/h2&gt;

&lt;p&gt;The controls above change &lt;em&gt;how&lt;/em&gt; tasks run. &lt;strong&gt;Subflow&lt;/strong&gt; changes &lt;em&gt;what counts as a task&lt;/em&gt;: it starts another workflow as a child job of the current one, passes it inputs, and hands the child's output back as the step's output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"subflow_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"subflow/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"workflowUuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"notify-the-team"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"channel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#ops"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"=map_1"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the composition problem solved: build "notify the team" once, with its own inputs, and call it from all five workflows. When it changes, it changes everywhere. Subflows show up in execution history as their own jobs, and the editor knows how to &lt;a href="https://blog.bytechef.io/blogs/building-subflow-navigation" rel="noopener noreferrer"&gt;navigate into them&lt;/a&gt; so you can follow the chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which One Do I Reach For?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You want to…&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Repeat steps over a list, one at a time, in order&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Loop&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run a task for every item at once, no results needed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Each&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transform every item at once and keep the results, in order&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Map&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run a fixed set of independent single steps concurrently&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Parallel&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run several multi-step pipelines concurrently, then continue&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fork/Join&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reuse another workflow as a step&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Subflow&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Take one of two paths based on true/false&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Condition&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Take one of many paths based on a value&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Branch&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two quick heuristics cover most decisions: &lt;em&gt;per-item vs. fixed set&lt;/em&gt; (Each/Map/Loop iterate over data; Parallel/Fork-Join run a structure you defined), and &lt;em&gt;results vs. side effects&lt;/em&gt; (Map collects, Each doesn't).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a Feature Flag, and Why It's Leaving
&lt;/h2&gt;

&lt;p&gt;The workflow engine has been able to dispatch all of these for a while - the engine side of a task dispatcher is comparatively contained. The long tail was the &lt;strong&gt;editor&lt;/strong&gt;. Every flow control is a nested structure on the canvas: it owns child tasks, those children need placeholders, drag-and-drop targets, correct auto-layout, and data pills that respect iteration scope. Getting Condition right taught us how much surface area each control adds, so we didn't ship the rest as one big drop.&lt;/p&gt;

&lt;p&gt;Instead, the remaining controls went in behind a feature flag (&lt;code&gt;ff-1057&lt;/code&gt;, named after the issue), which let us enable them incrementally, polish the rough edges. With every control now holding up in real workflows, the flag is being removed and the complete set becomes the default for every ByteChef instance - cloud and self-hosted.&lt;/p&gt;

&lt;p&gt;If your workflows have been running in a single lane, &lt;a href="https://app.bytechef.io/" rel="noopener noreferrer"&gt;give the new controls a try&lt;/a&gt; - the fastest way to feel the difference is to take an existing Loop over an independent list of items and swap it for a Map.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>bytechef</category>
      <category>agents</category>
    </item>
    <item>
      <title>Stop the Workflow, Ask a Human: Human-in-the-Loop Approvals in ByteChef</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Thu, 13 Aug 2026 15:20:34 +0000</pubDate>
      <link>https://dev.to/bytechef/stop-the-workflow-ask-a-human-human-in-the-loop-approvals-in-bytechef-1hbf</link>
      <guid>https://dev.to/bytechef/stop-the-workflow-ask-a-human-human-in-the-loop-approvals-in-bytechef-1hbf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; ByteChef's &lt;strong&gt;Approval component&lt;/strong&gt; pauses a running workflow until a person approves or rejects, optionally filling in a form whose answers flow straight into the next steps. Delivery is pluggable: Slack (with inline Approve/Discard buttons), Gmail, Outlook, Discord, Telegram, WhatsApp, and more - or ByteChef's new &lt;strong&gt;in-app Approval Tasks inbox&lt;/strong&gt;. The approver clicks a signed link and needs no ByteChef account, and the workflow waits up to 60 days without holding a thread - &lt;strong&gt;human-in-the-loop (HITL)&lt;/strong&gt;, with no infrastructure of your own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You build a workflow, and it runs beautifully - right up to the step you don't actually want it to run on its own. Issue the refund? Create the customer account? Book the leave?&lt;/p&gt;

&lt;p&gt;Some steps shouldn't happen without a human's yes. What you want is simple to say: the workflow pauses, the right person gets pinged where they already work, they approve - maybe fill in a couple of fields - and the workflow picks up exactly where it stopped, with their answer in hand.&lt;/p&gt;

&lt;p&gt;That pattern has a name - &lt;strong&gt;human-in-the-loop (HITL)&lt;/strong&gt; - and in ByteChef it's the &lt;strong&gt;Approval component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you've read our use-case tutorials, you've already met it without an introduction. The &lt;a href="https://blog.bytechef.io/blogs/automating-kyc-compliance-building-a-smart-onboarding-workflow-in-bytechef" rel="noopener noreferrer"&gt;KYC compliance workflow&lt;/a&gt; gates onboarding on a compliance officer's review. The &lt;a href="https://blog.bytechef.io/blogs/building-liferay-integrations-in-bytechef" rel="noopener noreferrer"&gt;Liferay onboarding workflow&lt;/a&gt; waits for a manager to fill in account details. &lt;a href="https://blog.bytechef.io/blogs/pto-elf" rel="noopener noreferrer"&gt;PTO Elf&lt;/a&gt; holds leave requests for sign-off.&lt;/p&gt;

&lt;p&gt;In each of those, approval was a supporting actor: "add an approval task here" and the tutorial moved on. This post is the missing introduction - what you configure, what your approver sees, and what the platform quietly does for you in between.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding an Approval Step
&lt;/h2&gt;

&lt;p&gt;In the workflow editor, Approval is one component with one action: &lt;strong&gt;Request Approval&lt;/strong&gt;. The minimal setup is no setup at all - leave everything blank and your approver simply gets Approve and Reject buttons.&lt;/p&gt;

&lt;p&gt;Usually, you'll give it a form title, a description, and a list of form inputs. The form builder supports thirteen field types: text, textarea, number, email, password, checkbox, radio, select, date and datetime pickers, file upload, hidden fields, and raw custom HTML for anything else.&lt;/p&gt;

&lt;p&gt;Each field carries the knobs you'd expect from a form builder: a label and description, a placeholder, a default value, and a required flag. Radio and select fields take label/value options, and a select can allow multiple choices with a minimum and maximum selection count.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Approver's Answers Become Data Pills
&lt;/h2&gt;

&lt;p&gt;Here's the part that makes forms genuinely useful downstream: the approval step's output schema is generated from the fields you configure.&lt;/p&gt;

&lt;p&gt;Add an &lt;code&gt;accountName&lt;/code&gt; text field and a &lt;code&gt;creditLimit&lt;/code&gt; number field, and the step's output is &lt;code&gt;{approved: boolean, accountName: string, creditLimit: number}&lt;/code&gt;. Every one of those shows up as a data pill for the steps that follow.&lt;/p&gt;

&lt;p&gt;That's how the Liferay tutorial creates an account "from the information received from the onboarding approval task" - the approver's answers are just the step's output, referenced like any other: &lt;code&gt;${approval_1.accountName}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Approver Finds Out
&lt;/h2&gt;

&lt;p&gt;A paused workflow is useless if nobody knows it's waiting. That's what &lt;strong&gt;approval channels&lt;/strong&gt; are for - delivery mechanisms you attach to the approval step, right under the node's Channels port.&lt;/p&gt;

&lt;p&gt;Most channels deliver the approval link to people &lt;em&gt;outside&lt;/em&gt; ByteChef - a manager who has never opened the app and never will. Pick where your approvers already live: &lt;strong&gt;Slack&lt;/strong&gt;, &lt;strong&gt;Gmail&lt;/strong&gt;, &lt;strong&gt;Outlook 365&lt;/strong&gt;, plain &lt;strong&gt;Email&lt;/strong&gt; (SMTP), &lt;strong&gt;Discord&lt;/strong&gt;, &lt;strong&gt;Telegram&lt;/strong&gt;, &lt;strong&gt;WhatsApp&lt;/strong&gt;, &lt;strong&gt;Twilio&lt;/strong&gt; (SMS), &lt;strong&gt;Mattermost&lt;/strong&gt;, &lt;strong&gt;Rocket.Chat&lt;/strong&gt;, &lt;strong&gt;Infobip&lt;/strong&gt;, or the embeddable &lt;strong&gt;Chat&lt;/strong&gt; widget. Each uses its own connection.&lt;/p&gt;

&lt;p&gt;The Slack channel has my favorite detail. If your approval has no form fields, there's no reason to send anyone to a web page, so it doesn't. Approvers get &lt;strong&gt;Approve&lt;/strong&gt; and &lt;strong&gt;Discard&lt;/strong&gt; buttons right in the Slack message, and the approval resolves without leaving the chat. If there &lt;em&gt;is&lt;/em&gt; a form, the message carries a single "Open Approval Form" button instead.&lt;/p&gt;

&lt;p&gt;One channel is different: &lt;strong&gt;Approval Task&lt;/strong&gt;. Instead of sending the link out, it creates a task &lt;em&gt;inside&lt;/em&gt; ByteChef, on the new &lt;strong&gt;Approval Tasks&lt;/strong&gt; page - an approval inbox for teams that live in the app.&lt;/p&gt;

&lt;p&gt;Each task has a status (open, in progress, completed), a priority, an assignee, and a due date, and the page supports filtering, search, and sorting. If your approvers are ByteChef users, their pending approvals queue up in one place instead of scattering across inboxes.&lt;/p&gt;

&lt;p&gt;One small courtesy across all channels: they're skipped when the step runs inside the workflow editor's test mode, so testing a workflow doesn't spam your approvers.&lt;/p&gt;

&lt;p&gt;And because channels are plug-ins (cluster elements) rather than baked-in integrations, the delivery list can grow without touching the Approval component itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Approver Experiences
&lt;/h2&gt;

&lt;p&gt;Your approver clicks a link and lands on a form page: title, description, fields, and environment badge. No login, no account, no "first, install ByteChef" - which is the point, because the person approving is often exactly the person who'd never log in.&lt;/p&gt;

&lt;p&gt;That works because the link itself is the credential. The token in the URL wraps the approval's identity in an HMAC signature, so it can't be guessed or forged - the same trust model as any webhook callback. Possessing the link &lt;em&gt;is&lt;/em&gt; the authorization.&lt;/p&gt;

&lt;p&gt;A link is good for exactly one decision. Once the approval is submitted - or the 60-day window passes - the link answers &lt;code&gt;410 Gone&lt;/code&gt;, so a stale email can't resurrect a settled question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meanwhile, the Workflow Waits
&lt;/h2&gt;

&lt;p&gt;While your approver takes their time, what is the workflow doing? Nothing - and that's the engineering trick worth knowing about.&lt;/p&gt;

&lt;p&gt;The approval action doesn't block a thread, poll a flag, or sleep. It registers a suspension with the engine and returns; the engine parks the execution, persists everything, and releases the worker. The workflow can stay parked for up to 60 days; the server can restart, redeploy, or scale to zero in the meantime. Nothing waits in memory.&lt;/p&gt;

&lt;p&gt;When the approver submits, the engine re-enters the action through a second entry point with the submitted data, and the workflow resumes exactly where it stopped - the form answers flattened into the output schema those data pills promised.&lt;/p&gt;

&lt;p&gt;Long-time users might remember the old ways of doing this: a dedicated &lt;code&gt;wait-for-approval&lt;/code&gt; flow control and a &lt;code&gt;Create Approval Links&lt;/code&gt; action that handed out bare approve/reject URLs. Both are now deprecated, because a flow control can pause but it can't &lt;em&gt;be a component&lt;/em&gt; - with a form builder, a typed output, delivery channels, and one more trick below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming Next: The Same Step, Inside an AI Agent
&lt;/h2&gt;

&lt;p&gt;Human-in-the-loop matters most where the human is easiest to lose: AI agents. An autonomous agent is exactly as trustworthy as its worst tool call, and "pause and ask a person" is the simplest guardrail there is.&lt;/p&gt;

&lt;p&gt;The suspend-and-resume machinery above is exactly what an agent needs, so we're working on exposing Approval as a &lt;strong&gt;tool&lt;/strong&gt; you can hand to a ByteChef AI agent: the agent decides it needs sign-off, composes the form, calls the tool, and the whole agent conversation parks until a human answers. From the model's perspective, it asked a tool a question and the tool answered - it just took a day and a half.&lt;/p&gt;

&lt;p&gt;It's not in today's build - we'd rather ship it solid than early - but it's close, and it lands in one of the next releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  When You'd Reach for It
&lt;/h2&gt;

&lt;p&gt;The use-case posts each show one pattern, and they generalize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gate&lt;/strong&gt;: Nothing proceeds without a yes/no compliance review before account creation (KYC) or manager sign-off before booking PTO. No form fields needed; Slack buttons suffice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate with input&lt;/strong&gt;: the approver doesn't just consent; they &lt;em&gt;contribute&lt;/em&gt; - the Liferay onboarding manager supplies the account name and description the next step uses to create the account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Threshold escalation&lt;/strong&gt;: the workflow handles the routine cases on its own and branches into an approval only for the consequential ones - refunds over a limit, contract changes, anything you'd want a human to see before it happens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to see approval in a full workflow, the &lt;a href="https://blog.bytechef.io/blogs/automating-kyc-compliance-building-a-smart-onboarding-workflow-in-bytechef" rel="noopener noreferrer"&gt;KYC compliance&lt;/a&gt; and &lt;a href="https://blog.bytechef.io/blogs/building-liferay-integrations-in-bytechef" rel="noopener noreferrer"&gt;Liferay onboarding&lt;/a&gt; posts both build one end-to-end, and now you know what's happening under the pause.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>bytechef</category>
      <category>agents</category>
    </item>
    <item>
      <title>See What Your Workflow Was Thinking: Surfacing Component Logs in ByteChef</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Fri, 07 Aug 2026 19:55:03 +0000</pubDate>
      <link>https://dev.to/bytechef/see-what-your-workflow-was-thinking-surfacing-component-logs-in-bytechef-362</link>
      <guid>https://dev.to/bytechef/see-what-your-workflow-was-thinking-surfacing-component-logs-in-bytechef-362</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; ByteChef's &lt;strong&gt;Logger component&lt;/strong&gt; could always write log messages - but they vanished into the server console, where workflow builders could never see them. We fixed that by capturing log calls at the layer &lt;em&gt;every&lt;/em&gt; component passes through, storing them per execution, and exposing them in a new &lt;strong&gt;Logs tab&lt;/strong&gt; in both the workflow builder and the execution history. Every component's logs - not just Logger's - now show up next to the step's Input and Output, with level badges, JSON pretty-printing, and expandable stack traces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every automation platform eventually gets this ticket. Ours was &lt;a href="https://github.com/bytechefhq/bytechef/issues/2896" rel="noopener noreferrer"&gt;issue #2896&lt;/a&gt;, and it was refreshingly short:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As a Workflow Developer, I want to see logs from the Logger component in the workflow builder and workflow executions, so that I can see details of how my workflows are executing.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ByteChef has had a &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;Logger component&lt;/a&gt; for a long time. You drop it between two steps, give it a message - usually with a few data pills in it - and pick a level: &lt;strong&gt;Debug&lt;/strong&gt;, &lt;strong&gt;Info&lt;/strong&gt;, &lt;strong&gt;Warn&lt;/strong&gt;, or &lt;strong&gt;Error&lt;/strong&gt;. That's the whole component.&lt;/p&gt;

&lt;p&gt;The problem: the message went to the server log and nowhere else. If you self-hosted ByteChef and had shell access, you could tail the server log and find it. If you were a workflow builder working in the UI - the person the Logger component exists for - it went into a void. The component technically worked and was practically useless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deciding Where to Capture
&lt;/h2&gt;

&lt;p&gt;The obvious fix would have been to special-case the Logger component: make it return its message as step output, or write to some Logger-specific store. We went a different way, and it's the decision the whole feature hangs on.&lt;/p&gt;

&lt;p&gt;Every component action in ByteChef receives an execution context, and that context's logging method is the sanctioned way for &lt;em&gt;any&lt;/em&gt; component to log - the HTTP client logs request failures, Script components log from user code, AI components log token usage warnings. All of those messages were equally invisible.&lt;/p&gt;

&lt;p&gt;So instead of touching the Logger component at all, we instrumented the logging implementation inside the component context - the single funnel that every log call in every component already passes through. Each message still goes to the server log like before, but now it also becomes a structured entry: timestamp, level, component name, operation, the step it came from, the message, and - when there is one - the exception type, message, and stack trace.&lt;/p&gt;

&lt;p&gt;Because the capture point sits below every component, the feature ships for all 180+ components at once. The Logger component didn't change by a single line. It just became visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing Logs: One File per Execution
&lt;/h2&gt;

&lt;p&gt;Logs are append-heavy, read-rarely data with an obvious partition key: the job - a single workflow execution. That ruled out a database table. We didn't want every workflow run inserting rows into PostgreSQL for data that's mostly never queried.&lt;/p&gt;

&lt;p&gt;Instead, each job gets one file in ByteChef's existing file-storage abstraction, which means logs land wherever your deployment already puts files - the filesystem, a database blob, or S3-compatible storage. The format is JSON Lines: one JSON object per line, so appending an entry is just serialize-and-append.&lt;/p&gt;

&lt;p&gt;Two properties of the writer matter more than they look.&lt;/p&gt;

&lt;p&gt;First, &lt;strong&gt;writes are asynchronous&lt;/strong&gt;. Logging must never slow down the workflow itself - a component that logs five times shouldn't pay five rounds of storage I/O on the execution path. Java 25's virtual threads make that fire-and-forget pattern nearly free.&lt;/p&gt;

&lt;p&gt;Second, &lt;strong&gt;the read path is guarded by the same permission model as everything else that touches executions&lt;/strong&gt;. Logs frequently contain payload data - that's the point of logging them - so they inherit the exact visibility rules of the execution they belong to. If you can't see the run, you can't see its logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Environments, Two Pipelines
&lt;/h2&gt;

&lt;p&gt;There's a wrinkle: ByteChef has two kinds of "execution". There are &lt;strong&gt;production runs&lt;/strong&gt; of deployed workflows, and there are &lt;strong&gt;test runs&lt;/strong&gt; you trigger with the Test button while building a workflow in the editor. Test runs are ephemeral - their logs shouldn't accumulate in long-term storage next to production history.&lt;/p&gt;

&lt;p&gt;So the feature is split down the middle. Production runs write to the long-term log area and are served to the execution history view. Editor runs write to a separate area with their own cleanup, served by a parallel query. The context factory decides which writer a component gets based on which environment it's running in, and the client picks the matching query. Same UI, same log format, different lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Read API
&lt;/h2&gt;

&lt;p&gt;The read API is GraphQL, matching where the rest of ByteChef's newer client-server surface has been heading. It supports pagination and filtering from day one: minimum level, component name, a specific step, a time range, and free-text search.&lt;/p&gt;

&lt;p&gt;The per-step filter is what powers the most-used view: click a node in the execution panel, and you see only that step's logs. Look at the job as a whole, and you see everything, with a small component-name chip on each row so you can tell who said what.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Logs Tab
&lt;/h2&gt;

&lt;p&gt;On the client, the execution detail panel - the one with &lt;strong&gt;Input&lt;/strong&gt; and &lt;strong&gt;Output&lt;/strong&gt; tabs you get when you click a step - gains a third tab: &lt;strong&gt;Logs&lt;/strong&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%2Fblog.bytechef.io%2F_next%2Fimage%3Furl%3D%252Fblogs%252Fsurfacing-workflow-execution-logs%252Flogs-tab.png%26w%3D3840%26q%3D75" 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%2Fblog.bytechef.io%2F_next%2Fimage%3Furl%3D%252Fblogs%252Fsurfacing-workflow-execution-logs%252Flogs-tab.png%26w%3D3840%26q%3D75" alt="Alt Text" width="3010" height="2020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a real run above - and it's worth noting whose log you're looking at. The workflow has a Logger component in it, sitting right there in the graph on the right. But the entry on screen came from the &lt;strong&gt;OpenAI&lt;/strong&gt; step, which logged its outgoing request without anyone asking it to. That's the capture-one-layer-down decision paying off in a screenshot: the component that made the ticket necessary isn't even the one being shown.&lt;/p&gt;

&lt;p&gt;Each row shows a timestamp, a colored level badge (blue &lt;code&gt;INFO&lt;/code&gt;, purple &lt;code&gt;DEBUG&lt;/code&gt;, yellow &lt;code&gt;WARN&lt;/code&gt;, red &lt;code&gt;ERROR&lt;/code&gt;), and the message. Two small touches make it feel finished rather than bolted on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON detection.&lt;/strong&gt; People constantly log entire objects - dumping a payload into a log line is a very common debugging move. If a message parses as JSON, the tab renders it with the same collapsible tree viewer we use for step outputs, instead of an unreadable one-liner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expandable errors.&lt;/strong&gt; When an entry carries exception details, the row becomes clickable and expands into the exception type, message, and full stack trace - so a failed step's story is readable in place, without asking an operator to grep the server log for you.&lt;/p&gt;

&lt;p&gt;And because the editor pipeline exists, the same tab appears in the workflow builder's test output panel. Run a workflow with the Test button, click a step, open Logs - the feedback loop that issue #2896 asked for, closed.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Layer Down
&lt;/h2&gt;

&lt;p&gt;The lesson we're taking from this one: when a ticket says "make the Logger component's output visible", the right fix might be one layer down. By instrumenting the context instead of the component, a request about one component became execution-level observability for every component in the platform - including the ones we haven't built yet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>bytechef</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Intelligent Automation with ByteChef and AI Agents</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Tue, 16 Jun 2026 17:46:21 +0000</pubDate>
      <link>https://dev.to/bytechef/building-intelligent-automation-with-bytechef-and-ai-agents-1bg5</link>
      <guid>https://dev.to/bytechef/building-intelligent-automation-with-bytechef-and-ai-agents-1bg5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; ByteChef's AI Agent is a visual, no-code building block for agentic workflows, powered by Spring AI under the hood. It's composed of five cluster elements: a &lt;strong&gt;Model&lt;/strong&gt;, &lt;strong&gt;RAG&lt;/strong&gt;, &lt;strong&gt;Memory&lt;/strong&gt;, &lt;strong&gt;Tools&lt;/strong&gt;, and &lt;strong&gt;Guardrails&lt;/strong&gt;. And you don't build blind — the editor's &lt;strong&gt;Agent Playbook&lt;/strong&gt; lets you test the agent live as you configure it. Together, they give you everything needed to build production-grade AI agents without writing your own AI infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Artificial intelligence is supported for every programming language nowadays. With the right tools, every developer can embed intelligent behavior directly into their workflows and automations. ByteChef's &lt;strong&gt;AI Agent&lt;/strong&gt; component makes this possible by integrating deeply with &lt;a href="https://spring.io/projects/spring-ai" rel="noopener noreferrer"&gt;Spring AI&lt;/a&gt;, the leading Java framework for building AI-powered applications. Exposing it through a visual, no-code/low-code interface.&lt;/p&gt;

&lt;p&gt;In this post, we'll walk through how ByteChef's AI Agent is structured, what each of its cluster elements does, and how Spring AI powers it all under the hood.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the AI Agent Component?
&lt;/h2&gt;

&lt;p&gt;The AI Agent is ByteChef's core building block for agentic workflows. Rather than making a single call to a language model, an AI Agent can: reason, retrieve context, remember past interactions, call external tools, and even delegate to other agents. It is capable of handling complex, multi-step tasks.&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%2F6rcm82zl8zo1g0h5dw7o.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%2F6rcm82zl8zo1g0h5dw7o.png" alt="AI Agent Component" width="484" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI Agent is composed of a set of &lt;strong&gt;cluster elements&lt;/strong&gt;: configurable sub-components that each handle a specific aspect of agentic behavior. These are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt; - the language model powering the agent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAG&lt;/strong&gt; - retrieval-augmented generation for grounding responses in your data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt; - persistence of conversation history across turns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt; - actions the agent can do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails&lt;/strong&gt; - filters for safe and appropriate responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's explore each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Model
&lt;/h2&gt;

&lt;p&gt;The model is the brain of the AI Agent. It defines which LLM receives prompts, thinks and generates responses. Spring AI provides a unified &lt;code&gt;ChatModel&lt;/code&gt; abstraction that normalizes communication across many different LLM providers, so ByteChef can support a wide range of models without changing the underlying agent logic.&lt;/p&gt;

&lt;p&gt;ByteChef currently supports the following models, all integrated through Spring AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Bedrock Converse&lt;/strong&gt; - access to AWS-hosted models including Anthropic Claude, Meta Llama, and more via a unified AWS API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic&lt;/strong&gt; - Claude models, known for their strong instruction-following and reasoning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure OpenAI&lt;/strong&gt; - OpenAI models deployed on Microsoft Azure infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek&lt;/strong&gt; - high-performance models with strong coding and reasoning capabilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vertex Gemini&lt;/strong&gt; - Google's Gemini models via Google Cloud's Vertex AI platform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Groq&lt;/strong&gt; - ultra-fast inference for open-source models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mistral AI&lt;/strong&gt; - efficient, open-weight European models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NVIDIA&lt;/strong&gt; - models served via NVIDIA's NIM inference platform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; - open-source models locally with no cloud dependency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perplexity&lt;/strong&gt; - models with built-in web search and citation capabilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI&lt;/strong&gt; - OpenAI models deployed by OpenAI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to these Spring AI-backed providers, ByteChef also supports &lt;strong&gt;OpenRouter&lt;/strong&gt;, a gateway that aggregates hundreds of models from dozens of providers under a single API. This means that even if your preferred model isn't in the list above, there's a very good chance you can still connect to it through OpenRouter. This makes ByteChef's AI Agent one of the most model-versatile automation platforms available.&lt;/p&gt;




&lt;h2&gt;
  
  
  RAG (Retrieval-Augmented Generation)
&lt;/h2&gt;

&lt;p&gt;Language models are powerful, but they only know what they were trained on. If you want your agent to answer questions about your internal documents, product catalog, support tickets, or any proprietary data, you need &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;RAG works by searching a knowledge source for documents relevant to the user's query, then injecting that context into the prompt before the model generates a response. Spring AI provides a rich, modular RAG architecture that ByteChef exposes directly in the AI Agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vector Store Providers
&lt;/h3&gt;

&lt;p&gt;To perform semantic search, documents are embedded into high-dimensional vectors and stored in a vector database. ByteChef supports the following vector stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Couchbase&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MariaDB&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Milvus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neo4j&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oracle&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PostgreSQL (pgvector)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pinecone&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Knowledge Base
&lt;/h3&gt;

&lt;p&gt;Don't want to set up your own vector database? ByteChef also offers a built-in &lt;strong&gt;Knowledge Base&lt;/strong&gt; — an internal, managed knowledge store where you can upload documents (PDFs, text files, and more) directly. ByteChef handles the chunking, embedding, and storage automatically, so you can start building RAG-powered agents without configuring any external infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  RAG Strategies
&lt;/h3&gt;

&lt;p&gt;Spring AI supports two RAG approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;QuestionAnswerAdvisor&lt;/strong&gt; is Spring AI's out-of-the-box RAG implementation. When a query comes in, it performs a similarity search against the vector store, retrieves the most relevant documents, and appends them to the prompt as context before the model responds. It supports configurable similarity thresholds, top-K result limits, and dynamic filter expressions so you can scope searches to specific subsets of your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modular RAG&lt;/strong&gt; is based on Spring AI's &lt;code&gt;RetrievalAugmentationAdvisor&lt;/code&gt; and inspired by the research paper &lt;em&gt;"Modular RAG: Transforming RAG Systems into LEGO-like Reconfigurable Frameworks."&lt;/em&gt; Instead of a fixed pipeline, it lets you assemble a RAG flow from individual building blocks, each responsible for one well-defined step. ByteChef exposes the following modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query Transformers&lt;/strong&gt; - applied &lt;strong&gt;before&lt;/strong&gt; retrieval to reshape the user's query into something that retrieves better results:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compression&lt;/strong&gt; - condenses a long conversation history and a follow-up question into a single standalone query, so the retriever receives focused input rather than a wall of chat context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rewrite&lt;/strong&gt; - rewrites verbose, ambiguous, or poorly structured queries into a cleaner form that maps more accurately to the content in your knowledge source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translation&lt;/strong&gt; - translates the query into the language of your documents, enabling cross-lingual retrieval without requiring your data to be multilingual.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi Query Expander&lt;/strong&gt; - uses a language model to expand the original query into multiple semantically diverse variations, each capturing a different angle or phrasing of the user's intent. Documents are retrieved for all variations in parallel, increasing the chances of surfacing relevant results that a single query might miss. Any model available in ByteChef can be used to power the expansion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Retriever&lt;/strong&gt; - the step where documents are actually fetched from a vector store using semantic similarity search. You can select any of the vector stores ByteChef supports (Couchbase, MariaDB, Milvus, Neo4j, Oracle, PostgreSQL, or Pinecone), or point it at the built-in Knowledge Base.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Joiner&lt;/strong&gt; - when multiple queries or multiple data sources are involved, this module merges all retrieved document sets into a single, deduplicated collection. Duplicate documents are resolved by keeping the first occurrence; relevance scores are preserved as-is from the retriever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contextual Query Augmenter&lt;/strong&gt; - enriches the user's query with contextual information extracted from the retrieved documents before it is sent to the model. This helps the model produce more grounded, contextually aware responses.
Together, these modules let you design a RAG pipeline tailored to your data and use case — from a simple single-retriever setup to a multi-source, multi-query flow with query rewriting and context augmentation — without writing any retrieval infrastructure yourself.
---&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Memory
&lt;/h2&gt;

&lt;p&gt;A single question-and-answer interaction is useful, but many real-world use cases require the agent to maintain context across a conversation. Remembering what was said earlier, tracking user preferences, or picking up where a previous session left off are what &lt;strong&gt;Memory&lt;/strong&gt; provides.&lt;/p&gt;

&lt;p&gt;Spring AI's &lt;code&gt;ChatMemory&lt;/code&gt; abstraction handles storing and retrieving conversation history. ByteChef exposes multiple memory backend options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External memory providers&lt;/strong&gt; - for durable, production-grade memory that persists across sessions and scales with your application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cassandra&lt;/li&gt;
&lt;li&gt;Cosmos DB&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;Neo4j&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;Oracle&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, all vector stores supported for RAG (Couchbase, MariaDB, Milvus, Neo4j, Oracle, PostgreSQL, Pinecone) can also serve as memory backends, enabling semantic retrieval of past conversation turns rather than just chronological lookups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;InMemory Chat Memory&lt;/strong&gt; is a lightweight option that stores conversation history in a simple HashMap in application memory. It requires no external setup and works great for development, testing, or short-lived sessions — but the history is wiped when the chat session ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chat Memory&lt;/strong&gt; (ByteChef's internal store) is the managed alternative to external providers. Like the Knowledge Base for RAG, it lets you persist conversation history without configuring a separate database. ByteChef handles the storage backend for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;One of the defining features of an AI agent is its ability to &lt;em&gt;act&lt;/em&gt;. Tools let the AI Agent go beyond generating text and actually interact with external systems: querying databases, sending emails, creating records, calling APIs, and more.&lt;/p&gt;

&lt;p&gt;ByteChef's tool support is one of its most powerful differentiators, and it comes in several forms:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component Actions&lt;/strong&gt; - ByteChef integrates with over 200 applications and services through its component library (think Slack, GitHub, Salesforce, Google Sheets, HubSpot, and many more). Any action within any component can be exposed to the AI Agent as a tool. When configuring a tool, you choose which properties the AI should determine dynamically based on context, and which ones are fixed constants — so you stay in full control of what the agent can and cannot change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Tool&lt;/strong&gt; - ByteChef supports the &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt;, an emerging open standard for exposing tools to AI models. The MCP Tool cluster element lets the agent connect to any compatible MCP server and use its tools, opening up the ecosystem beyond ByteChef's built-in integrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills Tool&lt;/strong&gt; - ByteChef supports the concept of &lt;em&gt;Skills&lt;/em&gt;: reusable, self-contained packages of instructions and files that you build once and reuse across agents. The Skills Tool cluster element lets the agent invoke any Skill available in your ByteChef workspace. (More on creating and managing Skills later in this post.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Agent as a Tool&lt;/strong&gt; - the most powerful option of all: an AI Agent can use &lt;em&gt;another AI Agent&lt;/em&gt; as a tool. It's important enough that it gets its own section below.&lt;/p&gt;




&lt;h2&gt;
  
  
  Guardrails
&lt;/h2&gt;

&lt;p&gt;Guardrails are ByteChef's own layer of control on top of the Spring AI-powered capabilities. While the other cluster elements are about making the agent smarter and more capable, Guardrails are about keeping it appropriate and safe.&lt;/p&gt;

&lt;p&gt;Guardrails can be configured to inspect both incoming requests and outgoing responses. Common use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content filtering&lt;/strong&gt; - blocking or censoring sensitive, inappropriate, or offensive words and phrases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Topic restrictions&lt;/strong&gt; - preventing the agent from discussing subjects outside its intended scope&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance controls&lt;/strong&gt; - ensuring responses don't contain regulated or legally sensitive information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike the other cluster elements, Guardrails are a ByteChef-native feature, not part of Spring AI. They sit as a wrapper around the agent interaction, giving you a transparent enforcement layer regardless of which model, RAG strategy, or memory backend you've chosen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Skills: Build Once, Reuse Across Agents
&lt;/h2&gt;

&lt;p&gt;The Tools section introduced the &lt;strong&gt;Skills Tool&lt;/strong&gt;, which lets an agent &lt;em&gt;call&lt;/em&gt; a Skill. But where do Skills come from? ByteChef includes a dedicated &lt;strong&gt;Skills&lt;/strong&gt; area for building and maintaining them, so a capability you define once becomes available to every agent in your workspace.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Skill&lt;/strong&gt; is a self-contained, reusable package of instructions and supporting files — essentially a &lt;code&gt;.skill&lt;/code&gt; archive built around a primary &lt;code&gt;SKILL.md&lt;/code&gt; (the instructions, with optional frontmatter metadata) plus any extra files it needs. Each Skill has a name and a description, and once it lives in your workspace, any number of agents can invoke it through the Skills Tool. Build the capability once; reuse it everywhere.&lt;/p&gt;

&lt;p&gt;There are three ways to create one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write instructions&lt;/strong&gt; - give the Skill a name and description, then write what it should do in plain text. ByteChef packages it for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload a &lt;code&gt;.skill&lt;/code&gt; file&lt;/strong&gt; - drag in a pre-built Skill archive, handy for moving a Skill between workspaces or sharing it with teammates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create with AI&lt;/strong&gt; - describe what you want ("a skill that summarizes my Gmail every morning") and let Copilot draft the Skill's structure and content for you.&lt;/li&gt;
&lt;/ul&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%2Fks5a7lqfpntobux8t4mt.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%2Fks5a7lqfpntobux8t4mt.png" alt="Skills: Build Once, Reuse Across Agents" width="800" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once created, a Skill opens in a built-in editor: a file tree on the left, and a dual-mode view that toggles between a &lt;strong&gt;source&lt;/strong&gt; editor (Monaco, with syntax highlighting for Markdown, Python, JavaScript, YAML, JSON, and more) and a &lt;strong&gt;Markdown preview&lt;/strong&gt; for &lt;code&gt;.md&lt;/code&gt; files. You can edit any file in the Skill, save your changes, &lt;strong&gt;download&lt;/strong&gt; the Skill as a &lt;code&gt;.skill&lt;/code&gt; archive to share, or delete it.&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%2F8y68ml8ss7bxe001n76d.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%2F8y68ml8ss7bxe001n76d.png" alt="Skill opens in a built-in editor:" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because Skills are decoupled from any single agent, they become a shared library of capabilities for your whole workspace: capture a procedure or a piece of know-how once, then wire it into as many agents as you like through the Skills Tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Agents as Tools: Multi-Agent Systems
&lt;/h2&gt;

&lt;p&gt;Perhaps the most powerful tool an AI Agent can use is &lt;em&gt;another AI Agent&lt;/em&gt;. Because the AI Agent is itself a cluster-element building block, you can configure a second agent — complete with its own model, RAG, memory, tools, and guardrails — as a tool for the current agent to call.&lt;/p&gt;

&lt;p&gt;This is the foundation for building &lt;strong&gt;agentic patterns&lt;/strong&gt; such as orchestrator/subagent hierarchies, where a supervisor agent breaks a complex request into parts and delegates each one to a specialized sub-agent — a research agent, a drafting agent, a data-lookup agent — each tuned for its own job. The supervisor decides which sub-agent to call and when, then combines their results into a final answer.&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%2F11r3knk4wrpuhjt5m0mi.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%2F11r3knk4wrpuhjt5m0mi.png" alt="AI Agents as Tools: Multi-Agent Systems" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the composition is recursive — agents calling agents, which can in turn call their own sub-agents — there's no artificial ceiling on how sophisticated the system can get. That recursive composability is what makes ByteChef's AI Agent a genuine platform for multi-agent systems, not just a runtime for a single agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;The power of ByteChef's AI Agent comes from how these cluster elements combine. A production-grade agent might use:&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%2F9ft21mohozj2mdzcayiq.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%2F9ft21mohozj2mdzcayiq.png" alt="Putting It All Together" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI GPT-4o&lt;/strong&gt; as the model for strong reasoning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular RAG&lt;/strong&gt; with a Pinecone vector store to ground answers in internal documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL memory&lt;/strong&gt; to remember past conversations per user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component actions&lt;/strong&gt; to create CRM records, send notifications, or update spreadsheets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails&lt;/strong&gt; to ensure every response is appropriate for the audience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because ByteChef is built on Spring AI, you benefit from a well-maintained, actively developed foundation that keeps pace with the rapidly evolving AI ecosystem, new models, new vector stores, and new capabilities get integrated continuously.&lt;/p&gt;

&lt;p&gt;Whether you're building a customer support agent, an internal knowledge assistant, a data processing pipeline, or a complex multi-agent system, ByteChef's AI Agent gives you the building blocks to do it without needing to write your own AI infrastructure from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Your Agent as You Build It
&lt;/h2&gt;

&lt;p&gt;Assembling an agent is only half the job — you also need to know it behaves the way you expect before it ever touches a real workflow. ByteChef bakes this in. The AI Agent editor is a &lt;strong&gt;split view&lt;/strong&gt;: your configuration sits on the left, and an interactive testing panel — the &lt;strong&gt;Agent Playbook&lt;/strong&gt; — sits on the right. You build and test side by side, without ever switching screens.&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%2Fwxsn4zmhf7fpxj2pddb1.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%2Fwxsn4zmhf7fpxj2pddb1.png" alt="Test Your Agent as You Build It" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Test Agent&lt;/strong&gt; and the panel turns into a live chat. Send sample messages that imitate the kind of input real users will send, and watch the agent respond in real time — responses stream in token by token, exactly as they will in production. A couple of suggested prompts, like &lt;em&gt;"What can you help me with?"&lt;/em&gt; and &lt;em&gt;"What tools do you have access to?"&lt;/em&gt;, give you a quick way to get started.&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%2Fpg3a31a94weby5dwvp6s.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%2Fpg3a31a94weby5dwvp6s.png" alt="Click **Test Agent** " width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What makes the Agent Playbook more than a chat box is its &lt;strong&gt;transparency into the agent's reasoning&lt;/strong&gt;. Whenever the agent decides to call a tool, an expandable card appears inline in the conversation, showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which &lt;strong&gt;tool&lt;/strong&gt; was invoked,&lt;/li&gt;
&lt;li&gt;the agent's &lt;strong&gt;reasoning&lt;/strong&gt; for choosing it,&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;confidence&lt;/strong&gt; score, when the agent provides one,&lt;/li&gt;
&lt;li&gt;the exact &lt;strong&gt;input&lt;/strong&gt; parameters the agent passed, and&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;output&lt;/strong&gt; the tool returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means you're not just seeing the final answer — you're seeing &lt;em&gt;how the agent got there&lt;/em&gt;. If it picks the wrong tool, invents an argument, or skips a step, you'll catch it right away instead of discovering it in production.&lt;/p&gt;

&lt;p&gt;Crucially, testing runs against your &lt;strong&gt;in-progress configuration&lt;/strong&gt;. There's no save-and-deploy cycle: tweak the system prompt, swap the model, add or remove a tool or a guardrail, then hit &lt;strong&gt;Reset conversation&lt;/strong&gt; and try again. The loop between changing the agent and seeing the effect is measured in seconds. And because the panel lives inside the workflow context, you can feed it workflow variables (data pills, via &lt;code&gt;$&lt;/code&gt;) to mirror the data the agent will actually receive at runtime.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to try building with the AI Agent in &lt;a href="https://app.bytechef.io" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; for yourself?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>springai</category>
      <category>automation</category>
      <category>aiagents</category>
      <category>bytechef</category>
    </item>
    <item>
      <title>Welcome to ByteChef</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Thu, 23 Apr 2026 16:12:12 +0000</pubDate>
      <link>https://dev.to/bytechef/welcome-to-bytechef-5b3o</link>
      <guid>https://dev.to/bytechef/welcome-to-bytechef-5b3o</guid>
      <description>&lt;p&gt;&lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; is an open-source, AI-native &lt;strong&gt;data orchestration&lt;/strong&gt; platform created for teams that want to treat automation as infrastructure and not just a collection of app connections.&lt;/p&gt;

&lt;p&gt;It removes common operational pains such as high costs, inefficiency, human error and growth limitations. &lt;/p&gt;

&lt;p&gt;With &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; you can &lt;strong&gt;automate repetitive tasks&lt;/strong&gt; that waste time and introduce mistakes and also orchestrate complex, multi-step business processes that would otherwise slow growth and reduce operational reliability.&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%2F4ck52my66av9bhk54jh5.jpg" 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%2F4ck52my66av9bhk54jh5.jpg" alt="ByteChef platform overview" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stepping Outside the Comfort Zone
&lt;/h2&gt;

&lt;p&gt;Being in the familiar space is comfortable, but growth begins the moment you step into the unknown. New ways of working can feel very intimidating at first, especially when it comes to improving how your systems, data and processes connect and operate together. &lt;/p&gt;

&lt;p&gt;There is no perfect starting point, you experiment, adapt, and gradually discover better ways of working. Over time, what once felt complex becomes intuitive and you begin to see the real value of using the right tools effectively. &lt;/p&gt;

&lt;p&gt;Properly orchestrating your data and apps, removes burdens from your daily operations.&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%2Fb938jzsblsmv2avitskz.jpg" 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%2Fb938jzsblsmv2avitskz.jpg" alt="ByteChef workflow step-by-step" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; is built on a simple idea, that &lt;strong&gt;people shouldn’t spend their time repeating the same steps every day&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;That energy is far more valuable when focused on thinking, creating and solving meaningful problems.&lt;/p&gt;

&lt;p&gt;As an &lt;strong&gt;open-source&lt;/strong&gt; platform, &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; gives teams the freedom to experiment, innovate, and build solutions that truly match the way they work. &lt;/p&gt;

&lt;p&gt;Instead of adapting your processes to fit rigid tools, you can design workflows around your real operational needs, without vendor lock-in.&lt;/p&gt;

&lt;p&gt;You can &lt;strong&gt;build&lt;/strong&gt;, &lt;strong&gt;test&lt;/strong&gt; and &lt;strong&gt;validate&lt;/strong&gt; workflows step by step &lt;strong&gt;before&lt;/strong&gt; deploying them, with full transparency and control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Visual Workflows that Simply Make Sense
&lt;/h2&gt;

&lt;p&gt;To simplify workflow creation and help you visualize how data moves between tasks, &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; provides a free-form workflow editor with intuitive &lt;strong&gt;drag-and-drop&lt;/strong&gt; functionalities. &lt;/p&gt;

&lt;p&gt;This allows you to quickly adapt and update each step as your processes evolve. Every step is laid out on the canvas, connections are clear and you always know what’s happening and why.&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%2Fdb1zlhhymtvpu970kxg2.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%2Fdb1zlhhymtvpu970kxg2.png" alt="Automate with drag-and-drop in ByteChef" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Purpose‑built &lt;strong&gt;flow controls&lt;/strong&gt; such as condition, branch, loop, parallel, and many more, allow you to precisely manage how data moves through each workflow and apply custom logic wherever needed.&lt;/p&gt;

&lt;p&gt;Whether you need to split logic based on conditions, process lists of items one by one, run tasks at the same time, or repeat steps until a condition is met, the visual tools turn complex ideas into simple logic. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All of this is possible without writing a single line of code&lt;/strong&gt;, but if you prefer a more technical approach, &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; also supports code-based workflows through a built-in code editor and custom script component.&lt;/p&gt;

&lt;p&gt;This clarity makes workflows easier to build, review and maintain. &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%2Fznz5vptd711ct4bhdjbh.jpg" 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%2Fznz5vptd711ct4bhdjbh.jpg" alt="Flow Controls in ByteChef" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Data is at the heart of every workflow and that's where the &lt;strong&gt;dynamic values&lt;/strong&gt; shine. They allow you to securely reuse data across different apps and workflow steps without manual copying, pasting or reformatting.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;, every component produces &lt;strong&gt;structured output data&lt;/strong&gt; and those outputs automatically become dynamic values that can be used in any step that follows. &lt;/p&gt;

&lt;p&gt;This creates a continuous, traceable data flow where information moves logically from one task to another.&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%2F6nmvmwsu01g0inn98272.jpg" 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%2F6nmvmwsu01g0inn98272.jpg" alt="ByteChef workflow" width="800" height="818"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You always know what data you’re working with, where it comes from, and where it goes next. This removes one of the biggest sources of uncertainty in automation: &lt;strong&gt;invisible data handling&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Powered by the Models You Choose
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; allows you to integrate &lt;strong&gt;Large Language Models&lt;/strong&gt; directly into your workflows, making it easy to add intelligence wherever it is needed.&lt;/p&gt;

&lt;p&gt;Instead of being locked into a single provider, you can connect to a wide range of leading &lt;strong&gt;AI model&lt;/strong&gt; services and use them as part of your automation logic. This gives you the flexibility to choose models based on performance, cost efficiency and internal compliance requirements.&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%2Fy4129j6rma4n666gbwp8.jpg" 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%2Fy4129j6rma4n666gbwp8.jpg" alt="AI models in ByteChef" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because LLMs operate as workflow components, their outputs become data that can be reused in later steps just like any other dynamic value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; continues to expand its AI capabilities with upcoming enhancements such as an in-app &lt;strong&gt;AI Copilot&lt;/strong&gt; for natural language workflow building, advanced &lt;strong&gt;AI Agents&lt;/strong&gt; for autonomous task execution and extended integration frameworks that connect AI systems more deeply with business tools.&lt;/p&gt;

&lt;p&gt;Our goal is to make AI practical, controllable and seamlessly embedded into real operational processes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Built for Control and Trust
&lt;/h2&gt;

&lt;p&gt;Powerful workflows require more than flexibility, they require governance, security and full operational control.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; allows you to automate with confidence while meeting internal security standards and compliance requirements. Every workflow can be observed, tested and managed with transparency across its entire life cycle.&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%2Fecjgl1u07fivb1nuo8qx.jpg" 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%2Fecjgl1u07fivb1nuo8qx.jpg" alt="Testing workflows in ByteChef" width="800" height="806"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can deploy &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; on your &lt;strong&gt;own infrastructure&lt;/strong&gt; for full data sovereignty or run it in the &lt;strong&gt;cloud&lt;/strong&gt;, depending on your operational and regulatory needs. &lt;/p&gt;

&lt;p&gt;For sensitive operations, &lt;strong&gt;approval steps&lt;/strong&gt; can be added directly into workflows, allowing human oversight where it matters most. Detailed &lt;strong&gt;audit logs&lt;/strong&gt; track workflow activity and system actions, providing traceability and accountability for enterprise environments. &lt;/p&gt;




&lt;h3&gt;
  
  
  Focus on What Matters, Automate the Rest
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; is designed for messy, real-world use cases, complex tasks that need better solution, so it enables teams to design automation as operational infrastructure rather than temporary shortcuts.&lt;/p&gt;

&lt;p&gt;Time is lost on repetitive tasks, jumping between apps, manual handovers and keeping systems in sync. These small inefficiencies build up creating friction, avoidable errors, rising operational costs and unnecessary complexity that slows growth.&lt;/p&gt;

&lt;p&gt;With more than &lt;strong&gt;180 integrations&lt;/strong&gt;, &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; connects the tools your team already relies on and turns disconnected processes into coordinated workflows.&lt;/p&gt;

&lt;p&gt;If you’re curious to see how we can help your team reclaim time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Explore the platform&lt;/li&gt;
&lt;li&gt;Start automating :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's that simple!&lt;/p&gt;

&lt;p&gt;Focus on the work that truly matters, and let &lt;a href="https://www.bytechef.io/" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; handle the rest.&lt;/p&gt;

</description>
      <category>bytechef</category>
      <category>automation</category>
      <category>nocode</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
