Hi, and welcome to this AI and C-Sharp video on the Microsoft Agent Framework.
Today is going to be a bit different, because this is about some of the things I don't use in the Agent Framework,
and particularly around the workflows, because I simply cannot see why they are needed.
There might just be me, it might just be my scenarios, but every time I try to use a workflow,
I end up writing some regular code that is much simpler.
So, and it is a big part of the Agent Framework, at least the name says it's the agent part that is
an important part,
but we have this entire workflow, agentic workflows and so on, but I just don't see the value in them.
And again, it might be me, I would very much like an open discussion in the comments about this,
because I want to see the light, but I haven't.
And for that reason, let me show you some of the arguments and some examples I have made.
So, let's jump in.
And I have made various videos on this.
I've made sequential workflows, concurrent workflows, handover workflows.
I've done a human-in-the-loop, I've made the AI-assisted, where we are more manual in our workflows.
I've looked at group chat and simply just threw it away, because there was no value in it.
And also, I've looked at all the samples from Microsoft themselves, and there's samples,
but there's no real business value in my book.
So, it's not like I don't want to do stuff in sequence,
but it's more cumbersome to do it in a workflow like this.
And I know there's things about being able to checkpoint it and resume it and all these kinds of things.
Again, the kind of things I do don't take that long.
If a workflow runs for like five minutes, it's a long...
An AI task runs for five minutes, and probably so are yours.
So, again, I'm not saying that you can't use workflows,
but I've also heard from a lot of people that just want to use workflows for workflow's sake,
and I think that's wrong to do.
That's the main part of this video, because let's see a concurrent...
No, let's start with sequential. This is the simplest one.
And I made an example back in the day where we took a summary agent and a translation agent
and took some legal text and then let it first summarize it and then translate it.
So, putting those two agents in sequence.
And we can do that, and we can see we'll use 62 lines of code,
and we need to do this streaming and turn token and watch for the events in order to get them out.
And this is an object, so we need to know to turn it into a list of chess matches and so on.
So, it can certainly be done, but up here I have the exact same kind of code for sequential.
And it's even taking up a bit extra here, because I need a namespace and stuff,
because I put it into a subclass.
But I do exactly the same up here. We can't save in setting up here.
But then I just go in and take my summary agent, run async, get the response back, get my messages,
and then take my translation and take the output of the summary response, and then we're done.
This is exactly the same.
So, this is essentially the code I'm replacing with this code here.
There, this couldn't appear.
It is no objects at all. It's just pure strongly typed all the way.
Very, very simple to understand.
So, if I were to ever do sequential, I would do this.
Let's look at concurrent.
So, concurrent is nice sometimes if you have enough tokens to do it.
But in this case, it was just, again, a legal text with a legal agent and a spelling error,
which would probably not run concurrent anyway.
But if they could run concurrent, I have very few times where things can run concurrent like that
because they need each other when they are in a kind of workflow.
But again, we can do some of the same, and we get these, again,
the in-process execution and stuff like that.
And if we look up in a version of that, we have, again, exactly the same start.
We can't change that.
But then I will just use a task when all started to agents,
and then when I get both back, just write out my for each.
Give exactly the same results, and these three, four lines of code
takes away all this very hard to understand and debug as well.
So, why not just these three lines of code?
Why put in an entire workflow for such simple things?
And I know it's simple scenarios here, but even if it's more advanced,
I would just put it out in various classes and have them run it in a simple flow.
And of same situation, we get some three different agents,
an intent agent, and a movie agent, and a music agent,
and we need to have the intent agent pass it on to
or hand it off to someone, the others.
There we begin to make these with hands-off that this one can send it
to these ones, and these ones can send it back to this one, and such things.
And then we make our workflow run where we need to send the events
and find the right person talking, and all these kinds of things.
So, if we do that, we can either do it by tools,
so we can just set up the same agents, but instead the intent agent
also get two tools, which are the two other agents,
and then we just ask, and then we are basically done.
If we want to see what agent it calls, it's not necessary.
We put in a little function called middleware, but beyond that,
we are down to these few lines of code compared to all this.
And I simply don't understand why people want to sit and write things like this
because there's no reuse.
That was one of my things.
I thought in the beginning that it couldn't make things be more reusable.
I've not seen the scenario.
I've simply not seen the scenario, and again, code is very reusable
in general in C Sharp in general.
But this is how we could do it with just tools,
but we could also do it with structured output
in a much more similar fashion.
We just make our agents again, and then we just use structured output
to get out the type of question.
Is it a movie question or a music question?
Then a switch case on that and write out with full control,
with nothing making our run async for us
so we can not control anything or anything.
So very simple to do.
Human little loop. Let's have a look.
For the human little loop, we need to make some agents,
find the animal to guess.
This is a small guessing game.
We find an animal to guess and give some hints,
and then we make our request port
so we can get human little loop interventions,
and we need our executor down here
where it takes the input, which is the guess.
If it's not the right one, then give a new hint,
else say the game is over.
And up here we need to go start our event
and listen for all these various things.
So it's possible again,
but if we look in just normal code,
we do exactly the same up here.
But then we just make a while loop in this case
or however you want to have your GUI, of course,
and then we just take our guess.
If the answer is right, break the loop,
else give a new hint.
We're saving lines of code,
and it's much more simple to understand this code,
in my book at least.
And the most strong example is the pizza example.
So if we look at the pizza example down here
where we use the executors.
So if we go in here,
then we need to make an order parser,
and the order parser gets an AI
to do structured output on that.
So in here we just do this,
but we need to have all this ceremony
above and below for almost nothing.
The stock taker is just checking through
the various toppings of the order
and check if the mushroom is out of stock sample here
and put it into a warning.
And the success executor then says the pizza is okay,
and the other one will say it is not okay
and send a mail to the customer.
And then we need to build the workflow,
we need to build the edges,
and we need to build the switch
so it switches between the end success
or the warning part of it.
Have the workflow run
and react to the various events in it.
We look at that without a workflow.
We simply just go and say the input.
We take our order agent and give us back an order.
We immediately loop over that and make some warnings.
We check if there's warnings.
If not, it says okay,
else the other is not okay.
Up here I'm using the same objects down here,
so we'll still need to have the objects
and the creation of the agents,
but the flow of this is so much simpler
in my book to understand.
So then some of you might argue,
okay, what if you get a very, very complex workflow?
Well, then I would probably use a workflow engine
like N8n, Logic Apps, Make,
all these that are actually good for that
with very complex setups,
and then I will build small entries into an API
that could help with the scenarios
that the workflow engine couldn't do by itself,
because then I have that someone else takes care
of running the workflow,
saving all the workflow data and so on.
I don't want to store all that
because even now we can do workflows
and we can save how they went and so on.
We still would need to build something
that could show these workflows executions and so on.
So there I would outsource it
to a real workflow engine system.
And then if I have the need,
but again, this is simple code.
Yes, there are some if statements.
Ooh, that's scary. That's wrong.
Or yes, it can break in the middle.
Yes, the others can also break in the middle,
and yes, there is some robustness in there to build in,
but in reality, I don't see them happening.
But that's for the comments of this video.
Tell me how I'm wrong.
Tell me why I'm wrong.
Tell me what you use your workflows for
because there is a reason
why this YouTube series has not shown workflows so much
because, again, every time I try to find,
oh, yes, now I have my bank statement,
which I made a video on,
on how to balance my banking book.
Yes, then I could use concurrent
to both check for the dividend company
and match the output or the PDF.
But then suddenly I couldn't do that
because I needed something from the dividend
before I could actually find the PDF.
And just every time there's something
that turns out to be, yes, yeah, this cannot be concurrent
or, yes, I'm using so many tokens
that concurrent would just lead to rate limits
or, yeah, I could do this,
but it would add me 50 lines extra of code
or complexity to look at it.
So I can't see why workflows need...
I understand why they are there.
I can live with them being there,
but please, sometimes you just need to write good code
instead of trying to fit it into a workflow
just because they're there.
So that's my message,
but also my question to you.
Tell me why I'm wrong with this video.
I really, really want to know so I can see the light,
but I can't see it at the moment.
But, yeah, different video.
Hope it still is beneficial.
Hope it will spark some discussion down in the comments
and help you also understand that you don't need if I'm right,
and it's an if, it's not a because I'm right, if I'm right,
that you don't spend your time writing code
that looks like this down here
where it is so difficult to actually understand
six months from now.
But that's everything for this video.
See you in the next one.