AIAI EngineerApr 8, 2026· 40:50

Bending a Public MCP Server Without Breaking It — Nimrod Hauser, Baz

Nimrod Hauser, founding engineer at Baz, presents a hands-on guide to adapting third-party MCP servers for production, using Playwright's MCP server as an example. He demonstrates five best practices—curation, wrapping descriptions, deterministic guardrails, composing new tools, and treating tools as deterministic functions—to transform a brittle setup into resilient infrastructure. Hauser shows how curating tools from 21 to 16 reduces context load, while enhanced descriptions guide agents to use accessibility snapshots before clicking. Deterministic path validation prevents agents from saving screenshots outside a designated folder, and a new 'evidence tool' with tailored instructions improves spec review accuracy. The talk culminates with Baz's Spec Reviewer, an agentic code review tool that compares requirements against implementation, successfully passing a test after applying all optimizations.

  1. 0:00Intro
  2. 1:17Tool friction
  3. 4:36Spec Reviewer
  4. 10:36Baseline failure
  5. 14:17Five practices
  6. 15:47Curating tools
  7. 18:07Wrapping tools
  8. 22:33Guardrails
  9. 28:39Composing tools
  10. 33:00Deterministic calls
  11. 36:50Improved run
  12. 39:06Wrap-up

Powered by PodHood

Transcript

Intro0:00

Nimrod Hauser0:01

Hi everyone, and welcome to our talk today about bending a public MCP server without breaking it. But today we may have just broken it, because our MCP server seems to have caught on fire. We're glad you're here; we need all the help we can get.

Let's go through our talk and see how we can improve whatever is going onright here. I'm Hauser, I work at Baz. We've been building AI-powered code reviewers for the past few years now, as well as a bunch of other features—anything that can make the lives of people at R&D easier and better, whether they're devs, PMs, anything else.

If it's agentic, we're probably tinkering with it. But let's jumpright in and start looking at what's going on with our MCP server: I suspect it's the tools. We're going to talk about third-party tools and why they might blow our applications.

First of all, it's me. As I said, Nimrod Hauser, a founding engineer at Baz. I've been with the company since it was founded in 2023. I've been at backend and data for the past 20 years or so. In my career, I had a brief stint in Salesforce, and ever since, mostly startups, cyber, crypto, and now developer tools.

Nowadays I mostly want to talk to you guys about agentic tools.

Tool friction1:17

Nimrod Hauser1:17

Alright, agentic tools, and specifically third-party tools. They can be a great force, a great addition to our application, but they don't always work out of the box. We expect them to make our application better; sometimes we'll see degradation, and we'll try to understand why that happens.

After that, we'll explore a framework of 5 best practices that we can follow in order to turn this around and make our application kick ass. Along the way, hopefully, we'll fix the busted MCP server that we just saw put out that fire, make it work, and make our agents behave the way we want them to.

Yep, this is looking kind of bad. I think we should dive in. So, we're going to talk about agentic tools. When we use MCP servers, we get tools coming from the MCP server. So as long as we're talking about third-party tools, I don't care if they're coming from an MCP server, from a library, maybe we copy and pasted them from somewhere else.

If they're agentic tools, they were written by a different team, they're relevant for this discussion. So what are these tools? Essentially, tools are just callable functions wrapped with a nice description. The description is important because it lets the agents know when to use the code and how to use the code.

And we'll dive deep into these aspects of the description. But again, it's kind of like glorified integration code written by a third party. In today's talk, we're going to take Playwright's MCP server as an example. So essentially, we're looking at integration code written by the good people at the team of Playwright, wrapped with their descriptions.

And we'll see how we can make these tools work better, kind of tailor them for our use case.

Yeah, so third-party tools have their challenges. First and foremost, they might cause our agents to behave unexpectedly. You know, agents are already non-deterministic, unpredictable things. You give them tools, and you get unpredictability at scale. But also, they can just degradate performance.

You might want the agent to do a certain thing, and you get subpar results, wrong results, or maybe it just does it but in a way that's not optimal. And through today's best practices, hopefully we can see how we can make the implementation of third-party tools in our agentic workflows much, much better.

Last and foremost, these bad performances, that unexpected behavior, that can also mean full-blown security issues. I mean, just imagine a scenario, a pretty classic scenario, like a multi-tenant architecture, and your agent might not know all there is to know about your architecture and the division into folders or databases and schemas.

It just doesn't have the proper guardrails, and it might leak client data to another client, things of that nature. You really want to guardrail your agents, and this becomes even more important when dealing with third-party tools who are not aware of your architecture.

So we'll cover that as well.

Spec Reviewer4:36

Nimrod Hauser4:36

Alright, I think we're about ready to look at a use case, to look at some code actually. But we'll need a use case, and with your permission, we'll choose one of ours. So today our use case will be Baz's Spec Reviewer.

So what is the Spec Reviewer? It's one of our products, which is essentially an agentic reviewer that knows how to compare requirements with implementation. So as a first step, it needs to kind of collect requirements. It will go to your ticketing systems, like your Jira or Linear or anything of that nature, and read a ticket.

And it can also go to Figma and look at visual designs in kind of a multi-modal way of operation. It will actually see the design that is intended, and that part is the requirements. Once it understands what a developer was tasked with, that's when it will spin up Playwright's MCP server to actually open up a browser, go into your system, check the branch, see the implementation, and it will need to assess whether the implementation meets the requirement.

It will give us kind of a verdict, it will take a snapshot as evidence whether this was fulfilled or wasn't fulfilled. And it does all this automatically and can save people, mostly PMs, a lot and lot of time doing menial validation work.

So we've built a toy example of our Spec Reviewer, and we're going to see how we handle the tools to get the most of it. I hope this makes sense at a high level. I think it's time to look at some code, and hopefully everything will be much, much clearer.

Alright, so we have a toy example of our Spec Reviewer. We'll go through it kind of quickly. We don't need to dive into every aspect of it. It's a pretty small project, and we'll see what's going on and focus on the parts that we care about.

So we start here with our main function. And

we have a directory where we want to save snapshots. We'll get to that later. Butright off the bat, we have our MCP server configuration. We have just the one. We're using only Playwright's MCP server. This is pretty standard.

So we have the one MCP. As we go into our main function, you can see that we're defining our MCP client. And we're going to use that in just a little bit. We'll put it in our agent. But I want to focus on this.

This is where the magic of this talk happens. We have built a base class

for getting the tools. And all it does, it has one function called getTools. As we will go through the talk, we will go in increasing complexity and improve the way we handle the tools that are coming from our third-party MCP server.

So here it is. We're starting with the baseline. We'll look at it in just a second. And as we start our session,

this is where this inheritance is going to take place. Every time we run this, the getTools will do something a little bit more advanced. So we want to start our flow. We have this function called loginToBaz, because for this talk, our example is going to be logging into our system.

And we will talk about why we need this. Towards the end, there's actually an interesting point here. We will define an LLM. We'll create an agent. We will give it a system message and a human message to start, to kick it off.

These are the messages it's going to get. And we will invoke it.

You're probably kind of wondering, maybe you want to see a little bit more under the hood, maybe look at the prompts. So this should be relatively straightforward. You know, system prompt, this is mostly AI generated, saying things like, "You are a meticulous QA agent.

You need to review requirements from the ticket as well as visual verification." Everything we talked about at high level isright here. Some guidelines, first read the ticket, understand it, navigate through the system. And then at the end, like we said, it needs to give us a pass or fail verdict, specific observations, and reference everything with a screenshot for evidence.

A human prompt is very similar. It does have a multi-modal aspect to it, where we take images and we embed them in the human prompt. But these days it's very straightforward, and any coding agent can just whip that out for you if you need it.

Speaking of images, we have two images here. We have a ticket that we took a snapshot of. Our real product doesn't take tickets as snapshots. We were just lazy. But the agent can definitely read this, understand the requirement.

There is an accompanying design, which is this one. So the ticket states that we want to have a configuration drawer for our Spec Reviewer in our system, in Baz. It explains how it should look, and a design is given.

So the agent should understand that it's looking for a drawer inside our agents tab for Spec Reviewer, and it should look roughly like this. Amazing. I think it's about time we just fire this up, and hopefully it will make everything so much clearer.

We have a breakpoint hereright after we get the tools. Almost forgot. Our first run is going to be with this, V0, the benchmark. What is our benchmark? If we go to our getTools, we see that what we do for V0 is classic out of the box.

Baseline failure10:36

Nimrod Hauser10:54

We just use LangChain's loadMCPTools method. That is it. For the first round, we're not tinkering with tools at all. Let's see how it behaves, vanilla. Alright.

Okay, so this is starting up, and we have our tools. Let's see what we have here. Soright off the bat, the good people at Playwright have given us 21 tools. And everything that has to do with manipulating the browser, browser close, browser resize, console messages, handle dialogue, file upload, fill form, install, all the press key.

And then we can look at the descriptions. What is the description for a tool called press key? Press a key on the keyboard. What is the description for something like resize? Resize the browser window. Browser close? Close the page.

These seem very shallow and very generic, but we don't blame them. The people at Playwright don't know what our specific use case is. This MCP server will need to cater to, I don't know how many different use cases.

It has to be generic. But for us, using this, and we'll see this going forward, we might want to put in our own descriptions that really are tailored to our use case. But we're not there yet. We're still at the baseline.

So let's just continue. And we will see that this is running.

Okay. So Playwright is running. It's spinning up a browser. And now it's going to log in. And once it's logged in, the agent is going to take over and start running according to the prompt.

And there, it's off to the races. It's logged in. This is our homepage, which is the changes screen. And now it's going to need to find the relevant

page, which is the agents tab. So it's going to need to explore the system a little bit. And it might work, it might not work. Remember, the tools are not optimized at this point. And it's done. Let's see how it did.

So looking at the results, it tells me that the requirement is not implemented, that the status is a failed verdict. It gives me an observation, and it tells me that the requirement is not met because it couldn't navigate to a seemingly made-up page called bazco/specreviewer.

This might be a hallucination, a laps in judgment on the agents part, a bunch of other things. And it gives an evidence of a 404 screenshot, which probably took, and we can probably check out in our screenshots folder.

It didn't even manage to take the screenshot properly. So a lot of things went wrong. And this is actually a great outcome for the beginning of the talk, whose whole concept is optimizing our use of agentic tools. So let's see what we can do to improve our tools.

And we'll run this again and see if we can turn this upside down.

Five practices14:17

Nimrod Hauser14:17

Alright, cool. Our MCP server is already starting to look a little bit better. The fire is put out. It's just this spark now. And this is probably because we've gone through some code. We're starting to understand the problem.

But we still need to start actually implementing our improvements and see what can be done to really make the system better. So time to introduce our five concepts that we're going to go over. We're going to look at how we can curate third-party tools, wrap third-party tools with our own descriptions, and perhaps some additional things.

Adding deterministic guardrails whenever we feel it's necessary, and we'll give an example. Creating new tools out of the existing tools, actually using the existing tools as building blocks. And lastly, there's always the option to treat tools as simple functions, just calling them, using them as that integration code we spoke about, written to us by the good people at the team of Playwright.

You know, taking some parts of the workflow outside of the agentic flow. Whenever we feel it's necessary, we'll talk about this towards the end. So it's also a tool in our arsenal. I did kind of split these into two buckets.

One is more in the realm of context engineering, the other deterministic guardrails. It doesn't really matter. At the end of the day, whatever gets our application to work as we want it, that's what we need to use. So now we'll go over them one by one, looking at code, see how we can improve our toy example that we just saw.

Curating tools15:47

Nimrod Hauser15:47

Starting with our first point, curating third-party tools. Alright, let's see how this one looks. Alright, we're back here at our familiar project. And through the magic of video editing, we have now important V1. It used to be V0 original.

It's now V1 curated. The only difference, like we've seen, is that now we have this as V1, and this, as we said, it's that class that inherits from the base class. It used to have just getTools, vanilla, using LangChain's function.

Now we can see what we have implemented here. So we go in, and we used to return this,right? But now we have this big list of all the tool names that we get from our Playwright MCP. And this small list, this is pretty standard stuff in Python,

list comprehension. So we just created this list of tools that we want to exclude. We just went over them, and we know the tools. We've been using this MCP server for a while. And we decided that for our use case, we might not need resizing the browser.

We don't want our agent to drag things. We don't want to run code inside the browser on its own. These are just not things that our Spec Reviewer needs to do as part of its operations. Maybe for your use case, this is needed.

But for ours, not so much. So all we do is we get all the tools, and instead of just returning them, we simply exclude the ones that we don't want. So there are a bunch, your six here, that we're going to simply not use.

We fire this up. We have our breakpoint. And instead of 21 tools, which we used to have, I expect to see less. And so we have 16. Amazing. So this means our context window already has less tools in it.

Our agent has less to choose from. So everything might become simpler. We'll see that not all the guidelines that we're going to go through will necessarily reduce stuff from our context window. Some will actually add to it. But this is all part of this trade-off, this juggling act that we're going to talk about.

Moving on to our next point, the practice of wrapping third-party tools. This is amazing. We talked about how the descriptions, specifically coming from the Playwright MCP, are super shallow and very, very generic, and that it's totally understandable because they need to cater to every possible use case in the world that might want to use the browser.

Wrapping tools18:07

Nimrod Hauser18:31

But if you really want to optimize, you might want to start tailoring stuff for your own use case. Let's see how this happens. Okay, this is becoming familiar territory by now. And as always, through the magic of video editing, we have V2 imported, wrapped.

So we're wrapping tools this time. Going down, we see that we're calling the V2 class, which will implement getTools. And we'll see what's going on here. If I go to V2 wrapped, I see that we, as before, we get all the tools.

But now we have this new class called toolWrapper, which has a method that we're calling wrapPlaywrightTools. Let's see what's going on here. As before, we still have this list of all the tool names. We'll do the filtering a little bit further.

But instead of just the tool names, we also have all these descriptions. And so for every tool, we want to specify what needs to happen. And from experience, we have our own kind of little emphasis that we want to give our agent.

We might tell it, you know, before calling the browser tool, first call this other tool. This tool we found to be especially helpful. It has kind of a misleading name. It's called the snapshot tool. It's actually not a visual snapshot.

It's the accessibility snapshot that kind of shows you all the different buttons and all the different menu items in text. And we feel that the agent really gets a good understanding of what is in a page when it calls that tool.

So we tell it for a bunch of tools, you know, before calling hover, before calling click, please use this tool before. So we can kind of really affect its behavior. We can make it more eager to choose one tool over the other.

We can do a bunch of things. For instance, this is the tool I just talked about, the accessibility snapshot. We will tell it, always prefer this over taking an actual snapshot, which is this tool. So you can really give a lot of guidance from your own experience for your own particular use case.

And this is very, very powerful. In here, we have this dictionary, which just maps tool names with their new enhanced descriptions. Still, we have our tools to filter. At the end, we have the function that we called wrapPlaywrightTools.

And it just goes through all the tools that we get from Playwright out of the box. We filter what needs to be filtered. And for other tools, we get our enhanced description based on the tool name, and we create this tool, and we append it to the list of wrapped tools.

So we get enhanced tools. What is this method that creates an enhanced tool? Well, it's a method that gets the original tool and the enhanced description, creates a new tool, and returns it. And so what does this amazing new tool, what does it do?

Exactly what the old tool did. It just invokes the original tool. It just has an enhanced description. So if we run this, going back to main, and we run this, and we still have our breakpoint, we can see that we still have less tools like we wanted to from before, even less.

We filtered a bunch more. But when we look at the descriptions, you see that they're much longer, and they are the ones that we wanted. For example, here is the tool we spoke about, browser snapshot, capture an accessibility snapshot of the current page, yada, yada, yada.

All the things we said. If we look at another one, browser click, here's our guideline for first call the other tool, and then call this one. Now our agent knows how we want it to behave.

Alright, onto the next one.

Guardrails22:33

Nimrod Hauser22:33

First of all, our MCP server, I don't know if you can notice, but things are looking even better. Some of the interfaces seem to work. Lights blinking, things firing, but we're still far from the home stretch. We'll move on to point number three and keep making this better.

Now we're moving into the realm of deterministic guardrails. And this is putting in deterministic guardrails. Taking control of sensitive or mission-critical aspects of our tasks with deterministic logic that is not up to agentic decision making. Sometimes there are aspects of your tasks that are just too sensitive to leave at the hands of the agents.

We talked before about scenarios like multi-tenant architecture and scenarios where the agent might not be fully aware of your architecture, things of that nature. And of course, you need to specify everything you can in the tool descriptions and the prompts.

But sometimes you really want to enforce that it is not doing anything funky. You know, agents are non-deterministic things, and sometimes they will ignore you. We know of all these phenomenons such as needle in the haystack and lost in the middle, and a lot of instances where agents will just not work as you intended them to.

This is where you want to put some deterministic enforcement. We did this around the tool that takes actual visual snapshots. Not the accessibility snapshot we talked about before, but the actual visual snapshots. We had a folder that we defined, and we said, this is the output folder.

This is where we want you to put images. But there is a possibility that the agents will go rogue and just store images in other places. So that's where we want to draw the line and make sure this never happens.

Okay, so as always, we have V3 now, which is the one we want to look at. So going back to main, we see we have this here, V3 guardrailed. We dive in, and we see that we have, again, our wrapPlaywrightTools.

Obviously, this time it's going to do something a little bit different as we increment every time. So we still have the names, we still have the descriptions. And going down, down, down, down, by the way, we can already see that apart from the V3 that we always have, which looks like this, and the toolWrapper, which we had before, we now have another class called pathValidation.

Let's see where we use it. So we're going down, down, down. We're going past the dictionary, past the tools to filter. We're in the method that we're always importing, wrapPlaywrightTools. And wrapPlaywrightTools, as before, it goes over all the original tools we got from our Playwright MCP, filters what needs to be filtered, gives the enhanced description for each of the tools if we find it.

And then, as before, we have the same helper function, createPlaywrightToolWrapper. That function that takes a tool, gives it the enhanced description, and creates a new tool out of it. Same functionality, new description. Let's see what's changed now. So when we want to create the new tool,right, so this is the tool we're creating.

As we said, a tool is just a callable function with some description. We give the new description. And before, we had this part, because we said, what does the new tool do? Exactly what the old one did. But we added this part.

We're saying, if the tool that is now being activated, if it is the takeScreenshotTool, and we've kind of researched the tool, and we know that it uses under the hood, it will use either the path or file name as keywords, at least the relevant keywords for us.

So if you're trying to invoke the tool and it is this tool, then find these keywords and validate them. And we have some helper functions. This pathValidation, these are just helper functions. We don't need to go too much into them.

But they're just deterministic logic where we take the path that the tool chose, and we take our path where we want to enforce things being stored. We call it the screenshots route. And we just use this method. We want to know if that path is relative to the chosen path, is relative to the screenshot path.

So it is a deterministic way, once we understand where the tool intends to store the image, we know if it is inside theright folder. So going back to our helper function, every time the tool is invoked, before it actually gets invoked, we kind of extract the path it intends to save to, to invoke it with.

We try to validate. And if it is not a valid path, it will not reach invocation. It will raise an error. So this is a deterministic way where we can stop the toolright in its tracks with a deterministic guardrail.

Now, another nice thing to note is that we might raise an exception. We don't return an exception. We don't want the whole agentic process to fail. Instead, we handle this nicely by creating a very nice agent-facing explanation. And what the agent will get back is this nice message saying, "Listen, access is denied.

You can't save it there. You need to save it here. Please provide a proper file name and proper path." An agent that gets this message is most likely to just try again, but aligned. This is our way of aligning it.

And it will try again, give a correct path, manage to traverse this, get here, and save the image. So that's exactly what we want to happen in these very mission-sensitive, security-related scenarios. So that is amazing. Okay, personally, I love this point.

I think it is so common and a tool everybody must have in their arsenal. But it is time to go forward. We have two more. This might be a little bit more niche, more on the advanced side, but it is worth kind of checking out, knowing that it is a possibility.

Composing tools28:39

Nimrod Hauser28:55

This talks about composing new tools from existing tools. And the place where we did that was interesting. It also had to do with the same takeSnapshotTool. We felt that sometimes we want to take snapshots in general. It's kind of a generic thing.

But when we take screenshots in the context of evidence, at the end of the flow, we felt that maybe having a separate tool for that was in order. Why? We can create a new tool whose functionality is essentially pretty much the same as takeRegularSnapshot.

But because it will have separate descriptions, the agent can choose either this or that. And we can also tell it to behave slightly differently in both cases. And we can also give some additional actions to do, maybe even deterministic actions, just before invoking the original tool.

So we created a new agent called the Evidence Tool. And let's take a look at what we did there.

Allright, this time around, we have V4 imported, as we would expect by this point. So we can take a look at V4, see how it implements getTools. We go in, this opens up. This looks very similar to before.

Actually, everything looks similar. We have toolWrapper, we have pathValidation, very, very similar. What's the difference? Well, we inject a new tool. So we have inside toolWrapper, what we would have come to expect by now. We have the tool names, the tool descriptions, the dictionary.

We have our tools to filter. Everything's the same. And then we have the same old, same old wrapPlaywrightTool, which iterates over all the tools, filters what needs to be filtered, and creates any tools that we need to create with enhanced descriptions.

So this is what we used to have. We finished the loop, and we have this. We have this part injecting a brand new tool. We chose, and you don't have to go the same route, but we said, because this is building on the screenshot tool, then only create this new tool if the screenshot tool has not been filtered out.

Totally optional, just what we chose to do in this particular use case. And so we have our new description for this new tool. And we create a new tool. Let's take a look at the screenshot. Sorry, the description.

So

a description, as you might expect from a description of this kind of tool, take a screenshot specifically for the purposes of evidence. And because the prompt, when it describes the flow, tells it that this ends with taking snapshots for evidence, the agent will probably know to choose this tool over the regular screenshot-taking tool.

We tell it to use this only when capturing things for evidence. And we also specify how to go about doing evidence. We say, for example, that when it creates an image and it wants to store it, we want it to identify the relevant ticket and include the ticket number in the file name being saved.

And so you can see a nice example of how we're going to have two tools. The agent will know to differentiate when to use this one or whether to use the other one, specifically in the context of evidence taking.

And when it chooses that tool in the context of evidence taking, this will cause it to have different considerations when choosing the image name, for example. And you can do a bunch of other things. You can add guardrails or deterministic actions that are specific to this tool, for example.

So really, the sky's the limit, the world is your oyster, and knock yourselves out. So this was this. Moving on to our final, fifth, and final point. Look at this. Our server, all the fires out. The system is booting, looks meh.

Deterministic calls33:00

Nimrod Hauser33:00

And still, we have one final point, which we actually touched on in the beginning of the talk. This is treating tools as deterministic functions or callable functions. Sometimes we get all these wonderful functions, all this code from the people at these third-party teams.

In our case, the team of Playwright, they gave us all this really nice code. And we can just call this code outside of the agentic flow. Just call it. Just disregard the description and just use the function they gave us.

Where do we use that? I don't know if you remember, but when we first looked at the code, we had this function called logInToBuzz. And we said, we'll get back to that. This is us kind of closing that loop.

Let's take a look.

Okay, back to the top of our main Py file. We go down, down, down, down, down, down, down, down, down. Here is the imported V4. But today we're interested in something. But now we're interested in something else, which is this part.

When we just start out, we kind of define the MCP client. We define this class that implements getTools. We get our tools. And the first thing we do is we have this deterministic function called logInToBuzz. Only after we logInToBuzz do we actually create an agent, and then we give it all the messages it needs, and we invoke it.

So why is the logging deterministic here? Well, it seems that logging is kind of tricky because this is a toy example, again. But in our real product, we need to log into our system. We need to log into client systems.

And each client might have a different logging mechanism. And they can be tricky, and they can have secrets. And a lot of things can make this kind of complicated. So on the one hand, it's complicated. And on the other hand, it is an action that we will always want to take.

There is no agentic flow for spec reviewer that does not begin with a login. And so

we do use tools we got from MCP server in order to achieve this. We're just not letting the agent try to do it because we saw it gave us subpar results. So for these very specific niche use cases, sometimes you might want to take matters into your own hand.

Here, if we go into the function, not much going on.

Again, toy example, the real product behaves very differently. But here, I just hid some JWT tokens as environment variables. And this function accepts all the tools from the MCP server. We kind of pluck the ones we want. And

the gist of it is that we are going to inject these JWT tokens into the browser's local storage. And then when we click the login button, we will just log in like magic. So we just do this deterministically.

Once we have logged in, we take the reins and give it to the agent. We say, "You're logged in. You're off to the races." And that's how we just unburden the agent from this somewhat clunky action it needs to take, which we can just take off its hands, not bother it and its context with it.

Cool. So that simplifies things, at least for us. Oh, I almost forgot. I still owe you one last thing. I think we should fire this thing up now with all the improvements and see where we land. We failed on the previous run, didn't we?

Improved run36:50

Nimrod Hauser36:50

Okay, let's see how it works. So going back to the familiar code base, our main, nope. And we run this. We no longer need the breakpoint. I think I took it out. Yep. And this is just running. Okay, so this is going to start by doing all that JWT magic in the back, which we now know how it works.

And let's see how it goes. I'll take the time to remind you that we gave it a ticket and a design. And it needs to see this drawer. That's what it's actually doing now. Okay, so it kind of reloaded.

I think maybe the JWT tokens have kicked in. It's going into our homepage called Changes. And it's probably going to do a little bit of reasoning. And it's going to need to find the way to navigate itself through the system to the Agents tab.

It doesn't always show it. It has a lot of latency and lag, at least from our experience. But it does take a screenshot as evidence. It finished. Let's see what it did. So it says that this passed. It claims that the configuration drawer is present and includes the sections that need to be there.

It has a screenshot. The screenshot has a file name that includes the ticket, like we said. It has reasoning. Let's take a look at the screenshot. So you see the image we gave it was a dark mode. And it was navigating in light mode.

And it took it. And it looks great. It looks like it's done. And it's correct. Now, I will say that it did see a configuration drawer. It did see everything that's supposed to be in it. It might not be pixel perfect, but pixel perfect verification is something that we worked very hard on in our real product.

So outside of this toy example, pixel perfect does work because it is super important for front-end validations, making sure the padding and the margins and all the style is just as it needs to be. Amazing. So with that done, I think it's sad.

Wrap-up39:06

Nimrod Hauser39:06

It's almost goodbye time. So I think we're starting to get ready to wrap up. Look at our server. Look at it. It's amazing. It's beautiful. It's working. Green. Lights are blinking. Engines roaring. GPUs churning. Millions of spec reviewers being executed and a great acceptance rate.

Thank you for all your help. Let's just do this one final summary before we each go our separate ways. So as we said, we looked at agentic tools today, whether they come from libraries, MCP servers, or any other place.

We saw that sometimes they will fail out of the box. They might be very generic. They might be not tailored enough for our use case. And tailoring them is what's going to make our agents pop. Now, sometimes we wanted to curate the tools and kind of ease the load on the context window.

Sometimes we wanted longer descriptions and more verbose tools. So there's no one-size-fits-all. It's mainly a question of how do I kind of mold the tools to best fit my use case. Sometimes they'll be deterministic. Sometimes they'll be flexible.

It depends. And you're going to need to tinker with it and make it your own and strive for the best possible setup that you can do to achieve your goals. I hope this has given you a few pointers, things that you can try out.

This has been amazing and great fun. I'm going to move up here now because I have a shameless plug after I thank you for listening. And so always feel free to reach out. I will see you guys in the next one.

Cheers.