<b>Flowise 2. 0 introduces one of the most</b> <b>powerful features to date,</b> <b>sequential agentic flows. </b> <b>With sequential agents, you can control</b> <b>your multi-agent</b> <b>applications like never before.
</b> <b>You can call agents conditionally, run</b> <b>them in parallel, add</b> <b>human in the loop, and much,</b> <b>much more. Unlike multi-agent flows,</b> <b>where the supervisor controls</b> <b>the flow of the application,</b> <b>sequential agents give you full control. </b> <b>In this video, we will look at the most</b> <b>important concepts</b> <b>related to sequential agents.
</b> <b>If you're new to Flowwise, then you're</b> <b>definitely in for a treat. </b> <b>Flowwise is a low-code platform</b> <b>for building advanced AI applications</b> <b>using a simple drag-and-drop interface. </b> <b>It's open source and completely free to</b> <b>use.
I have plenty of</b> <b>videos on my channel showing you</b> <b>how to install, update, and self-host</b> <b>Flowwise. But in order to</b> <b>make this a complete tutorial</b> <b>for beginners, we will set up Flowwise on</b> <b>our local machines. If</b> <b>you already have Flowwise</b> <b>installed, then please ensure to update</b> <b>your instance to version 2.
0 or greater. </b> <b>In order to install Flowwise on your</b> <b>machine, you need to</b> <b>install Node. js from this website,</b> <b>and after installing Node, open the</b> <b>command prompt or terminal</b> <b>on your machine, and enter</b> <b>"npx flowwise start".
The first time you</b> <b>execute this, you will be</b> <b>asked whether you want to</b> <b>install Flowwise and its dependencies. </b> <b>Simply enter "y" and press</b> <b>enter. And once installation</b> <b>is complete, you can access Flowwise in</b> <b>your browser by going to</b> <b>localhost 3000, and you</b> <b>should be presented with a dashboard like</b> <b>this.
Now, in order to</b> <b>build multi-agent flows, we need</b> <b>to go to "agent flows", and let's add a</b> <b>new flow. I'll start by giving</b> <b>my flow a name, and I'll call</b> <b>this "sequential agent basics". Within</b> <b>Flowwise, we can build all sorts of</b> <b>multi-agent solutions.
</b> <b>If we go to "add nodes", we can of course</b> <b>use multi-agent teams,</b> <b>where a supervisor will control</b> <b>the logic flow between the different</b> <b>worker nodes. But with</b> <b>the release of Flowwise 2. 0,</b> <b>we now have sequential agents, which</b> <b>gives us way more control</b> <b>over the flow of our application.
</b> <b>And at first, this might seem extremely</b> <b>intimidating, as we have several nodes to</b> <b>choose from. But in this video, we will</b> <b>go through each of these nodes, and by</b> <b>the end of the video,</b> <b>you will be able to create extremely cool</b> <b>and complex multi-agent applications. </b> <b>Let's start by looking at the start node.
</b> <b>The start node does</b> <b>exactly what you would think. </b> <b>This represents the start of our</b> <b>sequential flow. The start node takes in</b> <b>a chat model as input,</b> <b>as well as memory, state, and input</b> <b>moderation.
Let's start by adding our</b> <b>LLM. Let's go to "add</b> <b>nodes", and under "chat models", we can</b> <b>add any of the available</b> <b>chat models to our application. </b> <b>If you want to follow along without</b> <b>incurring any costs, then I</b> <b>highly recommend using the</b> <b>"grok chat model".
It's free to use and</b> <b>blazingly fast, and I</b> <b>already created a separate video</b> <b>showing you how to integrate grok chat</b> <b>with Flow-wise. But for</b> <b>this demo, I'll actually use</b> <b>the "chat OpenAI" node. So I'll start by</b> <b>adding this node to the</b> <b>canvas.
Let's start by setting</b> <b>our OpenAI credentials by clicking on the</b> <b>drop-down, and let's click on "create</b> <b>new". Let's give our</b> <b>credential a name, like "OpenAI API". Now</b> <b>we just have to fit our</b> <b>OpenAI API key, which we can get</b> <b>from "platform.
openai. com slash API</b> <b>keys". Let's create a new key by clicking</b> <b>on "create new secret</b> <b>key".
Let's give it a name, and let's</b> <b>click on "create secret key". Then copy</b> <b>this key, and paste it into</b> <b>this field in Flow-wise. Let's click on</b> <b>"add", and then let's select our model</b> <b>name.
For this demo,</b> <b>I'm going to select the "gpt40" model,</b> <b>and I'm going to change the</b> <b>temperature to 0. 2. And let's</b> <b>attach our chat model to the start node.
</b> <b>Great! Now let's add our</b> <b>first agent to this Flow. Let's</b> <b>go to "add nodes", and then under</b> <b>"sequential agents", add the agent node.
</b> <b>Let's connect our start node</b> <b>to our agent node. Now let's have a</b> <b>closer look at the agent node. For agent</b> <b>nodes, we can assign</b> <b>tools.
We can also add a preceding node,</b> <b>which could either be a</b> <b>start node, another agent,</b> <b>an LLM node, or a tool node. We can also</b> <b>assign a chat model, but this is</b> <b>optional. If we don't</b> <b>assign a chat model, the agent node will</b> <b>simply inherit the model</b> <b>assigned to the starting node,</b> <b>which in our example is this chat openai</b> <b>node.
We also need to</b> <b>provide our agent with a name,</b> <b>and take note this name needs to be</b> <b>unique. Let's call this agent</b> <b>"assistant". We can also enter</b> <b>a "system" prompt, which we can use to</b> <b>prime the model, provide context, set a</b> <b>role, etc.
Let's clear</b> <b>these values, and let's set our prompt as</b> <b>"You are a friendly</b> <b>assistant called John". Let's have a</b> <b>look at the rest of this node. "Require</b> <b>approval" can be used to enable human in</b> <b>the loop functionality,</b> <b>which we will look at later on in this</b> <b>video.
You can use "format</b> <b>prompt values" to set the values</b> <b>of variables, which we will look at as</b> <b>well, and if we click on additional</b> <b>parameters, we can use</b> <b>the "approval prompt approve button text</b> <b>and reject button"</b> <b>when the human in the loop</b> <b>functionality is enabled. We also have</b> <b>the capability of updating</b> <b>state, which we will look</b> <b>at later as well. But for now, we are</b> <b>done with the agent.
Now before we can</b> <b>run this, we do need</b> <b>to set some sort of end state. Let's go</b> <b>to add nodes, and with "in sequential</b> <b>agents", we can either</b> <b>add an end node or a loop node. Both of</b> <b>these nodes represent an end</b> <b>state in our flow.
For now,</b> <b>let's simply add an end node, and let's</b> <b>attach our agent to this end</b> <b>node like so. We can now save</b> <b>our flow, and in the chat, let's test</b> <b>this out. Let's say "hello".
And of</b> <b>course, we can see that</b> <b>the assistant node was executed as well</b> <b>as the response from that node. </b> <b>Fantastic! We now have an</b> <b>agent that we can talk to.
Now let's</b> <b>discuss agent memory. During the</b> <b>execution of the flow,</b> <b>the conversation history is added to a</b> <b>global state, and after</b> <b>execution, all those messages</b> <b>are deleted. So when we execute the flow</b> <b>again, our agent will not</b> <b>be able to recall information</b> <b>from past messages, and I can prove that</b> <b>to you.
Let's enter</b> <b>something like "my name is Leon". Our</b> <b>agent will greet us with my name, but if</b> <b>I then ask it "what is my</b> <b>name? ", the agent can't recall</b> <b>that information.
So to add memory to our</b> <b>flow, we can simply go to add</b> <b>nodes, then within "memory",</b> <b>we can add the agent memory node. I'm</b> <b>actually going to move these</b> <b>nodes around just to make a</b> <b>bit of space. And now let's attach our</b> <b>agent memory node to the agent memory</b> <b>input on the start node.
</b> <b>With this node, the conversation history</b> <b>will actually be stored</b> <b>in a SQLite database. Let's</b> <b>go ahead and test this out by saving the</b> <b>flow, and in the chat, let's try</b> <b>providing my name again</b> <b>by entering "my name is Leon", and now</b> <b>let's ask it "what is my</b> <b>name? ", and this time our assistant</b> <b>was able to recall my name.
Great! Now</b> <b>let's discuss the state node. </b> <b>By default, the conversation</b> <b>history is added to state and shared</b> <b>amongst all the agents in the</b> <b>flow, but we can also use the</b> <b>state structure to store our very own</b> <b>values, and these values will be shared</b> <b>amongst all the agents</b> <b>in the state as well.
Let's have a look</b> <b>at an example. Let's go to</b> <b>add nodes under sequential</b> <b>agents. Let's add the state node.
Let's</b> <b>attach this node to our</b> <b>starting node, and now we can</b> <b>click on additional parameters to add our</b> <b>very own state properties. </b> <b>Now take note we do not have to</b> <b>add a property for the conversation</b> <b>history as that is handled for us by</b> <b>default, so all we have to do</b> <b>is add any additional values to the state</b> <b>which we want to make available to our</b> <b>agents. As an example,</b> <b>let's set a value for my name in state.
</b> <b>Let's click on add item. Let's enter a</b> <b>key value as a name,</b> <b>and for the operation let's simply select</b> <b>replace. You can use the</b> <b>append operation to simply add</b> <b>values to an array or a list of values.
</b> <b>For now we simply want to</b> <b>replace the value with my name. </b> <b>Great! This value can be retrieved by the</b> <b>agents from the state</b> <b>structure.
Let me show you how that</b> <b>works. Let's make the name available to</b> <b>this agent by changing the</b> <b>system prompt slightly. Let's add</b> <b>something like you are talking to, and</b> <b>instead of hardcoding my name</b> <b>like this, we want to retrieve</b> <b>the value from the state.
So let's add a</b> <b>variable value using</b> <b>opening and closing curly braces,</b> <b>and within the braces let's give this</b> <b>placeholder a name. I'll just call mine</b> <b>name. Let's click on save.
</b> <b>Now we just have to link up this</b> <b>placeholder with the value from state,</b> <b>and we can do that by</b> <b>clicking on format prompt values. At the</b> <b>moment the name variable</b> <b>is simply an empty string,</b> <b>and we can change that by clicking on the</b> <b>edit button, and if we</b> <b>click on this field we can now</b> <b>select from a range of values. The</b> <b>question is simply the</b> <b>message from the chat window.
We can</b> <b>also access the chat history, or we can</b> <b>fetch the first message from</b> <b>the content, or the last message</b> <b>from our list of messages. What we are</b> <b>interested is this option over here. </b> <b>Let's then edit this</b> <b>value, and let's replace this with our</b> <b>name value in state.
So this</b> <b>is referring to this key value</b> <b>in the state structure, which has a value</b> <b>of Leon. So let's test this</b> <b>out by going through the chat,</b> <b>and it say hello, and as you can see the</b> <b>agent now knows our name. So</b> <b>let's say we wanted to change</b> <b>this value from Leon to John.
Let's save</b> <b>this flow, let's test it again, and let's</b> <b>ask what is my name,</b> <b>and as you can see it is pulling the name</b> <b>from the state. Great! </b> <b>Now let's have a look at the</b> <b>condition node.
We can use the condition</b> <b>node to conditionally call</b> <b>agents. Let's assume that the</b> <b>first time you execute this flow the</b> <b>user's name in the state</b> <b>property will actually be blank. </b> <b>If the value is blank then we want to</b> <b>call an agent which will be</b> <b>responsible for collecting</b> <b>the user's name and then storing that</b> <b>name in the state property.
So</b> <b>the second time we execute the</b> <b>flow and then if the name is populated</b> <b>this assistant over here</b> <b>will be triggered. So let's</b> <b>set that up. First I'm just going to make</b> <b>some space by moving this</b> <b>agent over.
Let's break this</b> <b>connection and let's add a second agent</b> <b>which will be responsible for collecting</b> <b>the user's information. </b> <b>So let's add that agent, let's give it a</b> <b>name like name collection</b> <b>agent, and in the system</b> <b>prompt let's enter something like you are</b> <b>responsible for</b> <b>collecting the user's name. </b> <b>Let's also provide the steps that the</b> <b>agent can follow like if the</b> <b>user has not provided their</b> <b>name then politely ask for their name and</b> <b>if the user provided their</b> <b>name then ask them how can I</b> <b>assist you.
Let's save this agent and</b> <b>let's attach our agent to the</b> <b>end node. So now we have two</b> <b>agents which we want to call</b> <b>conditionally based on whether the name</b> <b>is set in state. Let's go to</b> <b>add nodes and with the sequential agents</b> <b>let's add the condition node.
Let's</b> <b>attach the start node</b> <b>to this condition node and now let's have</b> <b>a look at the details of</b> <b>this condition node. First let's</b> <b>give our condition node a name. This can</b> <b>be anything you want like check if the</b> <b>user has a name.
Then</b> <b>let's click on this condition button. </b> <b>Here we can set up the different</b> <b>conditions for this node. </b> <b>We can either use this condition table or</b> <b>we can handle this</b> <b>programmatically using code.
Let's</b> <b>stick with the condition table. Let's add</b> <b>a new item and for the</b> <b>variable we can access the name</b> <b>property in state. So we can say that if</b> <b>the name is not empty we</b> <b>then want to simply continue to</b> <b>our agent node.
You can call this output</b> <b>whatever you want. I'll</b> <b>simply call it continue but if we</b> <b>save this you will now notice this</b> <b>continue output over here. If none of the</b> <b>conditions in this list</b> <b>is met the end output will be executed.
</b> <b>We can also have additional</b> <b>outputs so for example let's</b> <b>say we had a specific output for a name</b> <b>that is Leon. We could add</b> <b>a Leon output as well and if</b> <b>I save this you will now notice this</b> <b>connection over here for Leon but of</b> <b>course we don't need</b> <b>that for now. But if the name is empty</b> <b>this end output will be</b> <b>triggered which we can hook up</b> <b>to our name collection agent.
Like so</b> <b>let's test this out by saving the flow</b> <b>and just as a reminder</b> <b>if we go to state the name is currently</b> <b>John. So we would expect this flow to</b> <b>trigger the continue</b> <b>output over here. In the chat let's say</b> <b>hello and indeed this triggered our</b> <b>assistant node.
So let's</b> <b>test this end scenario by going to state</b> <b>let's clear the name then</b> <b>let's save the flow and in the</b> <b>chat let's say hello and this time it is</b> <b>triggering the name</b> <b>collection agent. Great it's very</b> <b>important to note that although we</b> <b>provided our name this name was not</b> <b>stored in the global state</b> <b>so in order to grab this name from the</b> <b>user's message and then</b> <b>store it in state we will be</b> <b>using another node called the LLM node. </b> <b>We can use the LLM node to</b> <b>process unstructured data</b> <b>like a user's message to extract</b> <b>information from the message and then</b> <b>output the data in a</b> <b>structured format.
Let me give you an</b> <b>example of why you would</b> <b>want to parse unstructured data. </b> <b>In this example I simply parsed my name</b> <b>so you might think that</b> <b>it's simple enough to simply</b> <b>grab the value that the user provided and</b> <b>install that value in state</b> <b>but what if the user entered</b> <b>something like my name is Leon that would</b> <b>mean that the agent would</b> <b>store this entire string</b> <b>as the name in the state which is not</b> <b>correct. We want to use the intelligence</b> <b>of an LLM to identify</b> <b>a human name from the string and then</b> <b>output only that name and store it in</b> <b>state.
All right enough</b> <b>talk let's actually implement this. Let's</b> <b>go to add nodes and with in</b> <b>sequential agents let's add</b> <b>the LLM node. Before we attach this node</b> <b>to anything let's first</b> <b>have a look at this node</b> <b>in isolation.
This node can be triggered</b> <b>by the starting node another</b> <b>agent an LLM or a tool node</b> <b>so effectively this node will receive the</b> <b>output of one of these</b> <b>nodes and then process that data</b> <b>in any way that we want. Let's actually</b> <b>start by giving this node a</b> <b>name like name collector and</b> <b>within additional parameters we can</b> <b>provide clear instructions on what sort</b> <b>of data this node needs</b> <b>to extract. For example your job is to</b> <b>identify and extract a human</b> <b>name from the user's message</b> <b>only respond with the name.
We'll leave</b> <b>the human prompt empty and</b> <b>what we can then do is add a</b> <b>variable for the user message and again</b> <b>we can create variables</b> <b>using opening and closing curly</b> <b>braces. Let's call this question or</b> <b>whatever you want then with informat</b> <b>prompt values we can</b> <b>simply assign the question from the chat</b> <b>box like so. So this will</b> <b>now receive something like</b> <b>my name is Leon and with this prompt the</b> <b>model will try to extract</b> <b>the name.
Now one of the</b> <b>benefits of the LLM nodes is we can</b> <b>return the data in a fixed structure. In</b> <b>this example we want</b> <b>to return the name so let's add an item</b> <b>let's call this name which is of type</b> <b>string and we can add a</b> <b>description like the name of the user. So</b> <b>as this LLM node would have</b> <b>extracted the name from the</b> <b>user's message it will then assign the</b> <b>name to this key value over</b> <b>here and additionally we can</b> <b>also use this node to update state and</b> <b>that is exactly what we</b> <b>want to do.
Let's click on add</b> <b>item within the state we want to reassign</b> <b>this name property and</b> <b>for the value we want to use</b> <b>this name output over here so from this</b> <b>list of values we will</b> <b>select flow dot output and we will</b> <b>replace this key value with name. This is</b> <b>the value from this JSON output</b> <b>structure. I know there</b> <b>was a lot to process but these LLM nodes</b> <b>are extremely powerful.
</b> <b>Simply see it as a node that</b> <b>can receive output from another node,</b> <b>extract information from that output,</b> <b>store the information</b> <b>that it extracted into this structured</b> <b>output list and optionally</b> <b>we can use the values that it</b> <b>extracted to update state. Now the</b> <b>question is where do we add this node in</b> <b>this flow and for me</b> <b>it makes sense to add it after this</b> <b>condition node and during this flow where</b> <b>we collect the name. </b> <b>I'm actually going to move these nodes</b> <b>over let's break this connection let's</b> <b>bring in the LLM node</b> <b>let's attach this end connector to the</b> <b>LLM node and then let's</b> <b>connect our LLM node to our agent.
</b> <b>So let's quickly have a look at this</b> <b>again initially the name</b> <b>property in the state is blank</b> <b>so the condition node will route us down</b> <b>this path where the agent will ask the</b> <b>user to provide their</b> <b>name. If the user simply enters something</b> <b>like hello this LLM node</b> <b>will not be able to extract</b> <b>the name from that text and therefore</b> <b>also not set the name in</b> <b>state then the name collection</b> <b>agent will be called to ask the user for</b> <b>their name. The user will</b> <b>then enter their name which</b> <b>will again trigger this path this time</b> <b>the name collector will be able to</b> <b>extract their name and</b> <b>update state and the name collection</b> <b>agent will then determine</b> <b>that the name was provided</b> <b>and then ask the user how the agent can</b> <b>help them.
In fact in the</b> <b>scenario where the user enters</b> <b>something that's not a name we simply</b> <b>want the LLM node to return a</b> <b>blank value so let's announce</b> <b>this slightly to add something like if</b> <b>you are unable to determine a</b> <b>name like if the user entered</b> <b>hello or hi then return a blank value for</b> <b>the name. Let's save our</b> <b>flow let's enter hello and</b> <b>in the name collector we can actually see</b> <b>the changes that were</b> <b>made to the state which was</b> <b>simply a blank value because we were</b> <b>unable to determine a name. </b> <b>Also the name collection agent</b> <b>responded with what is your name now</b> <b>let's see what happens if we actually</b> <b>enter a name.
My name</b> <b>is Leon this time the name collector was</b> <b>able to extract the name</b> <b>and store that value in state. </b> <b>Now the name collection agent is asking</b> <b>us how they can help if we</b> <b>send another message we will</b> <b>expect the flow to take us to the</b> <b>assistant agent so let's enter something</b> <b>like why is the sky blue</b> <b>so we can now see that the condition node</b> <b>called the assistant</b> <b>agent and it was the assistant</b> <b>agent that responded so I hope you will</b> <b>agree that the LLM nodes are extremely</b> <b>powerful for parsing</b> <b>unstructured data and for setting state.