Transcripts
1. Getting Started with AI Agents: Welcome everyone to this class, which is AA agents
for Business process. Before we jump into
the first session, I brief about myself. My name is Javin and I have been working with
Fortune 500 companies, specifically in the technology
and the media space. Now, with that experience, I have curated course which can help you
to build agents for your own business to solve the problems or to
increase the efficiency. Now, what are the skills that you'll be learning
in this session? So you'll be learning right
from the fundamentals of what is an lem,
what is an agent, how do you build a single agent, and then going towards
the intermediate of how do you build
multiple agents together? Coming to the advanced
part, which is, how do you build
multiple agents and make them communicate with each other to solve
a business problem? Also, how do you
delegate your task to different agents and solve
the business problem? Now, having said that, we'll also see how do
you actually build an enterprise grade
agentic system using different
architectural patterns. So you'll be able to walk
away with the ability to design and build
production grade A agents that are practical, skiable and industry ready. So let's go and I'll see
you in the first class.
2. What is AI Model?: All right, welcome
back. Now, let's start by understanding
what is an AI model. Now, here is a question
for you. What do you think is an AI model? Do you think it is an algorithm
wherein we have written multiple conditional
statements in the files? If your answer to that is yes, most probably your understanding about an AI model is inaccurate. Now, let me ask you
another question. Now, I am on Chat GPT, and if I ask this question, what is the capital of
USA, what do you think? The answer is, which
is the correct one, that the capital of
USA is Washington, do you think this answer is being retrieved
from any database? Do you think this is coming
from any database is Open EI or GPT storing the answer to each question
that you might ask? No, right? Then how would
this answer generated? Now, let's go back and
understand what is an AI model. So think of AI model
as a newborn child. So as a newborn
child, he's unaware about all the things that are happening in his environment. So what do we do? We teach
our child different things. For example, if your child
knows what a dog looks like, but he's unaware about the characteristics of a cat or how a cat would look like. And if you try to
ask your child by showing him an image of a cat and asking
him, What is this. Most probably you'll get an
answer that I don't know. Or he might also say that
this is a funny looking dog. Right? So what do we do? We show multiple images to him, multiple images of cat so that
his brain will be trained. The weights and the biases
that he have will be trained, and then it will be stored. Now, what would happen is, again, if you show
an image of a cat, this time you show a
different image of a cat, this time the child will be able to answer the
question straightforward. The reason being,
you have showed him you have trained the mind. You have helped him in understanding what
are the characteristics, what are the dimensions
of a cat would look like? And if you even show a
different colored cat, he will be still able
to understand what a cat would look like
and identify it, right? So similar to that, in the
space of computer science, we have something known as machine learning model or
a deep learning model. So predominantly, those are artificial neural
networks, ANN or CNN. So similar to a child, here we have a model, which is a computer model
which ANN or a CNN. And if you try to show
him a picture of a cat, most probably he
would throw an error. Why? Because the weights
and the biases that he have does not recognize
the image as a cat, right? So what do we do? We again feed in multiple amounts of data
and we retrain the model. Retraining means changing
the weights and the biases. Now let me do one thing. Let me actually show you what
a neural network looks. Okay. So this is
a neural network. The neural network,
think of it as a similar to what our
brain would have. So a neural network would
have multiple neurons. So all these circles that
you can see is a neuron. So in a neural network, we have an input layer which
takes the input given by us. Then we have multiple
hidden layers. Now, hidden layers, the
purpose of it is to understand the input and also predict what it might be and then give
the output, right? So these lines that you say or as these neurons are connected to each other
neuron in each layers, there are weights and
there are biases. When you try to train the model by feeding
in multiple images, what we are essentially
doing is we are using a mathematical
equation to change the weights and the biases
of the each neuron. Now, once that is completed,
we freeze the neuron, and then we can say
that now the model has the capability to understand the difference between
a cat and a dog. So this is on a high level, but a few things to
note are the neurons, the weights, and the biases. Now, you would ask
me a question. If chat repeat when
I ask a chat repeat, what is the capital of USA, it is not retrieving
from any database, then where is the data stored? Now the data is
stored as a weights. So when we say we are training, predominantly we are computing the weights and the biases. So all the data that is
being stored is the weights. So each neuron has small
amount of weights. Now, you might ask me another
question if it is storing, Is it storing in a question
and answer format? Do you think that
would be the case? The answer is no. And we will
see how it is storing in what format and how
this computation takes place in the
future sessions. But let's now
understand that this is an artificial neuron network which has weights and biases. We feed in the input data. We have multiple hidden
layers which will compute the thing using the
weights and the biases, and it will give us an output. Now, let's go back to the slide. Similar to this is
how it would be. Once you train the model with enough information
about the thing, then it would be able
to answer or predict the question with the
right answer correctly. Right? So model is nothing
but a composition of huge mathematical
equation whose parameters or weights change as
we train in, right? So if I show a picture if
I show the data of lion, then again, the
weights and the biases has to be pre trained, right? If I show a different data, again, the model has to
be trained upon that. Now, there are multiple
different neural networks. And each neural network has its own advantage
and disadvantages, and what it is able to solve. For example,
anything that has to be taken care similar to
image classification. For example, whether
it is a cat or a dog, whether it is a fraud
or not a fraud, right? So CNN takes care
of those things. For example, the object
detection, image classification. In COVID, you can see that
if you don't wear a mask, it would red flag you, right? That was done using CNN. Then we have RNN, which is most probably used for
language models, speech recognition and time
series predictions, right? Now, out of these all
different things, there are a few architecture which are predominantly used, and those are auto encoder, transformer, but and
diffusion models. Now, the architecture that is powering the GPT models is
that transformer architecture. The architecture that is
powering the image modeling. So you might have
seen that people are showcasing AI
generated videos, AI generated images, right? The diffusion model is
the architecture that is being used to create
those kind of AI models. And also, transformer is
also predominantly used, but we will be
seeing in depth of what this each
architecture is about. We'll be going in depth of it. So I think you have got a
gist of what an AI model is. AI model is nothing but a huge
amount of neural networks. Which have weights and biases, and based on the input data, it will compute
what it is about. For example, if you give
in multiple images of cat, it might be able to
understand, okay, you have multiple images
of cat and then it might answer whether
it is a cat or a dog. That is an EI model.
3. What is Generative AI Model: Come back. Now, we are going to learn about
what generative AI. In the previous session, we have seen what
an AA model is, and based on the image that
we pass on that the model is able to predict whether it is the given images of a
cat or a dog, right? Now, if you think in
terms of outcomes, the model is only
able to predict whether it is a cat or not. So the answer is binary, yes or or no, right? So that is an AI model. But when we come to
a generative AI, generative AI models, based on the input that we give, the model will actually go
and generate new content. It can be text, it can be image, and it can be audio. Now, let me demonstrate. I'm using hat GPT, and
let me ask this question. Explain generative
AI in a single line. Okay. So it gives me an answer that generative VA is a type of artificial intelligence
that creates new content like text, images or music based on patterns learned
from existing data. Now one thing to
understand from this is the patterns learned
from existing data. Remember in the
previous session, we actually have shown
multiple images of a cat, like 1,000 images of cat
in order for that model to understand the difference
between a cat and a dog, right? So let's broaden our
horizon and now let's train the entire model on the entire data that is available on the
Internet. Just think of. If you're able to
predict whether it is a cat or a dog based on just showing you training the
model on, let's say, 5,000 images, what
would be the capability of that model if you train it on the entire data that is
available on the Internet? Think of it, right? So let me try to give the
same question again. Can you see the difference?
I'm giving the same input, but it is giving me
a different answer, even though the intent of that answer is
one and the same. So generative A is
an A that produces new content by learning
patterns from existing data. Now, let me try to
do it once more. Right? So it's an Adi
intelligence that creates original content
from the wn patterns. So did you see a pattern? Every time I give
the same input, the model is giving me answer
in a different format, but the intent of
that answer is same. So this is what happens
under the hood, as what we have seen, right, the weights and the biases. Now, every time I
give the input, the weights and biases and the mathematical
equation that performs the entire computation
is probabilistic. Now, when I say probabilistic,
it would change. Not necessarily all
neurons would be triggered for the
same question, right? So hence, we get a
different variety of answer back altogether. So similar to this,
Generative AI is a model wherein based
on the input given, it will go and
generate a new answer. It won't go and fetch the data from any database or
a thing. Now, think of it. If it was fetching
from a database, for the same input that I give, I should get the
same output, right? The reason why it is not
happening is because it is generating it by itself. It is not fetching anything
from the database. Now, what are the
different generative AI applications that are
available out there? I'm sure most of you would have used so generative A models
create new content like text, images, or code based on the learned patterns
from existing data. Now, popular A application
that we use day to day. And let's see what is the underlying model
that they are using. And what is the
category of that is it? So Gemini, GPT, we are all
familiar with CloudA as well. So it uses transformer
architecture and GPT 4.1 GPT 40, 3.5 Gemini 2.5 P flash
Gemini three, right? And so on it has
their own models. But they are all in terms of text generation and
multimodel, right? Multimodel as in the model has the ability to
understand images, text, audio, and language. Similar to that, we also have diffusion, stable diffusion, which says an application
which uses diffusion model. So remember the architecture
that we saw right? So transformers and
the diffusion models, so diffusion models
predominantly used for, you know, generating
new images and videos. So similar to that,
we have a diffusion, stable diffusion as
in company who has f trained their model on multiple images so that they
are able to generate images. Similar to that is Bit
Journey, runway three. And there are a few
more which are able to generate video as well. For example, they're
using diffusion plus transformer architecture in
order to generate video. We have popular website, which is Snot TI, which is pretty cool altogether. You should try it,
which generates music based on input given
in natural language. We have whisper speech to text. So whatever I'm
talking right now, it will take that as an input as an audio file and it will
convert it into a text. Then we have multiple
other things which are into
scientific generation. So scientific here, Deep Mind is from Google,
and they're using. They have created an arc
model which is able to help scientists in
the development of new proteins, right? And similar to that,
we have others. So that's it for this session, and we will see what is under the hood of an
LLM and how it is
4. Setup Environment & LLM Keys: Welcome back, everyone.
Let's go ahead and create an environment
that we are going to use in order to understand or explore the components
of ADK and its features. Going forward, we are
also going to use VS code in order to develop an
enterprise grade, multi agent a. Now, the most important part once you open your Google Colab is to make sure that you click
on this reconnect button, which will connect instance
running in the Google server. Second part is to
get an environment where you can store
Gemini APAKys, right? Similar to how we have
in a development area which we do in VS
code as dot ENV. If you have your APIKey created, you can directly click on Add New Secret and
you can page those. If you don't have it, you can also go ahead
and create new APAKes. You can go ahead
and create APAKys with the help of
Google AS studio. Now, let's go ahead
and create an APIKey. Let's name the key as agent. Let's select any project, or you can go with the
default project settings. Which will create
the API key for us. Now, let's go ahead and copy this APAkey and add it to
our environment variables, which is nothing but
secrets in Google Colab. Now you can give a key which is Gemini and its value is the
key that we have copied. Now, make sure that
you can enable this so that your code can
access this key. Now let's close this. Now, once we have
the LLM API set, the second part is to
install the libraries. Now the most important
library is the Google ADK. Let's go ahead and run that. Now, it will go
ahead and install all the libraries required. Now, you can see that as
the ADK is developed by Google and the Colab is also
from the Google itself, it already has the
installed ADK into it. Now, let's go ahead and
check the version of which AD Google ADK
library we are using. So it is 1.20. So make sure that anytime that you go ahead and
input any library, make sure that the version
that you're using is 1.2 0.0 in order to
follow along with me. In future, if I go and change
any version of any library, I will mention those changes
in the requirement dot TxD. Now, let's go ahead and add
a few more configurations. Now, let me explain why
we are adding this. So we are going to
add Cloudfare tunnel, and the reason is
that we will be required in order to
access the ADK web. And I will explain why
we are required to do this only in Google Colab. If we are going to do this
setup in the VS code, we are not required to
install these libraries. Now, that's it for the
installation step. The main things were creating an API key and
installing the library. Now, you have set up your
APA keys in the secret. But how do you
actually go ahead and use those keys inside your code? So this is the piece of code, which will actually go ahead and fetch the keys from
the Google Colab. And remember we have set up
a key which named Gemini. So it will go ahead and check if the user data has anything related to a
name such as Gemini, that is a Google API key. And then we are going
to go ahead and set up it in the environment. All right, so we have the
Gemini API key setup done. So that's it for the setup
that we are going to use in order to explore
the Google ADK feature.
5. Building First Agent: All right, welcome back. So once you open your Google Colab, make sure that you
first go ahead and reconnect and you have
the LLM key setup. All right, we have
connected to the server. Now, let's go ahead and
execute these cells. So I'll collapse this. Once that is done, we execute the remaining
cells as well. Now what we can see is
to understand how we are going to build
our first agent. Now to do so, we have to import few components
from the ADK. Now, I'm importing agent. I'm importing Gemini as we
are going to use Gemini keys. I'm going to import
in memory runner, Googled search as a tool and types for the
validation part. Now, as we are working
with LLMs, right, we might encounter
rate limit errors or a temporary service
on availability error. Now, in order to automatically handle these failures by
retrying the request, we are going to set up
this configuration, which is the retry
configuration, where we set the number of
atoms we want to retry again, the delay and the
ATTP status code. Now, these are the codes. If we get any of this code, we will go ahead and retry for the maximum retry atoms
set, which is five. Let's go ahead and run this. Let's go ahead and see
what is the difference between a normal API
call and an agent. What makes it
different? So you might have used Gemini or any
chatbots like GPT, right? When you give a prompt, it will go to an LLM, and then it will give the text back. But when it comes to an A agent, it will take it one step further wherein when the
user gives a prompt, it will go to an agent. The agent will think
about the input. What is the output that
the user is expecting? Based on that, it will create a detailed execution plan and perform actions in order
to reach the goal. Now the output from these actions is
again fed to the LLM, where it will understand
and observe whether the output is according to
what the user's expectations. If it is, then it will be sent back to the user
as a final answer. Now let's understand how
we are going to leverage the Google ADK library
and build agent. Now, to build any agent, there are few main
properties that are required
initialize any agent. Now these main
properties are name, description,
instruction, and a tool. Now let's see how we
do it in the code. So we have imported agent, which is the component from ATK, and we provide these
main properties inside it, which is the name. So we are going to build
helpful assistant. We are going to provide this
agent access to a model, which is nothing but
will act as a brain with a retry option which
we have set over here. So, in case if it
fails to connect to this API due to a rate limit or temporary service
unavailability, it will go ahead and retry. It will not break
the entire code. And then we have a description. Now, this description
is important in order to understand what
is this agent about. Then we have an instruction, which is the guidelines of
how this agent should process the user input and what is the expected output
from this agent. Then we have given
access to Google Search, which is tool to this agent so that this agent can go ahead and use this Google search tool in order to fulfill the task. Now that we have
built this agent, it's important to
understand that how we're going to interact
with this agent, right? We might have a single agent, we might have multiple
agents altogether, right? Now there is another
component which is central to the ADK that will act
like orchestrator. Now that is known as
a in memory runner. Now, this will go
ahead and manage the conversation between what the user is going to
send to the agent and the response from the
agent back to the user. Now we have imported this
from the Google ADK, which is known as runners. Now let's go ahead and call this runner and interact
with our agent. So we'll call this runner
and we will use a run debug. Now, this method is used to send out prompt
and get an answer. Now, this method will abstract
the process of creating a session and maintaining it throughout this life
cycle of an agent. Now, this is mostly used in testing your agents
at an atomic level. So for example,
you have an agent, and you want to test by invoking it whether the tools are
being implemented correctly, whether it is able to follow the guidelines or the
instruction that you have given. Now let's go ahead
and give a prompt, which is what is Agent
development Get from Google and which language
is the SDK available in. So it will go ahead and call the agent and we'll
give the output to us. And congratulations
that you have built your first agent
using Google ADK. Now, this is the
most simplest agent that we can build
using Google ADK. Now, let's go ahead and see what are the different
types of agents, different types of patterns used in order to build
multi agent system.
6. Multi-Agent Orchestration: Alright, welcome back. So I have re connected to the system, and I have installed
these all libraries. Now in the previous class, you have learned
about how you can build a single agent
that could take action. Now let's see how we
can build agent teams. Now, think of agent teams
similar to a team of people. Now, you can create specialized agents that can collaborate to solve
complex problem, right? And this is called
multi agent system, and it's one of the
most powerful concepts in AI agent development. Let's first start by installing
few libraries again. So over here, we
are going to import those components which
are sequential agent, parallel agent, loop agent. Apart from that, we also
have additional agent tool, function tool, Google
search as tools. Now understand this why
multi agent system. Now let me bring image, which will make it much
more clear on why it is important to build a
multi agent system and where it is important to
build a multi agent system. Now the problem is that
it is do it all agent. Now, the agent
that we have built previously was do it all agent, where a single agent can do
a lot. But think about it. What will happen when
the task gets complex? A single monolithic agent tries to do the
research, writing, and then editing, and then also fact checking all at once, and it can become
a problem, right? Think of the instruction
prompt, how long it will take. And it can also
become confusing. Apart from that, it will
become difficult in order to debug which part has failed. For example, fact checking
age might have failed, but in the monolithic agent, as it is a task within those multiple input or the
prompt the user has given, it is difficult to maintain and often it can produce
unreliable results, right? So the solution is to build
a team of specialist, where we have multiple agents, a team of simple
specialized agent that can collaborate just like a real world team would do. So let's see how we can build a research
summarization system. So we have two agents in that. First is the research agent. And then second agent is
the summarizer agent. And these both agents will be orchestrated with the
help of a root agent. We also have a shared state. Now remember, I talked
about a runner, which is in memory runner, which acts like an orchestrator
between multiple agents. Now, when I say orchestrator, it is not an actual
orchestrator, but it is a message queue
between these agents. So it will help in order to pass the output of one agent
to another agent. And any agent can
access the output of any agent with the
help of the shared state, which is available inside
this in memory runner. Now, first, let's go ahead
and build a research agent. Is the output key. Now, the output key
is used in order to make sure that the Output that is being produced
by this agent can be dumped into the shared
state with a key. For example, once
the research agent has completed its task, it will write the answer to the shared memory with a key
as research finding, right? So the result of
this agent will be stored in this
session with the key. So it will be easier
for the agent to understand what is the output
of the particular agent. Alright, now that we have
built these two agents, let's build a root coordinator. Now root coordinator
is nothing but another agent with a different
set of instructions. Now, let's go through what is the instruction for
the research agent. So you are a specialized
agent and the job is to use Google search tool to find articles relevant
to the given topic. And the summarizer agent
instruction is to create a concise summary with three
to five key points, right? Now that we have the root agent, which will take care of
the orchestration part between the two agents, right? So you are a research
coordinator, where the goal is to
orchestrate the query. First, we must call
the research agent, which will get the
relevant information. Next, we are going to
provide the output of the research agent to the summarizer agent to
create a concise summary. Now, once we have the output, present the final summary clearly to the user as
your response, right? So that is what the root agent will actually go ahead and do. Here we are using Agent tool. Now, as a tool, this agent is only using
Google Search, right? Summariz agent is not using any tool because it is just summarizing the output
of the research agent. But root agent is going to use tools as the agent.
So think of this. Here we are using Agent tool
to wrap the sub agents, which is the research agent
and the summarizer agent. To make them callable
tools for the root agent. Now we will explore more on the agent tool in detail
in the upcoming session. But for now, just think of this. You're giving root agent
access to the sub agent, which are the research agent
and the summarizer agent. And this root agent can call these agents like
a tool calling. Now that we have this set, similar to how we
will go ahead and interact with any
agent we will call the in memory runner and then
we will also run it in the Run Debug mode and
send in our input, which is what are the
latest advancement in the quantum computing and
what do they mean for AI? It will go ahead and use delegate between the
research agent and the summarizer agent and
give us the output back. Now, let's see what
is the output. Now, in this output, you can see that it is using
a function call, right? The function call
is done because this research agent has access to a tool known
as Google Age search, which is nothing but a function calling or a tool
calling to this agent. Now we have just built a first multi agent system with a root agent
as the coordinator. Now, this coordination is
happening with the help of the instructions that we
have given as a guideline. That's it for this. This is our first multi
agent system using a single coordinator agent
to manage the workflow, which is powerful and a
flexible pattern. All right. Now we will see there are multiple patterns in
the upcoming session.
7. Sequential Agents: All right. Welcome back.
And congratulations on building your first
multi agent system. Where you have used a single coordinator agent
to manage the workflow, but relying on an
LLMs instruction to control the order can
sometimes become unpredictable. Now, here we are going
to explore what are the different patterns
that will help us to build a system which will give us a guarantee on the step by step execution
of those agents. Now, we call those thing
as a sequential workflow. Now we have imported the component which
is sequential agent. Now, why multiagent why we have to build a
sequential workflow where it is important. Now, we have to use
sequential workflows when the order matters, or you need a linear
pipeline where each step would build on
top of the previous one. So think of a scenario
or before that, let's think about the problems. The previous multi
agent system worked, but it relied on the
detailed instruction prompt to force the LLM to run
the steps in order. Now, this can be
unreliable, right? A complex LLM might decide to skip a step or run
them in the wrong order. Now, the solution is to build a fixed pipeline or a
sequential workflow. Now, when we need the task to happen in a guaranteed
or a specific order, we can use a sequential agent. Now the agent acts
like a assembly line. Now, think of this as a block
post creation agent system. Over here, the order in which I want the agent to be
executed is fixed. I want the outline agent
for to be invoked. Its output should be given
to the writer agent. Once the writer agent
completes its output, it should be given
to the editor agent, which will go ahead and edit a blog post or draft for a
clarity and a structure, and then it will give
the final output. So the entire flow is
deterministic and fixed. And hence we can leverage
something known as sequential. But before that, let's first go ahead and build these agents. We have three specialized
agents, an outline agent, which will create a
block outline for the given topic then we
have a writer agent, which will write a blog post, and then we have
an editor agent, which will edit a blog post for clarity and the structure. Now that we have the outline
agent over here with the instruction of create a blog post for the given topic, and it should have
a catch headline, an introduction hook, three
to five main sections, and a concluding thought. So that is the
instruction given to it. There are no access to
any tools given to it. Along with the model, and they mean properties are required
to define any agent. Similarly, we have
the writer agent with the instruction like follow this outline
strictly and we can specify the
outline that we want. Now, one more important
thing to notice is Outline agent has an output
key which is blog outline. So the output of this
agent would be traced with the help of this
key in the shared state. This writer agent will actually consume the
output from this agent. So remember, the
shared state has a key which is blog
underscore outline. So in the instruction,
it will go ahead and take that
as an input with the key which is present in the shared state and then go ahead and process
the information. Similar to that, the output
of this writer agent will be written to the shared state with the key blog
under scope draft. So the editor agent will go
ahead and use the output of the writer agent in
order to curate blog by fixing grammatical errors and the instruction
given to this. Now, let's go ahead and
initialize the three agents. Now that we have
three agents created, we need to call those agents
in a sequential manner, and the way we do it is with the help of a sequential
agent component. Now we define a root agent, and instead of a agent, we will go ahead with
a sequential agent, and the name of that
sequential agent will be a blog pipeline. Now, the subagents are those
agents which we have defined earlier and we will call them in the order that we want to call. Now that we have
defined a root agent, where it is able to call those agents in the
order which we want. Now, remember, the
order in which you specify the sub agents in the sequential agent is the order in which those
agents will be executed. Now, again, in order to interact with these agentic system, let's go ahead and call
the runner and again, run the in memory runner using a run debug
method and with an input of write
a blog post about the benefits of
multi agent system for software developers. It will again go
first, write a blog. It will first go to
an outline agent once the outline agent
will give its output. So this is the entire output with the instruction
that we have given like have a catchy headline and introductory hooked
three to five main sections. So it is adhering to all the instructions
that we have given. Once that is done,
it will go ahead and give that output
to the next agent. That is the writer agent. Writer agent will
get the output, it synthesize that and go ahead and give it
to the editor agent. Now let's see what is the final
output that it will give. As there are three agents, it will take some time in order to execute everything, right? This is how we can use sequential agents
where each step runs in a predictable
order, right? Now, this is perfect for task
that builds on each other. Now, as you can
see, this is slow. If the task are independent, we can solve it via
different agentic pattern. Now, the editor agent
has given us the output, which is this entire one. All right. That's in
this and we are going to see multiple different patterns. And when we should
use which pattern, what are the pros
and cons of it?
8. Parallel Agents: I'm back. So I have
connected to the server, and I have installed
all the libraries and the code which is required
to fetch the APA key. And congratulations on building
an assembly line using a sequential agent where each step runs in a
predictable order, right? Now, this is perfect for task
that builds on each other, but it will be slow if the
tasks are independent. Now let's look into a different
pattern where we can run multiple agents at the same time to speed up the
workflow. All right? Now, the major pitfall with the sequential agent is that it's an assembly
line, right? Each step must wait for the
previous step to finish. But what if you have
different tasks which are not dependent
on each other. So we can execute all
those tasks independently, and execute those
agents parallel, which will dramatically
increase up the speed of the workflow. And then at the end,
we can just combine all the output and then give it as a final
output to the user. Now we can use perl agent when
the tasks are independent. Think of this multi
topic research agents. Over here, we have four agents, which is that tech researcher, health researcher,
finance researcher, and an aggregator agent. Now, these all four agents are atomic and have a
specific task to follow. Now, let's go ahead and
build a system with these four agents
and execute them parallel as the tasks for each agents are not dependent
on each other, right? So let's first go ahead and
build the tech researcher. Now, again, similar to how we build agent with the main
properties which are name, model, instruction, tool, and an output key as we
have multiple agents. The output of this tech
researcher would be dumped into a shared state with
a key tech research. Similar to a tech researcher, we also have to build
another agent which will go and do a research
about all the topics or the breakthroughs in
the health research. And similar to that,
you also have to do it in the finance domain. Let's go ahead and build these three atomic agents
and initialize those. Now, once the output of these all agents are dumped
into the shared state, we need an aggregator agent which will take the
output of these agents and create a combined report
for the user to go through. So this will be done
with the help of a root agent or an
aggregator agent. Now. Each agent will be dumping their output in the output key with
the respective key, which is tech research
for tech researcher, health research and
finance research. All three agents will
use Google search as a tool in order to find
the relevant topics. Now coming to the
aggregator agent, it will take the output of these three agents with
the help of the key, which is tech research, health research, and
finance research. And then with an
instruction that your summary should highlight common themes,
surprising connections. The most important key takeaways from all the three reports. Now, let's go now that we
have created these agents, let me initialize this
aggregator agent. We have to somehow call
these three agents parallel. Now, in order to bring
these agents together, let's go to the architecture
and do a brainstorming. Can we divide these agents
into multiple patterns, pause this video, and
then give it a thought? I hope you have given a thought. No. Let's divide
it into two parts. We have to execute
tech research agent, health research agent, and finance research agent parallel. Let's run this paralle
and then output of the three agents will be an
input to the aggregator. So can we think in this way, running these parallel and then running these
sequentially as well? Let me tell you how we are going to do it with the help of a code so that it will be more clear. So this is how we will do it. So first, we will execute
all the three agents in the parallel manner with
the help of parallel agent. We will give a name to the parallel agent and the sub agents that it
should execute parallel. Now, as the name
says parle agent, it does not matter
the order in which we give the agents in this list, as each agent will be
executed parallel. Once we have the output generated in the
parallel research team, it will be used as an input
to the aggregator agent. Now once we have
this parallel agent, we'll build a sequential
agent which will take the output of all these agents and give it to the
aggregator agent. Now, as this is
sequential agent, the order in which we define
these agents is important. The reason being, we have
to execute this first, and the output of that
should be used in order to give it as an input
to the aggregator agent. Now let's go ahead and
initialize these agents as well. Now let's go ahead
and interact with our agent team with the help of in memory runner
in the debug mode. Now that we have the
root agent defined, which is a sequential agent, which indirectly is calling
the parallel research team, which contains all
these three agents, and then output of that will be passed to the
aggregator agent. So we have all the four agents, and this is the root agent which will take the user input. Let's go ahead and ask run the daily execution briefings on tech, health and finance. Now, as you can see, the health,
technology, and finance, all these three agents
are running parallel, thus reducing the execution
time drastically. Now, having said that, it
will go ahead and give us the report with the help
of an aggregator agent, and you can see how
dramatically the speed of the workflow has
increased by running independent task
concurrently or parallel. So far, all our workflow run
from start to finish, right? So we have a start step and
then we have a stop step. But what if you need to review and improve and output
multiple times? For example, I want to review the health
researcher output, and if there are
any corrections, I would like to make it
there and there itself. How would we do it? Think
of this as a loop, right? So we will see that pattern
in the next session.
9. Loop Agents: All right, welcome back. I
have connected to the server, and I do have the
credentials with me as well for the
Gemini LLM keys. I have executed these cells, which will install all
the ADK components, and today we are going to
understand about loop pageants. So far, all our workflows have
run from start to finish, and then it will stop, right? But what if we need to review and improve an
output multiple times? Now, let me tell you the problem that we face with
traditional workflows, like the sequential workflows
that we have built. Eight. So these workforce will produce their final output,
and then they will stop. So it's a one shot approach. Now the solution is to build an iterative refinement
loop into the agents, and we will do it with
the help of a loop agent, which will run a set of
subagents repeatedly until a specific condition is met or a maximum number of
iterations is achieved. Let's think of a scenario where we are building
a story writing and a critic loop where we
will have an initial prompt, which will go to a writer agent, where predominantly
the writer agent will write a draft of a short story. Then it that story will go to a critique agent
where it will review and give a short critique on the story and suggest any
improvements if required. Based on the condition, we have another agent which will decide
whether I should approve or whether I should
send it back again to the writer agent to enhance or to improve
the story, right? Now, the most important
part over here is how do we add a loop into agents, and that we can do with
the help of a loop agent. Now, let's go ahead
and build our agents, which is the writer agent, and we will do it with the
help of agent component. Which will have a name, model, instruction, and output. The output key is
required in order to dump the output of this
initial writer agent into a shared state. Now, shared state
is where all agents can see what other agents
have produced as an output. We have the initial
writer agent. Let's go ahead and execute it. Now let's go ahead and
build a critique agent. Now critic agent is
something we will also build using a
normal agent component, which will have a name, model, instruction,
and output key. Now in the instruction, we have specified a prompt wherein it will take the input as a story written by
the writer agent. Then it will evaluate
the stories, plot, character, and the pacing. If the story is well
written and complete, it will only respond with the
phrase which is approved, and nothing more than that. If the agent thinks that the
story is not well written, it will provide two to three specific actionable
improvements for that story, and then the output of
this agent will also be stored in the shared state
with the key as critique. Now that we have
built two agents. Now let's see how we are going to incorporate the
looping mechanism. How do we build it
in place, right? Before that, the way we can implement the loop
is in two parts. First, we have to write
a Python function. Now I will explain why we need a Python
function altogether. Now, this is a simple
Python function with the name as exit loop, which does not take input. So if I execute this
tool by default, it will return a
predetermined output, which is a dictionary which
contains the status as approved message as story approved exiting the
refinement loop. So this is just a
simple Python function written which does
not take any input. Now that we have this
function written, somehow we need the agent, the refiner agent to use this tool in order
to stop the loop. The reason being the agent will not be able to understand
what an approve means, right? So the critic agent, if the story is well written, it will give the
output as an approved. But how will an agent
know that when I get a word as an approved
or a phrase as an aprud, I have to stop the loop and give the final
output to the user. And in order to
incorporate that, we need to write a
Python function. Which will be consumed
by the agent. Now, let's understand how
we are going to do that. Now that I have a
refine the agent with a name, model, instruction. Now, the instruction is that it will take
the current story. It will take the critics output, which can be either
improvements or either a simple
phrase as approved. Now the task is to
analyze the critique. If the critique is
exactly approved, you must call the exit loop. Now, remember, we have written this exit loop as
a Python function. So it will call the exit loop
function and nothing else. So it will stop if it has
called the exit loop. Otherwise, rewrite
the entire story and fully incorporate the
feedback from the critic given. Remember, if the critique
will not approve it, then it will add in the actionable suggestions for the improvement in the stories. Now the way we have incorporated this Python function and created a tool out of that is with the help of
a function tool. Now, till now, we have seen multiple ways of
incorporating tools. If you want to give any agent access to
an agent as a tool, you're going to
use an agent tool. Now let me show you
how we are doing it. Now, you can see
from the tools we have imported agent tool.
10. Agent Patterns Overview: All right. Welcome
back. Now that you have a complete understanding
of workflow patterns, let's put it all
together and review. How do we choose the right one for the uses
that you are building? Let me build a small tigra which will help us in
order to take decisions or understand which kind of a workflow should we
use and why, right? Now, if the pipeline or
the agents needs to be or the task that we are
working on needs to be executed in a in a sequence, then we use a sequential agent. If the tasks are not
dependent on each other and we can run
them concurntly, then we can go ahead
with the parl agents. In terms of building a
refinement loop in any agents, for example, we have to go
and validate the output of a few agents with the
help of guiding prompts. Then we can go and
use loop agents. Now, this loop agent is
somewhat different of R. It is not similar to
a human in the loop. Now, human in the loop is
also a kind of a loop, but this loop agent
is something which will leverage the LLM and the guiding prompts
that we have given in order to implement the loop. So we will be going in depth of human in the loop as well. But for now, this is how a loop is implemented
using an agent. Then the last part is
where we let the LLM orchestrate the task
to the agent based on the capabilities
that the agents have on quick reference diagram related to which pattern,
when should we use it? An example, what are
the key features? So if you are going with
LLM based orchestrator, when to use it when the dynamic
orchestrator is needed, where we are not sure of what kind of a task should be delegated to what
kind of an agent. It is not something
which we are sure of. That we can go with an
LLM based orchestrator. Examples are research
process summarization. The key feature is
that the LLM will go ahead and decide which
agent should be called, which tool should be used. In sequential agent,
the order matters. We have a linear pipeline
where the output of one agent is an input
for another agent, so it is a deterministic
or workflow. The pattern parallel
should be used when we have independent task
and the speed matters. So conquer day execution
is something which should be used when we have tasks which are
independent to each other. Looping should be used
in order to incorporate the iterative refinement
within the agents. And if we require repeated cycles for
agents to improve upon, then we can go with loop. Now, all these patterns altogether used within a multi agent system
will make more sense. In an enterprise grade solution, all these patterns should be used in the right
appropriate manner. You won't find an enterprise
system which will only have sequential
agents or parallel agents. These all kind of
patterns would be used in hybrid mechanism in order to build an enterprise grid,
multi agent system.
11. Advance Tools for Agents: All right. Welcome back. Now I have connected through
to the server, and I have imported all the
libraries and the components. Now that we have a
fair understanding of what are the different
kind of workflows and agent patterns and
when we should use which type of agent pattern to solve
the business problem. Now, one thing which
you might have observed is the most important part
of an agent is a tool. Right? Now, without tool, the agent is just a simple
API called to the LLM. So let's go ahead and actually understand how we can
build custom tools and it can help us
in order to solve business problems
which are unique, right, which traditional
gently tools can't handle. So we are going to build a
custom tool using ADK and we will understand how we
can incorporate it with the hell along with an agent. Now let's take it
with an example. Now before going to an example, I will require a helper
function written in a Python. And we will come to
this and explain what is this function all about and where it is being used. Now let's start by
understanding how we can build a tool with the
help of an example. Let's think of a solution where we're building a
currency converter agent, where we have a single agent, and we will build
two custom tools. One is to get fee for payment method and
then exchange rate. Now, these tools are
nothing but helping this agent in order to perform a task in a
deterministic manner. Now let's go ahead and understand how do we define
a custom tool altogether? Now, we can define a custom tool with the help of a
Python function, a simple Python function. But there are few frameworks
or guidelines that needs to be implemented in order to
create a custom function. Now, what are these best
practices in action that we should remember in order to
create a custom function? The first point is a dictionary. The function should written in a dictionary which should
have status and the data. It should have a clear dox ting. Docting as in an
explanation of the agent, what the Python
function is about. What is the input,
what is the output, and what that function
is capable of. Type is to implement validation for the
input and the output. And again, error handling as we have to handle the
failures gracefully. Now, taking into
this consideration, let's go ahead and build our first custom
tool using Python. And this is how an
function is written, which is absolutely simple. Let me walk you through what we have done in this function. Now, we are going to
build a currency agent, which will have access to get free for payment
method as a function. Now this is the function named as get fee
for payment method. It will take input as a method, which will be in string. Now, this is the third
point type hens. Now type hens will help us in order to validate
the right type of input and the right type of an output is being
given or received back. Now, it helps LLM understand
or an agent understand. In order for me to
use this custom tool, the method should be
passed in as a string, and the output of
this tire function would be in the form
of a dictionary. And hence, these
are the type hens. What you can see in this
triple codes is the docstring. Now, this docting explains what is this function all about. Arguments is what input
this function will accept, and return is what is
the final output of this function along with when it is successful
and when it fails. Then we have a simple
dictionary named as fee database where based
on the type of method, we have the method as key and the appropriate
conversion rate as the value. Now, this is just a mocking data that we are going to use. After that, we are going
to take the input, and we are going to check
it against this dictionary. What is the method, and what is the appropriate
value for that? And that will be written. If we find the method to be present in the
existing fee database, it will be returned
with a dictionary as status success and the fee
percentage as the fee retreat. If we do not find anything, then we will return
it as an error with a doc string as payment
method not found. This is just a simple function. It will take method as
an input in a string. It will check in this
database whether what is the percentage fee
for that payment method, and it will return it as it is. Now, let's execute this Alright. Now that we have this
first function written. Let's go ahead and
see how we are going to build a
second function. Now, this is the second function which is get exchange rate, which will take two inputs, which is the base
currency of what is the base currency that you are
going to give as an input, and what is the conversion currency or the target currency? The base currency has
to be converted into. So these are the two inputs
which are in string, and this entire
function will return the data in the form
of a dictionary. And hence, we have
this type hens. Going forward, we
have a doc string, which explains what is
this function all about? What is the input
that it will accept? What is the output
that it will return? For success, what is the type of data it will
return and for error, what is the type of
data it will return with an error message of
unsupported currency pair. Then it will go and check
in the mob database, which is the ad database, it is a dictionary, where
it will check against each, what is the currency conversion? For example, if I'm
trying to convert USD to any one of
these currency, this is the corresponding
conversion rate. For example, USD to Europe, conversion rate is 0.93. So again, it will take
the input base currency and the target currency. It will go and check
against the database, retrieve the appropriate
conversion factor, and it will return. If the rate is available
in this conversion factor, it will written as dictionary, which is with status
as success and rate as the retrieved
read from this database. If the convergent factor is not available
within this database, then it will simply return
as status error with the error message to unsupported
currency pair given. Now, these are the two simple functions that we have created. One is to understand what is the convergence
rate or the payment method, and the second one is to find
out the conversion fact. Now let's go back and
see what is this about. Now, this agent can convert the currency from one
denomination to another. Also calculate the fees to
do the conversion, right? So converging the denomination from one to another and the
fees required for that. That is what we are
trying to build. Now that we have these
two methods built, which are custom tools
defined in the Python, let's build a currency
agent and give access to these tools now let's go ahead and create
the agent using a LLM agent with a name
model with Jeremi 2.5 Flash, with the retry options. And then we have an instruction. You are a smart currency
conversion assistant. For conversion request, this
is the method in which you should follow in order
to give the answer back. So first, you have to go
and execute this tool, which is get fee for payment method to find
the transaction fees. Once you have the
transaction fees, you should go ahead and fetch the exchange rate for
that currency conversion. Once you have both of
these details, go ahead. Check for the status, fill
in each tools response. Remember, we have defined this return status of each function as a
dictionary with a status and the rate so it helps
in order to identify whether the tool
has been executed properly or it is
throwing any errors. Even if it throws an error, we are gracefully handling it, and we are returning the proper response back
to the allem in order to understand
whether the tool has worked or whether
the input is wrong. Now, once we have those things, calculate the final amount after the fees based on
the output from these two tools and then provide the final
converted amount back to the user, right? So this is what we have
done using the prompt. If any of the tool
returns error, explain the issue to
the user clearly. So we will have the tools
and inside the function, we will gain access to
both the functions. Now, these are the
function names which we have provided
back to the user. Now let's go ahead and
initialize this agent. Now, how do we interact
with an agent? The main thing is to use
the in memory runner. Now we are going to dig deep into different types
of runners as well. But for now, as
we are doing this at an atomic level
for testing purposes, it is always a better
to use in memory runner as this takes care of all the session management
in this runtime. Now let's go ahead and
initialize in memory runner and give this agent as currency agent as we
have a single agent. And then run the runner
in the debug mode, and let's give it an input, which is, I want to convert $500 to Euro using the
platinum credit card. So this is the payment type, and this is the base currency
and the target currency. Now, based on the prompt, it has used the tools, and it found that the
fee for the payment, which is platinum
credit card was 2% ten USD is the amount. And then after the fee, the remaining amount
would be $490 with an exchange rate about
0.93 for the conversion. The total amount would be 490
USD converted to 455 euros. So this is how you can build
a custom function and give the custom function in order to solve the day to day task or any complex
visitance problem. So that is a quick
glance on how we can build a custom
function in Python and give this function
to the agent to solve or create
multiple integrations in the enterprise as well.
12. Building Reliable Agents: Alright, welcome back. Now
that we have built an agent, which now uses our custom built logic and is able to give us the structured
response, right? Now, think of a
way on how we can improve the agent's
reliability with code. The reason being the
agent's instruction says, calculate the final amount after the feeds. But
think of this way. LLMs aren't always reliable at solving mathematical
equations. They might make
calculation errors or are inconsistent in solving
mathematical formulas. So the solution for this is to ask our agent to
generate a Python code. And do the maths and run it
to give us the final result. So code execution is
much more reliable than having LN try math at its own. So let's understand how
we can do that with the help of enhanced agent. Now, we have built
currency agent. We have the custom functions, which is get fee
for payment method and get exchange rate. Let's add an addition to
this system by adding a calculation agent with a
built in executed code tool. The reason is that we will ask the LLM to generate
a Python function to solve that problem, and then we will execute the code in order to
retrieve the answer pack. So ADK has a built in code executor capability of
running code in a sandbox, which is one of the tools. Now, let's create a
calculation agent which takes in a Python code and uses the built in code
executor to run it. Now this is another agent. With a name as calculation
agent model instruction. Now, let's specify what is the purpose of
this agent, right? So the task is to take a
request for a calculation, as we can see clearly that this calculation agent is a part as a sub agent to the
main currency agent, or enhanced currency agent. So the specific task of this
agent is to take the request for a calculation
and translate it into into a single
block of Python code. For now, the built
in code executed tour only executes
Python language. And we have also defined few guidelines or rules for
it to generate the code. Similar to how we have
as a guideline for designing custom
tools in Python, we also asking the agent or an LLM to write the
Python code with few rules. So the output must only be
a Python code block and not an explanation of what it
will do or the doc string. So do not write any text before
or after the code block. The Python code must
calculate the result. The Python code must print
the final result to STD out. Now the reason we have
added this line is as the Python code would be executed inside this built
in code executed tool, it is required to write the
final output to this SDD out. And you are also prohibited for performing the
calculations yourself. So you should not use the LLM to calculate
the final answer, but you should use the M to write a code which will
solve the problem for me, which will calculate
the result for me. Right? So let's go ahead
and initialize this agent, which is the calculator agent. And then let's update
the instruction and the toolset for the main
enhanced currency agent. And we will see
what enhancements we need to do in
order to bring in the code execution as a sub
agent for that main agent. Now, update the currency
agent's instruction to generate the Python code.
Which we have done, right? So originally, calculate the
final amount after fees, which was taken care
by the LLM itself. Now, in enhanced agent, what we are doing is generate a Python code to calculate
the final amount and use the calculator agent to run the code and compute
the final amount. So we are specifying
in this prompt to the enhanced currency agent
that we have another agent, which is the calculator agent, which is capable of generating a code,
executing the code, and giving the final
answer back to us or this enhanced
currency agent. The second part is the
calculation agent. Now the EDC will let you
use any agent as a tool, using the agent tool, right? So what we have done
is inside this tool, we have given this agent as a sub agent or a tool
calling to this main agent, using the agent tool. So agent tool lists down all the agents which we have to provide it
as a tool calling, so that this agent will be a callable tool to
the rote agent. Now let's go ahead and run this. Again, we need to define
a runner for this. Which will take care of all the session management,
memory management, maintaining the state
between the multiple agents, tools, and the user. Now, let's go ahead and convert 12 50 USD to ANR using a Bank transfer and show me
the precise calculation. Now let's see how it is going to solve this problem using the code execution
tool that we have. And remember, in
the last session, I have written a
utility function. We are going to use
that utility function in order to see what
is the code that is being generated by the calculator agent and
how it is being executed. So that utility function is nothing but written in order to understand what is the
code generated and how it is executed by the
agent under the hood. So let's give this some
time for it to run. Okay, I think I
need to stop this. The reason being I have
exhausted flashlight for today. Let's go with flash. Yeah, I will give me an error. The reason being I have
paused it in between. Now let's go ahead
and run it again. That's important. The reason why I
did have not got an error is because I was
using this retry mechanism. Even though if I would have not used
this retry mechanism, this would have failed
the first time. As I have this retry
option in place, it will go ahead and retry for the set iterations in
the retry configuration. Now let's debug and see how
is the output looking at. So original amount is 12 50 USD. The method is bank transfer,
calculation breakdown. The fee is 1%. So fee
amount would be $12.50. And then the final amount
comes to around this much NR. The most important part is
about how the calculator agent has used the tool in
order to generate the Python code and then
execute it. All right. Now, generated Python code, I have exuded provided
Python code block. Fee amount is 12 50, which is correct amount
after fee is this much and the final amount
is this much, right? 13430. So that is how it is done with the
help of a code executor, which brings in some
deterministic level of understanding so
that we can inspect the generated output using
the helper function. And that's how we can build
agents with custom tools. Also use the inbuilt tool, which is the built in code
executed tool in order to make these workflows much more
reliable with the help of code.
13. Agent Tools vs Sub Agents: Alright, welcome back. Now I'm pretty sure that you might be confused about sometimes we are calling sub agent sats tool. Sometimes we are calling
tools at the root agent. What is this going on, right? Now, let me break it
down and explain what is the difference between Agent
tool versus the subagent. So this is a common thing, both involve using
multiple agents, but they work very differently. Now, Agent tools is
what we were using. So this is used when agent
calls agent B as a tool. Agent B's response goes
back to the agent A. And then agent A stays in control and continues
the conversation, right? So agent E is always at
the center of everything. This is something as
an orchestrator or or the main root agent, which is deciding
based on the task, whether I should call any
other agent which will solve the small problem and then use the output of that agent to proceed further
with the main task. Hence, we use Agent tools. Now, agent tools as I
will explain that in depth now this is used for delegation for specific
tasks like calculation, which we have done, right? Now, when do we use subagents? No, it is a different
pattern altogether. The agent A will
transfer the control completely to the agent
B. Wherein agent A will not understand what
is the output of agent B or it will not
care about the output from the agent B because the complete control has been transferred from the
agent B to the agent B. Now, the agent B takes over and handles all the
future user input. So it is like a workflow where once the agent A has
completed its task, it's no longer required to
solve the user question. Whereas in the initial phase where we have the agent tools, agent A is the main orchestrator where it will solve the
problem till the end. Now over here, AgenD
is out of the loop. In Agent tools, agent A always stays in the control and
continues the conversation, and it might call another
tools if required. But the main center at
the stage is the agent A. Now, the use case for
subagents is to hand off to specialists like
custom support tiers. Now, in our currency example, we want the currency agent
to get calculations, result and continue
working with them. The reason being,
let me show you. Now we have this
enhanced currency agent. Over here, we have the
calculation agent. Where this root agent will give the input to
this calculation agent, it will go ahead
and calculate with the help of its tool
and then again, give back the output to
the main root agent. Hence, it is an agent tool
and not a sub agent Now, now that we have a
fair understanding of what is Agent
tool and sub agents, although we are
going to see this in depth on when we should
use what type of tool. Now let's go ahead with
some inbuilt components or the tools that we have from the agents or the ADK framework. Let me bring up that
slide so that it will be far more clear.
Let me zoom in. So inside ADK, we
have multiple tools. Now we have custom tools. In which we have function
tools where we will define the Python function according to the business problem that
we are trying to solve. Now, we also have long
running function tools, which we have not
touch based yet, which we'll be covering in detail in the
upcoming sessions. But these are used where human
in the loop is required, and these tasks can take a
longer duration to complete, such as few hours or few days. Then we have agent tools, and we have used these where other agents are used as a tool. Similar to what we have done in the currency
conversion agent. Then we have MCP, which is
model context protocol. These are servers where
these can be file systems, Github MCP, Google Map MCP, or any database connector. So we can connect to
these services without writing a lot of custom to code in order to
incorporate their EPs. And then we have open tools. These are tools automated generated from the
APS specifications. Now, these are all about the
custom tools that we have. But what about in
build tools that we are from the ADK as well? We have used few tools, but let's go in depths of it. Now we have used Gemini tools, which is the Google search and the built in code
executive, right? Are there are multiple
more tools in total, till now there are
32 tools available, which are Gemini tools. We will be covering in
the upcoming sessions in the Capston
projects that we are going to build and the future learning that
we are going through. Then we have Google Cloud tools, which are specifically
tools designed in order to integrate with
the GCP services, which is the BigQuery,
Spanner tool set, and much more, right? And then we have
third party tools like Github, Hing face, Cagle, and multiple More now, I think you have a
fair understanding of what are the different types of tools that are
provided by the ADK, how we can define custom tools. What is the difference
between calling an agent tool
versus a sub agent?