Master Sequential Agents: Build Complex AI Apps with Flowise β
Flowise AI (2024) TutorialAgingπ
2024-07-31
Build Process β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BUILD CHATBOT WORKFLOW β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β PLANNING β
β ββββββββ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β Define βββββΊβ Choose βββββΊβ Setup β β
β β Scope β β Stack β β Project β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β
β βΌ β
β DEVELOPMENT β
β βββββββββββ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β Build βββββΊβ Add AI βββββΊβ Test & β β
β β Features β β Logic β β Debug β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β
β βΌ β
β DEPLOYMENT β
β ββββββββββ β
β βββββββββββββββ βββββββββββββββ β
β β Deploy βββββΊβ Chatbot β βββ LIVE! β
β β to Cloud β β Running β β
β βββββββββββββββ βββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββKey Components β
- Project architecture
- Core features implementation
- Best practices
Transcript β
[00:00] Flowise 2.0 introduces one of the most powerful features to date, sequential agentic flows. With sequential agents, you can control your multi-agent applications like never before. You can call agents conditionally, run them in parallel, add human in the loop, and much, much more. Unlike multi-agent flows, where the supervisor controls the flow of the application, sequential agents give you full control. In this video, we will look at the most important concepts
[00:31] related to sequential agents. If you're new to Flowwise, then you're definitely in for a treat. Flowwise is a low-code platform for building advanced AI applications using a simple drag-and-drop interface. It's open source and completely free to use. I have plenty of videos on my channel showing you how to install, update, and self-host Flowwise. But in order to make this a complete tutorial for beginners, we will set up Flowwise on our local machines. If you already have Flowwise installed, then please ensure to update
[01:03] your instance to version 2.0 or greater. In order to install Flowwise on your machine, you need to install Node.js from this website, and after installing Node, open the command prompt or terminal on your machine, and enter "npx flowwise start". The first time you execute this, you will be asked whether you want to install Flowwise and its dependencies. Simply enter "y" and press enter. And once installation is complete, you can access Flowwise in your browser by going to
[01:34] localhost 3000, and you should be presented with a dashboard like this. Now, in order to build multi-agent flows, we need to go to "agent flows", and let's add a new flow. I'll start by giving my flow a name, and I'll call this "sequential agent basics". Within Flowwise, we can build all sorts of multi-agent solutions. If we go to "add nodes", we can of course use multi-agent teams, where a supervisor will control the logic flow between the different worker nodes. But with
[02:05] the release of Flowwise 2.0, we now have sequential agents, which gives us way more control over the flow of our application. And at first, this might seem extremely intimidating, as we have several nodes to choose from. But in this video, we will go through each of these nodes, and by the end of the video, you will be able to create extremely cool and complex multi-agent applications. Let's start by looking at the start node. The start node does
[02:36] exactly what you would think. This represents the start of our sequential flow. The start node takes in a chat model as input, as well as memory, state, and input moderation. Let's start by adding our LLM. Let's go to "add nodes", and under "chat models", we can add any of the available chat models to our application. If you want to follow along without incurring any costs, then I highly recommend using the "grok chat model". It's free to use and
[03:06] blazingly fast, and I already created a separate video showing you how to integrate grok chat with Flow-wise. But for this demo, I'll actually use the "chat OpenAI" node. So I'll start by adding this node to the canvas. Let's start by setting our OpenAI credentials by clicking on the drop-down, and let's click on "create new". Let's give our credential a name, like "OpenAI API". Now we just have to fit our OpenAI API key, which we can get from "platform.openai.com slash API
[03:40] keys". Let's create a new key by clicking on "create new secret key". Let's give it a name, and let's click on "create secret key". Then copy this key, and paste it into this field in Flow-wise. Let's click on "add", and then let's select our model name. For this demo, I'm going to select the "gpt40" model, and I'm going to change the temperature to 0.2. And let's attach our chat model to the start node. Great! Now let's add our first agent to this Flow. Let's
[04:10] go to "add nodes", and then under "sequential agents", add the agent node. Let's connect our start node to our agent node. Now let's have a closer look at the agent node. For agent nodes, we can assign tools. We can also add a preceding node, which could either be a start node, another agent, an LLM node, or a tool node. We can also assign a chat model, but this is optional. If we don't assign a chat model, the agent node will simply inherit the model
[04:41] assigned to the starting node, which in our example is this chat openai node. We also need to provide our agent with a name, and take note this name needs to be unique. Let's call this agent "assistant". We can also enter a "system" prompt, which we can use to prime the model, provide context, set a role, etc. Let's clear these values, and let's set our prompt as "You are a friendly assistant called John". Let's have a look at the rest of this node. "Require
[05:13] approval" can be used to enable human in the loop functionality, which we will look at later on in this video. You can use "format prompt values" to set the values of variables, which we will look at as well, and if we click on additional parameters, we can use the "approval prompt approve button text and reject button" when the human in the loop functionality is enabled. We also have the capability of updating state, which we will look at later as well. But for now, we are
[05:45] done with the agent. Now before we can run this, we do need to set some sort of end state. Let's go to add nodes, and with "in sequential agents", we can either add an end node or a loop node. Both of these nodes represent an end state in our flow. For now, let's simply add an end node, and let's attach our agent to this end node like so. We can now save our flow, and in the chat, let's test this out. Let's say "hello". And of
[06:16] course, we can see that the assistant node was executed as well as the response from that node. Fantastic! We now have an agent that we can talk to. Now let's discuss agent memory. During the execution of the flow, the conversation history is added to a global state, and after execution, all those messages are deleted. So when we execute the flow again, our agent will not be able to recall information from past messages, and I can prove that
[06:47] to you. Let's enter something like "my name is Leon". Our agent will greet us with my name, but if I then ask it "what is my name?", the agent can't recall that information. So to add memory to our flow, we can simply go to add nodes, then within "memory", we can add the agent memory node. I'm actually going to move these nodes around just to make a bit of space. And now let's attach our agent memory node to the agent memory input on the start node.
[07:18] With this node, the conversation history will actually be stored in a SQLite database. Let's go ahead and test this out by saving the flow, and in the chat, let's try providing my name again by entering "my name is Leon", and now let's ask it "what is my name?", and this time our assistant was able to recall my name. Great! Now let's discuss the state node. By default, the conversation history is added to state and shared amongst all the agents in the
[07:49] flow, but we can also use the state structure to store our very own values, and these values will be shared amongst all the agents in the state as well. Let's have a look at an example. Let's go to add nodes under sequential agents. Let's add the state node. Let's attach this node to our starting node, and now we can click on additional parameters to add our very own state properties. Now take note we do not have to add a property for the conversation
[08:20] history as that is handled for us by default, so all we have to do is add any additional values to the state which we want to make available to our agents. As an example, let's set a value for my name in state. Let's click on add item. Let's enter a key value as a name, and for the operation let's simply select replace. You can use the append operation to simply add values to an array or a list of values.
[08:50] For now we simply want to replace the value with my name. Great! This value can be retrieved by the agents from the state structure. Let me show you how that works. Let's make the name available to this agent by changing the system prompt slightly. Let's add something like you are talking to, and instead of hardcoding my name like this, we want to retrieve the value from the state. So let's add a variable value using opening and closing curly braces,
[09:22] and within the braces let's give this placeholder a name. I'll just call mine name. Let's click on save. Now we just have to link up this placeholder with the value from state, and we can do that by clicking on format prompt values. At the moment the name variable is simply an empty string, and we can change that by clicking on the edit button, and if we click on this field we can now select from a range of values. The question is simply the message from the chat window. We can
[09:53] also access the chat history, or we can fetch the first message from the content, or the last message from our list of messages. What we are interested is this option over here. Let's then edit this value, and let's replace this with our name value in state. So this is referring to this key value in the state structure, which has a value of Leon. So let's test this out by going through the chat, and it say hello, and as you can see the
[10:24] agent now knows our name. So let's say we wanted to change this value from Leon to John. Let's save this flow, let's test it again, and let's ask what is my name, and as you can see it is pulling the name from the state. Great! Now let's have a look at the condition node. We can use the condition node to conditionally call agents. Let's assume that the first time you execute this flow the user's name in the state property will actually be blank. If the value is blank then we want to
[10:55] call an agent which will be responsible for collecting the user's name and then storing that name in the state property. So the second time we execute the flow and then if the name is populated this assistant over here will be triggered. So let's set that up. First I'm just going to make some space by moving this agent over. Let's break this connection and let's add a second agent which will be responsible for collecting the user's information. So let's add that agent, let's give it a
[11:27] name like name collection agent, and in the system prompt let's enter something like you are responsible for collecting the user's name. Let's also provide the steps that the agent can follow like if the user has not provided their name then politely ask for their name and if the user provided their name then ask them how can I assist you. Let's save this agent and let's attach our agent to the end node. So now we have two agents which we want to call
[11:58] conditionally based on whether the name is set in state. Let's go to add nodes and with the sequential agents let's add the condition node. Let's attach the start node to this condition node and now let's have a look at the details of this condition node. First let's give our condition node a name. This can be anything you want like check if the user has a name. Then let's click on this condition button. Here we can set up the different conditions for this node. We can either use this condition table or
[12:30] we can handle this programmatically using code. Let's stick with the condition table. Let's add a new item and for the variable we can access the name property in state. So we can say that if the name is not empty we then want to simply continue to our agent node. You can call this output whatever you want. I'll simply call it continue but if we save this you will now notice this continue output over here. If none of the
[13:02] conditions in this list is met the end output will be executed. We can also have additional outputs so for example let's say we had a specific output for a name that is Leon. We could add a Leon output as well and if I save this you will now notice this connection over here for Leon but of course we don't need that for now. But if the name is empty this end output will be triggered which we can hook up
[13:32] to our name collection agent. Like so let's test this out by saving the flow and just as a reminder if we go to state the name is currently John. So we would expect this flow to trigger the continue output over here. In the chat let's say hello and indeed this triggered our assistant node. So let's test this end scenario by going to state let's clear the name then let's save the flow and in the chat let's say hello and this time it is
[14:04] triggering the name collection agent. Great it's very important to note that although we provided our name this name was not stored in the global state so in order to grab this name from the user's message and then store it in state we will be using another node called the LLM node. We can use the LLM node to process unstructured data like a user's message to extract information from the message and then
[14:34] output the data in a structured format. Let me give you an example of why you would want to parse unstructured data. In this example I simply parsed my name so you might think that it's simple enough to simply grab the value that the user provided and install that value in state but what if the user entered something like my name is Leon that would mean that the agent would store this entire string as the name in the state which is not correct. We want to use the intelligence of an LLM to identify
[15:06] a human name from the string and then output only that name and store it in state. All right enough talk let's actually implement this. Let's go to add nodes and with in sequential agents let's add the LLM node. Before we attach this node to anything let's first have a look at this node in isolation. This node can be triggered by the starting node another agent an LLM or a tool node so effectively this node will receive the output of one of these
[15:36] nodes and then process that data in any way that we want. Let's actually start by giving this node a name like name collector and within additional parameters we can provide clear instructions on what sort of data this node needs to extract. For example your job is to identify and extract a human name from the user's message only respond with the name. We'll leave the human prompt empty and what we can then do is add a variable for the user message and again
[16:08] we can create variables using opening and closing curly braces. Let's call this question or whatever you want then with informat prompt values we can simply assign the question from the chat box like so. So this will now receive something like my name is Leon and with this prompt the model will try to extract the name. Now one of the benefits of the LLM nodes is we can return the data in a fixed structure. In this example we want to return the name so let's add an item
[16:41] let's call this name which is of type string and we can add a description like the name of the user. So as this LLM node would have extracted the name from the user's message it will then assign the name to this key value over here and additionally we can also use this node to update state and that is exactly what we want to do. Let's click on add item within the state we want to reassign this name property and for the value we want to use
[17:12] this name output over here so from this list of values we will select flow dot output and we will replace this key value with name. This is the value from this JSON output structure. I know there was a lot to process but these LLM nodes are extremely powerful. Simply see it as a node that can receive output from another node, extract information from that output, store the information that it extracted into this structured
[17:43] output list and optionally we can use the values that it extracted to update state. Now the question is where do we add this node in this flow and for me it makes sense to add it after this condition node and during this flow where we collect the name. I'm actually going to move these nodes over let's break this connection let's bring in the LLM node let's attach this end connector to the LLM node and then let's connect our LLM node to our agent.
[18:15] So let's quickly have a look at this again initially the name property in the state is blank so the condition node will route us down this path where the agent will ask the user to provide their name. If the user simply enters something like hello this LLM node will not be able to extract the name from that text and therefore also not set the name in state then the name collection agent will be called to ask the user for their name. The user will
[18:46] then enter their name which will again trigger this path this time the name collector will be able to extract their name and update state and the name collection agent will then determine that the name was provided and then ask the user how the agent can help them. In fact in the scenario where the user enters something that's not a name we simply want the LLM node to return a blank value so let's announce this slightly to add something like if you are unable to determine a name like if the user entered
[19:17] hello or hi then return a blank value for the name. Let's save our flow let's enter hello and in the name collector we can actually see the changes that were made to the state which was simply a blank value because we were unable to determine a name. Also the name collection agent responded with what is your name now let's see what happens if we actually enter a name. My name is Leon this time the name collector was able to extract the name and store that value in state.
[19:49] Now the name collection agent is asking us how they can help if we send another message we will expect the flow to take us to the assistant agent so let's enter something like why is the sky blue so we can now see that the condition node called the assistant agent and it was the assistant agent that responded so I hope you will agree that the LLM nodes are extremely powerful for parsing unstructured data and for setting state. Now let's have a look at implementing
[20:19] human in the loop with human in the loop enabled the agent will stop the process and first ask the user's approval before calling tools for instance let's add a simple tool to this agent by going to add nodes then under tools let's simply add the calculator tool like so let's attach the calculator to the agent now by default the agent will not ask our permission and it will simply call the tool you can test this out by asking some math question and our
[20:50] assistant used the calculator tool to perform this calculation but what if we wanted our agents to first ask our permission before calling tools to do that we can simply enable this require approval toggle and if we had to ask it another math question the agent will now ask us whether we want to proceed or not I'll simply go ahead and approve this we can also customize the human in the loop behavior by going to additional parameters and here we can set the approval prompt and we can also set the
[21:22] text for the approval and rejection buttons next we'll have a look at the condition agent node and the loop node but first if you find this video useful then please support my channel by hitting the like button and subscribe to my channel for more flow-wise content now let's have a look at the condition agent node condition agents can be an extremely powerful tool for identifying the user's intent and then routing them down a specific path for example let's say you had a very complex flow where you had
[21:53] different functionality based on whether the user wants to talk to reception house cleaning room service maintenance etc that would be a very difficult use case to implement using the standard condition node but with a condition agent node we can use the reasoning power of an annul m to figure out which route the user should take so let's actually use that hotel example then for simplicity's sake let's say we have three different departments in our hotel represented by three different agents we
[22:23] have reception with a system prompt like you work at reception at a hotel welcome the user and ask them how you can assist them let's copy this node three times and let's set a maintenance agent with a system prompt and let's set an agent for the restaurant with a system prompt as well and these system prompts are really simple they honestly don't do much they simply welcome the user and if you wanted to you could extend each of these agents with custom tools related to their department but what we want to focus on
[22:54] is the ability to take the user's question or message figure out which department they're trying to access and then conditionally call these agents to figure out the user's intent we can add a condition agent so with sequential agents let's add the condition agent node let's attach the start node to the condition agent and let's give our conditioned agent a name like router agent now on this condition agent we actually want to have different outputs one for
[23:25] the rest to run one for the reception and one for maintenance and we'll have this end node as I fall back let's start by clicking on additional parameters here we need to provide a system prompt and a human prompt in order for this to work let's start with the system prompt your job is to route the user to the correct department at our hotel from the user's message try to determine if you should route the user to reception maintenance or the restaurant then for the human prompt let's tell this model how to determine
[23:55] these different routes here we're simply saying that if the user's query is related to the checkout time the wi-fi password or information about the hotel then respond with reception or if the query is related to room service the food menu or the restaurant then respond with restaurant and then we're just telling it to only respond with that specific word in the json structured output let's add a new item and let's call this route this is of type enum and enum is
[24:27] simply a list of available values that we will expect from the model which would be the three values in this prompt so reception maintenance and restaurant let's add reception comma maintenance comma restaurant for the description i'll enter something like the route the user should take something like that let's close this pop up and then let's click on condition we can add these different conditions by clicking on add item we can refer to flow dot
[24:59] output route and we could repeat the process for the other routes as well and we will see those different conditions over here but at the time of recording there seems to be a small bug which means that the end node will always be executed irrespective of whether or not the llm correctly identified the route or not the chances are that by the time you watch this video this bug will be resolved but i'm also going to use this opportunity to show you how to use the code condition
[25:30] solution and please don't worry if you're not familiar with code this is super simple let's click on see example and this will pull in a little bit of code for the first line let's change this from content to the value that we called it which was route now we can say that if the result includes something like reception then we need to trigger the condition called reception let's actually copy this for the rest of this conditions as well so the second one we called maintenance
[26:02] and we want to make a condition available called maintenance as well and let's paste this one more time and let's call this one restaurant and let's add a condition called restaurant as well and we'll simply leave this end condition as well when we save this we can now see those different conditions pulling through and we can start hooking them up to our agents so let's attach our maintenance condition to our maintenance agent let's do the same with reception and let's do the same
[26:32] for the restaurant as well if the allylm was unable to determine any of these routes then we'll simply end this flow so with sequential agents let's add the end node and let's hook up the end condition to this end node like so great let's test this out so i'll save the flow and let's say something like what is the wi-fi password oh yes and this is a mistake that i make all the time don't forget to add end nodes to your agents let's add the end node and let's
[27:03] connect our agent to the end node i'm actually going to copy this end node a few times and let's assign these agents to the end nodes as well great so let's test this flow by saving it and let's try this again what is the wi-fi password and indeed reception was triggered let's try my faucet is leaking and let's trigger the maintenance agent let's try the restaurant please can you deliver a burger to my room and the restaurant node was triggered so hopefully you'll agree that condition agents are an
[27:35] incredible tool for determining the user's intent then branching off into different functionality based on that intent and this brings us to the final topic of this video loops if you made it this far then please give yourself a pat on the back sequential agents might seem like a very intimidating topic to a lot of people but you stuck it through and hopefully this video gave you the confidence to start playing with and using sequential agents now let's build a fun little project to demonstrate loops we will also use
[28:07] some of the other nodes that you learned about in this video just to tie everything together so in this project we're actually going to create a flow that will write and grade essays so a writer node will write the essay and a teacher node will grade the essay and provide feedback to the writer and that process will run three times and then provide a final essay so let's first add our writer node instead of using an agent i'm actually going to use an allyl m node instead just to demonstrate
[28:38] another ability of the allyl m nodes and that is to provide simple output like writing poems essays lyrics etc let's attach the start node to the allyl m node and let's call this writer in the additional parameters let's add a system prompt like you are an essay assistant tasked with writing excellent three paragraph essays generate the best essay possible for the user's request if the teacher provides critique respond with a revised version of
[29:09] your previous attempts let's save this and let's close this pop-up now that we have our writer let's also add our teacher so let's add another allyl m node and let's connect these allyl m nodes like so let's call this node teacher and in the additional parameters let's enter the following system prompt you are a teacher grading an essay submission generate critique and recommendations for the user submission provide detailed recommendations including requests for length depth etc it's close
[29:41] to pop-up and lastly let's simply end this flow we will add the looping functionality in a second let's test this out by saving the flow and let's enter an idea for the essay like write an essay about ai let's run this and let's have a look at the output first the writer node executed and it's provided this essay then the teacher node executed and provided the following critique and recommendations now let's say we wanted this process to run three
[30:12] times and then provide the final output we can add a loop to our project by going to add nodes and then with the sequential agents we can simply add the loop node so instead of connecting this end node we can instead attach the loop node with the loop node we can specify the allyl m node or agent which we would like to loop back to for this we can simply copy the name of either the allyl n node or agent and then paste that into the loop node
[30:42] watch what happens when we execute this i'm going to clear the chat and if i run this again the writer will produce its output then the teacher will provide its feedback and as you can see this is still running because our process just looped back to the writer and now the teacher node will execute again however there is nothing telling this process how or when to stop so this will run indefinitely so what we could do is add a condition node to determine whether the teacher should be called or whether we should
[31:13] call the end node let's actually move the loop and the allyl m node over and let's add a condition node so under sequential agents let's add the condition node let's make some more room and let's pass the output from the allyl m node into our condition node let's give the condition node a name like we'll check if the loop is greater than three let's go to conditions and in the conditions let's click on add item and for the variable we will actually have a look at the amount of messages in the state if the amount of
[31:45] messages is less than or equal to six messages so this would be the combination of the user message the essay is written by the writer as well as the revisions from the teacher if all those messages are less than or equal to six messages then we will follow the grading condition let's save this we can now see this grading condition over here which will attach to the allyl m node or if we've exceeded the amount of iterations then
[32:16] we'll simply trigger the end node like so now let's go ahead and test this out in the chat let's enter write an essay about ai and this time the process will not run indefinitely but after the sixth message the process will end and we should see the final result from the writer and after the sixth message the process was automatically stopped and we can see the final and revised essay from the writer node please subscribe if you want to see more videos on sequential agents or
[32:48] check out this other video where we create multi-agent teams using flowwise agent flows