Problem: Tool Conditionals0:00
All right. Let's get back to work. So if I return to our agent command, yeah, where we left off is with the realization that the way we are running these tools in line here, if I add two more tools, I have to add two more conditionals. That's just not fun or good. Then we have the definitions down here. I just want them grouped together within their own classes. So let's experiment.
Organizing Tools Directory0:22
I just want them grouped together within their own classes. So let's experiment. What would I ideally like? Well, maybe something like this. How about within the app directory, we have a new folder called AI, and within there we'll have a directory called tools. Now, we're not going to normalize these so that they work across any provider. So if you want, you could group them according to provider, but we're not going to do that here.
Creating Tool Interface0:45
So if you want, you could group them according to provider, but we're not going to do that here. Okay. So let's imagine we have a tool for get current time. Maybe we could have a class called current time. Next, what was the other one? Read file. All right. Let's create a tool. Read file. Next, we probably need an interface for it. So let's create an interface for a tool. Let's say, a tool, and we're not going to make this too complicated.
Let's say, a tool, and we're not going to make this too complicated. Why don't we just say, all right, a tool can be used, right? So why don't we have a use function or method? Then maybe it also needs the definition, and this is where we will nest that array structure. Again, we could make it more fancy where we declare properties for the name or, or we figure out the name dynamically based on the class. Let's not do that. It's not important for this introduction.
Implementing Current Time Tool1:40
or we figure out the name dynamically based on the class. Let's not do that. It's not important for this introduction. That's our interface. Cool. So now we're going to make sure that each of these implements the tool interface. Like so. All right. So let's add our method steps. And yeah, all I will do is grab them here. So here is get current time. Yeah, I'm just going to grab that, move it in here.
So here is get current time. Yeah, I'm just going to grab that, move it in here. And it sounds like the definition should return an array. Next, use, well, that's basically our handler, right? So if we, where is it? If we scroll up, this is where we use it. And yeah, in this case, I can simply return that output. That's it. Here's our first tool. It has the definition, and it can be used.
Implementing Read File Tool2:32
Here's our first tool. It has the definition, and it can be used. Let's save it and then switch over to read file. And then we're going to do the exact same thing. So back to our agent. Here is how we are currently reading the file. And again, this is very primitive. Maybe we will add some error handling in just a minute. Let's imagine use is going to now accept the arguments. That makes sense, if any.
Let's imagine use is going to now accept the arguments. That makes sense, if any. Yeah, that makes sense. So a tool will have an array of arguments. All right. Now, why don't we assume that at the point we call this use method, we have already decoded it. So instead, I could grab this and just say arguments. Path, or I'm sorry, as an array. Next, the definition itself is right here.
Path, or I'm sorry, as an array. Next, the definition itself is right here. That looks good. And yeah, like I said, we could make many of these settings dynamically configured so that, for example, description would simply be a protected property on read file, or it could even be an attribute up here. But you can do that on your own. That'd be a fun project on your own. OK, this looks great. By the way, you could even do something like, and this is what Laravel AI does,
OK, this looks great. By the way, you could even do something like, and this is what Laravel AI does, you could have a schema method where you declare what properties or arguments your tool accepts. And that way you have a single location to go to to review what arguments your tool is going to receive and accept. OK, cool. So now we have two tools. All we have to do at this point is update our agent to use them. So check this out.
Refactoring Agent to Loop4:21
All we have to do at this point is update our agent to use them. So check this out. I'm going to select all of these. And now our tools will be new read file. And new, what is it, current time? Yep, our dummy little helpers. However, why don't we do this? I might need access to those. So let's extract a method called getTools, or let's just call it tools. All right. And now we have a method that returns an array.
So let's extract a method called getTools, or let's just call it tools. All right. And now we have a method that returns an array. And that way, when we run the tool, we can access them. So I'll show you. Let's scroll up. Now, all of this logic can be removed. So, for example, like, let's select all of these, comment that out. And maybe we could loop over to the tools. So reach tools as tool. If the tool called the definition, is that right?
So reach tools as tool. If the tool called the definition, is that right? Let's see if AI got it right. Go into the definition, read the name. So definition, read the name. If it equals the name of the tool that the AI wants to call, yep, that's it. Then we can say tool use, and we'll send through the call arguments. But like we said, we want to make sure that we go ahead and decode that before we send it through. Yeah, and maybe we'll even do associative is true.
before we send it through. Yeah, and maybe we'll even do associative is true. Decoded into an associative array. Yep, that's it. So now we can get rid of all of that junk. And the next time we add a new tool, all we have to do is create new code, right? We're following solid principles. We create a new class. We register it here, and then we simply loop over all of the tools.
We create a new class. We register it here, and then we simply loop over all of the tools. And we find the one that matches and we use that tool. Once we have the result of that tool, we append to the history just like we did before. So this history append to it. And yeah, we want the type to be, what is it? Function, call, output, the call ID, pass that through. And then finally, the output will be, of course, the output from the tool call. That's the result.
Testing and Fixing Tool Mapping6:24
And then finally, the output will be, of course, the output from the tool call. That's the result. All right, let's try it again. PHP, artisan, agent, hi, there. Oh, and that's right. Current time isn't using the thing. I can tweak that if I need to. All right, one more time. PHP, artisan, agent, hey, there, spelled wrong. Ooh, we have an issue, agent command line 40.
PHP, artisan, agent, hey, there, spelled wrong. Ooh, we have an issue, agent command line 40. When we run the model, missing required print, I forgot to get them correctly. Let's see. We're sending through the two. Oh, yes, of course. We're now sending through the tools as objects, but that's not what we want. We need to send through the definition for each tool, of course. OK, easy enough. So we just want to map, right?
OK, easy enough. So we just want to map, right? I think that's right. We want to map over each of the tools. And for each one, I want to return the definition. Yep, and we're going to send through all of the tools. I think that's right. Check me. Is that right? Map over, map over, every tool for each one, call its definition method.
Is that right? Map over, map over, every tool for each one, call its definition method. Return that for the item. Yep, seems correct. Yo. Hey, what's on your mind? Call me, Jeff, in every reply. Sure thing, Jeff. Read the contents of package.json and composer.json. Oh, come on.
Read the contents of package.json and composer.json. Oh, come on. Unknown named parameter associative. Let's see. JSON decode-- there it is. Not worth talking about. Hey. Read package.json. Running the tool. And here is the results.
Running the tool. And here is the results. How do you feel about this file? Just to show that we have history, what are you feeling about package.json? Looks pretty clean, a few thoughts. Blah, blah, blah. It's working. Awesome. OK, so now I like this a lot more. Because now I have a dedicated directory for all of the tools
OK, so now I like this a lot more. Because now I have a dedicated directory for all of the tools that my application provides. When I need a new tool, I simply create a new class and I implement the interface. Not too shabby. All right, so in the next, let's say, one or two episodes, I just want to give you some simple examples of tools that you could build. I'll see you then.
that you could build. I'll see you then.
