Mastering LLM Agent Frameworks: LangGraph, AG2, CrewAI, Semantic Kernel for AI Development

Shane | LLM Implementation · Beginner ·🤖 AI Agents & Automation ·1y ago

Key Takeaways

Explores LangGraph, AG2, CrewAI, and Semantic Kernel LLM agent frameworks for AI development with hands-on Python examples

Full Transcript

Hey everyone, welcome back to my channel on large language model implementation. I'm super excited today because we're diving into some really cool stuff about agent frameworks. If you're as passionate about this as I am, you're in for a treat. So, let's get started. So, there are quite a few frameworks out there for for building agents. And in this video, I'm going to walk you through the examples provided on their official websites. My goal is to help us get familiar with how these frameworks work. That way, down the line when we start exploring more advanced concepts like agent to agent communication, we'll already have a solid foundation. We'll understand how these systems are set up and how agents from different frameworks can interact with each other. It's going to be a great learning journey. Before we jump into the complex stuff though, we need to build a basic understanding of each framework. That's what makes this so exciting. We're laying the groundwork today. Let's kick things off with our first framework called Langraph. So, what exactly is Langraph? Well, it's a framework built on top of another system called Lang Chain, but it focuses on being a lowlevel tool for orchestrating and managing long running stateful agents. Think of it as a conductor for a symphony. It helps organize multiple agents to work together, share memory, solve tasks, and deliver results back to the user. It's all about making sure everything runs smoothly in a coordinated way. All right, let's dive into some hands on examples to see how this works. I've prepared a notebook for you all to follow along with so you can quickly run these examples and get a clear understanding of langraph without any hassle. Let's take a look at an overview first. As I mentioned, Lang graph offers some really useful features. For one, it supports human in the loop approvals, which means you can step in and provide input during a process. It also provides context for long running workflows, helping agents stay on track over extended tasks. On top of that, it's great for building custom agents tailored to specific roles or use cases. You can even visualize the workflow through graph nodes and edges, which makes it super clear to see how everything connects. Plus, it lets you stream intermediate steps and watch in real time what the agent is doing and what actions it's taking. Pretty neat, right? So, let's get started with the basics of Langraph. In this section, we're going to build a simple chatbot, add tools to it, incorporate memory, include human in the loop controls, customize its state, and even explore a cool feature called time travel. Let's begin with the first step, building a basic chatbot. All right, let's build our chatbot from the ground up. First, we need to install a few necessary packages like the core langraph library and another tool called Lang Chain. While we won't be using everything today, I'm also integrating Google Geminy for this example. So, we'll need that extension as well. Once that's set up, we'll restart our environment to make sure everything's ready to go. The first key step in working with Langraph is creating something called a state graph. This is basically the structure or blueprint for our chatbot. Think of it as a state machine that defines how our chatbot operates. We're going to add nodes to this graph to represent the language model and the functions our chatbot can call. Then we'll connect these nodes with edges to specify how the chatbot should move from one function to another during a conversation. Let's get into the details. We start by importing the necessary components for building the state graph including a starting point and a way to handle messages. Then we define a state class to manage the conversation data. This state will include a list of messages and instead of overwriting the list every time, we've set up a function to simply append new messages to it. That way, the conversation history builds up naturally as we go. Next, we initialize the state graph by passing this state structure into it. What's cool here is that each node in the graph can take the current state as input and then output an update to that state. Thanks to a pre-built function for adding messages, any updates to the message list will be appended rather than replacing what's already there. If you're curious about the deeper concepts behind this, I've got some resources you can check out for more details. Now, let's add a node to our graph specifically for the chatbot. This node will act as our large language model agent. To set this up, we import a library for integrating Google's generative AI, provide an API key from Google Studio, and initialize the model with the appropriate name. Once that's done, we're ready to define how this chatbot node functions. Here's how it works. We create a function for the chatbot that reads the current state, which includes the list of messages in the conversation. Based on that, it triggers the language model to generate a response, retrieves the message, and returns it as an update to the state. Then we add this chatbot node to our graph using a method to name it and link it to the function we just defined. Just to break it down a bit more, the chatbot node takes the state as input and returns a dictionary with an updated list of messages. This is a standard pattern for all nodes in Langraph. The built-in function for adding messages ensures that the language model's response is appended to the existing conversation history rather than overwriting it. Next, we need to tell the graph where to start each time it runs. We do this by adding an edge, which is like a connection from a predefined starting point to our chatbot node. This ensures the conversation always begins with the chatbot. We'll visualize the graph in just a moment to see how it looks. But first, let's compile everything to make sure it's ready to run. All right, let's take a look at the graph we've built. You can see the chatbot node right here with an edge connecting the starting point to the chatbot. After the chatbot responds, it automatically connects to an endpoint showing the flow from start to finish. It's a simple structure for now, but it gives you a clear picture of how the conversation moves. Now, let's run the chatbot and see it in action. Set up a method to stream updates, so we can watch the responses as they come in. This method reads user input, passes it to the graph in a specific format. basically labeling it as a user message and then loops through the responses from the language model to display them. Also added a little loop so you can keep chatting with the bot until you decide to quit. Let's test it out with a sample question like uh what do you know about langraph? So here's what we got. I asked what do you know about langraph and the response from the Google geminy model tells us that lang graph is a library that extends the capabilities of lang chain it's designed for building robust stateful multi-actor applications that's spoton the response also explains the core concept of state which is like a shared object passed between different nodes in the graph each node can read from or write to this state allowing information to persist across multiple steps. It also mentions multi-turn conversations, nodes as individual units of work and edges as transitions between nodes. There are even conditional edges that let you define transitions based on a node's output. All of this makes Langraph a powerful tool for orchestration, handling complex logic and enabling human in the loop interactions. It builds on Langchain's basic components like models, chains, and tools. Adding an orchestration layer to structure how everything interacts in a stateful, often cyclical way. That's what makes it so valuable. In summary, if you're building anything beyond a simple linear language model application, especially if you need to manage state handle conditional logic or support iterative self-correcting behavior, Langraph is the go to tool within the Langchain ecosystem. All right, let's move on to the next step. Adding tools to our chatbot. Tools are essentially functions that the language model can use to perform specific tasks. For this example, we're going to integrate a web search tool using a service called Tavali. If you head to their website, you can sign up for an API key with a thousand free credits to get started. Once you've got the key, we'll configure it in our setup. Install the necessary package for for tavly search and define the tool with a limit of two results per search. Then we'll add this tool to a list so our chatbot can access it. You can even add multiple tools to this list if you want. Let's see a quick example of invoking the tool with a query like what is a node in langraph. The tool performs a web search and pulls back relevant information from blogs and articles. Pretty handy. Now, let's connect this tool to our language model using a method to bind tools to it. Just like before, we set up the state and initialize the graph. We define the chatbot node and add it to the graph. Since we've added a tool, we also need a way to run it. Luckily, Langraph provides a pre-built class for handling tool nodes. This class identifies when a tool needs to be called based on the language models response and executes it. We just pass our list of tools into this class. Name it something like tools and add it as a node to the graph. Next, let's talk about conditional edges. These are like decision points in the graph, similar to an if statement that route the flow to different nodes based on the current state. For our chatbot, the language models response can decide whether a tool needs to be used. We set up a conditional edge to check for tool calls in the chatbot's output and route accordingly. Langraph even offers a pre-built condition for this which we can use directly. So we add a conditional edge from the chatbot node to the tool node. Anytime a tool is called, the flow always returns to the chatbot to decide the next step. So we add another edge from the tool back to the chatbot creating a loop. Then just like before, we connect the starting point to the chatbot and compile the graph to visualize it. Take a look at the updated graph. Now you can see the tool node has been added and the conditional edge we defined lets the chatbot decide whether to use a tool based on the language model's response. If a tool is needed, the flow moves to the tool node, executes the action, and then loops back to the chatbot. It's a nice little cycle that shows how everything works together. Let's test this out by asking the same question of what do you know about Langraph. Watch how the assistant calls the tool to gather information from the web, summarizes the results, and returns a detailed response to the user. It's a seamless process asking the question, using the tool to search, summarizing the findings, and delivering the answer. That's the power of integrating tools. All right, let's move on to adding memory to our chatbot. Lang graph makes it easy to persist conversation history by using something called a checkpointer. When you compile the graph, it tracks the state of each conversation using a unique thread ID. Let's see how this works. We import a memory saver component, initialize it, and add it as a checkpoint when compiling the graph. Then we can interact with the chatbot and test if it remembers past exchanges. For example, I'll say, "Hi there. My name is Will." And see if it recalls my name in a followup question like, "Uh, what what is my name?" Since we're using the same thread ID, it remembers and responds your name is will. But if I switch to a different thread ID, it won't have access to that memory and will say it doesn't know my name. You can also inspect the state of a specific thread ID to see the full conversation history. It's a great way to maintain context over multiple interactions. Let's dive into adding human in the loop controls to our chatbot. Agents, as you might know, can sometimes be a bit unpredictable and there are moments when you'll want a human to step in either to guide the process or to give a thumbs up before certain actions are taken. This ensures everything runs smoothly and as intended. With Langrass persistence layer, we can pause the chatbot's execution and pick things back up later based on user feedback. The key feature here is something called the interrupt function. When we use it inside a node, it halts the process and we can resume it by providing a command with new input from a human. Think of it as a way to hit pause and ask for help. kind of like Python's builtin input function, though it has its own quirks. To do this, we import that command and the interrupt function, redefine the state of our system, and configure the setup for building our workflow graph. Here's where we create our human assistant tool. We mark a specific function as a tool using a decorator, a little tag that tells the system this function is something the AI can use. This function takes a query as text input, calls the interrupt function, and returns a simple structure with the query inside it. Later on, when we get a human response, it'll come back with a specific format that includes a data field. It might sound a bit odd now, but I promise it'll make sense as we go along. Next, just like we did earlier, we set up another tool for searching information online called the Tavali search tool. Then, we combine this search tool with our human assistant tool and link both of them to our language model, which is the brain behind the AI's responses. After that, we define the chatbot's behavior, set up the connections between different parts of the system, and configure the memory to keep track of the conversation. Nothing too fancy there. Now, let's test this out by prompting the chatbot with a question that will trigger the human assistance tool. For example, we ask, "I need some expert guidance for building an AI agent. could you request assistance for me? We're using a thread ID of one to track this conversation. When we run this, you'll see the user's message appear followed by the AI's response, which includes a call to the human assistance tool with the query about needing expert guidance. At this point, the chatbot pauses. It's hit the interrupt we set up. If you check the graph state right now, you'll see that execution has stopped at the tools node waiting for human input. To get things moving again, we need to provide input through a command object. For our human assistance tool, this means passing in a dictionary with a key called data that holds the response. In this case, the human responses is we the experts are here to help. We'd recommend you check out lang graph to build your agent. We wrap this in a command and resume the graph with the same configuration. What happens next is pretty cool. You'll see the AI's original tool call followed by a tool message showing the human provided content. And finally, the AI relays the expert advice back to the user. The input has been processed and the graph picks up right where it left off to deliver the final answer. Awesome job. You've just added human in the loop execution to your chatbot using the interrupt feature. Looking ahead, so far we've been working with a simple state that just tracks a list of messages. That's powerful on its own, but if you want to create more complex behaviors without relying solely on the message history, you can add extra fields to the state. Here, we're going to add more fields to the state beyond just the list of messages, allowing us to define more intricate behaviors for our chatbot. In this example, the chatbot will use its search tool to find specific information, then pass it along to a human for review while updating custom state fields along the way. Let's start by updating the chatbot to research the birthday or release date of something like a library or tool. We'll add two new fields to our state. Um, one for the name and another for the birthday. By including these in the state, they become easily accessible to other parts of the graph and are saved in the persistence layer for later use. It's a straightforward way to keep track of important details as the conversation unfolds. Now, let's make sure these new state fields get populated within our human assistance tool. This way, a human can review the information before it's officially stored in the state. We're going to use a command to update the state directly from in inside the tool. The tool which we'll call something like how human assistance for name and birthday takes the name the birthday and a tool call ID to link everything together. When it runs it pauses with a question like the this correct and displays the name and birthday it found. If the human confirms by starting the response with uh yes, it keeps the provided details. If not, it uses any corrections the human provides. Then it creates an update for the state with the verified name and birthday along with a message reflecting the response and returns this update through a command. It's a neat way to ensure accuracy with human input. Let's put this to the test by prompting the chatbot to look up the release date of the Langraph library. When you have the answer, provide the name, which should be Langraph, and the birthday. Then use the human assistance tool for name and birthday to review. If you can't find the details, just use random ones. Once you have corrections from humans, give the users the correct answers without any explanations. When this runs, you'll see the user's message, followed by the AI using the search tool to look up long graph release date, getting some results, then refining the search for a specific version's release date. Finally, the AI calls the human assistance tool with a guest release date and the name graph pausing for human review. At this point, execution stops because we've hit the interrupt again, waiting for verification. So let's say the chatbot didn't quite get the date right. We'll step in as the human and provide the correct information. We send a command resuming execution with the name as elangraph and the birthday as January 17, 2024. When we run this, the output shows the AI's original tool call followed by a message noting the correction with the updated name and date. And finally, the AI responds to the user with Langraph was released on January 17th, 2024. If you check the state now, you'll see these fields are updated with the corrected values, confirming everything is stored properly. You can manually override a value in the state. For instance, we can update the name field to something like lang graph library just to clarify what it is. If you check the state again after this manual update using the same configuration, you'll see the new name reflected alongside the birth date. Let's talk about time travel in Langraph. In a typical chatbot interaction, a user chats with the bot to get something done. And features like memory and human in the loop controls help save checkpoints of the state to shape future responses. But what if you want a user to jump back to a previous point in the conversation and try a different path? Or maybe you want to let users rewind the chatbot's work to fix a mistake or explore a new strategy. Something that's especially useful in applications like autonomous software engineering. Langraph makes this possible with built in time travel functionality. Just so you know, this builds on the custom state section we just covered. But for simplicity, we'll use a tool using graph with memory to demonstrate how it works. First, let's set up the graph we'll use for time travel. This is going to be a tool using agent with memory enabled. We define the state build the graph. Set up our search tool from Tavali. Connect the tools to the language model. Create the chatbot node and tool node. Add the conditional and standard edges to control the flow. And finally, compile everything with a memory saver to keep track of the history. It's the foundation we need to explore time travel. Now let's interact with the graph to add some steps. Every interaction gets saved as a checkpoint in the state history which is key for time travel. For example, the user starts by saying I'm learning Langraph. Could you do some research on it for me? The AI uses the search tool and comes back with information about Langraph. Then the user follows up with, "Yeah, that's helpful. Maybe I'll build an autonomous agent with it." Again, the AI searches for how to build an autonomous agent with Langraph and responds with some steps. Each of these exchanges is saved, building up a history we can revisit. With these steps in place, we can replay the entire state history to see everything that happened. This helps us pick a specific moment to travel back to. When we look through the history, we'll notice each state shows the number of messages and what comes next in the flow. For this example, we're targeting a state with four messages. Think of it as the point right after the first user interaction before the second question. Checkpoints like these are saved for every single step, even across different sessions, so you can rewind through an entire conversation thread if you need to. Here's where the magic happens. We're going to resume from that specific state with four messages. The checkpoint we've chosen has a unique ID tied to it. And by providing this ID, we tell Langraph to load the state from that exact moment in time. In this case, we're jumping back to just after the first user interaction. When we resume, the output shows the AI's response from that point. Something like langraph created by lang chain is an opensource AI agent framework since we didn't provide new input in this specific example. It simply replays the last message from that checkpoint. But if we had given a new user input, the conversation could have taken a completely different direction from that moment onward. You've just traveled through time with Langraph. Fantastic. You've now used time travel with checkpoint traversal in Langraph. Being able to rewind and explore different paths opens up incredible opportunities for debugging, experimenting, and creating interactive applications. If you're eager to take your LN graph journey further, I encourage you to explore topics like deployment and advanced features, check out resources like the Langraph server quick start, the Langraph platform quickart, and dive into the platform concepts to see what else you can build. Thanks for following along, and I'll see you in the next tutorial. All right, let's dive into the next agent framework we're exploring today called AG2. This is an open-source system known as Agent OS, specifically designed to help you build AI agents that are ready for real world production use. I believe it's developed by the Autogen team and it's packed with some really powerful features. So, let's get started with an overview of what AG2 is all about. At its heart, AG2 revolves around configuring large language models or LMMs to power its agents. The core building block here is something called the conversible agent, which lets you set up these language models to interact seamlessly with other agents or even with humans. It's pretty neat. On top of that, AG2 includes a feature called human in the loop, which means you can have human oversight at key moments. There's also agent orchestration which helps coordinate multiple agents working together. And if you need to connect to external services or APIs, AG2 has tools for that too, allowing agents to perform various functions. Another cool aspect is the structured output feature which ensures that agents give consistent welldefined responses using a validation system. So how do all these pieces come together? Let me walk you through the process. First, you start with the setup where you configure your language model settings and define how the structured outputs should look. Next comes the workflow design. This is where you create your conversible agents, set up how multiple agents will collaborate, whether that's in a group or through nested workflows, and decide how conversations will end. You can also choose to add the human in the loop feature if needed and extend the agents capabilities with tools. Once everything is combined, you finalize the workflow design. Finally, you run the workflow to see your solution in action. It's a straightforward but powerful process. Let's take a closer look at a specific workflow for a group chat. You begin with configuring the language models and setting up structured outputs. Then you define agents equipped with tools. These could be human agents or other AI agents. After that, you set up the orchestration which includes patterns for how agents interact, context variables to keep track of the conversation, handoffs between agents, and responses from tools. Once everything is in place, you execute the group chat. It's a collaborative autonomous setup that makes multi- aent systems really shine. Now, to help us understand AG2 better, we're going to dive into a practical example focused on financial compliance. I've prepared a notebook with this example to make it easy to follow and learn quickly. We'll be building a system to assist with financial compliance tasks, and I'm excited to walk you through it. So, let's get started. All right, here we go with a stepbystep tutorial to build a financial compliance assistant using AG2. This system will handle multiple agents working together to process transactions, flag suspicious ones for human review, check for duplicate payments, and generate a detailed summary report. This time, we'll be using an OpenAI model to power our agents. Let's kick things off by installing AG2, specifically the extension for OpenAI integration. Now that we've got AG2 installed, let's talk about how we're setting things up. We're using a system to create structured outputs, ensuring responses are consistent. We're also bringing in the conversible agent and language model configuration tools from the Autogen library. Plus, we'll use features for initiating group chats and defining interaction patterns, which I'll explain more as we go along. For now, let's configure our OpenAI API key to get started. With the API key set up, let's configure our language model. We're using a specific configuration tool from Autogen, setting the model to GPT for mini from Open AI. We'll pull the API key from our environment settings and adjust the temperature to 0.2. This lower temperature helps ensure more consistent and reliable results, which is especially important for financial analysis. Rate the setup is successful. Next, let's see how we can integrate this language model configuration with our agents. There are a couple of ways to do this. You can pass the configuration directly when creating an agent or use a context manager in Python which applies the settings to all agents created within a specific scope. Both methods work well. For example, you define an agent with a unique name as its identifier and give it a system message with instructions like you are a helpful AI assistant that provides concise answers. Then you attach the open AI configuration to it. It's a simple way to get an agent up and running. So, how do you interact with these conversible agents? It's pretty straightforward. You use a method to run a workflow which gives you an iterator to process the conversation. This mimics a chat like experience. For instance, let's say you want to ask a simple question like what's the capital of France? You run the workflow with this message. Set a limit of one turn to keep the conversation short for this basic query and disable user input for now. When we process this, we should see the response pop up in the console. All right, we've got our response. The agent tells us the capital of France is Paris. And since we limited it to one turn, the conversation ends there. That's working perfectly. Now, let's shift gears and dive into our financial compliance example. We're going to start by creating a basic financial agent to answer questions. We'll use the same language model configuration and define this agent with a name and a system message like you are a financial assistant who helps analyze financial data and transactions. Then we'll run it with a prompt like can you explain what makes a transaction suspicious and process the response to see what it says. Okay, the response is in. According to our financial assistant, a transaction might be considered suspicious for several reasons like unusually large amounts, inconsistent patterns, strange geographic locations or rapid movement of funds among other factors. There are quite a few ways a transaction can raise red flags. That's helpful to know. Next, we're going to add a human in the loop feature to our setup, which means incorporating human oversight into the process. This concept is similar to what you might find in other frameworks where a human can step in to review or approve actions. In AG2, we achieve this by setting a parameter for human input mode on the agent. You can choose options like always asking for human input, only asking when the conversation is about to end or never asking at all. For our scenario, we want the financial assistant to process transactions and ask a human for approval on any suspicious ones. Let's build that functionality. We'll craft a specific set of instructions for our financial assistant. The message will say something like, "You are a financial compliance assistant." You'll be given a list of transaction descriptions. For each one, if it looks suspicious, like if the amount is over 10,000, the vendor seems unusual or the memo is vague, ask a human for approval. If it looks fine, approve it automatically. Present the full set of transactions for approval at once. And once all transactions are processed, it'll summarize the results and prompt the user to type exit to finish. With that instruction in place, we'll initialize the language model setup. We'll set up a human agent with constant input mode. Generate some sample transactions. All right, let's run this. The initial prompt is please process the following transactions. and we've set a limit of three turns for this interaction. The financial assistant responds by indicating which transactions need approval or if they've all been approved automatically. In this case, it looks like everything was approved without issues. It then says you can type exit to finish. When I type exit and hit enter, the conversation ends as requested. That's a great demonstration of the human in the loop feature. Now, let's move on to coordinating multiple agents through a group chat setup for more complex workflows. AG2 has a feature called group chat pattern, which allows specialized agents to collaborate. We'll use an automatic selection pattern where a group manager agent picks the next speaker based on the conversation's context. In our system, we'll add a summary bot to generate reports and we'll set up automatic termination when a specific marker like summary generated appears in the chat. The finance bot will process transactions and hand over to the summary bot for a final report while the human agent remains in the loop for approvals. Once everything is set, we initiate the group chat and the system runs until the summary is complete and the chat terminates. We'll reuse the instructions for our financial assistant. For the summary assistant, the instructions will be you are a financial summary assistant. You'll receive transaction details and your task is to create a concise summary in a markdown table format. Once done, append a marker on a new line that's to indicate completion. We'll set up both agents using the shared language model configuration and define a function to detect that special marker for ending the chat. Then we'll configure the group chat pattern to manage which agent speaks next. Define the participating agents including the human participant and set up the group manager with the termination condition. Finally, we'll start the group chat with an initial prompt and print out the summary and final message once it's done. Let's run this now. Okay, the group chat is up and running. The human participant sends the initial prompt to the chat manager, which then selects the financial assistant as the first speaker. The financial assistant processes the transactions and if needed asks for human approval. In this case, the human responds with something like approve. The financial assistant confirms everything is processed and says handing over for final report. At that point, the manager picks the summary assistant as the next speaker. The summary assistant creates the markdown table and triggers the chat to end automatically. Perfect. Let's talk about extending agent capabilities with tools. Tools allow agents to interact with the outside world, like checking data or performing specific actions. In our case, we're going to add a tool to check for duplicate payments in our financial system. We'll simulate a database of past transactions with a mock function and create another function to check if a new transaction matches a recent one. say within the last 7 days based on details like the vendor amount and memo or the financial assistance instructions will update them to say for each transaction extract the vendor name amount and memo. Use the duplicate payment checker tool to see if it's a repeat. If it's flagged as a duplicate, reject it automatically and explain why. If not, evaluate it normally for suspicious traits like large amounts or vague memos. When setting up the agents, we'll register the duplicate checker tool with the financial assistant. We'll also prepare new transactions, including some potential duplicates, set up the group chat pattern like before, and run the workflow. Let's see how it handles this. All right, the financial assistant is now suggesting checks for duplicate payments on each transaction, passing the necessary details to the tool. The tool executor runs these checks and returns whether each transaction is a duplicate or not along with the reasoning. After getting the results, the financial assistant shares its evaluations. For example, it might say that two transactions were rejected as duplicates, one was approved and one is waiting for human approval. It then wraps up with all transactions have been processed, handing over for final report. The summary assistant steps in, creates the markdown table with the reason column included, and shows stats like total transactions processed, how many were approved, and how many were rejected. The chat terminates automatically after the summary marker is detected. Let's move on to structured outputs which help ensure consistent and predictable responses from our agents. This is especially useful for integrating with other systems. Keep in mind that structured output support depends on the language model provider and model. Luckily, OpenAI's GPT full mini handles this well. will define specific data models for the output structure like one for individual transaction audit entries and another for the overall audit log summary. Then we'll create a new language model configuration just for the summary assistant specifying the output format to match our audit log summary model. This ensures the output is structured properly without needing detailed formatting instructions in the system message itself which is a cleaner approach. The financial assistant and human participant can keep using the standard configuration since they don't need structured outputs for their responses. We'll also update the termination condition to check for a specific field in the structured output. Configure the group chat pattern and run this to see the results. Okay, the chat is running. The flow is familiar. The human sends the prompt. The manager directs it to the financial assistant which processes the transactions and uses its tool. Once done, it hands over to the summary assistant which now outputs the summary as a structured JSON string. The termination condition is met based on that output. And we can see the raw JSON content as the final message in the notebook. It's also displayed as a nicely formatted JSON object. And we've confirmed that the data model loaded correctly showing details like the total number of transactions processed. So congratulations, you've just walked through building a multi- aent financial compliance system using AG2. That's a huge achievement. I hope this tutorial has given you a clear understanding of how AG2 works and how you can use it to create powerful collaborative AI systems. Thanks for following along and let's keep exploring together. All right guys, next we're going to talk about the Crewi agent framework. So what is CRUi? FUAI is a lean, lightning, fast Python framework built entirely from scratch, making it completely independent of lang chain or other agent frameworks. It's developed with custom code. The Crui empowers developers with both highlevel simplicity and precise lowlevel control. Ideal for creating autonomous AI agents tailored to any scenario. It features two main components and cruise. These optimize for autonomy and collaborative intelligence enabling you to create AI teams where each agent has specific roles, tools, and goals. Plows. These enable granular eventdriven control using single LLM calls for precise task orchestration and natively supporting crews. How do crews work? So basically, you have a big crew. It's like a manager or something. And inside of the crew, you have a lot of LLM agents. And with each agent, it has the memory to store the conversations. For all agents, they have access to the tools. And those agents are dedicated to solving specific tasks and giving the final outcome. So that's the crew AI framework overview. Let's see the crew. The crew is the top level organization. It manages AI agent teams, overseas workflows, ensures collaboration, and delivers outcomes. AI agents are specialized team members. They have specific roles like a researcher or writer, use designated tools, can delegate tasks, and make autonomous decisions. The process is a workflow management system. It defines collaboration patterns, controls task assignments, manages interactions, and ensures efficient execution. Tasks are individual assignments. They have clear objectives. use specific tools feed into a larger process and produce actionable results. So how it all works together? The crew organizes the overall operation. AI agents work on their specialized tasks. The process ensures smooth collaboration. Tasks get completed to achieve the goal. Okay. So how flows work? The flow is the structured workflow orchestration. So it manages execution paths, handles state transitions, controls task sequencing and ensures reliable execution. Events are triggers for workflow actions. They initiate specific processes, enable dynamic responses, support conditional branching, and allow for realtime adaptation. States are workflow execution contexts. They maintain execution data, enable persistence, support resumability and ensure execution integrity. Crew support enhances workflow automation. It injects pockets of agency when needed, complements structured workflows, balances automation with intelligence and enables adaptive decision making. Basically an orchestration that manages the AI workflows. Okay. So here is the uh the comparison like between when to use the cruise when to use flows. So if you are doing some openended research it's recommended to use cruise. If you are doing some like decision workflows it recommends to use flows to make decision paths with the precise control. So it says choose the cruise when you need autonomous problem solving creative collaboration or exploratory tasks. Choose flows when you require deterministic outcomes, auditability or precise control over the execution. You can combine both when your application needs both structured process and pockets of autonomous intelligence. Okay. So, so I think ultimately you will use either of crews or flows or both of them depending on your, you know, project cases, use cases. First things first, let's make sure we've got the right setup for installing Crew I. You'll need a Python version higher than 310 but lower than 3.13. Once that's confirmed, we're going to install a handy tool called UV. Just to give you a quick refresher, UV is an incredibly fast Python package and project manager built in Rust. It's designed to replace tools like pip and pip tools and it's anywhere from 10 to 100 times faster than pip. That speed and efficiency are really noticeable when you're working on projects. Now, since I'm using a MacBook, I'll be running specific commands for MacOss, but the process is similar across platforms. After installing UV, we'll use it to install the Crew AI command line interface. Once that's done, you can check if Crewi is installed properly and even updated if needed by running a simple command. Let's walk through that step by step. Before we proceed, I like to set up a clean Python environment to keep things organized. So, I'm creating a virtual environment using the command to set one up. Once that's created, I'll activate it to ensure we're working in an isolated space. There we go. The environment is active. Let's double check the Python version again just to be sure. Yep, still 3.11.8. Everything looks good so far. Next up, we're going to install UV using the appropriate command. Once UV is ready, we'll use it to install Crew AI. In my case, I've already got Crew AI installed from earlier, but no worries if you're following along for the first time. This step will set it up for you. We can also check the version of Crewi to confirm everything is in place. Easy enough, right now that we've got Crew AI installed, let's move on to the exciting part, creating a Crew AI project. The recommended way to structure your project is by using YAML templates to define your agents and tasks. So, let's get started by running a command to create a new project called example.p project. When prompted, I'll choose Geminy as the provider and select the 2.5 flash model. I'll also input my Gemony API key. Don't worry, I'll make sure to remove any sensitive info from the video later. And you should always keep your keys secure to an analite. The example project is created. This gives us a basic structure that we can customize by defining our agents and tasks. Let's take a quick look at what's inside. The project includes several key files. There's a YAML file for defining the AI agents and their roles, a tasks, YAML file for setting up the tasks and workflows, an EVE file to store sensitive info like API keys, a main, pi file as the entry point for running the project, a crew, pi file for orchestrating the crew, and folders for custom tools and a knowledge base. Before we run the crew, we need to install any necessary packages. Let's run the installation command for crewi. Now, let's run the crew with the appropriate command. I can see the AI agents in action. A senior data researcher is conducting thorough research on AI language models and a reporting analyst is compiling the findings. Awesome. The tasks are completed and the crew execution is done. All right, I think that covers the basics of setting up and running a crew with crew AI. Next, I want to dive deeper and show you a more concrete example by building our first crew AI agents from scratch. We'll create a simple crew to research and report on the latest AI developments for a specific topic. First, let's set up a new project directory called latest AI development. Sticking with Germany as the provider and using the 2.5 flash preview model along with my API key, let's navigate to the new project directory and start customizing it. We'll modify the argent YAML file to define our agents. In this file, there's a placeholder for a topic that gets replaced by values from the main. defining two agents a senior data researcher for a specific topic whose goal is to uncover cuttingedge developments in that area with a backstory as a seasoned researcher skilled at finding the latest trends. The second agent is a reporting analyst for the same topic tasked with creating detailed reports based on the research findings with a backstory as a meticulous analyst who there's the tasks yam file where we define the tasks for each agent for the researcher. The task is to conduct thorough research on the topic, ensuring to find interesting and relevant information for the current year, which we'll set as 2025, and even specify the current month for more precision. The expected output is a list of the 10 most relevant pieces of information about the topic. For the reporting analyst, the task is to review the research and expand each point into a full section for a detailed report formatted in markdown. These tasks are assigned to the respective agents. Let's look at the uh crew pi file. This script imports essential components like agent, crew, process, and task from crew I along with decorators and base agent configurations. Here we define a class for our latest AI development crew. This class uses decorators to mark methods as agents or tasks pulling configurations from the YAML files. For instance, the researcher and reporting analyst are set up as agents with their respective roles and settings. You might wonder where some of these configurations come from. They are loaded from the base class that handles the YML files for agents and tasks up. also define tasks in this script, linking them to the configurations in the YAML files and even specify output files like a report. Additionally, we're adding a web search tool called serdev tool to help with research tasks. There's also an option to include custom functions that run before or after the crew kicks off, but for now, I'll skip those. In the main file, we set up the inputs for our crew like the topic, let's say AI, language, models, and the current year and month. Then we initialize the crew with these inputs and kick it off to start the process. Once everything is set, running the crew will trigger all the agents and tasks to work together. So that's the overview of building and running a crew for researching AI developments. Let's take a look at the generated report to see the results. I think that wraps up this part. Hey there and welcome to this tutorial on Crew AI flows. If you're looking to streamline the way you build and manage AI workflows, you're in the right place. Crew AI flows are a powerful feature that help developers combine and coordinate tasks and teams of AI agents efficiently. They provide a solid foundation for creating sophisticated automations, making your projects smoother and more effective. Well, they're all about creating structured eventdriven processes for your AI applications. They simplify the creation of complex workflows by letting you chain together different teams and tasks. They also make managing and sharing information between tasks incredibly easy. Plus, they're built on an event-driven model, which means your workflows can be dynamic and responsive. And if you need flexibility, flows allow you to add conditional logic, loops, and branching to fit your needs. Let's dive right in with a simple example to see how this works. We're going to build a flow that uses Open AI to pick a random city in one task and then generate a fun fact about that city in another task. In this code, we bring in some key components from crew AI like the flow class itself along with tools for listening to events and starting the process. We also pull in a few helper libraries to load environment variables and interact with AI models for text completion. Now let's break down what's happening in this example. We start by defining a class called example flow which builds on the base flow class from crui. Inside this class we specify a model to use for generating text something like gpt for mini. Then we create a method called generate city which is marked as the starting point of our flow with a special decorator. When this method runs it prints a message to let us know the flow is starting. Every flow automatically gets a unique identifier which we can access and display to track things. Next, we make a call to our AI model with a prompt asking for the name of a random city in the world. Once we get the response, we pull out the city name, store it in the flow state for later use, print it to the console, and return the city name as the output of this task. And after that we have another method called uh generate fun fact which listens for the output of the uh generate city method. This means it waits for the city name to be ready and when it is that name gets passed directly into this new method. Inside we make another call to our AI model. This time asking for a fun fact about the city we just generated. We take the response, store the fun fact in the flow state and return it as the output. Then now finally outside of the class, we create an instance of our example flow. Visualize how the tasks connect with a plotting tool and kick things off to run the whole process. Let's talk a bit about the special markers or decorators that we use in flows. First up, there's the start decorator. This marks a method as the entry point of your flow. Next, we have the uh listening decorator. This is used to make a method wait for the output of another task in the flow. There are a couple of ways to use the listening decorator. You can specify the task to listen to by its name as a text string like listening for generate city. When that task completes, the listening method kicks in. Alternatively, you can directly reference the task itself. Now, let's discuss how to handle the output of a flow. Getting access to the results is crucial, especially if you're integrating your AI workflows into bigger systems. To get the final output by calling the kickoff method, let me show you an example called output example flow. Here we bring in the necessary components from crew AI, define our flow class and set up two methods. The first method is marked as the starting point and returns a simple message. The second method listens for the output of the first one, takes that output as input and returns a new message that builds on it. Then we create an instance of this flow, optionally visualize it with a plotting tool, run it with the kickoff method, and print the final result. Looking at the output of this example, you'll see the final result is the message from the second method since it's the last one to complete. That's what gets returned when we kick off the flow and it's printed to the console. If we had used the plotting tool, it would also generate a visual representation saved as an HTML file. You can also access and update the state within your flow to store and share data between different methods. In this state example flow, we bring in the necessary tools, including a library for defining structured data models. We create a custom state structure with a counter and a message field and our flow class uses this structured state. The first method marked as the starting point sets an initial message in the state and increments the counter. The second method listens for the first one to finish, updates the message by adding to it, increments the counter again and returns the updated message. Then we create an instance of this flow. Visualize it if we want. Run it. Looking at the output for this example. You'll see the final message after both methods have updated it. And the state shows the counter has been incremented twice along with the full message. This shows how the state evolves as the flow progresses. Let's move on to managing the state of your flow because doing this effectively is super important. Crew AI flows offer robust options for handling state in both unstructured and structured ways. First, let's talk about unstructured state management. In this approach, all your data is stored in a general state attribute of the flow. It's super flexible since you can add or modify data on the fly without a strict format. Even in this flexible setup, Crew AI automatically assigns a unique identifier to each state instance for tracking. I've got an example here called unstructured example flow where we set up a flow. Start with a method that initializes some data like a counter and a message and then have subsequent methods update that data as the flow progresses finally printing the updated state. Here's the diagram for that unstructured example flow showing a sequence from the first method to the second and then to a third method. Just remember the unique identifier is automatically generated and maintained for you. So you don't need to worry about managing it yourself. Now let's look at structured state management. This approach uses predefined formats with data models to ensure consistency and type safety which means fewer errors. Each state still gets a unique identifier automatically for tracking purposes. I've got an example called structured example flow to show you. We define a specific state structure with fields like a counter and a message. And our flow class uses this structure. The methods in the flow update these fields in a typed predictable way. First setting values, then building on them in later steps, and finally printing the results. This structured setup gives you a clear outline of your data, ensures everything matches the expected types, and even helps your coding tools provide better auto completion and error checking. So, how do you choose between unstructured and structured state management? Go with unstructured if your workflow state is simple or changes a lot, if you value flexibility, or if you're just quickly prototyping something. On the other hand, choose structured when you need a consistent and welldefined state when type safety and validation matter or when you want to take advantage of features like auto completion in your coding environment. Crew AI flows give you the power to pick whichever approach suits your project best. Next, let's explore how to save the state of your flow with persistence. Crew AI flows have a special marker called persist that lets you automatically save the state so it's available even if you restart or run the flow again later. You can apply this at the whole class level or just to specific methods for uh class level persistence. Applying it to entire flow means all method states are saved automatically. I've got an example here called my flow where the starting method sets some initial data in the state and a following method shows that the state including its unique identifier is reloaded and can be updated. For more targeted control, you can use method level persistence. In an example called another flow, only the starting methods state changes are saved, like incrementing a counter to track how many times it's run. Here's how persistence works under the hood. Each flow state gets a unique identifier that's preserved across updates and runs. And this works for both structured and unstructured states. By default, Crew AI uses a local SQLite database to store the state with robust error handling builtin. All right, let's move on to controlling the flow of execution in more advanced ways. One powerful tool for conditional logic is the O or function. This lets a method listen to multiple tasks and run as soon as any one of them produces an output. I've got an example called or example flow to demonstrate. In this setup, we have a starting method and a second method that follows it. Then there's a logging method that listens for output from either the starting method or the second method using the or condition. When either one finishes, the logging method runs and prints the result. We create an instance of this flow, visualize it, and run it to see how it behaves. Looking at the output for this example, you'll see the logging method prints messages from both the starting method and the second method as they complete. And in the diagram you can see the starting method branching to both the second method and the logger with the second method also connecting to the logger showing how either path can trigger it. Next let's talk about conditional logic with the end function. This is different because it waits for all specified tasks to complete before triggering the listening method. In an example called an example flow, we have a starting method that sets some initial data in the state and a second method that adds more data after listening to the first. Then there's a logging method that only runs when both the starting and second methods are done using the end condition. It prints the combined state once everything is ready. Again, we create, visualize, and run the flow to see the result. In the output for this example, the logging method shows the complete state only after both tasks have finished. The diagram illustrates this with the starting method leading to the second method and both connecting to the logger with a special indication that it's in. Now let's look at routing logic with the router decorator in flows. This allows you to define conditional paths based on a method's output, giving you dynamic control over which tasks run next. It's a great way to branch your flow based on specific conditions or results. I've got an example called router flow to show you how this works. We start by bringing in necessary tools. Our flow class router flow has a starting method that prints a message. Generates a random true or false value and sets that as the success flag in the state. Then there's a second method marked with the rotor decorator which checks the success flag. If it's true, it returns a so success signal. If false, it returns a failed signal. After that, we have two separate methods listening for these signals. One runs and prints a message if it hears as success and the other runs if it hears failed. We create an instance of this flow, visualize it and run it to see which path gets taken based on the random value. Here's the diagram for rotor flow. You can see the starting method leading to the second method which then branches with special routing triggers to either a third method for success or a fourth method for failure. Let's move on to integrating individual AI agents into flows. Agents are a lightweight way to handle specific tasks without needing a full team, and they fit seamlessly into your workflows. I've got an example focused on market research to show you how this looks. In this market research example, we bring in a bunch of tools for typing external data access, structured data modeling, defining agents, and of course, building flows. First, we set up a structured format for our output using a data model called market analysis, which includes fields for key trends, market size, and competitors, each with clear descriptions. Then we define the state for our flow with fields for the product we're researching and the analysis results. Now our flow class called market research flow starts with an initialize research method that prints a message about the product we're focusing on and returns that product as input for the next step. The next method analyze market listens for that product and is set up to run asynchronously for efficiency. Inside we create an AI agent called analyst with a role as a market research expert. A goal to analyze the market for our specified product and a backstory to give it context. This agent uses an external tool for web data and is set to provide detailed feedback as it works. give the agent a specific query to research the market for our product asking for trends size and competitors and we request the response in our structured market analysis format. The agent runs the analysis and we check if the result matches our structure. If it does, we print the formatted data. If not, we show the raw output. Finally, we return the analysis to update the state. The last method present results listens for the analysis output. It prints a header for the market analysis results. Checks if the data is in the right format and if so displays the trends market size and competitors clearly. If not, it notes that structured data isn't available and shows the raw information instead. And to run this, we have a small async function that creates an instance of our market research flow, visualizes it, kicks it off with a specific product like a II powered chat bots as input and returns the result. This is wrapped in a standard code block to execute everything properly. Here's the diagram for this market research flow, showing the sequence from initializing the research to analyzing the market to presenting the results. This example highlights a few key features using structured data models for type safety, maintaining context with a dedicated state structure, and integrating external tools with agents to pull in real world data. Now, let's talk about adding full teams of AI agents or crews into flows. Let me switch to my coding terminal to show you this in action. I'm going to run the command to create a new flow project. And there we go. It's created successfully. When it comes to building your crews, you'll define them in the crews folder of your project. Each crew gets its own subfolder with configuration files. For example, the poem crew includes files for defining agents, tasks, and the crew itself. Here we define an agent called poem writer with a specific role, a goal to create a funny, light-hearted poem about how awesome crew AI is with a certain number of sentences and a backstory for context. There's also a tasks YAML file which outlines a task called write poem with a description expected output format and assigns it to the poem writer agent. Then in poem crew pi we have the actual code that brings this crew to life defining the agent and task based on the config files and setting up the crew to run sequentially with detailed logging. There's also a tools folder where you can add custom utilities. Let's take a closer look at main. We define a state structure for our flow with fields for the number of sentences in the poem and the poem text itself. Our flow class called poem flow has a method to start things off by generating a random sentence count between 1 and five. Then a second method listens for that count, creates an instance of the poem crew, runs it with a sentence count as input, prints the resulting poem, and stores it in the state. Finally, a third method listens for the poem, and saves it to a file. There's a simple function to kick off the flow and another to visualize it. Though for now, we're just running the kickoff back in the terminal inside our project folder. The first step is to set up the environment with crew install which creates a virtual environment and installs the necessary packages. Then I activate the environment and run crew flow kickoff to start the flow. Looks like we hit an authentication error for OpenAI because the API key in our environment file is just a placeholder. All right, let's try running. There we go. It's running. You can see the flow starting with a unique identifier, generating a random sentence count, say three sentences, then generating the poem using the poem crew. We get a funny poem about crew, something like my crew team, a quirky bunch of bots. The poem is printed, saved to a file, and the flow completes successfully. Perfect. Thanks so much for watching and I hope this tutorial helps you build amazing things with Crui Flows. All right, let's dive into something exciting today. I want to talk about a powerful agent framework called Semantic Kernel. First, let's break down the idea of the kernel itself. Think of the kernel as the heart of semantic kernel. It's like a central hub that manages everything your AI application needs to run smoothly. It handles all the services and plugins, connecting them seamlessly so the AI can use them whenever necessary. Essentially, you load up the kernel with the tools and capabilities you want and it takes care of the rest, making sure everything works together without a hitch. So, how does this actually work? Picture this. You choose the AI services you want to use like models from OpenAI Azure, hugging face or others. Then you craft some template prompts. These are like instructions or questions you send to the AI. The kernel acts as the middleman. It takes your request, sends it to the AI service, gets the response, processes the results, and even triggers events that can feed back into your application. It's a smooth, streamlined process that keeps everything organized. What makes this really cool is that you can customize the entire journey. At every step, you can set up events or middleware to jump in and do things like logging what's happening, updating users on the status, or super important, ensuring responsible AI practices are in place. Now, let's talk about the two main pieces you'll work with, services and plugins. Services are the engines that power your AI app. They include things like chat completion for conversational AI as well as other essentials like logging tools or web request handlers. Plugins on the other hand are like add ons that your AI services and prompts can tap into. They help with specific tasks like pulling data from a database or connecting to an external web service. Think of them as handy tools the AI can call on to get the job done. If you're ready to jump in, you'll start by bringing in the necessary tools for semantic kernel. For example, you'd pull in the main kernel package, connect to AI services like a chat completion tool from Azure, and even add useful plugins such as one for handling time related tasks. It's all about setting up the foundation so you can build something amazing. Next up, let's chat about adding AI services to your kernel. Semantic kernel supports a variety of services like chat completion for conversations, text generation for creating content, embedding generation for understanding data, and even text to image capabilities. Keep in mind though that some of these are still in the experimental phase. For today, I'm going to zero in on chat completion because it's such a core and useful feature. So, what's chat completion all about? It lets you create back and forth conversations with an AI, almost like chatting with a friend or a helpful assistant. This isn't just for building chat bots. It's also great for designing autonomous agents that can handle business tasks, write code, or solve complex problems. You've got a ton of model options to choose from, including those from OpenAI, Google, Mistro, and others. When picking a model, think about what it can do. Does it handle text, images, or audio? Can it call functions? How fast is it? And what's the cost for using it? These are all key things to consider. For this tutorial, I'm going to use the Google Germany model as an example. You'd start by installing the required package for it. Then you'd bring in the Google AI chat completion tool from semantic kernels connectors. Set up a variable for the chat service and initialize it with the Geminy model ID, your API key, and optionally a custom name if you want to label it. That's the basic setup for chat completion. And it gets you ready to start interacting with the AI. Now let's shift gears and dive into core topic for today, the semantic kernel agent framework. So what exactly is an AI agent? Think of it as a smart software helper designed to tackle tasks on its own or with some guidance. It takes input, processes information, and takes action to achieve specific goals. These agents can send and receive messages, crafting responses using a mix of AI models, tools, human input, or other customizable pieces. What's really neat is that they're built to work together, collaborating on complex workflows by interacting with one another. This framework makes it super easy to create both simple and advanced agents, keeping everything modular and userfriendly. So, why use AI agents? They solve a bunch of problems and bring some awesome advantages to the table. For starters, they're modular, which means you can create different agents tailored for specific jobs like scraping data from the web, connecting to APIs, or processing natural language. Each agent can be a specialist in its own area. Then there's collaboration. Multiple agents can team up on a task. Imagine one agent gathering data, another analyzing it, and a third making decisions based on the results. Together, they build a smarter, more capable system. Another great aspect is human agent teamwork, often called human in the loop interaction. Here, agents assist people by providing insights or analysis that humans can review and refine. Finally, agents excel at process orchestration, coordinating task across different systems, tools, and APIs to automate entire workflows. Think deploying apps, managing cloud services, or even supporting creative work like writing or design. So, when should you consider using an AI agent? This framework really shines when you're building applications that need autonomy, decision makingaking power, multi- aent collaboration, or interactive goal-driven systems. If your project fits into any of those categories, agents can give you a serious edge. Wondering how to get started with the semantic kernel agent framework? It's pretty straightforward depending on the programming language you're using and its package distribution system. Let's explore that next as we dig deeper into a specific type of agent. Since we've already touched on CH chat completion, let's see how that ties into the agent concept with the chat completion agent in semantic kernel. At its core, chat completion is about enabling conversational interactions with an AI model. The system keeps track of the chat history and includes it in every request to the model, ensuring a coherent conversation. Semantic kernel provides a unified way to handle this through its AI services and the chat completion agent can work with any of those services we've discussed. To get rolling, you'll need to install the semantic kernel package. It's as simple as running a command in your terminal to grab it. Once that's done, set up your Python environment, maybe create and activate a virtual space to keep things tidy, and you're good to go. I'll walk you through some examples to show how this works, and later we'll look at a practical case using a menu helper plugin. Let's focus on building a chat completion agent. There are two main ways to do this. First, you can provide a chat completion service directly. You'd bring in the agent tool, create an instance, and pass in your chosen service like a chat completion tool from Azure along with a name and some instructions for how the agent should behave. The second option is to start by building a kernel. You'd set up the kernel, add your chat completion service to it, and then create the agent using that kernel. Again, giving it a name and instructions. When it comes to picking a a service for your agent, it's similar to working with semantic kernel services directly. If your kernel has multiple chat completion services, you can specify which one to use with a selector. If you don't pick one, the system will follow default rules to choose. For instance, you could add two different Azure chat completion services to your kernel, each with a unique identifier and then specify which one to use when setting up or running the agent. So, how do you actually talk to a chat completion agent? The simplest way is to call a method to get a response passing in the user's input and it'll return the agent's reply. If you want to keep the conversation history going across multiple exchanges, you can use a chat history thread to store the context. There are also options for more advanced interactions like streaming responses in real time or handling a series of replies as they come in. One thing to note is that the chat completion agent often works behind the scenes to answer user questions, sometimes using tools to figure out the final response. If you want to see what's happening during those intermediate steps, like when a tool is called or a result is generated, you can add a callback function when you interact with the agent. This lets you peek into the process and track what's going on before the final answer is delivered. Let's make this concrete with an example. Imagine we've got a little helper plugin for a menu, something we call a kernel function using a decorator. Essentially, this function is designed to give us a list of specials from a menu. When we call this method to get the specials, it returns a string that lists out things like the special soup, the special salad, and the special drink. Pretty straightforward, right? Then we've got another kernel function with a decorator that helps us figure out the price of a specific menu item. This method which we can think of as a tool for getting the price of an item takes the name of the menu item as input and returns the price. For example, in this case, it just returns a price of $9.99. Simple but effective. Now, let's talk about this callback function. Inside this function, we loop through the items in the message and check a couple of things. first whether the item is related to a function call and second whether it's a result from a function. If it's a function call we print out a line that shows the details of that call. If it's a function result we print out the result itself. And if it's neither of those we just print the message content along with the role of the message sender. It's a neat way to keep track of what's happening step by step. All right, let's move on to the main function which is where a lot of the magic happens. Here we are setting up our agents using an asynchronous function. We define these agents with a specific service in this case Azure check completion and we give each agent a name, some instructions and a set of plugins. These plugins are basically a collection of function tools like the menu tools we talked about earlier. Then we set up a chat history thread to store the conversation state and keep track of everything that's been said. Next, we define the user input. Something like, "Hello, what's the special today? How much does that cost? Thank you." E. We loop through these user inputs and invoke the agent to get a response. The message gets added to the thread. And we can also print out intermediate messages using the handling function we defined earlier. After that we update the thread with the response making sure it always carries forward the previous conversation to the next agent call. So once everything is set up we can run it and see the results come to life. Now let's get into actually running this. I'm going to create a new Python script called the menu agent script. I'll just copy and paste the necessary code here. As I mentioned earlier, I'm switching things up a bit by using Google's Geminy model for this. So, I'll copy over the setup for Google AI chat completion and define the service with the Germany model ID, an API key, and a random service ID. For the main function, I'm updating it to use this Google AI service and giving it a name. Everything else stays the same for now. Once that's saved, it's time to run the script. I don't think there's anything else we need to tweak at this point. So, let's just go ahead and execute the menu agent script and see what happens. Okay, let's take a look at what's going on as the script runs. Here's what we're seeing. The user starts by saying, "Hello," and the assistant responds with, "Hello, how can I assist you today?" Then the user asks uh what is the special soup? At this point, the system makes a function call to the menu plugin to get the specials and the result comes back with the special soup listed as clam chowder along with a special salad called cob salad and a special drink chai tea. The assistant then replies, "The special soup is clam chowder." Next, the user asks, "How much does that cost?" Another function call is made to get the price of the item specifically for clam chowder and the result is $9.99. So the assistant says the clam chowder costs $9.99. Finally, the user says thank you and the assistant responds you're welcome. Is there anything else I can help you with? Friendly reply from the assistant. So there you have it. a rough example of how this semantic agent system works in action. Let's shift gears for a moment and talk about the bigger picture, the agent architecture. I want to give you an overview of how this all fits together. The agent framework we're working with was built with a few key goals in mind. First, it provides a core foundation for creating and implementing agent functionalities. Second, it allows multiple agents of different types to cooperate within a single conversation. And third, it enables a single agent to engage in and manage multiple conversations at the same time. At the heart of this setup is an abstract agent class which serves as the main building block for all kinds of agents. This base class provides the essential functionality that everything else is built on and it's pretty cool to see how it all comes together. Now, let's touch on the different types of agents you'll find in the semantic kernel framework. There are things like chat completion agents and open eye assistant agents. And we'll dive deeper into the chat completion agent in a bit. There's also something called the agent thread, which is an abstract class that acts as the core for managing the state of a conversation or thread. Think of it as a way to store the memory of a conversation. Some stateful agent services even keep track of conversation states directly within the service itself. Another piece of the puzzle is agent orchestration, but I'll be honest, it's still in an experimental stage right now. So, I'm not going to go too deep into that just yet. All right. I think we'll leave agent orchestration for another time. If there's more to cover on that in the future, I'll definitely come back to it. For now, let's wrap things up. I also want to mention another framework called the Google Agent Development Kit. I've actually covered this in some of my previous videos, so if you're curious, feel free to check those out. In those videos, I've gone through a quick start guide for the kit, and I've even used it to build multi- aent AI workflows. For example, I created a system to enhance YouTube titles and descriptions by having multiple agents work together, even voting on the best results. I've also set up a deployment for the kit, so there's plenty to explore there. Onanso, thank you so much for sticking with me through this super long video. I hope this basic walkthrough has given you a general idea of how these agent frameworks operate. I've definitely learned a lot myself while putting this together, and I hope you've picked up something valuable, too. If you enjoyed this, don't forget to check out my other content and I'll see you in the next video.

Original Description

Unlock the power of Large Language Model (LLM) agents and build sophisticated AI applications with this in-depth tutorial! For developers, AI enthusiasts, and students, we deep dive into four leading LLM agent frameworks: LangGraph, AG2, CrewAI, and Semantic Kernel. Learn their core concepts and practical implementations with hands-on Python examples, enabling you to create autonomous AI systems, advanced chatbots, and multi-agent workflows. **What you'll learn:** * **LangGraph:** Build stateful, multi-agent applications with memory (checkpointers), human-in-the-loop controls (interrupts), custom state, and even "time travel" to revisit conversation states. See a basic chatbot with web search (Tavily) integration. * **AG2:** Create production-ready AI agents focused on "Conversable Agents," covering orchestration, human-in-the-loop, tool integration, and structured outputs. We build a financial compliance assistant. * **CrewAI:** Explore this lean Python framework for building AI agent "Crews" (teams of agents) and "Flows" (event-driven workflow orchestration). Master project setup, defining agents/tasks in YAML, and leveraging conditional logic (@Or, @And, @Router decorators). Uses SerperDev tool. * **Semantic Kernel:** Understand the "kernel" as a central hub for managing AI services (like Google Gemini & OpenAI chat completion) and plugins (tools). Explore the Chat Completion Agent with a practical menu helper plugin, and learn about its agent architecture. This video is packed with hands-on code examples and aims to provide a solid foundation for anyone looking to build advanced AI solutions. **Don't miss out!** Like, share, and subscribe for more AI agent development tutorials and deep dives! Check out additional resources: LangGraph server/platform quickstarts, Google Agent Development Kit for multi-agent AI workflows and deployments. Timestamps: [0:00] Introduction [0:39] LangGraph Overview & Setup [2:38] LangGraph: Building a Basic Chatbot [9:29] LangGra
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Related Reads

📰
What Do Okta AI Data And Taylor Swift Have In Common? A Fearless Era
Learn how Okta AI data reveals 15 fearless findings and 4 essential moves for business leaders, inspired by Taylor Swift's Fearless era
Forbes Innovation
📰
AI Is Forcing Companies To Rethink Work Itself
AI adoption is forcing companies to rethink work itself, focusing on business value over personal productivity
Forbes Innovation
📰
Japan is building a 140MW AI factory for robots, and Nvidia is supplying all of it
Japan is building a 140MW AI factory with Nvidia's technology to power robots, learn how this massive infrastructure will work
The Next Web AI
📰
AI Agents with Cloud Credentials Are Outrunning Billing Guardrails Built for Human-Speed Mistakes
AI agents can outrun cloud billing guardrails, leading to unexpected high costs, and it's crucial to implement robust security measures to prevent such incidents
InfoQ AI/ML
Up next
How I Built a Self-Learning AI Trading Bot (Claude Code Live Build)
Alex Leischow
Watch →