Skip to content

Mocking API on Storybook using MSW

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

In this blog, you will learn how to mock APIs on Storybook using MSW. This blog will assume you have your project setup with either GraphQL, or a REST API like Axios or Fetch API and also will assume you have Storybook installed in your project. We will be covering how to mock for both GraphQL and REST API.

In this project, we will use Vue and our UI tool. But don't worry. The sample code will work for whichever framework you choose.

What is MSW?

MSW(Mock Service Worker) is an API mocking library that uses Service Worker API to intercept actual requests.

Why Mock?

Mocking helps us avoid making an actual HTTP request by using a mock server and a service worker. This, in turn, prevents any form of break in case something goes wrong with the server you would have sent a request to.

What is a Mock Server?

A mock server is simply a fake server that works as a real server to help users test and check APIs . It imitates a real API server by returning the mock API responses to the API requests. You can ream more here.

What is a Service Worker?

A Service worker enable communication between the application, the browser, and the networks (if netwrok is available). They are intended, among other things, to enable the creation of effective offline experiences, intercept network requests, and take appropriate action based on whether the network is available or not.

You can learn more about Service Worker API here.

Use Cases

Enough of all the stories 😃. Now we will be looking at two use cases:

  • GraphQL
  • REST API

We will need to install some pulig ins to maximize what msw has to offer by running one of these commands in the root directory of the project:

Installing MSW and the addon


# With npm
npm i msw msw-storybook-addon -D

# With yarn
yarn add msw msw-storybook-addon -D

Generate a service worker for MSW in your public folder.

npx msw init <PUBLIC_DIR>

Replace the <PUBLIC_DIR> placeholder with the relative path to your server's public directory. For example, the Vue command will be:

npx msw init public/

You can check here to see what path your framework will use.

Note: If you already use MSW in your project, you have likely done this before, so you can skip this step.

Configuring Storybook

In your .storybook/preview.js file, add this:

import {
  initialize,
  mswDecorator
} from 'msw-storybook-addon';

// Initialize MSW
initialize();

// Provide the MSW addon decorator globally
export const decorators = [mswDecorator];

You also want to ensure that your GraphQL set up is initialized in this .storybook/preview.js file if you are using Apollo Client.

Creating our mock API

Lets create where our mocking will be happening by first creating mock folder in the src folder.

Create a data.ts file in the mock folder, and add this code, which will serve as our fake response.

export const userDetails = {
  user: {
    name: "Jerry Hogan",
    login: "hdJerry",
    bio: "I am a Front-End Developer with about 3 years plus of experience and with a very good knowledge of JavaScript, Vue, React, Tailwind, Styled component",
    company: null,
    avatarUrl:
      "https://avatars.githubusercontent.com/u/28502531?u=c0598241c0ca3dba90aff9d21790cb330952fd94&v=4",
    followers: {
      totalCount: 19,
    },
  },
};

export const posts = [
  {
    userId: 1,
    id: 1,
    title:
      "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
  },
  {
    userId: 1,
    id: 2,
    title: "qui est esse",
    body: "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
  },
  {
    userId: 1,
    id: 3,
    title: "ea molestias quasi exercitationem repellat qui ipsa sit aut",
    body: "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut",
  },
  {
    userId: 1,
    id: 4,
    title: "eum et est occaecati",
    body: "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit",
  },
];

Create a mockedPost.ts file and add this code.

import { rest } from "msw";
import { posts } from "./data";

export const mockedPostFetch = rest.get(
  "https://jsonplaceholder.typicode.com/posts",
  (_, response, context) => {
    return response(context.json(posts));
  }
);

Create a mockedUserProfile.ts file and add this code.


import { graphql } from "msw";
import { userDetails } from "./data";

export const mockedUserProfileQuery = graphql.query(
  "UserProfile",
  (_, res, ctx) => {
    return res(ctx.data(userDetails));
  }
);

The concept of interception comes into place with these mocked files. For example, if there is any request outside of the mocked request, msw won't mock it. So every API url or query we want to mock must correspond to the component that's data you are trying to mock, regardless of if the API url is authentic or not.

Create a handlers.ts file and add this code. Handlers allow us to have multiple request, no matter its method [POST, GET]...

import { mockedPostFetch } from "./mockedPosts";
import { mockedUserProfileQuery } from "./mockedUserProfile";

export const graphQlHandlers = [mockedUserProfileQuery];
export const apiHandlers = [mockedPostFetch];

How do we make use of the Handler?

I created two components to test for our two use cases

  • Card
  • Posts

Card component

  • Create a Card folder in your component folder.
  • Create a Card.vue and add this snippet
<template>
  <div v-if="!loading" class="card">
    <div class="dp">
      <img :src="data.avatarUrl" alt="dp" />
    </div>
    <div class="user">{{ data.name }} 😎</div>
    <div class="bio">{{ data.bio }}</div>
    <div>Followers: {{ data.followers.totalCount }}</div>
  </div>
  <div v-else class="card loading">Loading...</div>
</template>

<script lang="ts">
import { USER_QUERY } from "@/graphql/user.query";
import { useQuery } from "@vue/apollo-composable";
import { defineComponent, computed } from "vue";
export default defineComponent({
  name: "UserCard",
});
</script>

<script lang="ts" setup>
const { result, loading } = useQuery(USER_QUERY, {
  username: "hdjerry",
});
const data = computed(() => result.value?.user ?? []);
</script>

<style scoped>
.card {
  width: 20rem;
  padding: 1rem;
  box-shadow: 0 0 20px 2px #ccc;
  border-radius: 6px;
  color: #333;
  min-height: 30rem;
}

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: 500;
}
.dp {
  width: 20rem;
  height: 20rem;
  border-radius: 100%;
  overflow: hidden;
  margin: 0 0 1rem;
}

.dp > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.user {
  font-size: 1.2rem;
  font-weight: medium;
  color: #2c3e50;
}
.bio {
  border-left: 4px solid rgb(154, 28, 179);
  padding: 0.2rem 0.5rem 0.2rem 1rem;
  margin: 1rem 0;
  background-color: #eee;
}
</style>

  • create an index.ts and add this code
import Card from "./Card.vue";
export default Card;
  • create Card.stories.ts and add this code
import { graphQlHandlers } from "@/mock/handles";
import Card from "./Card.vue";

export default {
  title: "Components/Card",
  component: Card,
  argTypes: {},
};

type Templates = {
  bind: (arg: unknown) => {
    parameters: unknown;
  };
};

const Template: Templates = () => ({
  components: { Card },
  template: "<Card />",
});

export const Default = Template.bind({});

Default.parameters = {
  msw: {
    handlers: graphQlHandlers,
  },
};

below is the UI expectation Card component

Posts component

  • Create a Posts folder in your component folder.
  • Create a Posts.vue and add this snippet
<template>
  <div v-if="!loading" class="posts">
    <div v-for="{ id, title, body } in data" :key="id" class="card">
      <h4 class="title">{{ title }}</h4>
      <div class="body">{{ body }}</div>
    </div>
  </div>
  <div v-else class="card loading">Loading...</div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "UserPosts",
});
</script>

<script lang="ts" setup>
const loading = ref(true);
const data = ref(null);

fetch("https://jsonplaceholder.typicode.com/posts")
  .then((data) => data.json())
  .then((res) => {
    data.value = res.slice(0, 4);
    loading.value = false;
  });
</script>

<style>
.posts {
  width: 100%;
  padding: 0.5rem;
}
.card {
  flex: 1;
  min-height: 5rem;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: justify;
}
.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: 500;
}
.card > .body {
  font-size: 1rem;
  font-weight: 200;
  line-height: 1.2;
  color: rgb(117, 114, 114);
  word-wrap: break-word;
}
.card > .title {
  text-transform: capitalize;
  color: #2c3e50;
}
.card:not(:last-child) {
  border-bottom: 1px solid #ccc;
}
</style>

  • create an index.ts and add this code
import Posts from "./Posts.vue";
export default Posts;
  • create Posts.stories.ts and add this code
import Posts from "./Posts.vue";
import { apiHandlers } from "@/mock/handles";

export default {
  title: "Components/Posts",
  component: Posts,
  argTypes: {},
};

type Templates = {
  bind: (arg: unknown) => {
    parameters: unknown;
  };
};
const Template: Templates = () => ({
  components: { Posts },
  template: "<Posts />",
});

export const Default = Template.bind({});
Default.parameters = {
  msw: {
    handlers: apiHandlers,
  },
};

below is the UI expectation Posts component

Code Explanation

We created a card and posts component that is making use of certain query/API call to get data.

msw has a property handlers which accepts an array of requests, giving us the ability to add as many requests as we want provided that they are in the component.

Overview Of the UI

Below is an overview of the UI, which brings together the components:

Home page

Whewww!!! 😌

Why mock?

  • You want test without hitting the actual API
  • Yhe API isn't yet avaible from the backend team.
  • During development to reduce dependencies between teams.
  • To accelerate third parties API integration.
  • during functional and integration testing.
  • to test various advanced scenarios more easily.
  • for demonstration purposes.

Conclusion

If you have any issues, we provided a repo which you can use as a template if you want to start a new project with the setup and use it to practice.

Please let me know if you have any issues or questions, and also contributions are welcome.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

Quick Guide to Playwright Fixtures: Enhancing Your Tests cover image

Quick Guide to Playwright Fixtures: Enhancing Your Tests

Introduction Following our recent blog post on migrating E2E tests from Cypress to Playwright, we've identified opportunities to enhance our test scripts further. In this guide, we'll delve into the basics of Playwright fixtures, demonstrating their utility and flexibility in test environments. Playwright fixtures are reusable components that set up and tear down the environment or conditions necessary for tests. They are crucial for writing clean, maintainable, and scalable tests. Fixtures can handle tasks like opening a browser, initializing a database, or logging into an application—actions you might need before running your tests. As a practical example, we'll revisit one of the tests from our previous post, enhancing it with a new fixture to streamline the testing process and significantly improve maintainability. This post is designed to provide the foundational skills to integrate fixtures into your testing workflows effectively, giving you the confidence to manage and maintain your test scripts more efficiently. Creating Our First Fixture To illustrate the power of fixtures in Playwright, let’s consider a practical example from a test scenario in our project. Below is a snippet of a test case from our newsletter page: ` This test scenario navigates to the newsletter page, fills in an email, submits the form, and checks for a success message. To optimize our test suite, we'll refactor common actions like navigation, form completion, and submission into reusable fixtures. This approach makes our tests cleaner and more maintainable and reduces redundancy across similar test scenarios. Implementing the Fixture Here’s how the fixture looks: ` This fixture encapsulates the actions of navigating to the page, filling out the email field, and submitting the form. By abstracting these actions, we simplify and focus our test cases. Refactoring the Test With the fixture in place, let’s see how it changes our original test file: ` A beforeEach method to reset the state of the NewsletterPage fixture ensures a clean and consistent environment for each test scenario. This practice is crucial for maintaining the integrity and reliability of your tests. By leveraging the NewsletterPage fixture, each test within the "Newsletter page" suite starts with a clean and pre-configured environment. This setup improves test clarity and efficiency and aligns with best practices for scalable test architecture. Conclusion As we've seen, fixtures are powerful tools that help standardize test environments, reduce code redundancy, and ensure that each test operates in a clean state. By abstracting common setup and teardown tasks into fixtures, we can focus our testing efforts on what matters most, verifying the behavior and reliability of the software we're developing. Remember, the key to successful test management is choosing the right tools and using them wisely to create scalable, maintainable, and robust testing frameworks. Playwright fixtures offer a pathway towards achieving these goals, empowering teams to build better software faster and more confidently....

Enhancing Your Playwright Workflow: A Guide to the VSCode Extension cover image

Enhancing Your Playwright Workflow: A Guide to the VSCode Extension

Introduction In my last post, Quick Guide to Playwright Fixtures: Enhancing Your Tests, I delved into some of the enhancements we've been implementing in our end-to-end (E2E) tests using Playwright. As I refine our testing strategies, I've come across a tool that has quickly become an essential part of my workflow: the Playwright VSCode extension. If you're like me and constantly looking for ways to streamline testing and debugging, you'll appreciate any tool that can make the process more efficient and enjoyable. That's where this extension comes in. It's not just about writing tests - it's about enhancing the entire development experience. In this post, I'll walk you through getting started with the Playwright VSCode extension, sharing some tips and tricks that have made a real difference in my day-to-day work. Installing the Extension & Basic Setup Before diving into the Playwright VSCode extension, it's essential to have Playwright installed on your machine. If you haven't done so already, you can quickly install it by running: ` This command will set up Playwright and ensure all necessary dependencies are installed. Once Playwright is ready, the VSCode extension will be installed next. Open Visual Studio Code, navigate to the Extensions view by clicking on the Extensions icon in the Activity Bar on the side of the window, and search for “Playwright”. The official extension, ID: ms-playwright.playwright / named: “Playwright Test for VSCode” by Microsoft, should appear at the top of the list. Click "Install," and you're all set. With the extension installed, you can start leveraging its powerful features to enhance your Playwright testing workflow within VSCode. Running the Tests and Identifying Outputs To run a test, simply open the test file in VSCode. The Playwright extension will automatically detect test files and display a "Run" icon next to each test and test suite. You can click on this icon to run individual tests or test suites. Alternatively, you can run all the tests in your project using the Playwright Test Explorer, accessible from the sidebar. Once you start running your tests, the extension provides real-time feedback within the editor. You'll see the status of each test - whether it passes, fails, or is skipped - right next to the corresponding test in your code. This immediate feedback loop is incredibly helpful for catching issues as you write your tests. The output of your tests will be displayed in the VSCode terminal. You'll see detailed information about each test run. Debugging Step-by-Step I find debugging particularly useful when a test fails unexpectedly or when I want to verify that certain actions are being performed as intended. Instead of guessing what might be wrong, I can see exactly what's going on in each test step, making debugging a much more straightforward and less frustrating process. To start debugging, you can easily set a breakpoint in your test file by clicking on the left margin next to the line number where you'd like the execution to pause. Once your breakpoints are in place, you can initiate the debug process by selecting the "Debug" option next to the test you'd like to investigate. Once the debugger is running, the extension allows you to step through your code, inspect variables, and evaluate expressions - all within VSCode. This real-time insight into your test execution is a game-changer, enabling you to pinpoint issues more effectively and confidently refine your tests. Using the Pick Locator Tool Another handy feature is the "Pick Locator" tool. If you've ever struggled with selecting the right element in your tests, this tool can be a time saver. It helps you generate reliable locators by letting you interact directly with the webpage elements you want to target. To use the Pick Locator tool, click the "Pick Locator" button in the Playwright Test Explorer. This will open a new window where you can navigate to the site you're testing. As you hover over elements on the page, the tool will suggest locators, allowing you to select the most appropriate one for your test. While the Pick Locator tool is handy, it’s important to ensure that the locators you generate are robust and maintainable. This is especially true when integrating them with the fixtures I discussed in my previous blog post. Combining the proper locators with well-designed fixtures can create more reliable and reusable test setups, ultimately making your E2E tests more efficient. Conclusion The Playwright VSCode extension has quickly become indispensable in my development workflow. It significantly enhanced my experience of writing and running Playwright tests. Whether you’re just starting with Playwright or looking to optimize your existing tests, this extension offers a range of features that can save you time and effort. Combining these tools with thoughtful test design, such as leveraging fixtures, you can create a more efficient and effective testing process. I hope this guide has given you a good overview of what the Playwright VSCode extension can do and how it can benefit your work. If you haven’t tried it yet, I highly recommend giving it a go. And as always, feel free to explore further and experiment with the features that best suit your needs....

How To Authenticate Your SolidJS Routes With Solid Router cover image

How To Authenticate Your SolidJS Routes With Solid Router

In this post, we will talk about how we can authenticate our SolidJS route with Solid Router. By the end of this article, we will understand what authentication is, and how it is used to guard routes in SolidJS using the Solid Router. Overview Route authentication has been around for a while, and is now a fundamental part of many applications like Facebook, Gmail, and Instagram. At this point, it’s about as ubiquitous as entering a password into a phone. Authentication through route guards in SolidJS can be achieved in two different ways. The first that we are going to cover in this app is the use of a Solid Router. The second is provided by Solid Start, which is more like a folder-based routing. It is a meta-framework (a framework built on another framework). At its core, it's powered by SolidJS and Solid Router. This article assumes that you have already set up a SolidJS project, and will not walk through that part of the process. If you have not yet spun up a project, you can find tutorials and instructions at SolidJS. What is Authentication? Authentication is a process of verifying the identity of the user. It provides access control to check if the user is authenticated. Authentication enables organizations to keep their networks secure by permitting only authenticated users or processes to gain access to their protected resources which, in our case, is the route in the application. To learn more about authentication, you can check out the following; - Authentication By Mary E. Shacklett - Authentication By Auth0 - Authentication By Wiki What is a route guard? A route guard helps to prevent unauthenticated users from accessing certain routes/parts in an application. For example, an app lock on a mobile phone can be seen as a guard. You may be able to access the phone and some apps, but you can’t access other apps. We can also use parental controls on the phone, internet, and so on as a type of guard. You can read more about route guard. Get Started If you haven't installed the Solid Router in your project, run the command below: ` Solid Router is a universal router for SolidJS which works whether you're rendering on the client or the server. It was inspired by and combines the paradigms of React Router and the Ember Router. To read more, check out Solid Router Having installed @SolidJS/router, we will be creating the following files; - Home: *src/pages/Home.jsx* - Signin: *src/pages/Signin.jsx* - Pricing: *src/pages/Pricing.jsx* - RouteGuard: *src/RouteGuard/index.jsx* - Header: *src/components/Header/index.jsx* - Header styles: *src/components/Header/Header.module.css* Terminologies - useNavigate: a library provided to us by SolidJS Router that is used to navigate. - createEffect: creates a listener, which calls it's first argument when attached signals change. - Outlet: serves as the children associated with RouteGuard wrapper - NavLink: used to navigate between pages just like a tag which takes a property href for the page route path. Home page Below is the code we will paste in our home page file. But if you already have a content for this, you don't have to change it. ` This is just a simple page component with a style imported at the top. Signin page This is the content of our sign in page, but if have a content already, that's fine. The most important contents are the logIn function and the createEffect. ` The logIn function will be called when the login button is clicked. When clicked, a hardcoded token is saved in the session storage. The user is then navigated to the home page, which by default, can only be accessed if the user has been authenticated. The createEffect ensures the authenticated user won't access the sign in page. Pricing page This is just another page which, in this project, represents another protected page that could only be accessed by an authenticated user. ` This is just a simple page component with a style imported at the top. RouteGuard Component ` This serves as the wrapper for routes you want to protect from unauthenticated users. If there is no token in the session storage, the user will be routed to the signin page. Header component If you already have the content for the header file, you don't have to change it. All you need is the logOut function. ` Above, we have styles imported from the header CSS module, and we have a logOut function that is used to remove the token from the session storage and also navigate the user to the signin page. Header styles This is the style for the header component. ` Updates for src/App.jsx This file is where the route is managed, and where we grouped certain routes we wanna guard or protect from unauthenticated users. ` Update for src/App.module.css ` Updates for src/index.jsx We have to update this file by wrapping our App with Router ` Update for src/index.css ` Conclusion In this article, we were able to understand what authentication is, and how to create a route guard which is very important when trying to prevent certain users from accessing certain routes in our application. I hope we have been able to help you see the possibilities of making use of SolidJS and Solid Router to build a well-authenticated application. If you are having issues, you can check out the repo for SolidJS-route-guard. Don't forget that you can see, in detail, how this was maximized in one of This Dot's open source project starter.dev GitHub Showcases. Happy coding!...

What Sets the Best Autonomous Coding Agents Apart? cover image

What Sets the Best Autonomous Coding Agents Apart?

Must-have Features of Coding Agents Autonomous coding agents are no longer experimental, they are becoming an integral part of modern development workflows, redefining how software is built and maintained. As models become more capable, agents have become easier to produce, leading to an explosion of options with varying depth and utility. Drawing insights from our experience using many agents, let's delve into the features that you'll absolutely want to get the best results. 1. Customizable System Prompts Custom agent modes, or roles, allow engineers to tailor the outputs to the desired results of their task. For instance, an agent can be set to operate in a "planning mode" focused on outlining development steps and gathering requirements, a "coding mode" optimized for generating and testing code, or a "documentation mode" emphasizing clarity and completeness of written artifacts. You might start with the off-the-shelf planning prompt, but you'll quickly want your own tailored version. Regardless of which modes are included out of the box, the ability to customize and extend them is critical. Agents must adapt to your unique workflows and prioritize what's important to your project. Without this flexibility, even well-designed defaults can fall short in real-world use. Engineers have preferences, and projects contain existing work. The best agents offer ways to communicate these preferences and decisions effectively. For example, 'pnpm' instead of 'npm' for package management, requiring the agent to seek root causes rather than offer temporary workarounds, or mandating that tests and linting must pass before a task is marked complete. Rules are a layer of control to accomplish this. Rules reinforce technical standards but also shape agent behavior to reflect project priorities and cultural norms. They inform the agent across contexts, think constraints, preferences, or directives that apply regardless of the task. Rules can encode things like style guidelines, risk tolerances, or communication boundaries. By shaping how the agent reasons and responds, rules ensure consistent alignment with desired outcomes. Roo code is an agent that makes great use of custom modes, and rules are ubiquitous across coding agents. These features form a meta-agent framework that allows engineers to construct the most effective agent for their unique project and workflow details. 2. Usage-based Pricing The best agents provide as much relevant information as possible to the model. They give transparency and control over what information is sent. This allows engineers to leverage their knowledge of the project to improve results. Being liberal with relevant information to the models is more expensive however, it also significantly improves results. The pricing model of some agents prioritizes fixed, predictable costs that include model fees. This creates an incentive to minimize the amount of information sent to the model in order to control costs. To get the most out of these tools, you’ve got to get the most out of models, which typically implies usage-based pricing. 3. Autonomous Workflows The way we accomplish work has phases. For example, creating tests and then making them pass, creating diagrams or plans, or reviewing work before submitting PRs. The best agents have mechanisms to facilitate these phases in an autonomous way. For the best results, each phase should have full use of a context window without watering down the main session's context. This should leverage your custom modes, which excel at each phase of your workflow. 4. Working in the Background The best agents are more effective at producing desired results and thus are able to be more autonomous. As agents become more autonomous, the ability to work in the background or work on multiple tasks at once becomes increasingly necessary to unlock their full potential. Agents that leverage local or cloud containers to perform work independently of IDEs or working copies on an engineer's machine further increase their utility. This allows engineers to focus on drafting plans and reviewing proposed changes, ultimately to work toward managing multiple tasks at once, overseeing their agent-powered workflows as if guiding a team. 5. Integrations with your Tools The Model Context Protocol (MCP) serves as a standardized interface, allowing agents to interact with your tools and data sources. The best agents seamlessly integrate with the platforms that engineers rely on, such as Confluence for documentation, Jira for tasks, and GitHub for source control and pull requests. These integrations ensure the agent can participate meaningfully across the full software development lifecycle. 6. Support for Multiple Model Providers Reliance on a single AI provider can be limiting. Top-tier agents support multiple providers, allowing teams to choose the best models for specific tasks. This flexibility enhances performance, the ability to use the latest and greatest, and also safeguards against potential downtimes or vendor-specific issues. Final Thoughts Selecting the right autonomous coding agent is a strategic decision. By prioritizing the features mentioned, technology leaders can adopt agents that can be tuned for their team's success. Tuning agents to projects and teams takes time, as does configuring the plumbing to integrate well with other systems. However, unlocking massive productivity gains is worth the squeeze. Models will become better and better, and the best agents capitalize on these improvements with little to no added effort. Set your organization and teams up to tap into the power of AI-enhanced engineering, and be more effective and more competitive....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co