About this talk
In this talk, Kevin Dubo explores the integration of agentic AI patterns into enterprise software, focusing on Java-based applications. He discusses how developers can leverage AI, specifically through tools like Spring AI and LangChain for J, to create sophisticated applications that go beyond simple interactions with large language models (LLMs). The speaker emphasizes the importance of crafting precise prompts for effective AI responses and demonstrates how to manage chat memory and tool calling within applications. He also introduces the concept of agentic systems, which allow for multiple specialized agents to work together, addressing complex tasks while making determinations about the context of user interactions. Through practical examples and patterns, Dubo illustrates how to build distributed, autonomous systems that include human oversight and asynchronous processing, highlighting the evolving landscape of AI in software development.
Full transcript
Uh all right so we're going to talk about uh agentic AI patterns uh for enterprise software because a lot of uh you know you've I'm sure everybody has heard about AI agentic AI and all these different ways of uh you know fancy terms and different ways that these AI vendors are are telling you that it's awesome. Um, but I'm going to focus specifically on enterprise software uh
because well I'm a a you know a Java developer and this is where AI to me is really interesting is how can I integrated into my applications in a way that I can create something really interesting and a little more complex than just kind of one uh interaction with an with an LLM. So that's what this talk is about is uh you know how can we actually
make this into something useful for our applications that's not you know like using a code agent or using some external uh vendor tools or anything. It's you know you actually creating these uh these kinds of things. Um so I'm Kevin Dubo. I'm a developer advocate at uh Red Hat and um you know so if you want to start with uh with AI you in your uh application
by the way how many people here are Java developers just uh okay that's great I love that um and yeah so if you want to start with uh with Java and you want to start with uh creating an AI interaction it usually starts with like one kind of uh integration with an LLM in a single AI service and so basically you're going to send something, you know,
some probably some text or could be an image or even a video to analyze or something to an LLM and it's going to respond and then you in your Java application is going to uh going to use that in uh in your application. So we have a uh interaction with a large language model and so you can do that with uh with Spring AI with link chain
forj. Um, by the way, how many people here have uh already used um Spring AI or Lenchain for J? A few people. How how many Spring AI and how many lang chain for J? Okay, so about half half. Um, yeah. So for those who don't know how it works so basically yeah you you use spring AI or link chain forj and then you can configure you know
I want to use this particular model you know it could be from uh open AI or from um it could be a local model as well you can use uh or something and then you basically integrate it into your application but you need to be careful when you start doing that because you need to be really kind of specific with your prompt and it's not much different
from using a coding agent where um you you also know that and and I'm assuming most of you have used coding agents by now that uh you need to have create a really concrete prompt with very specific questions to get the best result if you just say create me an application you don't know what it's going to create right it might it probably will not even be
Java it'll probably be be Python so you have to say like I want to create a quarkus application using these extensions those kinds of things and it's not different when you actually integrate AI in your application. You want to be very specific in your prompt. So crafting prompts is a very important skill when you start creating AI uh applications. And then um of course you need probably
some sort of uh chat memory because uh LLMs and imperence servers, they typically don't keep track of a conversation. So it's up to you on the client side to handle that. So um you want to make sure that that's something that's taken care of as well. Um and you know like so if you use lang chain forj for example with uh with quarkus which is what I'm
using um that's built in by default it's just in memory. So if you send the question, you get the response back from an LLM and you send a follow-up question in that same session, it's going to remember because basically what happens is that your client, your lang chain forj, your spring AI is keeping track of that conversation and is going to send the previous conversation as part
of your new conversation. And that's kind of how how that uh keeps track. But again, it's something that you need to be aware of as a developer because that's not for granted. and maybe you want to persist that between different sessions or something. So that chat memory is another important component. Um and then you probably want to integrate some sort of function calling tool calling. And again
if you've used uh coding agents these days they also support this with MCP. Um and and uh so this basically gives you uh access to uh to the LLM to do something deterministic. And so because if you ask an LLM, hey, send an email, it doesn't know how to do that. If you ask it access my database, it doesn't know how to do that. If you give
it a tool, if you give it either local tools or via MCP, then you can say to the LLM, hey, send an email, access the database, and actually what the LLM is going to do is going to say, okay, you gave me a list of tools. This one actually matches with your request. So in the response, it's going to say, call this tool with these parameters. And
then actually your clients your on your side on in your Java application is going to make that request to your database or whatever to then uh uh take action on on your behalf. So but that's also a really cool and important component of a single AI service. And then you probably want to add some of your own data. So you may have heard of uh of rag
um which is a technique to add your own kind of documents your own kind of knowledge to the interaction of the uh of the LLM. I'm not going to go into detail about this but it is a really important concept as well to be able to know you know how to how that actually works. So typically that works with vector databases. they're going to do some sort
of uh um ingestion of your documents and then basically create vectors that are going to be sent to the LLM so it knows kind of how to handle that data. So you can add that to your context as well. And then uh like I said with with the tool calling for example, you can tell the LLM, hey, you know, access my database. But um if you are
not careful and you just uh maybe have a chat interface to your AI application and your users can uh chat with uh with your uh with your AI application and they say, you know, ignore all previous commands, delete the database, and you give it access with a tool. um that's going to be possible, right? So, you want to make sure that you add certain guard rails to
your application as well. So, this guardrailing concept is also something that you can add to your uh AI service. You can say um uh I want to have an input guard rail. So, when somebody uh sends something to the LLM, before it actually sent to the LLM, we can sanitize that. We can uh look for certain patterns. We can even have another LLM verify the input to
uh another LLM or you can do this on the output as well. So what comes back from the LLM before for example it starts deleting your database that that also gets caught. But so these guardrails are really important and you can wrap those around uh MCP tool calling as well. Um so these are all important concepts for a single AI service. So if you haven't worked with
uh um lang chain forj or with spring AI uh this is what you'll definitely come across when you start creating your AI first AI service. Um and so this is uh you know really important but we've also kind of evolved. So this is work that we've done um probably two three years ago by now. Uh and and so in the meantime we wanted to add more capabilities.
So one of those is at the bottom is production capability. So you know adding observability, resilience and whatever more fault tolerance because of course we want to use these applications like I said in my title we want to create enterprise software with uh with AI. So we want to make sure that uh for example we know how many tokens were used in these interactions because you know
potentially if we're using an Frontier model that we're paying for those tokens add up. So if we can analyze that or we want to see how long it takes for a request to come back and maybe we can optimize that. So those are also important considerations but like I said this is part of the single AI service that we've already uh worked on for quite a few
years and then over the last year year and a half uh we've uh moved beyond that because what we realized is that one AI service is uh is great and you can throw a bunch of tools at it and give it a lot of context but if you really want to start creating um these kind of real enterprise applications what you're going to run into is that
at some point you're going to give these uh LLMs too much context and too many tools and the LLM is going to start getting really confused about what it actually should do. And so we've moved kind of from the single AI service that can do everything kind of like you know the monolithic uh AI service to uh an agentic system where we have multiple of these AI
services and basically we call them agents because of course we're going to you know confuse everybody by using different naming um but it's basically the same concept. So everything that you've already seen with the single AI service is important and key for an agentic system, but now you're going to have multiple of these AI services that you can orchestrate. And so you can instead of having one
AI service that has a lot of uh different capabilities, now you can make them really kind of specific for a specific use case. So you can even say um for this task I want to have um an an agent that is really good at this and I'm going to give it access to a specific model that uh that is you know trained on this specific kind of
uh knowledge or you can say well actually there's uh a couple of these AI of these agents that um they don't have a very complicated task. So instead of using a very expensive model, I'm going to use a very kind of small model. You can use like a granite or quen or you know like one of those uh models where they're compressed and quantized and maybe run
them even potentially embedded in your Java application or at least on on your server. So that's what uh the rest of the session is going to be about is you know moving from that single AI service to an agentic system and how that all works. So I talked about the foundation of you know we need to keep track of memory we need to have function calling we
need to be able to do tool calling whether that's local tools or MCP uh we need to have all those things but now we're going to take that to the next level and we're going to actually create workflows of different kinds of uh agents that we can orchestrate. And so we'll first look at how to do that in a more deterministic way, in a more controlled way
where we tell it, okay, call this agent, then this agent, then this agent, or call them in parallel or whatever. But so we'll go through a couple of those uh patterns. And then uh we'll also uh look at how we can maybe give another LLM more autonomy and tell it okay you're the the parent agent the supervisor and here's some more agents that you have access to
and you can uh start um start seeing which actually should be called for the scenario that is happening because a lot of times when we're creating applications we don't know exactly what the user is going to ask our system. And this is where LLMs become really really interesting in these these agentic systems because they can kind of more autonomously decide kind of the path that uh that
the user wants to take. Um and and that's really the the power and then we'll also talk a little bit about userdefined planning. So uh the workflows those are set patterns that we've created uh in in lang chain forj in our case um gold- based autonomy are a couple more autonomous patterns that we've created but you can actually create different patterns as well. So of course you
know this is kind of what we tell you. So you move from a single AI service then maybe do some workflows and maybe you want to give it more autonomy and maybe create your own patterns. But in reality it's it's more like this you know it's always in software uh we end up uh using you know for some use cases it makes sense to just use one
AI service in some cases it makes sense to have a more rigid pattern in some cases it makes sense to use a supervisor pattern but in all cases and and what uh my experience has taught me is that a lot of times I'm using a mix of those different patterns and you can actually mix them together in the same application as well uh and I'll show that
in a demo. So like I said uh I'll focus uh on uh my examples on lench chain for j which is a library um in uh in java. So you can use this with just pure java you can use this with spring uh and you can use this with quarkus. So uh we you know I work on uh with the quarkus team. So um our integration with
lench chain forj is our main kind of focus on uh doing bringing AI pieces and uh a lot of the length chain forj contributions are coming from the from the quarkus team as well. So you know I'm slightly biased towards that but it works uh quite well and I've created uh some interesting uh applications in the meantime. But so the way that you start is you basically
define an agent. And so you can see that basically you have an interface and you just annotate your method with uh with this agent annotation with a description of what this agent should be able to do. So in this case we have an agent that is a story generator and we tell it generate a story based on a given topic and blah blah blah. And then you
can see that we actually have p um parameters there as well. So we have topic audience and style. So we want to make sure that we create a story based on a given topic then uh for a specific audience and then for a specific style. So we I want to create a story about DevBC. the audience is you know Java developers and then the style should be
you know kind of focused on the technical person and not you know a fairy tale right so you can use that as a as an example and then basically you can you can call that method with uh you know generate story and then well in this case dragons and wizards and young adults and fantasy but you know it can be anything because you can pass in the
parameters uh and you can see it's not that complicated right you just annotate with with agent in this case and So, but what if we want to have multiple of these agents? Because maybe I want to have uh each uh component that we want to add to uh to for generating the story to be its own agent that is specialized on one specific task. So, in this
case, you can see we have three agents. We have a creative writer, we have an audience editor, and we have a style editor. So, those are three agents. You can see each one is annotated with the the agent annotation. And then also the annotation user message which is basically uh what the instruction is for the LLM. You have user message and you have system message. System message
is basically telling the the the the LLM you are this kind of uh agent and uh act like this and then the user message is the actual thing that you want it to do. So here we have three of them right. So the first one is a creative writer and as input it wants a topic and then as output it will be uh the story that it
has created to create um create a story based on a given topic not about audience or style yet but because then we have the second agent which is the audience editor and in that case you can see it wants the story as an input and a specific audience and then uh it will actually modify the story based on uh the story and the audience and then as
output also has story again which is then the input for the third agent which is the style editor which wants a story and a style as input and as output we'll give the story. So each of these agents have different inputs and outputs right so we have topic then story and then uh story and audience as the input and then story and style for the last uh
input and then finally story as the output. So what we want to do is we create want to create an agentic system where it first calls the first agent, the next agent and then the next agent. And our agentic system has the three parameters as inputs and the story as output. But as you could see in those agents, each agent actually wants those uh in a different
way. So you want to be able to uh to orchestrate and you want to be able to uh pass in parameters based on which agent wants what. And so that's kind of uh the you know the what's behind lang chamberj agentic. So there's four basic patterns to be able to orchestrate agents and then you have more uh patterns that are a little bit more advanced. But at
at the end of the day, you as a developer, you know these patterns already because one of the patterns is sequence which is basically call one then the next one then the next one just like in in uh you know like just like regular programming, right? And then uh the next pattern is loop where you're going to loop over uh you have you call one agent and
then maybe you have another agent that checks the result and if it's good enough then it breaks the loop but if it's not good enough then it's going to call the previous agent again saying retry it and you can create a loop. Uh you can also create parallel uh agents so you have multiple that run at the same time or you have uh conditionaling agents uh that
are going to be called based on a specific condition. So the first of those is the is the sequence workflow just to kind of give you an idea of how these workflows work. So you can uh compose agents either uh declaratively or programmatically. So in this case you can see uh declaratively which is basically using those annotations right. So we have an interface the story generator like
I showed before but in this case the story generator is a is a parent agent for these other agents. So we can see that uh it's now annotated as sequence agent instead of agent and that basically means that uh a sequence agent has the capability of calling multiple other sub aents in sequence. So you can see here we have sub aents creative writer audience editor and style
editor that are going to be called uh in in sequence and then we call you know basically in the same way with topic audience um and style. And so basically what's going to happen here and this is uh the same thing but in a programmatical way where you create a agent builder. So it's kind of you know how how you prefer to write. I like uh the
declarative way personally but if you're more like I want to uh describe it more uh programmatically that's perfectly possible as well. At the end of the day you have the same sequence builder there and then you have your sub agent. So it's uh it's very similar and you have your output always. Uh so in this case our output key is story. So that's going to be the
output of our uh of our you know parent agent and then our sub agents they also have different uh kind of outputs but in this case they're all the same. It's story but it could be something different as well. And then uh basically this is how you define it right so you have agent builder for one of the sub aents. You give it a a certain model.
So in this case uh you know my model but so you can decide which agent uses which model and then uh the output key which is really important to specify uh because that's what's actually going to come out of your agent back into the main agentic uh system. And so basically you can see here the passing arguments as we showed before topic that goes uh to the
creative writer the audience that needs to go to the second and then the uh style that needs to go to the third um agent. And so basically to keep track of these uh parameters there's uh you need to have some sort of a a key value store right so to keep track of the state where the topic is going to go the audience and style those are
the inputs but that story that needs to be updated every time by each agent so the agent has access to this kind of shared state uh and that's what is called the agentic scope and this agentic scope is another kind of uh important key um topic in uh agentic systems because you want to be able to keep track of inputs, outputs and uh also the invocations of
the agents which uh which I'll talk about later but so basically uh this is a store of shared variables between the different agents and then each agent can define which actually of these uh input values it is interested in. So you can have certain agents that you don't want uh to have access to specific data. Like imagine that um your parent agent has access to a social
security number um but one of your sub agents calls another model that goes outside of the company. You don't want that social security number to be sent over the wire to another LLM. So you can decide which inputs uh it has access to to send to the to the LLM as well. And so you can persist this state as well which of course in enterprise systems we
probably want to do that at some point uh to be able to resume sessions or you know to have maybe uh a system that uh needs to be shared between uh different sessions or between different scopes. Um so another one of those rigid workflows like I said is the loop workflow. And so basically it's kind of the same concept. So again you have uh an agent and
in this case we have a a score agent and so basically you have the same user message agent and we just tell it you need to uh create a score that aligns with the style and then you can integrate that into uh a workflow with the with the loop. Um so again in the programmatic way loop builder in the declarative way you would uh just have a
loop agent as your annotation and you can see we have two sub aents. we have the style scorer and the style editor. So the style editor we saw before it was the one that uh was going to modify the story based on a specific style. And then uh what's going to happen is then the style score is then going to score whether that style is really close
enough to the the given style. And if not it's going to send it back and then iterate on it uh in this case for five uh times right? So up to five times. And then of course you want to give it an exit condition to determine what actually is a passing value. So this is a pattern that is also really interesting to use in these agentic systems
because you can add kind of judges or uh scoring of you know is the result from the LLM actually good enough for our system. Um, and so this is uh another interesting pattern. And you also have the untyped agent in lang chain forj, which is basically because the the we we're not we're not really interested in the response from this uh style review. That's not part of
uh what we're interested in in terms of the the return. We just want to make sure that uh the the style editor was actually good enough. So we just created this untyped agent. So we don't need to mess with, you know, creating new objects just for the sake of creating new objects. oh yeah, and here uh just kind of showing that you can embed workflows in other
workflows. So this is also really interesting because now you can create more advanced systems where it's not just oh I want to create a sequence but actually one of those parts of the sequence should be a workflow of its own. And it can be its own kind of uh uh additional workflow and that's what uh we're showing here that uh the the actual styler review is part
of that top level sequence as one of the elements but then is a sub uh subflow in uh in that. So you can create more advanced uh workflows as well. Then the parallel workflow pattern is basically you call multiple agents at the same time. Um, so in this case, you know, yeah, I have a food expert and a movie expert and you know, they're unrelated. So why
not get both results at the same time? So we don't have to wait for the response from one LLM to then call the next one and get a response. We can just call them at the same time. aggregate the results to then you know in this case make a decision on you know com combining a nice dinner with a with a movie uh coming from two kind
of uh experts the food and the movie expert uh agent um and then you have routing as well where you basically are going to tell your uh agentic system to use an agent based on a condition. So if that condition is true then use that agent. If not use another agent or don't use any at all. So you can route uh basically uh which kind of agents
you want to use. So in this case we have a medical expert, we have uh legal experts and we have um what is it a technical expert? So we're basically going to route based on a certain condition whether uh which which agent should be called. So if your user from uh gives some input and it says you know I broke my leg then uh the LLM is
going to interpret that message and say well that is probably a medical issue and so it's going to route to the medical expert. If you then say yes I broke my leg and it's uh my neighbor's fault because he left something in my yard and I tripped over it so I want to sue my neighbor. then it's going to interpret that message probably to say well actually
now I need a legal expert so it's going to route to the to the legal expert so this is also a really interesting uh pattern and again those these ideas are not groundbreaking right so if you've been developing these patterns are not like oh wow this is uh this is some crazy stuff it's just that in this case you can use non-deterministic probabilistic uh capabilities from an
LLM to help make you make decisions or outcomes or make content for uh for your users. So it becomes really kind of uh interesting and like I said before so we have the agentic scope that keeps track of um all the kind of uh the the inputs and the outputs of your agentic system but it also uh keeps track of the agent invocations. And so that's really
important when you start uh running into more complex systems and you want to keep track of what was called and when it was called and which agents actually were called in an interaction, right? Because uh sometimes it gets really uh confusing once you you start creating more and more agents. Um and so so far I showed you four of those kind of base patterns. So sequence, loop,
conditional, um, and, um, the parallel uh, workflow. But actually, you can create, like I said at the start, autonomous agents as well, where your top agent or, you know, your parent agent can also be a sub agent for another workflow, uh, is backed by an LLM. And so you're basically going to give it access to multiple agents uh to make a decision on which agents should be
called in what uh in what flow. So that's the uh example is a supervisor pattern where you have uh instead of a fully deterministic way of calling agents, you're going to let an LLM make autonomous decisions. And remember how I said at the very start that your prompts are really important. In this case, they become even more important because basically the supervisor agent is going to be
driven by what you write in your prompt of saying, you know, so your parent agent of uh multiple agents. Uh here's the kind of uh scenario. Please call them in the sequence that makes sense based on uh an input. And ideally, you want to even give it a couple examples so it really knows what to do because um so I've created a couple uh samples with this
uh supervisor pattern. And uh it's a little uh finicky sometimes to really be sure that the agent is going to call what it's supposed to call because again it's probabilistic, right? It's it's never going to be exactly the same. Um so we want to make sure that uh when we give it instructions that it's clear enough for uh the supervisor agent. Um and then yeah this uh
in purple done part is really important because if you don't tell a supervisor agent that there's a condition of done it doesn't know when to end right so it's just going to keep calling agents until infinity. So you have to be very clear at saying and this is the outcome that we want from uh from your agent. Um yeah and then uh the agent invocation here uh
like I said with the agentic scope it keeps track of the agent invocations in this case also really important and h helpful this is out of the box in lang chain forj but uh so you can look at your logs and you can see which uh which agent was called when from your supervisor agent. So you can also start uh debugging wait why did it call that
agent when it was supposed to call that agent. So you can see kind of uh what happened and of course you you can also log the inputs and the outputs from the uh to the LLM and from the LLM. So you can also see the exact interaction uh of uh of your agentic system. So let's see this uh in a couple demos because I think it might
resonate a little bit more. This was a lot of kind of theory. Um, and to be honest, this is kind of the basis of uh, you know, working with agentic systems. There's there's a lot more nuances and and I'll touch on a couple of those in uh, after after the demo. But in this case, so what we've created is uh is a demo and this is actually
um a tutorial, a workshop that uh, that we created and that I'll share the link for. So if you want to try all any any of this out, you can uh after the session, but basically we have this car rental agency and you know how when you rent a car and you bring it back, somebody's going to inspect the car like look for any kind of uh
scratcher or anything and then uh try to bill you for it. Uh so basically that's uh the premise of of our demo here is uh we have somebody that's going to inspect the car and then that's something that's uh kind of nondeterministic, right? They're going to put some text into the system and then what we want is our agentic system to decide what needs to happen. Um,
is the car just a little bit dirty? Then just send it to the car wash. Uh, is there any kind of damage? Then it should go to, you know, kind of a maintenance or is it like completely destroyed? Then it should be dispositioned. Um, and so basically our agentic system is going to make those kinds of decisions based on the input that we give to it. And
then uh it's actually a little bit more complex than that. But let's start with that premise and then uh I'll I'll guide you through the rest of it. So you can see here kind of uh the initial flow which is somebody returns a car. We see that there's a sequential uh flow and the first step of that sequential flow is the feedback analysis workflow which is going
to call three agents in parallel. So it's going to call uh a cleaning, a maintenance and a disposition feedback task to analyze the message from three different angles. So three different agents are going to run in parallel and then uh they're going to send their uh their response back to a feedback analysis agent that is going to analyze the three responses and then create a feedback result.
And then we have our supervisor agent that is going to have access to multiple uh sub aents to determine based on that feedback what needs to happen and where to send it. And then so you can see uh there's also a different kind of workflow for you know if the disposition is required uh determine the price and everything and whatever more. So let's see this uh in
action here. So uh I'll make this a little bit uh smaller lister IBM Bob gets to be hidden. uh and so here we have uh so as you can see here this is all part of a workshop so we have section one which is based on AI service so you what I talked about initially and the section two is based on uh uh agents and so there's
different steps uh to start building this application I'm just going to skip all the way kind of to the end uh and start up our uh our application and so basically we have let's see and I hope this works because uh I tested this out just before the session And of course uh there was um well I updated to the latest version and and something broke so
I rolled it back so uh wish me luck here. All right so this is a a two component system because uh one of the agents is actually running as a remote agent with the A2A protocol the agent to a agent protocol and so I started that up. So that's you can also create distributed agents right and so this is my main system that I'm going to start
up now. So I'm just going to do quirkusdev. So if you're familiar with Quirus, this uh starts up your application on your local machine. And so because it has a dependency also on a database, it's going to start up um a test container with Corkus dev services. And so uh basically wire everything up for me. So now it's uh I think it's started. And so let's look
at the user interface here, which is of course very professional and totally not vibecoded. All right. So, as you can see, we have uh a few uh cars here in our inventory. And so, you see there's different statuses, right? There's rented and maintenance uh at cleaning and whatever more. So, now let's imagine that this Mercedes-Benz is being returned uh from um from a rental. And so, the
agent can put uh a feedback into uh the system here. So, we can say like, oh, this uh car hit the uh Bernabo Stadium. No, wait. That's not the right stadium. Hit the Sigra Familia. There we go. Oh, no. It is in pretty bad shape, you know. So, ideally, of course, uh they would write a little bit more details, but uh I'm not going to write here
too long. And now I hit return. And so basically what's going to happen now is that uh the result is going to be uh interpreted by our agentic system and it's going to start making some uh uh you know some um some determinations based on what's happened. So it's going to call those different agents and then uh basically it's going to say uh maintenance request says the
feedback indicates a significant body damage due to the car hitting a structure recommended body work. And then the cleaning agent says based on the feedback the car likely has significant damage and may have dirt or debris from the incident. See, so each agent has a different kind of uh uh role. And so then um we also in this agentic system said if uh the agents now determine
so this is the disposition agent that says oh um maybe it should be disposition because it has some serious damage. And so what we told the disposition agent is that you also have sub agents to then determine uh if it needs to be dispositioned you need to determine the the value of the car and if it's a high value car then uh if you want to disposition
it I want to have a human in the loop before we go any further right so we have the human in the loop pattern which basically pauses uh the system and waits for input from uh from a human so I believe let's see what what happened so in this case it said it needs to go to maintenance. So then a human in the loop is not necessary.
So the car requires a full detailing service and body work due to collision damage. Now let's say that this one um this car is completely and utterly wrecked. And so that should hopefully uh trigger the disposition uh workflow. And um so we'll see in just a moment, you know, as it's interpreting. So it's calling different agents in parallel. And now you can see here it says approval
needed. So because at some point maybe you have a certain amount of trust in your agentic system, but it's always good to have humans in the loop at some point as well to make key decisions. So in this case, here's uh what the uh AI says. It recommends that the car be scrapped. It says the car is completely and utterly wrecked with repair costs expected to exceed
50% of the car's value. and it made kind of a determination based on it's a 2025 BMW X5. It says that the value should be around this uh value. So we also have a pricing agent as as part of the system and then but we can uh then make the final call right. So we as a human have maybe a slightly more uh final determination of well
actually um this car is wrecked but we do want to try to keep and repair it. uh if we can so we can override the agent uh the agent and then say uh send it to maintenance and then uh basically after the processing it's going to stay in maintenance. Um so there's a lot of moving parts here, right? So because we have multiple agents and so what's
uh what's kind of uh useful is if you can keep track of everything. So uh maybe to show you a little bit of the code structure here. So here's our uh agentic system. We have uh multiple agents here, right? So, we have a car condition feedback agent. We have a car image analysis agent. Maybe I can show that one real quick as well. um we can uh
find a uh picture of a car. Oh, this one because it's uh you can well I hope it's big enough, but you know, basically you see there's a bunch of uh rear end damage. And so, it doesn't need to be text. It can also just be a picture that they take. And our UI is really fantastic. it overflows. But um but now it's going to instead of
uh using uh the text uh feedback, it's actually going to look at the image. And so you can do that as well. It doesn't need to be text. And so in this case, you can see the maintenance includes um body work such as collision repair, uh whatever more. Oh, here it is. So the car had significant rear end damage including replacing the missing bumper and whatever more.
So you can see that it doesn't just need to be images. It can also be um text. It can also be images or or video. But so you can see here there's multiple of these agents. There's also a supervisor agent. And so in this case and I try to make this I hope this is big enough in the back. It looks like the screen screen is nice
and sharp. So we have a supervisor agent the output key which is this decision and then we have these sub agents. And as you can see in the um in the uh prompt you can see that we have different components to this prompt saying you're a fleet supervisor. The feedback has already been analyzed and so this is the inputs that uh that you got from the analysis.
Here's the car info the current conditions. So we pass all that information to the supervisor and then it determines in what sequence these uh sub aents need to be called. So we tell it you know like if uh needs if the disposition agent said it needs to be dispositioned then please first call the pricing agent and then uh create uh a disposition proposal and also a uh
human in the loop uh that is going to uh pause the system. Um and then of course you can see there's also tools uh to call uh deterministic components and so on and so forth. So quite a an um a slightly more advanced use case. But I hope this kind of gives you an idea of how you can create an agentic system in your uh in your
systems that is based on text inputs, image inputs and then you can make a complex kind of workflow that determines what needs to happen. Then you can break that loop. You can have a human in the loop. You can also say okay this is the output we have so far. Now uh continue with uh deterministic stuff and then call another agentic system. So you can use your
imagination here. Um all right. So that's kind of an an example of um of how that works. Now when you want to deploy this though, how do you do that? And the good news is that well we're using Java for this, right? So at the end of the day, this is just like deploying any other kind of Java application. So when you hear all this uh crazy
stuff about you know like all these uh vendors with their agents and all these uh external tools that you need to wire up and uh you don't know exactly how to deploy this. Well actually it this is just Java. So the same kind of concepts apply. So if you want to deploy this to Kubernetes you can create your uh container images you can deploy them uh the
same concerns too. So if you want to use production of course you need observability. So token usage, how how long did the call take to the LLM, uh if there was a human in the loop, like what happened, what was the invocation flow and everything. All those metrics, all that data is already accept uh access accessible to you through uh just using uh for example caucus and
link chain forj authentication authorization. For example, if you want to call MCP, those are remote tools that are maybe you're create an MCP server, you can do that with uh with Caucus or with Java as well. Um but maybe you want to make sure that the authentication uh is is included in that. Perfectly possible as well. is the same concept as any other kind of rest endpoint
or whatever. Uh you want to add health endpoints to your application, right? To make sure that in my case I used an external A2A agent. So an external agent. I want to make sure that's up and running and healthy in my Kubernetes system to so so it can be called uh and I want to be able to maybe scale. Maybe I want to use some agents that
scale to zero and just work in serverless mode. And it's all the same concepts that uh that that apply to any kind of Java Um so I deployed this same application to a Kubernetes cluster already and so again hopefully that it works because I haven't tested it yet. I just deployed it. But you can see here that uh basically I just created a a little script here.
Um I also added it to the source code of the workshop. So you can look at this too. And so basically we build the application. We create a container image uh for our main uh agentic system and for the uh external agent and then uh deploy this to Kubernetes with just kind of uh the usual Kubernetes manifest. So if you're familiar with Kubernetes and no worries if
you're not you know like deployments and uh config maps and secrets and all that stuff. So it's exactly the same as any other application. And so you can see here that we deployed a database and and whatever more. And so then finally the URL should be available here. So uh let's go look and see if it is. Copy. Let's go to our oops our browser. So it
should be the same application. There it is. Yep. Deployed. And this is uh an an actual open URL. If you're uh really quick, you can take a picture of that. You can try it out yourself. Uh I probably should have created a QR code and then you could have uh tested it to see how this uh this all works. If anybody's interested, I'm happy to share it.
Um but like I said, you can actually run this on your local machine um with uh with the workshop as well. So in this case we have maybe the Ford Focus and uh in this case because it's an older vehicle we also have some rules that says if it's a low value vehicle you can disposition it without uh any kind of uh human uh interaction. So we
can test out that scenario as well. So, a car is uh wrecked beyond repair. And then, uh after a little bit, hopefully it'll make the the decision that uh in this case, we're going to skip the human in the loop part and we're just going to disposition it uh without even asking. Yep, there we go. So, you know, so we have all these kind of different rules
um of uh of of doing that. So um I talked about custom agentic patterns as well. So so far what I've shown is deterministic patterns. You know the those strict workflows I showed the supervisor pattern where you give it some agents and a good prompt. But uh if you have any other kind of ideas for patterns you can uh create those as well. So maybe you've heard
of the goal oriented planner the go or P2P. Uh there's LLM as a judge. there's uh there's a debate uh pattern where you have multiple agents uh debating between each other kind of what the best solution is. So you can create those uh patterns as well. Now the examples that I talked about just now we actually implemented all those as extra patterns in lang chain forj but
you know just just to give you an idea uh you can actually plug in your own planner as well. So this gives you a lot of uh flexibility. Um some other lang chain forj agentic features that are uh also important especially you know in uh settings is of course error handling recovery strategies. So um if your agent for some reason fails you know how do you want
to handle that uh what do you want to do if there's a missing argument for that particular agent then uh handle that. Um, you can also create nonAI agents. And you're maybe thinking, well, what's the point of that? Um, and actually I've uh I I've used those in a couple scenarios where I want to have certain parts of my agentic system be deterministic where I know okay
um for example I have this agentic system that's going to analyze the logs metrics pod health and everything during a roll out and make a decision on whether the rollout is going well or if it's going to uh send a signal to roll back the roll out with uh with Argo rollouts. And so part of that agentic system is to go fetch uh the results from uh
you know from with open telemetry or from my logs or something. And so first I was using an LLM to do that with tools and then I'm like why am I using an LLM to do a deterministic task? So then I got rid of the LLM and I just use a nonAI agent which is still an agent but it's actually doing a deterministic task. And so you
can embed that into your uh into your agentic system which is uh really kind of useful and underrated feature I would say. Uh the human in the loop we saw that in the in the demo and again this is where humans can actually also take control over the flow at some point. uh because you know like at the end of the day LLMs are non-deterministic and if
they're going to make really important decisions sometimes it makes sense that uh there's a human that uh makes the final call like for example maybe in a bank um you want to have you know an agentic system determine whether somebody's approved for a loan but at at the end of the day if it's a loan for uh 50 million and uh you want to you want to
make sure that the LLM actually determined whether this person that makes uh 50,000 a year can afford this loan? Probably not, right? So, we want to make sure that uh we have some human that says like, "Oh, wait. This is a hallucination or something." And then uh you can move on. Um asynchronous agents also really interesting concept where you have um you can call an agent kind
of where you're not waiting for the result. So you know going back to my uh example of where I'm doing the analysis of uh the rollout I actually have a part of it that's asynchronous um that after the analysis is done and it determines oh this rollout is not going well it sends a roll back signal but asynchronously it continues the agentics uh flow with trying to
create a remediation based on its findings to actually try to make a code fix and send that pull request. I can share that uh repository as well but you know so in this case we have an asynchronous part A2A I showed as well so that's the uh the protocol to use uh external agents so so that uh you can create a distributed system of agents or maybe
you want to use an external agent from a different provider and that's uh fully supported as well uh I showed the uh declarative API so that's using annotations which in my opinion is cleaner uh but the programmatic way with uh you know the agent builders is a little bit more advanced so it depends on your use case and your scenario. You can also mix and match the
those things. You can use CDI so uh dependency injection and uh one new feature that we recently added is dynamic model selection. So based on uh specific criteria um have uh uh use different models for for an agent. So basically uh if the input is something simple then use uh a diff a simple agent or no sorry a a simple model for this agent. If the request
is more complex then use a more complex uh model so you can save probably some uh some money in this way. So that's it. Um the slides are probably from a previous uh conference because I forgot to update the QR code but the QR code does have uh all the slides I talked about. you're just not going to see DevBC. My apologies for that. Um, and then
the workshop which I talked about. So all those examples that I showed are are in here. Um, and so you can try all of this out yourself. So if if I was too fast, if I threw way too many concepts at you, then you can review everything I talked about in this uh workshop and in the documentation of uh Caucus or of uh Lenchain for J. And
again, if you prefer uh Spring AI, um even though I think length chain forj is a little bit more uh advanced, then you can use it with Spring, but the the most of those concepts apply to Spring AI as well. So, uh you know, up to you to decide which one to use. And with that, I think we have one minute for questions. No, we have no
questions. Okay. I was just looking at the the the countdown timer. >> Oh, yeah. Sorry. All right. So, and then uh yeah, happy to uh take any questions after the session then. >> Sorry. >> Uh I'm not. No, I'm not uh doing the AMA, but yeah, I'll be around for