<?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>Share What You Built: Project &amp; Workflow Templates</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Tue, 08 Sep 2026 19:01:59 +0000</pubDate>
      <link>https://dev.to/bytechef/share-what-you-built-project-workflow-templates-2l98</link>
      <guid>https://dev.to/bytechef/share-what-you-built-project-workflow-templates-2l98</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Templates let you &lt;strong&gt;start from a working automation instead of a blank canvas&lt;/strong&gt; - and let you share your own. Browse the gallery of pre-built &lt;strong&gt;project&lt;/strong&gt; and &lt;strong&gt;workflow&lt;/strong&gt; templates and import one into your workspace, or turn something you built into a &lt;strong&gt;private import link&lt;/strong&gt; that you can disable at any time. Connections never travel with a template, so sharing an automation never shares your credentials.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best automation you'll ever build is one you don't have to build - because someone already did, and shared it. We wrote about &lt;a href="https://blog.bytechef.io/blogs/import-export-workflows-projects" rel="noopener noreferrer"&gt;import and export&lt;/a&gt; as the foundation for this a while back, and promised template support on top of it. This is that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start From a Working Automation
&lt;/h2&gt;

&lt;p&gt;There are two granularities, and both live behind a gallery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project templates&lt;/strong&gt; - open &lt;strong&gt;Projects → Templates&lt;/strong&gt; to browse pre-built projects. Selecting one imports it as a regular project you can edit, publish, and deploy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow templates&lt;/strong&gt; - inside a project, browse workflow templates and import one as a new workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each gallery has a search box and a category filter, and every card shows the components the template uses as icons - so you can tell at a glance whether a template touches Slack, Postgres, or an LLM before you commit to it.&lt;/p&gt;

&lt;p&gt;Picking a card takes you to an import page rather than importing blind. That page lists every component the template contains, which is your shopping list: those are the apps you'll need connections for once the automation is in your workspace. When it looks right, &lt;strong&gt;Import now&lt;/strong&gt; drops a copy into your current workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share What You Built
&lt;/h2&gt;

&lt;p&gt;The other half is publishing. Open the three-dot menu next to a project - or an individual workflow, from its own menu - and choose &lt;strong&gt;Share&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The dialog asks for one thing before it will do anything: a &lt;strong&gt;description&lt;/strong&gt;. It's required, and the export button stays disabled until you write one. That constraint is doing real work - a template with no explanation is a template nobody imports.&lt;/p&gt;

&lt;p&gt;Then click &lt;strong&gt;Export and generate template link&lt;/strong&gt;. The dialog turns into a link card with a &lt;strong&gt;Copy link&lt;/strong&gt; button, and the link looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-instance/import/shared/projects/{uuid}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Workflows get the same shape at &lt;code&gt;/import/shared/workflows/{uuid}&lt;/code&gt;. Anyone you hand that link to lands on the same import page described above - the component list, then &lt;strong&gt;Import now&lt;/strong&gt;. They do need an account on a ByteChef instance and a workspace to import into; this is a link for colleagues and collaborators, not an anonymous public download.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Link Stays Yours
&lt;/h2&gt;

&lt;p&gt;Three details make this comfortable to actually use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can turn it off.&lt;/strong&gt; A toggle at the top of the dialog disables the link at any time - the existing URL stops working immediately. Flip it back on later and ByteChef generates a fresh export.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It won't drift behind your project silently.&lt;/strong&gt; Keep editing after you've shared, and the dialog tells you that an older version is the one being handed out, and offers &lt;strong&gt;Update template based on the current version&lt;/strong&gt;. The link keeps pointing at whatever you last decided it should.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ByteChef doesn't distribute it for you.&lt;/strong&gt; The dialog says so directly: template links are not distributed by the app. Generating a link does not list your project anywhere, does not surface it in the gallery, and does not make it discoverable. You decide who gets the URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Travels, and What Doesn't
&lt;/h2&gt;

&lt;p&gt;A shared template is a small zip: a manifest with your description and the project version, the project metadata, and one JSON file per workflow definition. That's the whole payload.&lt;/p&gt;

&lt;p&gt;What is conspicuously &lt;em&gt;not&lt;/em&gt; in there: connections. No API keys, no OAuth tokens, no credentials of any kind. The importer wires up their own accounts against the component list on the import page. This is why sharing an automation is a low-stakes act - you're sharing the shape of the work, never the keys to your systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listing in the Public Gallery
&lt;/h2&gt;

&lt;p&gt;Private links are one route. If you want a template listed in ByteChef's official gallery for anyone to browse, that's a &lt;strong&gt;separate&lt;/strong&gt; action: &lt;strong&gt;Share with Community&lt;/strong&gt;, which opens the public template submission form. The two are genuinely different - one hands a URL to people you choose, the other proposes an addition to a curated catalog.&lt;/p&gt;

&lt;p&gt;Self-hosted instances behind a firewall can point the gallery at a mirror rather than reaching ByteChef's catalog directly; the GitHub proxy configuration in the docs covers it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Sharing Compounds
&lt;/h2&gt;

&lt;p&gt;A workflow you keep to yourself helps one team once. A workflow you template helps everyone who imports it - and they can adapt it, re-share it, and improve on it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding&lt;/strong&gt; - new users start from proven automations instead of a tutorial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardization&lt;/strong&gt; - a team's "the right way to do X" becomes a template everyone imports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community&lt;/strong&gt; - the best patterns rise to the top and spread.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Every automation you build is either a one-off or a starting point, and the difference is a description and a click. Templates let the good ones travel - built once, imported wherever they're needed, improved by whoever needs them next - without ever putting your credentials on the move.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built something worth reusing? Share it as a template - or browse the gallery and start from one instead of a blank canvas.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automaton</category>
      <category>bytechef</category>
      <category>agents</category>
    </item>
    <item>
      <title>Somewhere to Keep the Records: Data Tables in ByteChef</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Sun, 30 Aug 2026 09:59:22 +0000</pubDate>
      <link>https://dev.to/bytechef/somewhere-to-keep-the-records-data-tables-in-bytechef-371n</link>
      <guid>https://dev.to/bytechef/somewhere-to-keep-the-records-data-tables-in-bytechef-371n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; &lt;strong&gt;Data Tables&lt;/strong&gt; are ByteChef's built-in place to keep records. Create a table with &lt;strong&gt;typed columns&lt;/strong&gt; (string, number, integer, date, date-time, boolean), fill it in a spreadsheet-like grid or &lt;strong&gt;import a CSV&lt;/strong&gt;, and use it from your workflows through &lt;strong&gt;six actions&lt;/strong&gt; (create, get, find, update, delete, clear) and &lt;strong&gt;three triggers&lt;/strong&gt; that start a workflow whenever a row is created, updated, or deleted. Those same six actions are available to &lt;strong&gt;AI agents as tools&lt;/strong&gt;, so an agent can look things up and write rows for you. Your Development, Staging, and Production rows stay in &lt;strong&gt;separate tables&lt;/strong&gt;, so test data never leaks into live automations. No database to set up, no spreadsheet to babysit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There's a question every automation project runs into by week two: &lt;em&gt;"where do we keep the records?"&lt;/em&gt; The leads the workflow has already processed. The subscriptions to check against. The running list of approvals, orders, escalations. Workflow steps don't remember anything between runs; the data has to live &lt;em&gt;somewhere&lt;/em&gt;, and the classic answers are both awkward. A spreadsheet bolted onto the side is easy but fragile: no real types, no stable way to point at a row, rate limits, and an API that was never meant to be your database. An actual database is solid but heavy: someone has to provision it, design it, secure it, and write the plumbing for every read and write.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Tables&lt;/strong&gt; are ByteChef's answer to that gap: tables that live inside the platform, as easy as a spreadsheet from the front, as dependable as a database underneath, and already connected to everything else your workflows do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set One Up in a Minute
&lt;/h2&gt;

&lt;p&gt;A Data Table starts the way you'd hope. Open &lt;strong&gt;Data Tables&lt;/strong&gt; in the Automation workspace, click &lt;strong&gt;New Table&lt;/strong&gt;, give it a name, and add your columns; each one gets a type: &lt;strong&gt;string, number, integer, date, date-time, or boolean&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From there you get a familiar grid. Add a row by typing into the empty one at the bottom. Click a cell to edit it, and you get the right editor for the column: a checkbox for booleans, a date picker for dates, a number field for numbers. Select rows with checkboxes to delete them. Longer tables load more rows as you scroll.&lt;/p&gt;

&lt;p&gt;Already have the data in a spreadsheet? &lt;strong&gt;Import a CSV&lt;/strong&gt; from the table's &lt;strong&gt;⋮&lt;/strong&gt; menu and the rows land in the matching columns. The same menu &lt;strong&gt;exports&lt;/strong&gt; a CSV back out, so nothing you put in is trapped. Once you've got a few tables, &lt;strong&gt;tags&lt;/strong&gt; keep the list organized.&lt;/p&gt;

&lt;p&gt;Picking a type per column sounds like a small chore, and it pays for itself almost immediately: a date column is a real date rather than text that usually parses, numbers sort like numbers instead of alphabetically, and a boolean is true or false rather than "yes", "Y", and "TRUE" all living in the same column. Every row also gets its own &lt;strong&gt;id&lt;/strong&gt; that never changes, so you can hold onto a specific row and come back to it later, something row numbers in a spreadsheet can never promise you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Data Stays Test Data
&lt;/h2&gt;

&lt;p&gt;Here's the part people are usually surprised by. A Data Table isn't one shared pile of rows; ByteChef keeps a &lt;strong&gt;separate set of rows for each environment&lt;/strong&gt;. The table you filled with junk while building in Development is genuinely not the table your Production workflow reads from.&lt;/p&gt;

&lt;p&gt;That means you can test a workflow that inserts, updates, and deletes records without a moment's worry about what it's touching, then promote it and watch it run against real data. No "_TEST" prefix conventions, no second copy of a spreadsheet that drifts out of sync, no accidentally emailing your actual customers because a test row was sitting in the live sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six Actions: Tables in Your Workflows
&lt;/h2&gt;

&lt;p&gt;Add the &lt;strong&gt;Data Table&lt;/strong&gt; component to a workflow and you can read and write any of your tables. There's no connection to set up and nothing to authenticate against; the tables are part of the platform, so they're just &lt;em&gt;there&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create Records&lt;/strong&gt; - add one row or many at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get Record&lt;/strong&gt; - fetch a specific row by its id.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find Records&lt;/strong&gt; - list rows from a table, with limit and offset so you can page through them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update Record&lt;/strong&gt; - change the values on a row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete Records&lt;/strong&gt; - remove rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear Table&lt;/strong&gt; - empty a table in one step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick your table and the action's inputs reshape themselves around that table's columns, so you're filling in &lt;em&gt;Email&lt;/em&gt; and &lt;em&gt;Status&lt;/em&gt;, not guessing at field names.&lt;/p&gt;

&lt;p&gt;That covers the patterns automations lean on constantly: &lt;em&gt;accumulate&lt;/em&gt; ("append every order this workflow processed"), &lt;em&gt;enrich later&lt;/em&gt; ("store the record now, update it when the webhook finally lands"), &lt;em&gt;hand off&lt;/em&gt; ("one workflow writes the row, another picks it up"), and &lt;em&gt;keep a log&lt;/em&gt; ("record what this run did, so there's something to look at on Monday").&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Triggers: Tables That Start Workflows
&lt;/h2&gt;

&lt;p&gt;This is where Data Tables stop being just storage. Most built-in tables in other tools are passive: you read and write them, and that's the end of it. ByteChef's tables can &lt;em&gt;start&lt;/em&gt; a workflow. The component ships three triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Record Created&lt;/strong&gt; - a new row was added.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record Updated&lt;/strong&gt; - a row changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record Deleted&lt;/strong&gt; - a row was removed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which quietly changes the shape of what you can build. A table stops being a filing cabinet at the edge of your automations and becomes the thing they're organized around. One workflow adds a row; three other workflows react to it, and the one doing the writing doesn't need to know they exist.&lt;/p&gt;

&lt;p&gt;Say an intake workflow drops a new order into a table. A fulfillment workflow, a customer-notification workflow, and a reporting workflow each start themselves on &lt;strong&gt;Record Created&lt;/strong&gt;, independently. Want to add a fourth later? Build it and switch it on. Nothing else needs touching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agents Can Use Them Too
&lt;/h2&gt;

&lt;p&gt;Data Tables aren't only for workflows you draw by hand. Every one of those six actions is also available to &lt;strong&gt;AI agents as a tool&lt;/strong&gt;, so an agent can look up a record, add one, update one, or clear a table, using exactly the same operations your workflows use.&lt;/p&gt;

&lt;p&gt;That means a table can be shared ground between the two ways of working. A scheduled workflow keeps a table of open tickets up to date; an agent you're chatting with reads that same table to answer "what's still unresolved?" and writes a row back when it takes something on. Same data, same rules, no separate copy to keep in sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Fits
&lt;/h2&gt;

&lt;p&gt;Data Tables aren't trying to replace your production database; they're for the working data &lt;em&gt;of your automations&lt;/em&gt;. A rough guide:&lt;/p&gt;

&lt;p&gt;Data Tables are a good fit when…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your workflows need to share data or remember state between runs.&lt;/li&gt;
&lt;li&gt;You’re tracking processed items, queues, lookups, or workflow logs.&lt;/li&gt;
&lt;li&gt;You want one workflow to react when data changes.&lt;/li&gt;
&lt;li&gt;Your dataset is relatively small and primarily written by workflows.
Consider something else when…&lt;/li&gt;
&lt;li&gt;You need a system of record for your product → use a real database.&lt;/li&gt;
&lt;li&gt;People need to collaboratively edit free-form content → use a spreadsheet or document.&lt;/li&gt;
&lt;li&gt;You’re moving or syncing large datasets between systems → DataStream (coming soon).&lt;/li&gt;
&lt;li&gt;Your knowledge is stored in documents rather than rows → use a &lt;a href="https://blog.bytechef.io/blogs/bytechef-knowledge-base" rel="noopener noreferrer"&gt;Knowledge Base&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two things worth knowing before you commit. A Data Table is &lt;strong&gt;not a transactional system of record&lt;/strong&gt;: there's no cross-row transaction or multi-writer locking, so if several outside systems are writing the same data at the same time, point your workflow at a real database instead. And it's sized for small datasets, not warehouses: think lookup tables, queues, flags, and processed-item lists rather than millions of rows.&lt;/p&gt;

&lt;p&gt;That right-hand column is really a tour of ByteChef's storage story: &lt;strong&gt;Data Tables&lt;/strong&gt; for structured rows, the &lt;strong&gt;&lt;a href="https://blog.bytechef.io/blogs/bytechef-knowledge-base" rel="noopener noreferrer"&gt;Knowledge Base&lt;/a&gt;&lt;/strong&gt; for searchable documents, and &lt;strong&gt;DataStream (coming soon)&lt;/strong&gt; for moving bulk data between systems. Three shapes of data, three purpose-built homes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Remembering things is the unglamorous half of automation. Every workflow beyond the trivial needs to keep track of something, and &lt;em&gt;how well&lt;/em&gt; it remembers (real types or everything-as-text, stable ids or shifting row numbers, reacting to changes or polling for them) quietly decides how far that automation can grow before it starts to hurt.&lt;/p&gt;

&lt;p&gt;Data Tables give that job a proper home: tables you fill in like a spreadsheet, with types that hold, ids that stay put, test data kept away from live data, six actions to read and write them from your workflows or hand to an agent, and three triggers so a change to a row can set the next workflow going. No database to provision, no sheet to babysit, just somewhere real for your workflows to keep what they know.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Got a workflow juggling state in a spreadsheet? Open &lt;a href="https://app.bytechef.io" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;, create a **Data Table&lt;/em&gt;&lt;em&gt;, and give your records somewhere better to live.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>bytechef</category>
      <category>automation</category>
      <category>agents</category>
    </item>
    <item>
      <title>Agent Skills in ByteChef: Package Know-How Once, Give It to Every Agent</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Thu, 27 Aug 2026 16:19:30 +0000</pubDate>
      <link>https://dev.to/bytechef/agent-skills-in-bytechef-package-know-how-once-give-it-to-every-agent-11i1</link>
      <guid>https://dev.to/bytechef/agent-skills-in-bytechef-package-know-how-once-give-it-to-every-agent-11i1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; &lt;strong&gt;Agent Skills&lt;/strong&gt; are self-contained packages of instructions, scripts, and resources - built around a &lt;code&gt;SKILL.md&lt;/code&gt; file - that agents discover and load &lt;em&gt;on demand&lt;/em&gt;. The Spring AI team &lt;a href="https://spring.io/blog/2026/01/13/spring-ai-generic-agent-skills" rel="noopener noreferrer"&gt;just added generic support for them in Java&lt;/a&gt;. &lt;a href="https://www.bytechef.io" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;, which runs on Spring AI under the hood, goes a step further: a built-in &lt;strong&gt;Skills&lt;/strong&gt; workspace for creating, editing, and sharing skills; &lt;strong&gt;isolated GraalVM execution&lt;/strong&gt; for bundled scripts; and a &lt;strong&gt;Skills Tool&lt;/strong&gt; that plugs any skill into any AI Agent. Write the know-how once, reuse it everywhere - no code, no redeploys.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There's a moment every agent builder hits: your AI Agent works, but making it &lt;em&gt;good at your job&lt;/em&gt; means feeding it more and more instructions. The refund policy. The report format. The naming conventions. The seventeen edge cases finance cares about. Everything lands in the system prompt, which grows into an unmaintainable wall of text that every request pays for in tokens - whether it's relevant or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent Skills&lt;/strong&gt; are the answer to that problem, and they're having a moment. Anthropic introduced the pattern and its &lt;code&gt;SKILL.md&lt;/code&gt; convention; it quickly spread across the ecosystem. In January, the Spring AI team published &lt;a href="https://spring.io/blog/2026/01/13/spring-ai-generic-agent-skills" rel="noopener noreferrer"&gt;Agent Skills in Spring AI&lt;/a&gt; - the first post in their agentic patterns series - showing how to wire skills into any Java application with &lt;code&gt;SkillsTool&lt;/code&gt;, file-system tools, and shell tools.&lt;/p&gt;

&lt;p&gt;If you've read our previous posts on &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;the AI Agent component&lt;/a&gt; and &lt;a href="https://blog.bytechef.io/blogs/bytechef-agentic-patterns" rel="noopener noreferrer"&gt;agentic workflow patterns&lt;/a&gt;, you know where this is going: ByteChef is built &lt;strong&gt;on top of Spring AI&lt;/strong&gt;, and skills are no exception. But where Spring AI gives Java developers the building blocks, ByteChef ships the whole thing as a product - skills management, a visual editor, and one-click attachment to any agent.&lt;/p&gt;

&lt;p&gt;Let's dig in.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an Agent Skill?
&lt;/h2&gt;

&lt;p&gt;A skill is a folder. That's genuinely the whole format - and it's why the pattern is spreading so fast.&lt;/p&gt;

&lt;p&gt;At the root sits a &lt;code&gt;SKILL.md&lt;/code&gt; file: YAML frontmatter with metadata on top, Markdown instructions below. Around it, optional supporting files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;email-digest/
├── SKILL.md          ← metadata + instructions (required)
├── scripts/          ← executable helpers
│   └── run_digest.py
├── references/       ← extra documentation, loaded on demand
└── assets/           ← templates and other resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what a real &lt;code&gt;SKILL.md&lt;/code&gt; looks like - this is the email-digest skill we'll use as the running example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email-digest&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;Fetches unread emails from Gmail, summarizes key points using AI,&lt;/span&gt;
    &lt;span class="s"&gt;and sends the digest back to the user's Gmail inbox. Use when the&lt;/span&gt;
    &lt;span class="s"&gt;user asks to summarize their unread emails or get an email digest.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Email Digest Skill&lt;/span&gt;

&lt;span class="gu"&gt;## What It Does&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; Fetches unread emails from Gmail (up to a configurable limit)
&lt;span class="p"&gt;2.&lt;/span&gt; Uses an LLM to summarize key points per email
&lt;span class="p"&gt;3.&lt;/span&gt; Sends a formatted digest email back to the user's Gmail

&lt;span class="gu"&gt;## How to Run&lt;/span&gt;

Call the &lt;span class="sb"&gt;`email_digest_run_digest`&lt;/span&gt; tool. It runs the bundled
&lt;span class="sb"&gt;`scripts/run_digest.py`&lt;/span&gt;, which fetches the unread mail, summarizes
it, and sends the digest.

&lt;span class="gu"&gt;## Output&lt;/span&gt;

A single HTML email sent to the recipient containing a summary
of every unread message, grouped by sender.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to notice. First, the &lt;strong&gt;description&lt;/strong&gt; does double duty: it tells humans what the skill is for, and it tells the &lt;em&gt;agent&lt;/em&gt; when to reach for it - that last sentence ("Use when the user asks to…") is discovery guidance, not documentation fluff. Second, the instructions are written &lt;em&gt;for the agent&lt;/em&gt;, in imperative, unambiguous language. A skill is essentially an onboarding document for a very fast, very literal new hire.&lt;/p&gt;

&lt;p&gt;Because the format is plain Markdown in a folder, skills are &lt;strong&gt;portable&lt;/strong&gt;. The same convention is used by Claude Code, by Spring AI's implementation, and by ByteChef - a skill you write in one place can travel to the others.&lt;/p&gt;




&lt;h2&gt;
  
  
  Progressive Disclosure: Why Skills Scale Where System Prompts Don't
&lt;/h2&gt;

&lt;p&gt;The clever part of the skills pattern isn't the file format - it's &lt;em&gt;when&lt;/em&gt; the content gets loaded. Skills use &lt;strong&gt;progressive disclosure&lt;/strong&gt;, revealing themselves to the agent in three phases:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fezta496etfhy3khrej7e.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fezta496etfhy3khrej7e.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discovery.&lt;/strong&gt; By default, the agent only sees each skill's &lt;em&gt;name and description&lt;/em&gt; - a few dozen tokens per skill. This is what lets an agent carry dozens of skills without drowning its context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activation.&lt;/strong&gt; When a request matches a skill's description, the full &lt;code&gt;SKILL.md&lt;/code&gt; instructions load into context - only then, and only for that skill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution.&lt;/strong&gt; Referenced Markdown files and script outputs enter the picture on demand, while the skill runs, and not a moment earlier.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Compare that with the stuff-everything-into-the-system-prompt approach, where the refund policy is in context while the user asks about the weather. Progressive disclosure means you pay for know-how &lt;strong&gt;only when it's being used&lt;/strong&gt; - which is exactly what makes a library of specialized skills economically viable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Skills at Runtime: The Skills Tool
&lt;/h2&gt;

&lt;p&gt;On the ByteChef side, an agent gets access to skills through the &lt;strong&gt;Skills Tool&lt;/strong&gt; - one of the tool options in the AI Agent's &lt;strong&gt;Tools&lt;/strong&gt; slot, alongside &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;component actions, MCP tools, and sub-agents&lt;/a&gt;. Attach it, and the agent can discover and invoke any skill in your workspace.&lt;/p&gt;

&lt;p&gt;The runtime flow looks like this:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukwvsdc3c1kneashc7bg.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukwvsdc3c1kneashc7bg.png" alt=" " width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note what's &lt;em&gt;absent&lt;/em&gt; from that picture: routing logic. You don't configure which requests trigger which skill - the agent matches the user's intent against skill descriptions on its own. Add a new skill to the workspace and every agent with the Skills Tool can start using it immediately.&lt;/p&gt;

&lt;p&gt;When a skill bundles scripts, ByteChef doesn't hand the agent a shell. It walks the skill's &lt;code&gt;scripts/&lt;/code&gt; folder and turns every script that exports a &lt;code&gt;perform&lt;/code&gt; function into &lt;strong&gt;a tool of its own&lt;/strong&gt; - so &lt;code&gt;scripts/run_digest.py&lt;/code&gt; inside the &lt;code&gt;email-digest&lt;/code&gt; skill becomes a callable tool named &lt;code&gt;email_digest_run_digest&lt;/code&gt;. JavaScript, Python, Ruby, and Java all work, and each one is executed by a GraalVM polyglot engine rather than a subprocess. The agent sees a named tool it can call, not a command line it can compose.&lt;/p&gt;

&lt;p&gt;That distinction matters, because the Spring AI post is refreshingly honest about its own trade-off here: in the DIY setup, &lt;em&gt;"scripts execute directly on your local machine without sandboxing,"&lt;/em&gt; and the recommended mitigation is to containerize your whole application. A ByteChef skill script runs in a polyglot context with no host filesystem, no network sockets, and no native access - it reaches the outside world only through &lt;code&gt;context.component&lt;/code&gt;, the same action layer the rest of the platform runs on. It is not a resource sandbox: there are no CPU or memory ceilings on guest code, so skill scripts remain code worth reading before you attach them. But the ambient authority a loose &lt;code&gt;python3&lt;/code&gt; would inherit simply isn't there. Combined with &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;Guardrails&lt;/a&gt; on the agent itself, you get a controlled execution story without building any of it.&lt;/p&gt;

&lt;p&gt;There's a neat side effect. Because those scripts are just files, ByteChef reads them &lt;em&gt;before&lt;/em&gt; the workflow ever runs: it scans each one for &lt;code&gt;context.component.&amp;lt;name&amp;gt;.&amp;lt;action&amp;gt;(…)&lt;/code&gt; calls and surfaces a connection field for every component it recognizes. Bundle a script that calls &lt;code&gt;context.component.gmail.*&lt;/code&gt; and the Skills Tool node asks you for a Gmail connection. The skill declares its own dependencies in code, rather than in metadata you have to remember to keep in sync.&lt;/p&gt;

&lt;p&gt;And because model access goes through Spring AI's provider abstraction, skills are &lt;strong&gt;model-portable&lt;/strong&gt;: the same skill works whether the agent runs on GPT-4o, Claude, Gemini, or a local Ollama model. Define once, run anywhere - swap the model from a dropdown later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Built-In Skills Management
&lt;/h2&gt;

&lt;p&gt;In Spring AI, skills live in folders on the classpath or filesystem, next to your application code. ByteChef gives them a home in the product instead: the &lt;strong&gt;Skills&lt;/strong&gt; area, right in the AI section of the workspace.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgl5y0j0adv8xa82hgd0c.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgl5y0j0adv8xa82hgd0c.png" alt=" " width="800" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every skill in the list shows its name, its description (the same one agents use for discovery), and when it was last modified. From here you can search, create, and manage the whole library. Two ways to create a skill are available today, with a third on the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write instructions.&lt;/strong&gt; Give it a name and a description, write what it should do in plain text, and ByteChef packages it into the &lt;code&gt;SKILL.md&lt;/code&gt; structure for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload.&lt;/strong&gt; Drag in a &lt;code&gt;.skill&lt;/code&gt; archive, a &lt;code&gt;.zip&lt;/code&gt;, or a bare &lt;code&gt;.md&lt;/code&gt; file. This is the import path for skills built elsewhere - including skills from the wider &lt;code&gt;SKILL.md&lt;/code&gt; ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create with AI&lt;/strong&gt; &lt;em&gt;(coming soon)&lt;/em&gt;. Describe the capability ("a skill that summarizes my unread Gmail every morning") and let ByteChef's Copilot draft the skill's structure, metadata, and instructions. This path rides on the AI Copilot, which is on the upcoming release track rather than in the current release.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once created, a skill opens in the built-in editor:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwz2lgtxoqup8rgqr9e5n.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwz2lgtxoqup8rgqr9e5n.png" alt=" " width="800" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the email-digest skill from earlier, as it actually looks in ByteChef. On the left, the file tree - &lt;code&gt;SKILL.md&lt;/code&gt; plus a &lt;code&gt;scripts/&lt;/code&gt; folder holding the Python helper. The main pane renders the frontmatter as a metadata table above the formatted instructions - ByteChef validates and stores &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;, and displays whatever other keys the file carries verbatim, so a skill imported from another tool keeps its own metadata intact. A toggle switches between this preview and a full &lt;strong&gt;source editor&lt;/strong&gt; that picks its syntax highlighting from the file extension - Markdown, Python, JavaScript, TypeScript, Java, JSON, YAML, HTML, CSS, SQL - so you can edit any file in the package. Save, and the change is live - every agent using the skill picks it up on its next run, no rebuild, no redeploy.&lt;/p&gt;

&lt;p&gt;Need to move a skill between workspaces, share it with a teammate, or keep a snapshot before a big edit? &lt;strong&gt;Download&lt;/strong&gt; it as a &lt;code&gt;.skill&lt;/code&gt; archive and it becomes a file you can version, review, and re-upload anywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Payoff: One Skill, Many Agents
&lt;/h2&gt;

&lt;p&gt;Here's where the managed approach compounds. Because skills are decoupled from any single agent, they form a &lt;strong&gt;shared capability library&lt;/strong&gt; for your whole workspace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The support agent, the sales agent, and the internal helpdesk agent can all carry the same &lt;code&gt;refund-policy&lt;/code&gt; skill. Update the policy once; all three agents follow the new rules on their next conversation.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;release-notes&lt;/code&gt; skill encodes your changelog format and tone. Attach it to the engineering agent that drafts notes from merged PRs &lt;em&gt;and&lt;/em&gt; to the marketing agent that turns them into announcement posts.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;email-digest&lt;/code&gt; skill above doesn't care which agent invokes it - any agent with the Skills Tool and a Gmail connection can produce the digest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the same "build once, reuse everywhere" argument the Spring AI post makes with the composability of skills - except the unit of reuse isn't a folder you copy between codebases; it's a managed object every agent in the workspace can already see.&lt;/p&gt;

&lt;p&gt;And you can verify all of it before it touches production: open the agent in the editor, and the &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;Agent Playbook&lt;/a&gt; lets you chat with your in-progress configuration. Ask something that should trigger the skill, and the expandable tool-call cards show the skill being discovered and invoked - which tool ran, with what inputs, returning what output. If the agent picks the wrong skill (usually a sign your description is too vague), you'll see it in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Skills, System Prompts, or RAG?
&lt;/h2&gt;

&lt;p&gt;Skills join two other ways of shaping agent behavior, and it's worth being deliberate about which knowledge goes where:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;What it's for&lt;/th&gt;
&lt;th&gt;Loaded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System prompt&lt;/td&gt;
&lt;td&gt;Identity and ground rules: who the agent is, tone, hard constraints&lt;/td&gt;
&lt;td&gt;Always&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAG&lt;/td&gt;
&lt;td&gt;Facts: your documents, tickets, product data - &lt;em&gt;what is true&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Per query, by similarity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;Procedures: how to perform a task, step by step - &lt;em&gt;how it's done&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;On demand, by intent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A useful rule of thumb: if you're writing "always" or "never," it belongs in the system prompt. If you're writing "our Q3 pricing is…," that's a document - put it in &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;RAG or the Knowledge Base&lt;/a&gt;. If you're writing "first do this, then that, format the result like so," you're writing a skill.&lt;/p&gt;

&lt;p&gt;The three compose naturally on one agent: a lean system prompt for identity, RAG for grounding, and a library of skills for the procedures - each loaded at the moment it earns its context cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Inherit from Spring AI - and What ByteChef Adds
&lt;/h2&gt;

&lt;p&gt;The Spring AI team closes their post with the pattern's strengths, and being built on Spring AI, ByteChef inherits all of them: &lt;strong&gt;LLM portability&lt;/strong&gt; (define a skill once, run it on any supported provider), &lt;strong&gt;reusability and composability&lt;/strong&gt; (share skills across projects, version them, extend them), and &lt;strong&gt;no vendor lock-in&lt;/strong&gt; (the common &lt;code&gt;SKILL.md&lt;/code&gt; convention travels).&lt;/p&gt;

&lt;p&gt;They're equally upfront about the limitations. Their list runs to four items, and ByteChef's managed layer closes two of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Scripts execute directly on the local machine without sandboxing&lt;/em&gt; → in ByteChef, each script becomes a tool running inside a &lt;strong&gt;GraalVM polyglot context&lt;/strong&gt; with no host filesystem, network, or native access.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Script execution requires pre-installed runtimes&lt;/em&gt; → the polyglot engine ships &lt;strong&gt;in the platform&lt;/strong&gt;; JavaScript, Python, Ruby, and Java run with nothing to install.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The other two are honest gaps in both. There's still &lt;strong&gt;no built-in human approval step&lt;/strong&gt; before a skill's script runs, and &lt;strong&gt;skill versioning&lt;/strong&gt; is whatever you make of it - download a &lt;code&gt;.skill&lt;/code&gt; archive and commit it alongside your code, but nothing versions skills for you in-product.&lt;/p&gt;

&lt;p&gt;Two further differences don't appear on their list at all, because they're product concerns rather than framework ones: skills live in a &lt;strong&gt;managed workspace&lt;/strong&gt; with search and a visual editor instead of on the filesystem next to your code, and wiring is one &lt;strong&gt;Skills Tool&lt;/strong&gt; attached to an agent instead of dependencies and configuration code.&lt;/p&gt;

&lt;p&gt;Same foundation, same format, same portability - minus most of the infrastructure work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices for Writing Skills
&lt;/h2&gt;

&lt;p&gt;A few habits that separate skills agents &lt;em&gt;reliably&lt;/em&gt; pick up from skills that gather dust:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Treat the description as an API.&lt;/strong&gt; It's the only thing the agent sees at discovery time. State what the skill does &lt;em&gt;and&lt;/em&gt; when to use it: "…Use when the user asks to summarize their unread emails." Vague descriptions are the number-one cause of skills never firing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One job per skill.&lt;/strong&gt; "Handle refunds" and "write release notes" are two skills, not one. Small skills are easier for the agent to match and for you to maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep &lt;code&gt;SKILL.md&lt;/code&gt; lean.&lt;/strong&gt; The instructions load in full at activation, so they should carry the workflow - push long reference material into &lt;code&gt;references/&lt;/code&gt; files the agent reads only when needed. Progressive disclosure only saves tokens if you let it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer scripts for deterministic work.&lt;/strong&gt; If a step is exact - parsing, formatting, calling an API in a precise way - a bundled script beats prose instructions. The model decides &lt;em&gt;when&lt;/em&gt;; the script guarantees &lt;em&gt;how&lt;/em&gt;. Give each script under &lt;code&gt;scripts/&lt;/code&gt; a &lt;code&gt;perform&lt;/code&gt; function: that's what ByteChef looks for when deciding which files to expose as tools, and a script without one is quietly skipped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test in the Playbook first.&lt;/strong&gt; Phrase requests the way real users would, watch which skill activates, and tune descriptions until discovery is reliable.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Agent Skills solve an unglamorous but decisive problem: where does an agent's know-how &lt;em&gt;live&lt;/em&gt;? Not in a bloated system prompt, not scattered across duplicated agent configs - in small, portable, on-demand packages that any agent can pick up.&lt;/p&gt;

&lt;p&gt;Spring AI brought that pattern to the Java world as a library. ByteChef, standing on Spring AI's shoulders, turns it into infrastructure you don't have to build: managed storage, a visual editor, isolated script execution, and one-click attachment to any agent - with the Agent Playbook to prove it all works before you ship, and AI-assisted authoring on the way.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Got a procedure your team explains over and over? That's your first skill. Open &lt;a href="https://app.bytechef.io" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;, head to the Skills area, and teach it once.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Your Documents, Chunked and Searchable: The Knowledge Base in ByteChef</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Tue, 25 Aug 2026 19:46:33 +0000</pubDate>
      <link>https://dev.to/bytechef/your-documents-chunked-and-searchable-the-knowledge-base-in-bytechef-h9d</link>
      <guid>https://dev.to/bytechef/your-documents-chunked-and-searchable-the-knowledge-base-in-bytechef-h9d</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; A &lt;strong&gt;Knowledge Base&lt;/strong&gt; in ByteChef is a managed RAG store: drop in documents (PDF, Markdown, Word, JSON, plain text - and scanned PDFs or images, through an &lt;strong&gt;OCR&lt;/strong&gt; path) and ByteChef parses, &lt;strong&gt;chunks&lt;/strong&gt; (with size and overlap you pick per knowledge base), &lt;strong&gt;embeds&lt;/strong&gt;, and indexes them in a &lt;strong&gt;pgvector&lt;/strong&gt;-backed Spring AI &lt;code&gt;VectorStore&lt;/code&gt;. Retrieval is everywhere you'd want it: a &lt;strong&gt;Knowledge Base Search tool&lt;/strong&gt; for AI Agents (with tag filtering), &lt;strong&gt;Load/Search/Update/Delete actions&lt;/strong&gt; for workflows, and a built-in &lt;strong&gt;search interface&lt;/strong&gt; for testing. Keeping the index current is yours to drive - re-run an ingestion workflow on whatever schedule you like - and the part to plan for deliberately is upstream &lt;strong&gt;deletes&lt;/strong&gt;, which no refresh can spot on your behalf.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every team building with agents arrives at the same sentence: &lt;em&gt;"It should know our stuff."&lt;/em&gt; The product docs. The runbooks. The policy PDFs. And the standard answer - RAG, retrieval-augmented generation - is conceptually simple: chunk the documents, embed the chunks, search by similarity, hand the best matches to the model.&lt;/p&gt;

&lt;p&gt;The concept is a weekend. The &lt;em&gt;operation&lt;/em&gt; is a project. Someone has to parse five file formats, pick chunk sizes, run an embedding model, host a vector database, keep the index in sync when the source-of-truth changes - and notice when a document is &lt;em&gt;deleted&lt;/em&gt; upstream, because a knowledge base that confidently serves stale policy is worse than none at all. That's the gap between a RAG demo and a RAG system. ByteChef's &lt;strong&gt;Knowledge Base&lt;/strong&gt; closes most of it for you - and this post is honest about the part it leaves to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Knowledge Base Is
&lt;/h2&gt;

&lt;p&gt;In ByteChef, a Knowledge Base is a first-class object with its own home in the workspace: a named store of &lt;strong&gt;documents&lt;/strong&gt;, each broken into &lt;strong&gt;chunks&lt;/strong&gt;, each chunk embedded and indexed for semantic search. The layering is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documents&lt;/strong&gt; are what you put in - files you upload, or records a workflow or an agent writes in, organizable with &lt;strong&gt;tags&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunks&lt;/strong&gt; are what retrieval actually works with. You pick the chunking when you create a knowledge base - maximum chunk size (default 1024 tokens), the minimum chunk size in characters used to find a clean break point (default 100), and how many tokens neighboring chunks &lt;strong&gt;overlap&lt;/strong&gt; (default 200) - so a KB full of dense legal prose can chunk differently than one full of short FAQ entries. The splitter counts tokens with &lt;code&gt;CL100K_BASE&lt;/code&gt;, the same encoding GPT-4 uses, and prefers to break on sentence punctuation rather than mid-thought.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings&lt;/strong&gt; live in &lt;strong&gt;pgvector&lt;/strong&gt; - a Spring AI &lt;code&gt;PgVectorStore&lt;/code&gt; over a pgvector-enabled PostgreSQL database, built with the platform's configured &lt;code&gt;EmbeddingModel&lt;/code&gt; and indexed with HNSW over cosine distance. There's no proprietary vector service to sign up for and no new operational vocabulary to learn: it's Postgres, backed up and monitored like the rest of your Postgres, and ByteChef creates and maintains the schema, the index, and the per-knowledge-base partitioning for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in the Knowledge Base workspace, none of this is a black box. You can open any document and &lt;strong&gt;inspect its individual chunks&lt;/strong&gt; - and &lt;em&gt;edit&lt;/em&gt; them, because sometimes the fix for a bad retrieval is one badly split paragraph - watch a document's indexing status, and, before any agent ever touches it, try queries against the KB in a built-in &lt;strong&gt;search interface&lt;/strong&gt; to see exactly what retrieval returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Documents In
&lt;/h2&gt;

&lt;p&gt;There are three doors in, matched to three situations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upload.&lt;/strong&gt; Drag files into the workspace. The ingestion pipeline picks the right parser per format - a dedicated PDF reader (page- or paragraph-oriented), a Markdown reader, JSON and plain-text readers, and an &lt;a href="https://tika.apache.org/" rel="noopener noreferrer"&gt;Apache Tika&lt;/a&gt;-based reader as the catch-all for Word documents and other office formats. All of these are Spring AI's document readers; ByteChef orchestrates them into one pipeline that ends in chunks and vectors. With OCR enabled, PDFs and images take a different route entirely - straight through an OCR service - so the scanned contract and the photographed whiteboard land in the index like everything else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From a workflow.&lt;/strong&gt; The &lt;strong&gt;Load Data&lt;/strong&gt; action writes into a knowledge base from anywhere a workflow can reach. Attach a &lt;strong&gt;document reader&lt;/strong&gt; (plus any transformers you want), point the action at the target KB, and every run pushes documents through the same chunk-and-embed pipeline the uploader uses. Put that workflow behind a schedule, a webhook, or a file-landed trigger and ingestion runs without you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From an agent.&lt;/strong&gt; The &lt;strong&gt;Knowledge Base Update&lt;/strong&gt; tool is a cluster element you attach to an AI Agent, so an agent can contribute what it learns rather than only consume it - useful when the thing worth keeping is something the agent worked out mid-conversation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whichever door you use, everything downstream is identical - parse, chunk, embed, index. What differs is who pushes the button, and how often.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping It Current - and the Deletes Nobody Plans For
&lt;/h2&gt;

&lt;p&gt;An index is a snapshot, and snapshots rot. Re-running ingestion is the easy half: put the &lt;strong&gt;Load Data&lt;/strong&gt; workflow on a schedule and new and changed documents flow in on whatever cadence suits the material - nightly for a handbook, hourly for a status page.&lt;/p&gt;

&lt;p&gt;The hard half is the one that quietly poisons RAG systems: &lt;strong&gt;deletions&lt;/strong&gt;. A refresh that asks the upstream for "everything that changed since Tuesday" gets back the records that still exist - never the ones that vanished. Left alone, a document deleted at the source lives on in your knowledge base indefinitely, still retrieved, still quoted by your agent, long after somebody retracted it.&lt;/p&gt;

&lt;p&gt;That half is yours to own today - ByteChef has no "connect a source and forget it" option that derives deletions for you. It's worth owning deliberately rather than discovering later, and the shape of the fix is simple enough: tag each ingested document with its upstream id, and on the runs where you can enumerate the full current upstream set, use the &lt;strong&gt;Delete Documents&lt;/strong&gt; action - it removes documents by metadata filter - to drop whatever is no longer in it. Unglamorous, and far cheaper than the alternative, which is an agent confidently citing a policy that was withdrawn a month ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Knowledge Out
&lt;/h2&gt;

&lt;p&gt;A knowledge base earns its keep at retrieval time, and ByteChef exposes it on every surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;As an AI Agent tool.&lt;/strong&gt; The &lt;strong&gt;Knowledge Base Search&lt;/strong&gt; tool is a cluster element - attach it to any AI Agent (the same way as every tool in our &lt;a href="https://blog.bytechef.io/blogs/bytechef-agentic-patterns" rel="noopener noreferrer"&gt;agentic patterns series&lt;/a&gt;), pick which KB it searches, and optionally scope it by &lt;strong&gt;tags&lt;/strong&gt; (documents matching &lt;em&gt;any&lt;/em&gt; selected tag are eligible). From then on, the agent decides when to reach into the knowledge base, mid-conversation, on its own. There's a &lt;strong&gt;Knowledge Base Update&lt;/strong&gt; tool too - for agents that should be able to &lt;em&gt;contribute&lt;/em&gt; knowledge, not just consume it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As workflow actions.&lt;/strong&gt; The Knowledge Base component ships &lt;strong&gt;Load Data&lt;/strong&gt;, &lt;strong&gt;Search Data&lt;/strong&gt;, &lt;strong&gt;Update Documents&lt;/strong&gt;, and &lt;strong&gt;Delete Documents&lt;/strong&gt; actions, so ordinary workflows can query or maintain a KB with no agent involved - "on new support ticket, search the KB and attach the top three matches" is three nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One store, several ways in and out - and because retrieval is tag-filterable, a single knowledge base can serve multiple audiences ("customer-facing" vs. "internal-only") without maintaining parallel copies.&lt;/p&gt;

&lt;p&gt;If you want to tune retrieval &lt;em&gt;itself&lt;/em&gt; - query rewriting, expansion, custom joins over several stores - that's a different layer: ByteChef's RAG cluster elements, which work over any vector store you like. The Knowledge Base is the batteries-included end of the same spectrum: you don't configure retrieval, you just ask it questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Inherit from Spring AI - and What ByteChef Adds
&lt;/h2&gt;

&lt;p&gt;By now you know the shape of this section. The primitives are Spring AI's; the product around them is ByteChef's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Document readers exist as library classes (PDF, Markdown, JSON, text, Tika)&lt;/em&gt; → ByteChef &lt;strong&gt;auto-selects the parser per file&lt;/strong&gt; in one managed ingestion pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Spring AI has no OCR reader at all&lt;/em&gt; → ByteChef adds one, and &lt;strong&gt;routes scanned PDFs and images through it&lt;/strong&gt; before any other parser gets a look.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;code&gt;PgVectorStore&lt;/code&gt; + &lt;code&gt;EmbeddingModel&lt;/code&gt; are yours to configure and operate&lt;/em&gt; → ByteChef &lt;strong&gt;owns the schema, the HNSW index, and the per-knowledge-base partitioning&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Chunking is a splitter you instantiate with magic numbers&lt;/em&gt; → chunk size, minimum, and overlap are &lt;strong&gt;fields on the create-knowledge-base form&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Ingestion is a pipeline you assemble, wire, and run yourself&lt;/em&gt; → it's &lt;strong&gt;one action with a reader attached&lt;/strong&gt;, on any trigger - or no workflow at all, if you just upload.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Retrieval is code you write&lt;/em&gt; → it's a &lt;strong&gt;tool on any agent&lt;/strong&gt;, &lt;strong&gt;actions in any workflow&lt;/strong&gt;, and a &lt;strong&gt;search UI&lt;/strong&gt; for humans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same foundation as everything in this series - Spring AI under the hood - with the operational half of RAG, the half that actually hurts, absorbed into the platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running It Yourself
&lt;/h2&gt;

&lt;p&gt;If you're self-hosting, the Knowledge Base ships &lt;strong&gt;disabled&lt;/strong&gt; - two switches turn it on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;bytechef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ai&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;knowledge-base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;vectorstore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pgvector&lt;/span&gt;
      &lt;span class="na"&gt;pgvector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdbc:postgresql://localhost:5433/bytechef_vectorstore&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That second block is the part worth planning for. The vector index lives in its &lt;strong&gt;own&lt;/strong&gt; pgvector-enabled PostgreSQL database, separate from ByteChef's application database - the development compose file runs one for you alongside the main Postgres, and in production it's a second database to provision, monitor, and back up. Still Postgres, still nothing exotic, but not the &lt;em&gt;same&lt;/em&gt; Postgres. ByteChef creates the schema and the index inside it on first use.&lt;/p&gt;

&lt;p&gt;One more prerequisite, easy to miss: an &lt;strong&gt;embedding model&lt;/strong&gt; has to be active for the environment. Without one there's nothing to turn chunks into vectors with, and the Knowledge Base page says so outright rather than quietly indexing nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The distance between "agents are impressive" and "agents are useful &lt;em&gt;here&lt;/em&gt;" is almost always knowledge - your documents, your data, your vocabulary. RAG closes that distance in principle; in practice it comes bundled with a parsing zoo, a vector database, an embedding budget, sync jobs, and the deletion problem nobody budgets for.&lt;/p&gt;

&lt;p&gt;ByteChef's Knowledge Base packages most of it: documents in through upload, a workflow action, or an agent; chunks and vectors in pgvector; retrieval exposed as agent tools, workflow actions, and a human search box. What stays with you is the refresh policy - how often to re-run ingestion, and what to do about the deletes. Your agents get something to know, and you skip almost all of the machinery of knowing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a folder of PDFs your agent should be quoting? Open &lt;a href="https://app.bytechef.io" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;, create a **Knowledge Base&lt;/em&gt;&lt;em&gt;, drop them in, and attach the **Knowledge Base Search&lt;/em&gt;* tool to your agent.*&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>rag</category>
      <category>search</category>
    </item>
    <item>
      <title>Agentic Workflow Patterns in ByteChef: The Five Patterns, No Code Required</title>
      <dc:creator>ByteChef</dc:creator>
      <pubDate>Fri, 21 Aug 2026 21:21:45 +0000</pubDate>
      <link>https://dev.to/bytechef/agentic-workflow-patterns-in-bytechef-the-five-patterns-no-code-required-k2e</link>
      <guid>https://dev.to/bytechef/agentic-workflow-patterns-in-bytechef-the-five-patterns-no-code-required-k2e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Anthropic's &lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Building Effective Agents&lt;/a&gt; research identified five workflow patterns behind most successful LLM systems: &lt;strong&gt;chain&lt;/strong&gt;, &lt;strong&gt;parallelization&lt;/strong&gt;, &lt;strong&gt;routing&lt;/strong&gt;, &lt;strong&gt;orchestrator-workers&lt;/strong&gt;, and &lt;strong&gt;evaluator-optimizer&lt;/strong&gt;. The Spring AI team &lt;a href="https://spring.io/blog/2025/01/21/spring-ai-agentic-patterns" rel="noopener noreferrer"&gt;implemented them in Java&lt;/a&gt;. ByteChef - which uses Spring AI under the hood - lets you build every one of them &lt;strong&gt;visually, on a workflow canvas, without writing code&lt;/strong&gt;. This post shows you how, pattern by pattern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In late 2024, Anthropic published &lt;a href="https://www.anthropic.com/research/building-effective-agents" rel="noopener noreferrer"&gt;Building Effective Agents&lt;/a&gt;, a piece of research that has aged remarkably well. Its central claim: the most successful LLM systems in production aren't built on complex frameworks - they're built from &lt;strong&gt;simple, composable patterns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://spring.io/projects/spring-ai" rel="noopener noreferrer"&gt;Spring AI&lt;/a&gt; team followed up with an excellent &lt;a href="https://spring.io/blog/2025/01/21/spring-ai-agentic-patterns" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; implementing those patterns in plain Java. If you're a Java developer, it's a great read.&lt;/p&gt;

&lt;p&gt;But here's the thing: ByteChef is built &lt;strong&gt;on top of Spring AI&lt;/strong&gt;. Every model integration, every structured-output call, every RAG pipeline in ByteChef runs on the same Spring AI foundation described in that post. Which means the same five agentic patterns are available to you - except instead of writing Java classes, you &lt;strong&gt;drag components onto a canvas&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Anthropic draws a useful distinction between two kinds of agentic systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflows&lt;/strong&gt; - systems where LLMs and tools are orchestrated through predefined paths. &lt;em&gt;You&lt;/em&gt; decide the structure; the LLM fills in the intelligence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agents&lt;/strong&gt; - systems where the LLM dynamically directs its own process and tool usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most production use cases are best served by workflows: they're predictable, debuggable, and cheaper to run. And a visual workflow builder is arguably the most natural way to express them - the pattern diagrams in Anthropic's paper practically &lt;em&gt;are&lt;/em&gt; ByteChef canvases.&lt;/p&gt;

&lt;p&gt;Let's build all five.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Building Blocks
&lt;/h2&gt;

&lt;p&gt;Before diving into the patterns, a quick inventory of the ByteChef pieces we'll compose them from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI model steps&lt;/strong&gt; - every AI provider component (OpenAI, Anthropic, Vertex Gemini, Mistral, Ollama, and &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;many more&lt;/a&gt;) exposes an &lt;em&gt;Ask&lt;/em&gt; action: prompt in, response out. Crucially, you can set the &lt;strong&gt;Response Format&lt;/strong&gt; to &lt;em&gt;Structured data&lt;/em&gt; and define a &lt;strong&gt;Response Schema&lt;/strong&gt;, so the model returns typed JSON instead of free text - the visual equivalent of Spring AI's structured output converter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The AI Agent component&lt;/strong&gt; - ByteChef's full agent building block, with pluggable Model, RAG, Memory, Tools, and Guardrails cluster elements. We covered it in depth in &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;Building Intelligent Automation with ByteChef and AI Agents&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flow controls&lt;/strong&gt; - the visual control-flow primitives that give workflows the same expressive power as code: &lt;a href="https://blog.bytechef.io/blogs/guide-to-flow-controls" rel="noopener noreferrer"&gt;Condition, Branch, and Loop&lt;/a&gt; for choice and repetition, plus &lt;a href="https://blog.bytechef.io/blogs/flow-controls-complete" rel="noopener noreferrer"&gt;Parallel, Fork/Join, Each, and Map&lt;/a&gt; for fanning out. Loop Break, which ends a loop early from inside its body, pairs with Loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data pills&lt;/strong&gt; - ByteChef's way of wiring one step's output into another step's input. Wherever you see "pass the result to the next step" below, that's a drag-and-drop data pill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the whole toolbox. Now the patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Chain Workflow
&lt;/h2&gt;

&lt;p&gt;The simplest pattern, and the one to reach for first: decompose a task into sequential steps, where each LLM call processes the output of the previous one.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fztcbi0bgysewerx83g0e.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fztcbi0bgysewerx83g0e.png" alt=" " width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why bother with three small prompts instead of one big one? Because each step gets a &lt;strong&gt;focused, simple instruction&lt;/strong&gt; - and focused instructions produce dramatically more reliable results than one prompt trying to do everything at once. You're trading a little latency for a lot of accuracy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building it in ByteChef
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add an AI model step (say, OpenAI &lt;em&gt;Ask&lt;/em&gt;) with a prompt that handles only the &lt;strong&gt;first&lt;/strong&gt; transformation - e.g. &lt;em&gt;"Extract every numerical value and its metric from this text."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Add a second model step whose prompt performs the next transformation, and reference the first step's output as a data pill: &lt;em&gt;"Convert all values to percentages: &lt;code&gt;${openai_1}&lt;/code&gt;"&lt;/em&gt;. (In text mode an &lt;em&gt;Ask&lt;/em&gt; step outputs its response string directly - field references like &lt;code&gt;${openai_1.category}&lt;/code&gt; become available once you switch it to &lt;em&gt;Structured data&lt;/em&gt;.)&lt;/li&gt;
&lt;li&gt;Keep chaining. Each step sees only what the previous step produced.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also insert a &lt;strong&gt;Condition&lt;/strong&gt; between steps as a &lt;em&gt;gate&lt;/em&gt; - Anthropic's recommended addition - to verify an intermediate result before continuing (for example, checking that step one actually produced a number before running the expensive formatting step).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; the task has clear sequential stages, each stage builds on the last, and you'd rather wait an extra second than get a sloppy answer. A typical example: &lt;em&gt;extract data → normalize it → sort it → format it as a Markdown table&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Parallelization Workflow
&lt;/h2&gt;

&lt;p&gt;Some tasks aren't sequential - they're several independent subtasks that can run &lt;strong&gt;at the same time&lt;/strong&gt;, with the results aggregated at the end.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh132p2nsuuta4bjdea4f.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh132p2nsuuta4bjdea4f.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anthropic describes two flavors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sectioning&lt;/strong&gt; - split the task into independent subtasks (analyze the same document from a legal, financial, and technical perspective).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voting&lt;/strong&gt; - run the &lt;em&gt;same&lt;/em&gt; prompt several times and compare answers for consensus (useful for high-stakes classification).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Building it in ByteChef
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Fork/Join&lt;/strong&gt; flow control. Each branch runs in parallel as an isolated sub-flow.&lt;/li&gt;
&lt;li&gt;In each branch, add an AI model step with its own perspective-specific prompt. All branches can reference the same input via data pills.&lt;/li&gt;
&lt;li&gt;After the join, add one final model step that receives all branch outputs and synthesizes them: &lt;em&gt;"Combine these three analyses into a single executive summary."&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For list-shaped work - "run this same LLM analysis over 50 support tickets" - use the &lt;strong&gt;Each&lt;/strong&gt; flow control instead: it iterates over the items in parallel, applying the same steps to every one. And with the &lt;strong&gt;Parallel&lt;/strong&gt; flow control you can fire off a set of independent tasks without waiting for each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; subtasks are genuinely independent, you need multiple perspectives on the same input, or you're processing volumes where sequential execution would be painfully slow.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Routing Workflow
&lt;/h2&gt;

&lt;p&gt;Routing classifies the input first, then sends it down a &lt;strong&gt;specialized path&lt;/strong&gt;. Instead of one generalist prompt trying to handle billing questions, technical issues, and small talk equally badly, each category gets a handler tuned for exactly its kind of input.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft8hq4oaqvliw1rmy2ad8.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft8hq4oaqvliw1rmy2ad8.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building it in ByteChef
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add an AI model step as the &lt;strong&gt;classifier&lt;/strong&gt;. Set its Response Format to &lt;em&gt;Structured data&lt;/em&gt; and define a Response Schema with a single string field restricted to your categories (&lt;code&gt;billing&lt;/code&gt;, &lt;code&gt;technical&lt;/code&gt;, &lt;code&gt;general&lt;/code&gt;). Constraining the output through the schema is what makes routing dependable - instead of a free-text answer the Branch can't act on, you get one of your category strings back.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Branch&lt;/strong&gt; flow control keyed on the classifier's output. Branch executes exactly one path based on the expression value - a visual switch statement. Add a &lt;strong&gt;default branch&lt;/strong&gt; as well: the schema constrains the &lt;em&gt;shape&lt;/em&gt; of the answer, not its judgment, so a classifier can still misfire or return something you didn't plan for.&lt;/li&gt;
&lt;li&gt;In each branch, add the specialized handler: a model step with a category-specific system prompt, a full AI Agent with category-specific tools, or no LLM at all (some routes just need a Slack notification).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn't hypothetical - it's exactly the architecture of our &lt;a href="https://blog.bytechef.io/blogs/ai-email-classifier" rel="noopener noreferrer"&gt;AI Email Classifier&lt;/a&gt; tutorial, which routes incoming emails to Sales, Support, Finance, Operations, and HR using OpenAI structured output plus branching - default branch included. Routing is arguably the most production-proven agentic pattern there is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; inputs fall into distinct categories that benefit from separate handling, and classification is reliable. Bonus: you can route easy categories to a small, cheap model and reserve the expensive one for the hard cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Orchestrator-Workers
&lt;/h2&gt;

&lt;p&gt;The patterns so far have fixed structure - you know at design time which steps run. Orchestrator-workers is for tasks where the required subtasks &lt;strong&gt;can't be predicted in advance&lt;/strong&gt;. A central LLM analyzes the request, breaks it into subtasks dynamically, delegates each one to a specialized worker, and synthesizes the results.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0u5e56n2zjjdywk5zlt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0u5e56n2zjjdywk5zlt.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building it in ByteChef
&lt;/h3&gt;

&lt;p&gt;This is where ByteChef's &lt;strong&gt;AI Agent&lt;/strong&gt; component shines, because an AI Agent can use &lt;em&gt;another AI Agent as a tool&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add an AI Agent as the &lt;strong&gt;orchestrator&lt;/strong&gt;. Its system prompt describes its job: analyze the request, decide which specialists to involve, and combine their answers.&lt;/li&gt;
&lt;li&gt;Under its &lt;strong&gt;Tools&lt;/strong&gt; cluster element, add sub-agents - a research agent, a drafting agent, a data-lookup agent - each with its own model, system prompt, and tools. Give each a clear description so the orchestrator knows when to delegate to it.&lt;/li&gt;
&lt;li&gt;The orchestrator now decides &lt;em&gt;at runtime&lt;/em&gt; which workers to call, in what order, and how to merge their outputs. The composition is recursive: sub-agents can have sub-agents of their own.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Prefer to keep the orchestration explicit on the canvas? There's a workflow-level variant: have an orchestrator model step emit a &lt;strong&gt;structured list of subtasks&lt;/strong&gt;, feed that list into an &lt;strong&gt;Each&lt;/strong&gt; flow control that runs a worker step per subtask in parallel, then aggregate with a final LLM step. You get dynamic decomposition while every execution stays visible in the workflow history, step by step.&lt;/p&gt;

&lt;p&gt;We covered agent composition, the Agent Playbook for testing, and the full cluster-element architecture in &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;the AI Agent deep dive&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; you can't enumerate the subtasks up front - complex research questions, multi-file code changes, requests that span several domains at once.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Evaluator-Optimizer
&lt;/h2&gt;

&lt;p&gt;The last pattern adds something the others lack: &lt;strong&gt;self-correction&lt;/strong&gt;. One LLM generates a response; a second LLM evaluates it against explicit criteria. If the evaluation fails, the feedback goes back to the generator for another attempt - a draft-and-review loop, automated.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqjbyikwgtwywoh1ulpwu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqjbyikwgtwywoh1ulpwu.png" alt=" " width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building it in ByteChef
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Loop&lt;/strong&gt; flow control and set its &lt;strong&gt;List of Items&lt;/strong&gt; to a fixed three-element list. That caps the attempts at three - if it isn't converging by then, more laps rarely help.&lt;/li&gt;
&lt;li&gt;Inside the loop, add the &lt;strong&gt;generator&lt;/strong&gt; model step. Its prompt includes the task plus, via data pills, the previous attempt and the evaluator's feedback when they exist.&lt;/li&gt;
&lt;li&gt;Add the &lt;strong&gt;evaluator&lt;/strong&gt; model step with structured output: a schema with an &lt;code&gt;evaluation&lt;/code&gt; field constrained to &lt;code&gt;PASS&lt;/code&gt; / &lt;code&gt;NEEDS_IMPROVEMENT&lt;/code&gt; and a &lt;code&gt;feedback&lt;/code&gt; string. Give it concrete criteria - "evaluate for correctness, completeness, and tone" beats "is this good?".&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Condition&lt;/strong&gt; on the evaluation. On &lt;code&gt;PASS&lt;/code&gt;, put a &lt;strong&gt;Loop Break&lt;/strong&gt; in that branch - it ends the enclosing loop immediately and you carry on with the accepted result. Otherwise the loop runs again, and the generator sees the fresh feedback.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two different prompts - or even two different models - playing generator and critic consistently outperforms a single model trying to self-assess in one call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; you have clear evaluation criteria and the output is worth iterating on - customer-facing copy, generated code, translations, anything with a quality bar. Skip it for cheap, low-stakes outputs; the extra LLM calls should buy you measurable quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Spring AI Under the Hood Matters
&lt;/h2&gt;

&lt;p&gt;The Spring AI post closes by highlighting what the framework contributes to these patterns. Because ByteChef is built on Spring AI, you inherit every one of those advantages - plus a few that only a visual platform can add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model portability.&lt;/strong&gt; Spring AI's &lt;code&gt;ChatModel&lt;/code&gt; abstraction normalizes providers, so in ByteChef swapping OpenAI for Claude, Gemini, or a local Ollama model is a dropdown change, not a refactor. Build the pattern once, A/B the model later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured output.&lt;/strong&gt; Every response schema you define in a ByteChef AI step rides on Spring AI's structured-output machinery. Routing and evaluator-optimizer depend on this - patterns fall apart when the classifier answers with an essay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A consistent, maintained foundation.&lt;/strong&gt; New providers, new vector stores, and new capabilities land in Spring AI continuously, and ByteChef picks them up - without you rewriting workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And what ByteChef adds on top:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observability for free.&lt;/strong&gt; Every pattern above produces a step-by-step execution history: every prompt, every intermediate output, every branch decision, inspectable per run. No logging code required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools without glue code.&lt;/strong&gt; Any action from ByteChef's 280+ connectors can be handed to an agent as a tool - the orchestrator pattern gets Slack, Salesforce, and Google Sheets access in a few clicks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails and testing built in.&lt;/strong&gt; Wrap any agent in content and topic guardrails, and test it live in the &lt;a href="https://blog.bytechef.io/blogs/spring-ai-agent" rel="noopener noreferrer"&gt;Agent Playbook&lt;/a&gt; while you build.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Choosing the Right Pattern
&lt;/h2&gt;

&lt;p&gt;Chain - Fixed, sequential - The task has clear stages that build on each other&lt;br&gt;
Parallelization - Fixed, concurrent  -Subtasks are independent, or you want multiple perspectives&lt;br&gt;
Routing - Fixed paths, dynamic choice - Inputs fall into categories needing different handling&lt;br&gt;
Orchestrator-workers - Dynamic - Subtasks can't be predicted at design time&lt;br&gt;
Evaluator-optimizer - Iterative - Clear quality criteria exist, and iteration measurably helps |&lt;/p&gt;

&lt;p&gt;Anthropic's guidance - echoed by the Spring AI team, and just as true on a canvas as in Java - is worth repeating: &lt;strong&gt;start with the simplest pattern that could work&lt;/strong&gt;. A well-prompted single LLM step beats a five-agent system that nobody can debug. Add parallelization when latency hurts, routing when one prompt stops fitting all inputs, and orchestration only when the task genuinely demands dynamic decomposition. Complexity should be earned.&lt;/p&gt;

&lt;p&gt;The nice thing about building these patterns visually is that &lt;em&gt;upgrading&lt;/em&gt; between them is cheap: a chain becomes a routing workflow by dropping in one classifier step and a Branch; a single agent becomes an orchestrator by adding sub-agents to its Tools. Your architecture can grow exactly as fast as your use case does.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>bytechef</category>
      <category>spring</category>
    </item>
    <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>
