Now that you have a basic agent, in this lesson, you'll connect it to the outside world. You'll simulate connecting your customer support agent to services like a CRM, get customer details and to log support tickets. Let's take a look. And as always, the first thing we need to do is import the Boto3 library. But we also have a couple of other libraries here to import as well. If you remember from the last lesson, these will just be super useful. So uuid and also all of our helper functions as well. So with those now defined and with the environment variables we've got from everything which has been pre deployed into this environment, we're ready to go. So we do have an agent here running, which is the same agent as we had from the previous lesson. If it's not slightly bigger instructions this time around, just because I was able just to paste in a whole bunch more stuff. So let's have a play with this. So I'm just going to get my session ID and another message which is very similar to what we had in the previous lesson. So let me just define that. And then just quickly let's use a helper function to have a see of what happens. So we're going to use invoke agent and print the helper function. We're going to send the message in and let's do it. And it says my mortgage broker and I want a refund. We wait for the agent to respond. And the agent says, "Hey, Mike, I apologize, but I'm unable to directly process your refund." Blah blah blah blah blah. Okay, similar kind of situation to the way we were before. Excellent. So what we want to do is we want to connect our agent up with some tools. And inside of Amazon bedrock agents. These are called actions and action groups. And the logic that we're going to connect to for these actions are lambda functions. And there's a lambda function deployed inside of this account ready for us to use. So let's go and take a look at that. And the way it's written. And here it is. Now there is this unpack parameters. But I'm going to get back to that in just a moment. Let's have a look at the lambda handler itself. So this is the invocation point. This is the point at which the lambda code will start when it's called by the agent. It'll pass this event in. And the event will contain all information about the agent and why it's being called. While this why this lambda function is being called. So it'll include the agent, the name of the agent, the name of the action group which we haven't defined yet. Then something called a function. And this function is going to be the tool, essentially the action that we want to call. So there's a couple of different uses for function a lambda function. And then these functions which are sort of inside of the lambda function. Think of them as the tools. And then we also have some parameters. So these parameters are sent in for this particular function or tool. Okay. And so we need to send this response body syntax back. And so I'm just defining that up front. This is a very simple piece of code. You'd want something much more comprehensive in production of course. And then what we do is we start to look at which action has been called. And so we have two that are supported here. One called customer ID and one called Send to support. And so with customer ID the agent will send in either an email, a name or a phone number, something to define who this customer is. And the idea is that this function will return the ID for that customer, which is important for our agentic workflow, as you'll see in a minute. And in this particular case, though, as long as any one of those items has been sent in, then we'll send back an ID and it will be just a random number because we're just doing sample code here. So that's customer ID. We then have send to support. And send to support can accept a customer ID and a support summary. In fact both of those things will be required. And so as long as you've got both of those things then you can send a support ticket and we will respond with a support ID. And again that's just a random number in this particular case. But notice how we need a customer ID. And so we can get one of those from up above. But we're going to leave it to the agentic workflow to figure out that that's what it needs and that it needs to go there first. If it hasn't been supplied the customer ID in any other kind of way. And then the payload, once it's been sort of furnished with all of the outputs, whether it's an error or whether it's the actual, simulated response from a service, that output will get sent back to the agent. Now I'll just return back to this. We have this unpack parameters, and this is just a helper function which I've written inside of the lambda function, which can help to unpack the parameters that get sent in by the agent. So we'll see the format of it, in a moment. But when it sends in something like email, for example, it will be more, verbose than just saying email is this. It will say, you know, here is a parameter. It's some text. It's called email. Here is the value. So we just unpack all of that and make it a little bit easier for us to be able to consume inside of our code. So that's the lambda function already deployed inside of this environment. So let's see how we can hook this up to our agent. And so because we're going to make a change to the agent itself, we do need the client object. And we've created this before. So this is the bedrock agent client not the agent runtime. Go ahead and store that in a value so that we've got our bedrock agent one more time. And now what we're going to do is we're going to call that bedrock agent. And we're going to create an action group. So we're going to call Create agent action group. And as you can imagine, there are a lot of parameters that we need to send in here. But it starts off simple enough. We first of all need to pass in an action group name. And so we can call this action group anything we like. This is just for our own reference so we can see what's going on. But you may remember as well it did get passed into the Lambda function if that's useful. So I'm just going to call mine customer support actions. So it's a group of actions which help me with my customer support. We also have to pass it in a link to an actual agent. So which agent are we essentially trying to update here. So I'm going to pass in the agent ID and we have the agent ID from environment variables already inside of this environment. So that's all I need there. I then need to explain to the lambda function what is actually going to do. The running of the logic behind the scenes for this particular agent. And we've seen it is a lambda function. So I'm going to define that the action group executer here is going to be, and then I just have this small amount of configuration. So it's going to be a lambda function. And I need to point to which particular lambda function. And so a lambda function as I said has been deployed into this environment already. And we have an Arn for it. So the resource name for it I'm already in a variable called lambda function Arn. Okay. We've put this off long enough. We now need to give this particular agent, all of the details of that lambda function that we were just looking at. And so we do that through function schema. And this is a dictionary that we need to set. And we need to define the functions that we had. And so this is the use of the term functions in exactly the same way as we had inside of the lambda function code just a moment ago. And this is going to be a list of all of the functions that we want to use. And so each of these will be a dictionary. So let's start off with the first one and we'll call this one. We'll add the name rather it's already defined inside of the lambda function. But this is customer ID. So this needs to be a match for what we have inside of that code. And now we need to tell the large language model which is working inside of this agent. We need to tell it what this function does, what this function called customer ID does. And so we do that through a description. And this is exactly as it sounds a natural language description of what this function does. And we can be quite descriptive. So let's say I've got, get a customer id a given available details. At least one parameter must be sent to the function. This is a, this is private information and must not be given to the user. And so this is the first line of defense really to explain to the large language model that we don't want to be discussing this, with the user. There are other things that we can do. And we'll look at those a little bit later as well. So this is a description of what we want. So let's just get ourselves a new line here. And then the last thing to do is just to explain about the parameters that we need to send in to actually get this to work. And if you remember, we had email, name and phone. So we just need to describe those to the agent. So first of all let's have a look at email. And we can add in for that a description. And again this is a natural language description which will explain to the model what it is. Now it may well fully understand what email is just from the name email, but we're going to be more specific and say that this is specifically an email address. But we could we could add more details in here. If we found we needed to do that. Then we need to explain whether this is required or not. And I'm going to say for this false there we go. False. Because I don't want to have to require every single piece of information about the customer. Just one of them will be fine. So required is false. And then the type. So what data type are we looking at. And we're looking here at string. And so that is all of the information I need for email. So let's do the same with name. In this case we're going to say first and last name. And I'm sure I might change that for the particular example I've got where I just set my name to my. So let's just say this is the customer name. Just keep it simple for now. And then we'll add in phone. So we have a phone number and everything is exactly the same. So this is a complete description of customer ID and all of the parameters. And of course we have tool functions. So let's go and put in another definition here. And this is for send to support. So in this particular case I'm saying send a message to the support team used for service escalation. So essentially if the agent can't deal with it by itself, which in most cases it probably can't. It can use this to send a support escalation ticket off to a human in the loop. And so this requires customer ID this time I'm saying that's actually required. True. And then a support summary which is also required. And so this customer ID here, we're leaving it up to the agentic workflow to figure out that actually it's going to need to get that from somewhere. Finally, finally before we finish up this configuration, I've got one more thing to add in here. And that's the agent version. And because all of our agents are called draft, I'm just using draft. And that's it. That's the complete, action group definition that we need to send in. And before we actually run this, let's pop that into this value. So create agent action group response so that we've got hold of it. And then we can go ahead and run this. And nothing happens! Because we are obviously we have it all inside of that value. So let's run that and have a look. There we go. We've got all our response. Come back. So we've got the action group ID and we've got an action group state. I've enabled and we do have to wait for this to become enabled before we can do anything else. Let's just go and put in some helper code that will wait for it to be enabled, even though it already is. So if you do run this code from top to bottom, it will still work. And before we do that, I just need to grab the action ID out of that response that we were just looking at. And then I can put my helper code in here, which we know is going to come back straight away because it's already enabled, because we just made an change to the agent. We do have to prepare the agent again and then update the alias. So let's go and do that. Preparing the agent. Super simple as we've done before. We just call our client and say prepare agent. And I'll put my white code just beneath this so we can see it happen. Let's run that. Preparing. Preparing. And any moment now. Oh, preparing. Obviously working hard. And prepared. There we go. So that's now returned. And then we do need to update the agent alias as well. And so we use update agent alias. Passing in the ID and the alias ID and the alias name. And just as it did before, I'm going to put the wait code in there so that we can see that actually happen. So we're waiting for this to become prepared. Updating, updating and prepared. There we go. So now we have some actions inside of our agent. So we can actually start to do something a little bit more useful. So let me paste in here a call. So I'm going to reset my session ID and then I'm going to send in the message in again almost the same. So, "my name is Mike. My mug is broken and I want a refund." I've included my email address here or an email address. It's obviously not actually my email address. And the reason why I've done that is because I do find sometimes if I just say my name is Mike, then the customer support agent, and probably rightly so. It can use that to look up my customer ID and then sort of concludes that's actually just a first name like that. It's probably not actually going to be definitely Mike. So we should do something else. And it gets itself in a state. So I've provided my email address. So it will definitely be able to track down my, customer ID, which of course in this particular case will be a random number, but you get the idea. So let's paste in my helper function here, invoke agent and print. And at the moment we have enabled traces off or false. So let's just run that. In fact I need to run this first as well. And now I'll run this cell. Let's see what the agent comes back with. So "I want my refund." And the agent says, well, yeah," I've processed your request for a refund on the broken mug. And routed it to the customer support team." And now review your case. And it has in this particular case, given me an ID for my customer support case because I didn't say that that was private information, just my customer ID. "Let me know if you've got any more questions." Okay. Fantastic. It's actually done it, but let's actually peel back the lid. Look under the hood. And see it in action. So I'm going to say enable trace as true. And then I'm going to run it afresh. So this will be a different invocation. But let's see what happened. So, the first thing that happens is obviously, it looks at my initial message and it says okay, let's process this customer support step by step. The first thing I need to do, and it sets itself out a little plan actually with what it needs to do. And the first thing that it does is it calls out to the customer ID function, which is exactly what we want, and it passes in these parameters. So it actually does pass in the name value of Mike. And it also passes in the email value of Mike at Mike dot com, which obviously isn't my email address, but just for demo's sake. And so it gets back an ID, which is the ID for me as a customer. I forget again, this is just a random number in this demo. And it says, "Okay. I was able to look up the customer's ID using the provided name and email address. Now I need to determine the appropriate next step to handle this request." And so it knows this, from its previous planning. So it calls out to send to support and it passes in this payload into send to support. So it passes in the support summary, which is customer Mike. And it put my email address in there is requesting a refund for a broken mug. And then it passes in my customer ID as a piece of structured information, which is what was required. And obviously that's the customer ID that it determined before. So it's figured out its agentic workflow. It then gets a customer support ID back, which is 7750. And then it puts together its final response. And this is kind of interesting. I've reviewed the customer's request and determined that the appropriate next step is to escalate this to a human customer support team. But notice here has actually brought back my customer ID, even though I kind of asked it not to. And also the support ticket ID, which I'm fine with. So the prompting of the agent to ask it to not reveal that kind of information is not foolproof, is not completely robust, and there are other things that we need to do that we'll look at later on in this course to prevent that kind of thing from happening. But for now, we've got an agent which is actually responding and using tools to process my customer support case. And in the next lesson, we'll make our agent just a little more intelligent by getting it to make some calculations before sending the request off to support.