I'm very excited about this use case. you are going to use a new feature called Flows. And you're going to use it to build an agentic sales pipeline. Where we're going to have lead information, we're going to enrich it, we're going to score it and then write an email for this lead. It's going to be very interesting. So before we start building this, let's talk about what this looks like. We're going to start by loading leads. And that doesn't need to be agentic. That can be regular Python code. Tap from a database and loading all this data out. Then from there, we're going to send this to a lead scoring crew that you're going to build that is going to search information about this lead, is going to try to understand how to be scoring and how good of a match this is for the product and business that you're trying to sell them. From that point on, we want to save this data back into another database. And this again can be regular Python code. It doesn't need to be necessarily agentic. From here on, we want to make sure that you filter out any leads that are not that high score. And we keep the ones that are so that we can send to our next crew. This crew is going to use all the information that we found about this lead in order to write an email to them and optimize it for engagement. We're going to wrap all this into what we call a Flow. And the Flow is going to basically have events to make sure that we are going through all these different steps. And a Flow also has a state where we can store information to access during the Flow execution or after the Flow execution. And we're going to show how you can use that as well. Now let's zoom into the crews to talk about that for a second. The lead scoring crew is going to start by analyzing the lead data, then doing a research on the culture about that company and doing a final lead scoring. Then if the score is high enough, the email crew data is going to do an email drafting and then optimizing it for engagement. Another thing that I want to point out is that the lead scoring crew is going to output a structured data output, and we're going to use this in order to access this information and pass it along for the email writing crew. This is going to be super relevant, and also super interesting to see how you can have very complex structured data outputs from crews and agents. Now let's talk about what is the sales pipeline. The sales pipeline is basically going to research the potential lead. It's going to score them, given the person and the company and all the information that it was able to find on them. And if the sales lead is qualified, then the crew is going to write a proper initial email to reach out to this lead. This is so exciting because you could literally automate a sales pipeline for a company out there using exactly the stamps. And then you can train and fine tune this agents for your use case. Now let's get our hands dirty and actually build this. So let's go into the code. All right. So let's just start by importing our classes that we're going to need for this. It's going to be your regular agent task and crew classes. So let's start by importing those. Now we can set what will be our OpenAI model that we're going to be using for this one. We're going to be using GPT-4o- mini. Keep in mind that this is already the default for CrewAI, but we want to be verbose here and make sure that we are setting it up. Then the next thing that we need to do is load all our agents and tasks Yaml files in a similar way to like what do we have done in the past. Loading it is very straightforward with one difference. We are now using two crews, so we're loading two set of Yaml files, two kinds of agents and two kinds of tasks. So there's going to be lead agents there. Focus on lead scoring and researching. And email agents, they're focusing on writing the email for that lead the same way for the tasks. And we're just putting them into this four different variables so that we can use them later. Now let's create our pydantic models that we're going to use to structure this lead information and this lead data into something that we can use. So for this, we're going to be using four different models. We're going to be using a lead personal information model that holds personal information about the lead itself. We're going to use a company info model that holds information about the company like it, the company name, the industry the revenue. And then we're also going to use a lead score class that stores the information about the actual score that our agents are going to give for data specific lead. And then we basically bring everything together into the lead scoring result model. And that brings that personal info, the company info and the lead score and their one single model and object that we can use. Now that we have created our models, let's import the tools that we're going to be using for our crews. For these crews, we're going to be using only two tool: the serperdevtool and the scrapewebsitetool. These tools are going to allow our agents to research the internet using Google, and then scrape any URLs that it comes along with, in case they want to learn more about the specific person or any specific website that they get exposed to. Now let's actually load our Yaml agents and Yaml tasks to create our first crew. The lead qualification crew. This crew is very to the point. We're going to have three agents and three tasks. We have a lead data agent, a cultural fit agent, a scoring validation agent. Each of them are going to be focused on finding specific information about our lead. The lead data agents are going to try to enrich this lead with information about their role at the company, and kind of assessing it to see if they would be a good buyer for whatever we're trying to sell them. The culture of fit is going to make sure that this company feels like a good, ideal customer profile, given what we're trying to sell to them. And then the final scoring agent basically bring all this together to give a final score for this lead, with all the information around how that score came to be. we can look at those tasks in the Yaml in a second, but then we just bring it all together into this one single crew, and that's our first crew. Now let's check our agents real quick. And here you can see their role, their goals and their backstory. The agent definition for these agents are very straight to the point. The whole goal is for them to find information about this lead in order to make an informed decision on if this is a good lead or not. If we look at the tasks, we can see what kind of information we're trying to extract for every single lead. So there is personal information like the name, the job title, the role, the professional background. But then there's also company information like the industry, the company size, the revenue, and even the market presence. You can see that we are presenting what is the company and product that we are trying to sell. In this case, we're trying to sell them into CrewAI and the product. It's a multi-agent orchestration platform. So we tell them about what is our ideal customer profile and how we would reach this platform. And we then bring in the lead data to interpolate within this task definition. And we could be also interpolating the company and the product information in here, but for the sake of this example, we can just have a defined in the task definition given this is to qualify specifically for the CrewAI use case. You can see that our other tasks go along trying to find more information about the culture of value, strategic alignment and a qualitative scoring around how good of a lead this actually is. Now that we have seen a little bit about our agents and tasks, let's go back into our code. Now let's create our second crew. That's going to be an email engagement crew. That crew is the one that is actually going to write the email for a lead once that it's scored and classified. So this crew is very to the point. We basically have two agents, an email content specialist and an engagement strategist. And they're going to go through the steps of drafting the initial email and then optimize it to make sure that it's engaging. This crew is only going to focus on the very high score leads that we get to make sure that we can engage with them. Now that we have both crews created, we are ready to start creating our Flow. Flow is a brand new feature for CrewAI. And I'm so excited to show you this, because Flows allow you to do things that were just not possible before. You now can execute regular Python code before your crew, during our crew, or after your crew execution. That allows you to have more control and basically to build different and more complete automations where you have all the agency that agents bringing to the table, but also our ability to execute regular Python code if you really need to. So let's start by importing our classes and the function is that we're going to use for this one. You can see that I import our Flow class. And then two functions: listen and start. This is going to be a very straightforward Flow. But it's going to allow us to understand how powerful it is. The way that you create a Flow is basically creating a class that inherits from the Flow class from CrewAI. And you can define the initial function that is going to be executed by using the start annotation. So in this case the fetch_leads function, it's going to be our initial function because we annotated that with does start annotation. And the fetch leads here it could be pulling or leads from a database for example or doing anything else. In this case I'm marking it with some fake data for myself and a previous position that I had in a company called Clearbit. But now that we have that we want to make sure that we score whatever leads that we fashion. In order for us to do that, we can create a new function called score leads. And you can see that we're using a different annotation on this one called listen. And we are referencing the fetch leads function. What that means is that the score leads function is going to be executed after fetch leads is done. So after we pulled the leads from our database, we're going to get this information and then run this score leads crew for each of the elements in that array. You can see whatever fetch leads function returns, in this case, an array of leads is going to now be passed on the score leads function, and we can use that to kickoff our crew for each one of those leads. Another thing that I want to point out is how every Flow has a state, and you can access that by doing self dot state. In this case, we're throwing our scores inside self dot state. So that we can tap into those later for do some analysis on the information that was gathered, how much that cost and everything else. So we can save this one for later. After we have scored our leads, we want to do two different things. We want to store them in our database and also filter to get only the ones that have a very high score. Above 70. In order to do that, we create two new functions. A store leads score and a filter leads function, and you can see that both of these functions are actually listening to score leads. So once a score leads execution is done both of these functions are going to be executed in parallel. So the store leads function could actually store this information back into the database if we want to in the future leads function actually filters the list to remove anything that has a score under 70. So now we know that the return of this future leads function is going to be only the very high score leads that we got. And for those, we can add a new function to write the email with our second crew. So let's do that. Here we're adding a new function called write email that is listening to the filter leads. So once filter leads is done this write email is only going to get the leads that have a score above 70. And then for those we're going to call our email writing crew. We're calling kickoff for each again because this is an array of leads. And we want to perform this crew for every single one of them. And this is going to return a list of emails. So those emails should be ready to send. So if we wanted to send them right away, we could add a new function that is listening to write email that we can call send email that basically can send all these emails to us. This is the final function of the Flow. So whatever returns is going to be the final return of the Flow itself. For the sake of making this simple, we're just going to return the emails. So this is a Flow. And it's very straightforward to set up as you can see. In order for you to execute this, you can basically start by creating an instance author Flow or Flows called sales pipeline. So I'm going to create an instance of that and assign that to a Flow variable. Now, before we execute this Flow, we can actually plot it out so that we can see what this Flow actually looks like. So let's do that next. Plotting the Flow is super straightforward. All you got to do is call the plot function in your Flow instance, and that will automatically generate an HTML that has your entire Flow for you to look at. So let's go ahead and do it. Now that we have plotted our Flow, we can actually load this HTML here so we can see what that looks like. So let's do it. In here you can see your entire Flow. You can see how it starts with the fetch leads function. then calls the score leads, after score leads it does two things: It stores the leads into a database and filter leads for the ones that are above 70. And after that it writes the emails and then send them. You also have a nice legend in here that it shows you how to read this entire chart, so that you understand everything that is going on with your Flow. This is very good for you to export and have it on your Flow, to attach it to your GitHub repository, or even to understand or explain to others what is going on with our Flow execution. We're very excited about the fact that you can explore your Flows visually if you want to. Now, let's look at actually running this Flow and then checking some of the metrics behind it. Kicking off your Flow is very similar to kicking off a crew. All you gotta do is call the kickoff function on your Flow variable. And we are using a wait here to make sure that we wait for the Flow execution. And the reason why we're doing this is because a lot of these functions can be executed asynchronously. And you want to make sure that we assign the final result into this emails variable so that we can actually inspect some of their round numbers. So let's go ahead and kick off our Flow. So our flow very quickly fact the data from the database. And then we can already see it's processing to do the lead enrichment in lead scoring. So you can see that it got the information about myself, my job title, the company. And from that point on it starts to search the internet to find more information about the time that it was at Clearbit. Let's tag along this execution. Here you can see the final answer for our lead data specialist. You can see there is a very comprehensive data report with my name, the title, the relevance, some professional background and some detail about the company, including the industry, the company size, the revenue, and even the market presence. Let's keep tagging along the execution. Our second agent, the Cultural Fit Analyst, give us also another assessment, including a cultural fit score and then some text to support the analysis and overall comments about Clearbit. Now our final agent the lead score validator comes in. So let's check that out. So our lead score validator gives us a full-blown report on the final score of 85 and then some scoring criteria, some information about the company about the market presence, the culture fit and even some validation notes. All this information is going to be turned into those objects that we created early on in the beginning of the lesson. So we have a very structured output of everything that we learned about this lead in this company. Now let's keep tagging along our Flow execution. Here we can already see our second crew kicking off with the email content writer, and then followed up with the engagement optimization specialist. So we got our final email in here. We can look at that in a second. Let's first look at some of the metrics and how much it cost us to actually execute this Flow. So let's first look at how much it cost to execute our score crew. So we are going to be looking into that a Flow state variable. And this is very interesting because your Flow state is persistent on your initial Flow. So whatever information was added to the state during the Flow execution can now be accessed afterwards as we are doing here, assessing the initial score crew results to look into how many tokens were used to get to that data enrichment in the lead scoring process. And here we can see that the value was 0.015. And we can see how many tokens were used for our prompt and for completion tokens. Now that we know how much it cost for a score to live, let's see how much it cost us to actually write the email. This is basically looking at the final result offer Flow into that emails variable so that we can see how many tokens were used. And we can see that for the email, it cost us $0.0003 to actually generate the email. So it's very cost effective in a way. Now let's explore all the data that we're able to get for this lead, so that we can see some of the information that our agents were able to infer and define. So before we do this, I'm going to be throwing our score crew results into this variable called scores. So it's easily for us to access and to plot things out. Now let's basically convert all the data that we found in the pydantic models that we created into a Pandas dataframe, so that we can actually plot it out and see everything that we found about these lead. So, in here you can see some information like the job title, the role relevance. You can see the market presence, the lead score and even like some information around the scoring criteria and the validation. So this looks very interesting. And if we spend some extra time with our agents and tasks, we can definitely tune this to be even better so that we can get all the information that we need into this final result. Now let's look at the actual email. So to look into the email, I'm going to actually just print out what was the final result of our Flow. And you can see that it got my name right. And it mentions CrewAI. It talks about the orchestration platform and even talks about streamlining workflows and more. You can see there's also some links to scheduled demo or download use cases. Now that is very interesting and we would need to replace that with the actual links. But we can also spend some time with our agents at tasks to make sure that outputs exactly what we want. But in here you can see how super fast and straightforward it is to build an entire sales pipeline that can not only enrich data and score leads, but also write emails for them. Now, this was a very interesting use case for our Flows, but you can do way more complex use cases. So, how complex can it get? Let's take a look on if we build a more complex one, what that would look like. So for this use case we're going to be building a more complex Flow. It's going to start similar to our initial one. But we're going to be extending it in a few different ways to show how capable Flows are. Let's start by importing the classes and functions that we're going to need. One thing that you're going to notice is that when importing new functions, the and, the or, and the router function. And we're going to use all of them in our new sales pipeline Flow. So this Flow is going to start exactly like our initial one, where we're going to have a start function that is fetching the leads. We're going to have a score lead's function that's going to be executed right after that. And then a store_leads_score that is going to be executed right after that as well. Now we're going to make sure that we filter our leads. And that's going to be exactly like what we did on our initial sales pipeline, where our filtering out for anything that has a score less than 70. But here is where things get a little more complex. We're actually going to add a new function. And this function is going to be using this "and" function annotation that allows you to wait for two other functions to be done before it kicks off. So this log_leads function is going to wait for the filter leads function to be done and the store lead score could be done before it gets executed. This allows for very interesting use cases because let's say that the filter leads happens super fast by storing the leads score into a database takes a little longer. You don't have to worry about that, because this log leads function is only going to get executed after these two functions are done. So you can see how that unlocks more complex use cases that you could do in there. Now we're going to add another function that is going to be a router. And the router here is super interesting because it allows you to give multiple pathways for your Flow to go. So you can see that we are still listening to the filter leads function. So once that is done this count leads function will kick off. And it can go in three different paths. We call this high medium and low. We could call it anything else. We just choose this name for the sake of an example. You can see that we are getting our scores here after they being filtered. And what we are checking is how many leads we got with such a high score. If there are more than ten, then we want to return high. If it's more than five, then return medium, and if it's five or less leads, then the return to low. That allows us to listen to those different paths to execute different functions. So let's look at that. Here you can see that we are listening to those three different paths. So if our count the leads actually return high then we are just going to execute the store in Salesforce function, where we're just going to push these leads into Salesforce, each return medium, because we have more than five leads but less than ten, then we're just going to send them directly to the sales team. But if there is not too many leads like five or less, then it's going to go to the low path where we're going to write the email using our crew the same way that we used to do before. And if we go the path of writing the email, let's not forget to add a final function that will listen to that and then actually send those emails out. This is very interesting, and you can see how the combination of routers, listenings, ands and ors allows you to build super complex Flows, and then you can bring crews in the middle of them to do everything that you have been doing with crews throughout the entire course. This allows you to execute regular Python code before, during, or after your crew executions and locking so many interesting use cases. Now let's block this new Flow so that we can see how it looks like. To block this Flow, we're going to do the same thing that I did before where we create an instance of your Flow class. And then we call the plot function into that. So let's do that now. Now that generated an HTML that we can actually plot in here in order for us to see what that Flow looks like. So let's check it out. You can see that this Flow is way more complex. There's a lot going on in there. We start with fetching the leads and then scoring them after we score them, we store them in the database and we filter for the leads with a high threshold. After these two functions are done, we log the leads. So we get a confirmation that things are worked out. And you can see that this is an and condition because of the dot lines. You can also find out this information by looking at the legend here below. So you can see this is an and trigger that is waiting for these two functions to be done before actually executing the log reads function. And then it execute our count leads function that is actually a router. And depending on how it goes, it can go three different paths. Either store them in Salesforce, send them to the sales teams, or write an email. But once it writes the email, it's going to execute the send email function. Honestly, this is so exciting because you can build so many different use cases in here, and this is the best of both worlds, where you have crews scoring our leads in writing or email. But now it's easier than ever to execute regular Python code before, during or after your crew's executions. So this is very exciting. Now I want to show you more and how you can build more with crew. So let's jump into our next lesson where we're going to dive even further, and you're going to learn more on how you can unblock complex use cases in production using crewAI. I see you in a second.