<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Opemipo Disu</title>
    <description>The latest articles on DEV Community by Opemipo Disu (@coderoflagos).</description>
    <link>https://dev.to/coderoflagos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F392943%2F708b2716-2bb6-45ee-9662-ddb0288e3079.JPG</url>
      <title>DEV Community: Opemipo Disu</title>
      <link>https://dev.to/coderoflagos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coderoflagos"/>
    <language>en</language>
    <item>
      <title>AI Agents Calling Your Existing Backend Without MCP Development</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Thu, 24 Sep 2026 09:06:11 +0000</pubDate>
      <link>https://dev.to/coderoflagos/ai-agents-calling-your-existing-backend-without-mcp-development-320d</link>
      <guid>https://dev.to/coderoflagos/ai-agents-calling-your-existing-backend-without-mcp-development-320d</guid>
      <description>&lt;p&gt;AI agents are becoming more useful than ever; they’re now doing more than just generating text. They can now retrieve information from different sources, call tools, and act on a user's prompt. But the problem is that most AI applications are missing one thing: a way to reach systems where the real business logic lives.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol (MCP) solves part of this problem. It gives AI applications a standard way to discover and call external tools. The catch is that building a dedicated MCP server for your existing backend adds another piece of software you now have to maintain.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn what Graftcode is, how it connects to MCP, and how to expose an existing backend to an AI agent without writing a custom MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI Agents Need Backend Access
&lt;/h2&gt;

&lt;p&gt;Most agents start by connecting a language model to a user interface. Models can generate text, answer questions, summarize content, and perform reasoning tasks. However, the challenge arises when the AI needs context that isn’t present in the prompt.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer account details&lt;/li&gt;
&lt;li&gt;Subscription information&lt;/li&gt;
&lt;li&gt;Internal documentation&lt;/li&gt;
&lt;li&gt;Knowledge bases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Information like this does not exist inside the model itself. The model needs a way to retrieve it from external systems, and that’s where protocols like MCP come into the picture.&lt;/p&gt;

&lt;p&gt;Traditionally, giving AI agents access to backend functionality means introducing another layer to maintain. You build the backend, expose it through an MCP server, define tools, connect handlers, and keep everything in sync whenever the backend changes.&lt;/p&gt;

&lt;p&gt;Graftcode starts from a different place; Instead of creating a separate MCP representation of your application, Gateway discovers the public methods you've already exposed and makes them available through MCP.&lt;/p&gt;

&lt;p&gt;The backend stays as the source of truth, while AI agents become another consumer of those capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Graftcode?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://graftcode.com" rel="noopener noreferrer"&gt;Graftcode&lt;/a&gt; is a tool that makes public backend methods callable across languages, processes, and machines without the need to write API or MCP layer. You write normal business code. Graftcode Gateway loads that code, finds its public methods, and makes them available to consumers, including AI agents over MCP.&lt;/p&gt;

&lt;p&gt;It was built around a simple idea: business logic should be written once and reused by different consumers. Instead of exposing backend functionality through manually maintained integration layers, Graftcode treats public methods as the gateway to work with your backend.&lt;/p&gt;

&lt;p&gt;For example, a backend service may already have all the business logic an application needs. Customer management systems contain methods for retrieving account information. Payment/checkout systems have methods for calculating invoices. Support platforms contain methods for searching documentation and knowledge bases.&lt;/p&gt;

&lt;p&gt;But we can have those applications use generated Grafts or AI agents via MCP rather than the traditional approach that requires creating additional integration layers such as REST APIs, RPC services, or other custom integrations.&lt;/p&gt;

&lt;p&gt;There are two sides to this model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Receiver&lt;/strong&gt;: the module that contains your public methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caller&lt;/strong&gt;: the application or AI agent that consumes those methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Caller talks to the Receiver through a generated package called a Graft, or through MCP if the Caller is an AI client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graftcode Vs. Custom MCP Server
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Custom MCP Server&lt;/th&gt;
&lt;th&gt;Graftcode Gateway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tool definitions&lt;/td&gt;
&lt;td&gt;Written and maintained as an additional layer&lt;/td&gt;
&lt;td&gt;Discovered automatically from your code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keeping tools in sync with the backend&lt;/td&gt;
&lt;td&gt;Manual, on every change&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra integration layer&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who owns the source of truth&lt;/td&gt;
&lt;td&gt;The MCP server's tool schema&lt;/td&gt;
&lt;td&gt;The backend method itself&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use Cases for Graftcode and MCP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customer support agents that need account, subscription, or order details.&lt;/li&gt;
&lt;li&gt;Internal assistants that need to search a knowledge base.&lt;/li&gt;
&lt;li&gt;Sales agents that want to verify subscription or billing status before replying to customers.&lt;/li&gt;
&lt;li&gt;Operations agents that need to call existing internal systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Does Graftcode Work?
&lt;/h2&gt;

&lt;p&gt;When you host a module through Graftcode Gateway, it reads your backend, loads the modules, discovers their public methods, and exposes the package. Those methods become callable in two ways at once: via a &lt;strong&gt;generated Graft&lt;/strong&gt; for regular applications and through &lt;strong&gt;MCP for AI agents&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F254sys5owelqidac8kty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F254sys5owelqidac8kty.png" alt="AI Agent" width="800" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's no separate MCP implementation sitting between the Gateway and your backend. The public methods are the capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Using Graftcode
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less integration code&lt;/strong&gt;: You skip writing tool schemas and handlers manually&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One backend, two consumers&lt;/strong&gt;: The same methods serve regular applications through a Graft and AI agents through MCP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The backend stays the source of truth&lt;/strong&gt;: Update the method once, and both consumers see the change&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliberate exposure&lt;/strong&gt;: You choose which classes and methods are callable, so you're not handing an agent more information than it needs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Graftcode Gateway and the MCP Endpoint
&lt;/h2&gt;

&lt;p&gt;When Gateway hosts a module, it opens two ports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Port 80&lt;/strong&gt; for regular service calls (Grafts).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port 81&lt;/strong&gt; for Graftcode Vision and the MCP endpoint at &lt;code&gt;/mcp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No OpenAPI spec, no manually defined MCP tool, and no custom server. Gateway does the discovery for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filtering What Gets Exposed
&lt;/h3&gt;

&lt;p&gt;You don't have to expose every method in a module. Gateway supports filtering with flags like &lt;code&gt;--types&lt;/code&gt; and &lt;code&gt;--methods&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gg ./service &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--types&lt;/span&gt; SupportService &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--methods&lt;/span&gt; getCustomerProfile,getSubscriptionDetails,searchKnowledgeBase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This matters more with AI agents than almost anywhere else. Giving an agent access to a method means giving it a capability, so keep the exposed surface small and intentional.&lt;/p&gt;

&lt;p&gt;For MCP clients that send a bare method name, Gateway can resolve the right class with &lt;code&gt;--mcpBaseClass&lt;/code&gt;. Browser-based or edge MCP clients may also need CORS headers set through a &lt;code&gt;cors.config&lt;/code&gt; file passed with &lt;code&gt;--corsConfig&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement MCP with Graftcode
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create and initialize the Backend Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;customer-support-ai
&lt;span class="nb"&gt;cd &lt;/span&gt;customer-support-ai
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an &lt;code&gt;index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SupportService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getCustomerProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer-1001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer-1001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sarah Johnson&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sarah@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Professional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer-1002&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer-1002&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;James Wilson&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;james@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Starter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Customer not found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getSubscriptionDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer-1001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Professional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;billingCycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;monthly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;renewalDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-10-01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer-1002&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Starter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;billingCycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;monthly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;renewalDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-09-20&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Subscription not found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;searchKnowledgeBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;How subscription renewals work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Subscriptions automatically renew at the end of each billing period.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Changing your subscription&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Customers can change their subscription plan from the billing settings.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cancelling a subscription&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Customers can cancel their subscription before the next renewal date.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SupportService&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code has nothing MCP-specific in it. No decorators, no tool schemas, no handlers. That's the point. The backend doesn't need to know that an AI agent will use it later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Install and Run Graftcode Gateway
&lt;/h3&gt;

&lt;p&gt;Now that we have our backend service, we need a way to expose its public methods so they can be consumed by applications and AI agents.&lt;/p&gt;

&lt;p&gt;The easiest way to get started is by installing Graftcode Gateway using the official one-line installer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Windows
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iwr https://grft.dev/get|iex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Linux / macOS
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://grft.dev/get |sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you can verify the Gateway is available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gg &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Graftcode Gateway is responsible for loading your module, discovering its public methods, exposing them through Graftcode, and automatically making them available through MCP.&lt;/p&gt;

&lt;p&gt;After installation, you can host your service by pointing Gateway at your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gg ./package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, we need to host the module through Graftcode Gateway.&lt;/p&gt;

&lt;p&gt;Graftcode Gateway is the runtime host that loads the module, discovers its public callable surface, and exposes it to consumers.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll use Docker to work with Graftcode Gateway. Firstly, let’s create a &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:24&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; TARGETARCH&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /usr/app/&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; wget &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; wget &lt;span class="nt"&gt;-O&lt;/span&gt; /usr/app/gg.deb &lt;span class="s2"&gt;"https://github.com/grft-dev/graftcode-gateway/releases/latest/download/gg_linux_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TARGETARCH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.deb"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; /usr/app/gg.deb &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; /usr/app/gg.deb &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean &lt;span class="se"&gt;\
&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 81&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["gg", "./package.json"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="nt"&gt;--pull&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; customer-support-ai:test &lt;span class="nb"&gt;.&lt;/span&gt;

docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 80:80 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 81:81 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; graftcode_support_demo &lt;span class="se"&gt;\&lt;/span&gt;
  customer-support-ai:test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the MCP endpoint is already live. You haven't written an MCP server, defined a tool, or written an OpenAPI spec.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Inspect the Service with Graftcode Vision
&lt;/h3&gt;

&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:81/GV
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the methods Gateway found; &lt;code&gt;SupportService&lt;/code&gt;, &lt;code&gt;getCustomerProfile&lt;/code&gt;, &lt;code&gt;getSubscriptionDetails&lt;/code&gt;, and &lt;code&gt;searchKnowledgeBase&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vision also lets you try each method directly, so you can confirm what's exposed before connecting an AI agent.&lt;/p&gt;

&lt;p&gt;Graftcode Vision is useful because it allows developers to inspect what the Gateway has actually discovered. It also lets you try each method directly, so you can confirm what's exposed before connecting an AI agent.&lt;/p&gt;

&lt;p&gt;Before integrating a frontend application or AI client, you can verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which classes are exposed&lt;/li&gt;
&lt;li&gt;Which methods are callable&lt;/li&gt;
&lt;li&gt;Which parameters they accept&lt;/li&gt;
&lt;li&gt;What values they return&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a feedback loop that is much easier than repeatedly modifying prompts or MCP configurations while debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Connect an AI Client
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cursor.&lt;/strong&gt; Add this to &lt;code&gt;.cursor/mcp.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"customer-support"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:81/mcp"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude Desktop.&lt;/strong&gt; Claude Desktop only supports stdio, and Gateway exposes MCP over HTTP, so bridge the two with &lt;code&gt;mcp-remote&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"customer-support"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:81/mcp"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the client after saving the config.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Test and Query the Agent
&lt;/h3&gt;

&lt;p&gt;Ask your AI client: “What subscription does customer-1001 have?”&lt;/p&gt;

&lt;p&gt;The agent should call &lt;code&gt;getSubscriptionDetails("customer-1001")&lt;/code&gt; and return the real result from your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"customer-1001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Professional"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"billingCycle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"monthly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"renewalDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try asking a question that needs more than one method; for example, “What plan is customer-1001 using, when does it renew, and how do renewals work?&lt;/p&gt;

&lt;p&gt;To answer that, the agent needs to call &lt;code&gt;getSubscriptionDetails()&lt;/code&gt; and &lt;code&gt;searchKnowledgeBase()&lt;/code&gt;, then combine the results. If it does, your setup is working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices and Tips for Graftcode and MCP
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep the exposed surface small.&lt;/strong&gt; Use &lt;code&gt;--types&lt;/code&gt; and &lt;code&gt;--methods&lt;/code&gt; to expose only what the agent actually needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't skip authorization.&lt;/strong&gt; Graftcode removes integration plumbing, not the need for access control. Decide carefully which methods, like account deletion, should never be exposed to an agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a Project Key outside local development.&lt;/strong&gt; It gives you a stable MCP URL, a stable registry URL, portal visibility, and access control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let the backend stay the source of truth.&lt;/strong&gt; Update the method, not a separate tool definition or prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Use Cases for Graftcode
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Customer support tools that need real account and subscription data&lt;/li&gt;
&lt;li&gt;Assistants built around an existing knowledge base or documentation system&lt;/li&gt;
&lt;li&gt;Operational tooling that calls existing internal services instead of duplicating their logic&lt;/li&gt;
&lt;li&gt;AI features added to an existing SaaS app without rewriting the backend that already powers it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;MCP gives AI agents a standard way to call external tools, but building a custom MCP server for every backend adds a second integration layer to maintain. Graftcode starts from the backend instead. Write the capability once, host it through Gateway, and let both regular applications and AI agents call the same methods.&lt;/p&gt;

&lt;p&gt;The interesting part of MCP is not the protocol itself; it’s rather what it enables. Agents become more useful when they can work with systems instead of relying so much on prompts and fine-tuned data.&lt;/p&gt;

&lt;p&gt;Instead of building a custom MCP and connecting it to existing agents, developers can now expose existing business logic with Graftcode Gateway. Those capabilities become available to both traditional applications and AI agents while keeping your backend/logic as the source of truth.&lt;/p&gt;

&lt;p&gt;For teams already maintaining customer services, internal tools, knowledge bases, billing systems, or operational platforms, this can reduce the amount of integration work required when introducing AI capabilities into an existing application stack.&lt;/p&gt;

&lt;p&gt;If you already have backend functionality an AI agent could use, try exposing one of your own services through Graftcode's MCP quick start.&lt;/p&gt;

</description>
      <category>aiops</category>
      <category>ai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Top 5 AI Governance Tools for Enterprises (2026)</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Mon, 14 Sep 2026 13:29:28 +0000</pubDate>
      <link>https://dev.to/coderoflagos/top-5-ai-governance-tools-for-enterprises-2026-d2g</link>
      <guid>https://dev.to/coderoflagos/top-5-ai-governance-tools-for-enterprises-2026-d2g</guid>
      <description>&lt;p&gt;AI governance has already become one of the most important parts of running AI in production. As enterprises deploy AI agents, retrieval systems, and LLM applications, they need ways to control access, manage risk, monitor behavior, apply policies, and prove compliance.&lt;/p&gt;

&lt;p&gt;The best AI governance tools help organizations answer a simple question: “Can we scale AI across the company properly?”&lt;/p&gt;

&lt;p&gt;If you're evaluating the best AI governance tools in 2026, these are the platforms that are worth looking at:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bifrost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise teams building AI applications that need governance at scale&lt;/td&gt;
&lt;td&gt;Free OSS + Custom Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Credo AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI compliance and risk programs&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fiddler AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI observability and model monitoring&lt;/td&gt;
&lt;td&gt;Free tier + Usage-based + Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OneTrust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise AI risk and compliance management&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speakeasy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI access governance and permissions management&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each of these platforms approaches AI governance from a different angle; each also has its own strengths. Some focus primarily on compliance and risk management, while others focus on observability, access control, or the infrastructure layer that processes AI requests.&lt;/p&gt;

&lt;p&gt;Of all the platforms in this guide, Bifrost has a different approach to AI governance. It goes beyond governance workflows and compliance documentation; it works as an AI gateway that sits between applications and AI providers, allowing organizations to enforce policies, access controls, routing rules, and observability directly in the request path.&lt;/p&gt;

&lt;p&gt;Bifrost is also open source, allowing teams to inspect the implementation and contribute through the GitHub repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  How We Compared These Tools
&lt;/h2&gt;

&lt;p&gt;We looked at each tool from the perspective of an enterprise team that needs to control how AI is used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Governance coverage&lt;/strong&gt;: does it provide controls for AI inventory, policies, risk management, approvals, and ongoing governance rather than focusing on only one part of the AI stack?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access and policy enforcement&lt;/strong&gt;: can teams control which users, teams, applications, and models, and enforce those policies at runtime?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and compliance&lt;/strong&gt;: does it help organizations manage sensitive data, audit activity, maintain evidence, and align AI usage with frameworks?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability and Auditing&lt;/strong&gt;: can 88 see AI requests, model usage, costs, prompts, outputs, tool calls, and policy decisions, with enough logs to investigate what happened?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment and data control&lt;/strong&gt;: can the tools fit into an enterprise environment, and what data needs to leave the organization's environment?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing posture&lt;/strong&gt;: is pricing based on seats, AI inventory, usage, traces, or a custom enterprise agreement, and how predictable is that model as adoption grows?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational burden&lt;/strong&gt;: how much work is required to deploy, integrate, configure, and maintain the platform across an organization's existing AI stack?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Are AI Governance Tools?
&lt;/h2&gt;

&lt;p&gt;AI governance tools are platforms that help organizations manage the operational, security, compliance, and risk aspects of AI systems. They provide help managing AI models, applications, users, data, and vendors while giving security and compliance teams visibility into how AI is being used.&lt;/p&gt;

&lt;p&gt;Now, let’s have a look at the best AI governance tools, their features, pricing, and the teams they’re best fit for. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Bifrost
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Open-source AI gateway and enterprise control plane for LLMs, agents, and MCP tools&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing&lt;/strong&gt;: Bifrost has a free open-source edition for self-managed deployments. Enterprise pricing is custom, with a 14-day Enterprise trial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;: Self-hosted through Docker, Kubernetes, or a Go binary, with Enterprise deployment options including VPC, on-premises, and air-gapped environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vy5p6rjhvxxnw0i5izt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vy5p6rjhvxxnw0i5izt.png" alt="Bifrost Dashboard" width="799" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bifrost&lt;/strong&gt; provides a central gateway between applications and AI providers, where access, routing, budgets, and governance policies can be applied.&lt;/p&gt;

&lt;p&gt;Bifrost was developed by Maxim AI and takes an infra-level approach to AI governance. Instead of operating only as a risk or compliance system alongside the AI stack, Bifrost can sit between applications and AI providers and act as a control panel for model access, routing, budgets, observability, and policy enforcement.&lt;/p&gt;

&lt;p&gt;Bifrost extends its governance model beyond standard LLM requests. Its MCP Gateway provides a central place to manage MCP tool connections, authentication, security, and policy enforcement, which becomes increasingly relevant as AI agents gain the ability to interact with external systems. More details are available in the Bifrost documentation.&lt;/p&gt;

&lt;p&gt;The platform also provides OpenTelemetry support and built-in observability, alongside budgeting, provider fallback, virtual key management, and a unified interface for multiple AI providers. The current Bifrost site says the platform supports 25+ providers and more than 10,000 AI models, including custom-deployed models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Access profiles&lt;/strong&gt;: teams can create reusable policies defining permitted models, budgets, rate limits, and MCP tools, then attach those profiles to user roles, teams, or business units.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual keys&lt;/strong&gt;: each key can be restricted to specific providers, models, and MCP tools, while also being associated with a team or business unit for more controlled access and cost attribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RBAC and SSO&lt;/strong&gt;: Bifrost supports fine-grained roles and permissions and can connect to enterprise identity providers through SSO and SCIM provisioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budgets and rate limits&lt;/strong&gt;: organizations can establish spending limits across business units, teams, virtual keys, and providers, while rate limits can control token and request usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit logs&lt;/strong&gt;: requests can be recorded with details such as the user, virtual key, model, cost, and policy decision, with logs exportable to systems including S3, GCS, Datadog, and BigQuery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Gateway&lt;/strong&gt;: MCP connections can be centralized so organizations can apply governance, security, authentication, and tool-level policies instead of allowing every application to manage MCP access independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt;: OpenTelemetry support and built-in dashboards provide visibility into AI traffic and usage without requiring a separate observability layer for basic gateway monitoring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider fallback&lt;/strong&gt;: applications can automatically fail over between providers, helping maintain availability when a model or provider becomes unavailable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails&lt;/strong&gt;: Bifrost Enterprise includes guardrails designed to detect and block unsafe model outputs and enforce runtime policies across agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Strengths&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure-level governance gives engineering teams a central enforcement point between applications and AI providers.&lt;/li&gt;
&lt;li&gt;The open-source edition can be self-hosted, while Enterprise deployments can run in VPC, on-premises, or air-gapped environments, giving organizations full control over data, access, and execution while supporting enterprise security, policy enforcement, and governance requirements.&lt;/li&gt;
&lt;li&gt;Governance covers both model traffic and MCP tool usage, which makes the platform relevant to agentic AI architectures as well as conventional LLM applications.&lt;/li&gt;
&lt;li&gt;Budgeting, access control, virtual keys, routing, audit logs, and observability are handled through the same gateway rather than requiring separate controls in every application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't use if&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You primarily need an AI risk and compliance management system for maintaining AI inventories, risk assessments, regulatory mappings, and governance workflows rather than controlling runtime AI traffic.&lt;/li&gt;
&lt;li&gt;Your organization has only a small number of AI applications and models, so introducing a centralized gateway would add more infrastructure than value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Learn more about Bifrost
&lt;/h3&gt;

&lt;p&gt;Bifrost is available as an open-source project under Apache 2.0, with documentation covering gateway configuration, MCP governance, routing, observability, virtual keys, and deployment options. You can check the OSS version on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Credo AI
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;AI governance and risk management for enterprise AI systems&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Custom enterprise pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; Depends on the organization’s AI inventory, governance workflows, and integrations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo3kk8zw1wjf6skk917rb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo3kk8zw1wjf6skk917rb.jpg" alt="Credo AI Dashboard" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credo AI&lt;/strong&gt; is focused on governing AI across its lifecycle, from discovery and inventory through risk assessment, policy management, compliance, monitoring, and reporting. Its platform provides a centralized registry for AI systems, models, agents, applications, vendors, and shadow AI, giving governance teams a single place to track what is being used across the organization.&lt;/p&gt;

&lt;p&gt;The platform also provides policy packs and risk workflows mapped to different frameworks. Credo AI supports governance workflows such as approvals, risk assessments, evidence generation, and continuous monitoring, making it more focused on enterprise AI governance and risk management than on being an AI gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI inventory:&lt;/strong&gt; Centralizes models, applications, agents, vendors, and other AI systems so teams can see what is being used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk management:&lt;/strong&gt; Provides AI-specific risk assessments, risk registers, controls, and mitigation workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy and compliance:&lt;/strong&gt; Maps governance requirements to major frameworks and provides policy packs and audit-ready evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise governance:&lt;/strong&gt; Supports governance workflows across AI, data, compliance, and business teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Don’t use if
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You mainly need runtime AI traffic control:&lt;/strong&gt; Credo AI is primarily a governance and risk platform rather than an infrastructure gateway for routing model requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need a lightweight developer observability tool:&lt;/strong&gt; Its broader governance workflow may be more than a small engineering team needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployment options:&lt;/strong&gt; Enterprise SaaS and integrations with existing AI, data, security, and governance tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Fiddler AI
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;AI observability, evaluation, and runtime safety&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier; Developer is &lt;strong&gt;$0.002 per trace&lt;/strong&gt;; Enterprise pricing is custom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; Depends on the integrations and deployment model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhwgmayvr43cbuw3cc2d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhwgmayvr43cbuw3cc2d3.png" alt="Fiddler AI Dashboard" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fiddler&lt;/strong&gt; focuses on understanding how AI systems behave in production. Its platform provides AI observability, testing, experiments, custom evaluators, and visualization for AI applications and agentic systems.&lt;/p&gt;

&lt;p&gt;It also provides runtime guardrails for risks including hallucinations, toxicity, PII/PHI exposure, prompt injection, and jailbreak attempts. Enterprise customers can use SaaS, VPC, or on-premises deployment options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI observability:&lt;/strong&gt; Gives teams visibility into AI behavior and performance across production systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime guardrails:&lt;/strong&gt; Detects risks such as hallucinations, PII/PHI, prompt injection, and jailbreak attempts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation workflows:&lt;/strong&gt; Supports tests, experiments, custom evaluators, and bring-your-own judges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise deployment:&lt;/strong&gt; Enterprise supports SaaS, VPC, and on-premises deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Don’t use if
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need a full AI governance registry:&lt;/strong&gt; Fiddler is more focused on observability, evaluation, and safety than enterprise AI inventory and regulatory governance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need an AI gateway:&lt;/strong&gt; Fiddler is not primarily designed as a centralized model/provider routing layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployment options:&lt;/strong&gt; SaaS, VPC, or on-premises for Enterprise.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. OneTrust
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enterprise AI inventory, risk, compliance, and runtime governance&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Custom pricing, based on admin users and AI inventory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; Depends on the scope of the AI governance program and integrations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fai8iaosvakf5gfdutq4j.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fai8iaosvakf5gfdutq4j.webp" alt="OneTrust Dashboard" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OneTrust&lt;/strong&gt; brings AI discovery, inventory, risk assessment, policy management, monitoring, and compliance workflows into one platform. It can track AI systems, models, agents, datasets, vendors, projects, and use cases, while applying risk assessments and governance workflows across the AI lifecycle.&lt;/p&gt;

&lt;p&gt;OneTrust also extends governance into runtime environments. Its capabilities include monitoring AI behavior, detecting sensitive data and policy violations, applying controls to prompts and outputs, and governing agent permissions and MCP tool access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI inventory:&lt;/strong&gt; Provides a central system of record for AI systems, models, agents, datasets, and vendors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk and compliance:&lt;/strong&gt; Supports frameworks including the EU AI Act, NIST AI RMF, and ISO 42001.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance workflows:&lt;/strong&gt; Provides intake, approvals, attestations, evaluation gates, and audit-ready evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime controls:&lt;/strong&gt; Can detect policy violations and apply actions such as blocking, allowing, redacting, escalating, or routing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Don’t use if
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You only need an AI gateway:&lt;/strong&gt; OneTrust's broader governance and risk capabilities may be unnecessary if the main requirement is model routing and spend control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want a developer-first observability platform:&lt;/strong&gt; Its focus is broader enterprise governance rather than AI observability alone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployment options:&lt;/strong&gt; Enterprise deployment with integrations into supported AI platforms and runtime environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Speakeasy
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;AI control plane for agents, MCP servers, tools, and enterprise access&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Enterprise pricing is tailored to the organization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; Speakeasy says most teams can be up and running within a day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsqjdyjeqrsn0bxtet7ub.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsqjdyjeqrsn0bxtet7ub.jpg" alt="Speakeasy Dashboard" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speakeasy&lt;/strong&gt; takes an access-control approach to AI governance. Its control plane provides a catalog of approved agents, MCP servers, and Skills, while access can be scoped by team and role through an organization's existing identity provider. Every governed action can be recorded in an audit trail.&lt;/p&gt;

&lt;p&gt;The platform also checks prompts, responses, and tool calls against policy in real time. Speakeasy is designed to enforce least-privilege access for agents and can block threats such as prompt injection, PII exposure, and leaked credentials before they reach connected systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent access control:&lt;/strong&gt; Gives each agent an identity and controls what it can access based on roles and policies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP governance:&lt;/strong&gt; Provides a governed path for MCP servers and tools used by AI agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime enforcement:&lt;/strong&gt; Checks prompts, responses, and tool calls against policy before actions reach connected systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditability:&lt;/strong&gt; Records allow-or-deny decisions and agent activity for investigation and compliance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Don’t use if
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need a traditional AI GRC platform:&lt;/strong&gt; Speakeasy is focused on AI access, security, agents, and runtime control rather than being a broad AI risk-management registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You mainly need model evaluation:&lt;/strong&gt; Its core strength is controlling AI access and actions rather than model-quality evaluation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployment options:&lt;/strong&gt; Cloud or self-hosted deployment, including deployment in an organization's own cloud or on-premises environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison of AI Governance Tools
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Tool&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Best fit&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;AI governance capabilities&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Runtime / policy enforcement&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Deployment options&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Pricing posture&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bifrost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise teams that need AI gateway, governance, observability, and runtime policy enforcement&lt;/td&gt;
&lt;td&gt;Model access, virtual keys, RBAC, budgets, rate limits, audit logs, MCP governance, observability, and guardrails&lt;/td&gt;
&lt;td&gt;✅ Yes, policies can be enforced before AI requests reach providers&lt;/td&gt;
&lt;td&gt;Self-hosted; Enterprise VPC, on-prem, and air-gapped&lt;/td&gt;
&lt;td&gt;Free/open source; Enterprise custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Credo AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise AI governance and risk programs&lt;/td&gt;
&lt;td&gt;AI inventory, agent registry, risk management, policy packs, compliance, monitoring, governance workflows&lt;/td&gt;
&lt;td&gt;✅ Governance policies, controls, and trace-level policy enforcement&lt;/td&gt;
&lt;td&gt;Enterprise platform with integrations across the AI stack&lt;/td&gt;
&lt;td&gt;Custom enterprise pricing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fiddler AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI observability, evaluation, and runtime safety&lt;/td&gt;
&lt;td&gt;AI observability, evaluations, tests, experiments, custom evaluators, guardrails&lt;/td&gt;
&lt;td&gt;✅ Real-time guardrails for hallucinations, toxicity, PII/PHI, prompt injection, and jailbreaks&lt;/td&gt;
&lt;td&gt;SaaS; Enterprise VPC or on-premises&lt;/td&gt;
&lt;td&gt;Free; $0.002/trace Developer; Enterprise custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OneTrust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise AI inventory, risk, compliance, and runtime governance&lt;/td&gt;
&lt;td&gt;AI inventory, risk assessment, policy management, approvals, monitoring, audit evidence&lt;/td&gt;
&lt;td&gt;✅ Runtime controls across prompts, outputs, data access, and AI actions&lt;/td&gt;
&lt;td&gt;Enterprise deployment with integrations into AI environments&lt;/td&gt;
&lt;td&gt;Custom; based on admin users and AI inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speakeasy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI agents, MCP tools, and enterprise AI access control&lt;/td&gt;
&lt;td&gt;MCP governance, tool catalog, RBAC, identity, audit trails, observability, threat detection&lt;/td&gt;
&lt;td&gt;✅ Real-time inspection and policy enforcement across prompts, responses, and tool calls&lt;/td&gt;
&lt;td&gt;Cloud; self-hosted data plane in your VPC&lt;/td&gt;
&lt;td&gt;Made for enterprises only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pricing note:&lt;/strong&gt; Pricing and packaging change frequently, particularly for usage-based products and enterprise agreements. The figures above reflect publicly available vendor information checked in September 2026. Verify the current vendor pricing page before buying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which AI Governance Tool Should You Choose?
&lt;/h2&gt;

&lt;p&gt;The right platform depends on where governance challenges exist inside your organization.&lt;/p&gt;

&lt;p&gt;If compliance documentation and regulatory alignment are your biggest concerns, Credo AI and OneTrust are likely strong candidates.&lt;/p&gt;

&lt;p&gt;If monitoring and production visibility matter most, Fiddler is difficult to ignore.&lt;/p&gt;

&lt;p&gt;If access governance is your primary objective, Speakeasy deserves consideration.&lt;/p&gt;

&lt;p&gt;For engineering teams building AI products, agents, and infrastructure, Bifrost offers a different perspective. Instead of focusing exclusively on compliance workflows, it introduces governance directly into the AI request path where costs, permissions, routing decisions, observability, and policy enforcement can be managed centrally.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What are AI governance tools?
&lt;/h3&gt;

&lt;p&gt;AI governance tools help organizations manage AI risk, security, compliance, observability, and operational controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do enterprises need AI governance?
&lt;/h3&gt;

&lt;p&gt;Governance helps organizations safely scale AI usage while maintaining compliance, visibility, and control.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between AI governance and AI observability?
&lt;/h3&gt;

&lt;p&gt;Governance focuses on policies, controls, and compliance. Observability focuses on monitoring system behavior and performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the best AI governance tool?
&lt;/h3&gt;

&lt;p&gt;The best choice depends on your team’s priorities. Compliance teams often evaluate Credo AI and OneTrust. Observability teams evaluate Fiddler. Infrastructure teams often evaluate Bifrost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can AI governance tools reduce AI costs?
&lt;/h3&gt;

&lt;p&gt;Yes. Many platforms include budgets, quotas, spending controls, and cost monitoring. For example, Bifrost includes budgeting, virtual keys, rate limits, and provider-level controls that can help organizations manage AI spend across teams and applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do AI governance tools support AI agents?
&lt;/h3&gt;

&lt;p&gt;Most times, yes (depending on the tool). Modern governance platforms are starting to have models that support agents and MCP-based workflows. For example, Bifrost includes MCP governance capabilities designed to help organizations manage how agents access external tools and systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are AI governance tools required for compliance?
&lt;/h3&gt;

&lt;p&gt;While not always legally required, they can significantly simplify regulatory compliance and audit preparation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can startups benefit from AI governance?
&lt;/h3&gt;

&lt;p&gt;Yes. Governance helps organizations establish good operational practices before AI usage scales. Platforms like Bifrost introduce controls such as budgets, access policies, observability, and auditability early, making growth easier to manage later.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Calling a TypeScript Backend Without Integration Code - A Simple Task Tracker with Graftcode</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Thu, 20 Aug 2026 09:26:08 +0000</pubDate>
      <link>https://dev.to/coderoflagos/calling-a-typescript-backend-without-integration-code-a-simple-task-tracker-with-graftcode-1n7e</link>
      <guid>https://dev.to/coderoflagos/calling-a-typescript-backend-without-integration-code-a-simple-task-tracker-with-graftcode-1n7e</guid>
      <description>&lt;p&gt;Most developers building frontend applications spend a lot of time writing code that communicates with their backend due to the traditional approach (using APIs).&lt;/p&gt;

&lt;p&gt;This is not because the logic is hard to implement, but because the communication itself is complex. When using standard APIs, we build routes, define request and response models, generate clients, and keep multiple layers on track with application updates.&lt;/p&gt;

&lt;p&gt;Instead of exposing backend functionality through REST endpoints and consuming it through HTTP clients, Graftcode exposes backend methods directly and generates packages that applications can install and use as dependencies. The result is a communication model that is like you are calling a library rather than consuming an API with strongly typed clients. Working with Graftcode is very simple: &lt;strong&gt;install&lt;/strong&gt; your library and &lt;strong&gt;call&lt;/strong&gt; its functions.&lt;/p&gt;

&lt;p&gt;In this article, we'll be building a simple task tracker or to-do list application using React and a TypeScript backend to see what working with Graftcode looks like.&lt;/p&gt;

&lt;p&gt;In this blog post, we will learn the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why API layers require you to maintain APIs manually&lt;/li&gt;
&lt;li&gt;How Graftcode exposes backend functionality through Graftcode Gateway&lt;/li&gt;
&lt;li&gt;How Graftcode Vision helps discover backend capabilities&lt;/li&gt;
&lt;li&gt;Familiarity with APIs and &lt;code&gt;fetch()&lt;/code&gt; requests&lt;/li&gt;
&lt;li&gt;How React applications can use TypeScript backend logic without building API routes&lt;/li&gt;
&lt;li&gt;Why strongly-typed backend packages can improve developer experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;Let’s get our hands a bit dirty, but before we do, there are some need-to-haves to get you started. Let’s have a look at that in this section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latest Node version installed on your machine&lt;/li&gt;
&lt;li&gt;Basic knowledge of React and TypeScript&lt;/li&gt;
&lt;li&gt;Familiarity with how APIs and fetch requests work (for understanding how easy Graftcode’s approach is)&lt;/li&gt;
&lt;li&gt;A Graftcode account&lt;/li&gt;
&lt;li&gt;Graftcode gateway installed on your local machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these prerequisites, you’ll first understand why most to-do list applications rely heavily on APIs for their logic and what challenges that approach can introduce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do To-Do List Applications Rely on APIs?
&lt;/h2&gt;

&lt;p&gt;To-do list applications require some logic for functionality. However, most developers are familiar with exposing backend functionality through APIs and consuming that functionality from frontend applications. As much as task management applications are easy to build, they are also one of the most common examples of frontend-backend communication.&lt;/p&gt;

&lt;p&gt;The reason why even a simple to-do application needs logic is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create tasks&lt;/li&gt;
&lt;li&gt;Retrieve tasks&lt;/li&gt;
&lt;li&gt;Update task status&lt;/li&gt;
&lt;li&gt;Delete tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a to-do list application that uses an API, the frontend doesn't communicate directly with the logic responsible for creating, updating, or retrieving tasks. Instead, every interaction goes through different layers before reaching the actual functionality.&lt;/p&gt;

&lt;p&gt;When a user creates a task, the frontend typically sends a request using the &lt;code&gt;fetch()&lt;/code&gt; function or another HTTP client. That request is received by an API endpoint, processed by a controller or route handler, forwarded to the appropriate business logic, and often persisted to a database before a response is returned to the user.&lt;/p&gt;

&lt;p&gt;This architecture is widely used in the developer ecosystem and works well,  but it also means developers need to maintain more than just the feature they’re trying to implement. Every new feature often requires additional routes, request validation, response handling, documentation updates, and frontend integration work. As applications grow, the communication layer can even become as complicated as the initial logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fydntq5bbuib7frucxrfe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fydntq5bbuib7frucxrfe.png" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For context: when working with APIs, some endpoints get exposed - here are examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POST /tasks&lt;/li&gt;
&lt;li&gt;GET /tasks&lt;/li&gt;
&lt;li&gt;PATCH /tasks/{id}&lt;/li&gt;
&lt;li&gt;DELETE /tasks/{id}&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Delving into Graftcode
&lt;/h1&gt;

&lt;p&gt;Rather than creating another application with traditional APIs, we'll build a task tracker that communicates directly with backend functionality exposed through Graftcode (a tool that runs your backend as a package).&lt;/p&gt;

&lt;p&gt;The application will allow users to create new tasks, view existing tasks, mark tasks as completed, delete tasks, and view task status updates instantly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fonbvd3vxci3irdvxyih6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fonbvd3vxci3irdvxyih6.png" alt="Task Tracker output" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal isn't necessarily to build the most advanced task management application. But rather to understand how a React frontend can interact with backend logic without building API routes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use Case for Graftcode: To-do List Application with Graftcode
&lt;/h1&gt;

&lt;p&gt;In this section, we’ll take a look at how to work with Graftcode and when you should use it.&lt;/p&gt;

&lt;p&gt;Graftcode works particularly well when frontend and backend applications are developed together and benefit from a strongly typed integration layer. Instead of maintaining API routes, request models, and generated clients, developers can consume backend functionality through generated packages. &lt;/p&gt;

&lt;p&gt;This can be useful for internal tools, full-stack applications, prototypes, and systems where backend functionality is primarily consumed by trusted applications.&lt;/p&gt;

&lt;p&gt;We will be building a task tracker application without writing API routes, controllers, or integration boilerplate. To be clear, we need to create a project first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;vite&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;latest&lt;/span&gt; &lt;span class="nx"&gt;graftcode&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;todolist&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;graftcode&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;todolist&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;
&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt;
&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;tailwindcss&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;tailwindcss&lt;/span&gt;&lt;span class="sr"&gt;/vit&lt;/span&gt;&lt;span class="err"&gt;e
&lt;/span&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;vite&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;polyfills&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, you need to update your &lt;code&gt;vite.config.ts&lt;/code&gt; to enable the polyfills.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;tailwindcss&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tailwindcss/vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nodePolyfills&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite-plugin-node-polyfills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;tailwindcss&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;nodePolyfills&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/crypto-shim.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;src/index.css&lt;/code&gt;, put this code there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, create a &lt;code&gt;crypto-shim.js&lt;/code&gt; file in the  &lt;code&gt;src/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomUUID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;randomUUID&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Create the Backend Module&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, this is where everything begins. We need to work on configuring the backend module.&lt;/p&gt;

&lt;p&gt;Let's start with the backend service that will manage our tasks. Inside the project folder, create a &lt;code&gt;task-backend/&lt;/code&gt; directory and initialize it for the project’s backend logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;task-backend
&lt;span class="nb"&gt;cd &lt;/span&gt;task-backend
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After initializing the backend project, we need to tell Graftcode Gateway where the backend entry point is located.&lt;/p&gt;

&lt;p&gt;The gateway reads the &lt;code&gt;main&lt;/code&gt; field from &lt;code&gt;package.json&lt;/code&gt; to find and load your backend service. Since our service will live inside &lt;code&gt;backend/index.js&lt;/code&gt;, update your &lt;code&gt;package.json&lt;/code&gt; file and add the following &lt;code&gt;main&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;task-backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./backend/index.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the backend/ directory, create an &lt;code&gt;index.ts&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;randomUUID&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaskService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;createTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getTasks&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;completeTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;deleteTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s the entire backend logic for the to-do list application. As you can see, it’s very straightforward - we didn’t have to call any APIs, define routes, nor requests. Instead, we're focusing on the capabilities the application actually needs.&lt;/p&gt;

&lt;p&gt;We defined the &lt;code&gt;TaskService&lt;/code&gt; class with static methods. The class keeps tasks in memory, creates new tasks with a UUID, returns the full list, marks a task as complete, and deletes tasks when needed. Because everything lives in one exported class, Graftcode can expose those methods directly without us defining controllers or routes around them.&lt;/p&gt;

&lt;p&gt;The service exposes four methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;createTask()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getTasks()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deleteTask()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;completeTask()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Exposing the Service Through Graftcode Gateway
&lt;/h1&gt;

&lt;p&gt;Now that the backend logic exists, the next thing is to find a way for other applications to use it. In Graftcode, the way to do this is to use its gateway.&lt;/p&gt;

&lt;p&gt;Graftcode Gateway (gg) is the runtime that exposes your application's public methods for consumption. It can be installed using the official Docker image or directly from the releases page on the Graftcode Gateway GitHub repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gg ./package.json &lt;span class="nt"&gt;--projectKey&lt;/span&gt; YOUR_PROJECT_KEY &lt;span class="nt"&gt;--port&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get the project key, do the following in your Graftcode dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to the &lt;strong&gt;Vision&lt;/strong&gt; panel&lt;/li&gt;
&lt;li&gt;Create a new gateway&lt;/li&gt;
&lt;li&gt;In the deployment options section, hit the “&lt;strong&gt;I already have Graftcode Gateway&lt;/strong&gt;” button: This skips the download process and automatically generates a new project key for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbrf91fhq0d6iabpb4qe2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbrf91fhq0d6iabpb4qe2.png" alt="Deploy logic" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The gateway reads your &lt;code&gt;package.json&lt;/code&gt;, finds the &lt;code&gt;main&lt;/code&gt; entry point, loads &lt;code&gt;TaskService&lt;/code&gt;, and registers all four methods automatically.&lt;/p&gt;

&lt;p&gt;Once running, the gateway prints the exact install command for your project. The package name is generated automatically by the gateway. Copy the exact install command printed in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--registry&lt;/span&gt; https://grft.dev/YOUR_PROJECT_ID__graftcode @graft/npm-task-backend@1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the command exactly as printed, alongside the project ID in the URL, which is specific to your account.&lt;/p&gt;

&lt;p&gt;Once the gateway is running, open the Graftcode Vision URL displayed in the terminal output. This launches Graftcode Vision, where you can inspect your backend classes, methods, and installation details.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exploring Your Backend In Graftcode Vision
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Graftcode Vision&lt;/strong&gt; is the discovery layer for your backend. Instead of reading through Swagger docs or manually checking endpoint definitions, you can inspect the actual classes, package installation, and methods exposed by the service in Graftcode Vision.&lt;/p&gt;

&lt;p&gt;When Vision loads, you should see your &lt;code&gt;TaskService&lt;/code&gt; class and the methods it provides.&lt;/p&gt;

&lt;p&gt;In Graftcode Vision, you can inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installation/Configuration&lt;/li&gt;
&lt;li&gt;Available methods&lt;/li&gt;
&lt;li&gt;Parameters&lt;/li&gt;
&lt;li&gt;Return types&lt;/li&gt;
&lt;li&gt;Method descriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9l89q0eyhvfgkva9n5c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9l89q0eyhvfgkva9n5c.png" alt="Methods in Graftcode" width="799" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the Configured Package
&lt;/h2&gt;

&lt;p&gt;In the project’s root, configure the &lt;code&gt;@graft&lt;/code&gt; registry so npm knows where to find the generated package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"@graft:registry=https://grft.dev/YOUR_PROJECT_ID__graftcode"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to always replace your actual project ID as shown in your Graftcode portal. Then install the generated package using the exact command the gateway printed when it started - so this is wrapped into Graftcode now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--registry&lt;/span&gt; https://grft.dev/YOUR_PROJECT_ID__graftcode @graft/npm-task-backend@1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also test methods directly before connecting them to your frontend. That becomes useful as your service grows and exposes more functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the React Frontend
&lt;/h2&gt;

&lt;p&gt;Now that the backend is ready, let's build the frontend. In your &lt;code&gt;App.tsx&lt;/code&gt; file, import the generated package and configure the gateway host. You can have a look at your Graftcode Vision’s configuration and find the best route for importing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GraftConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graft/npm-task-backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`ws://localhost:8080/ws`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;GraftConfig.host&lt;/code&gt; is the WebSocket URL of your running gateway. Ensure the backend is currently running in a separate terminal. That is the entire connection setup you need to work with Graftcode. You don’t need any base URLs, HTTP clients, or middleware.&lt;/p&gt;

&lt;p&gt;After doing this, all you need to do is call your backend methods like regular functions in your frontend. You can paste this in your &lt;code&gt;App.tsx&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graft/npm-task-backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://localhost:8080/ws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchTasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the frontend loads, it automatically calls &lt;code&gt;fetchTasks()&lt;/code&gt; to get the current list of tasks from &lt;code&gt;TaskService.getTasks()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With the backend connection in place, we can build the rest of the task tracker. The complete App.tsx file below uses the generated Graft package to retrieve tasks, create new ones, mark them as completed, and delete existing items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graft/npm-task-backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://localhost:8080/ws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;submitting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSubmitting&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;actionLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActionLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchTasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getTasks error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to fetch tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetchTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;setSubmitting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

      &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to create task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setSubmitting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleComplete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setActionLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;completeTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to complete task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setActionLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDelete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setActionLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-delete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to delete task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setActionLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"min-h-screen bg-gray-50 p-5"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"max-w-lg mx-auto space-y-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Header */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center justify-between"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-lg font-semibold text-gray-900"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Task Tracker
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs text-gray-400"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; done
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Create Form */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;
          &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCreate&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-white border border-gray-200 rounded-xl p-4 space-y-2"&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
            &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Task title"&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-full bg-gray-50 border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:outline-none focus:border-gray-400 transition-colors"&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
            &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Description (optional)"&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-full bg-gray-50 border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-900 placeholder-gray-400 focus:outline-none focus:border-gray-400 transition-colors"&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;
            &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-full bg-gray-900 hover:bg-gray-700 disabled:opacity-30 text-white py-2 rounded-lg text-sm font-medium transition-colors"&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Adding...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add Task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Error */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs text-red-500 px-1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Task List */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"space-y-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-center text-gray-400 text-sm py-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              No tasks yet.
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
              &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`bg-white border border-gray-200 rounded-xl px-4 py-3 flex items-center gap-3 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
                &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;opacity-50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Complete */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
                &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
                  &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;handleComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
                  &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
                  &lt;span class="nx"&gt;actionLoading&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-shrink-0"&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-4 h-4 rounded-full bg-gray-900 flex items-center justify-center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;
                      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-2.5 h-2.5 text-white"&lt;/span&gt;
                      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
                      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
                      &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                      &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
                        &lt;span class="na"&gt;strokeLinecap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
                        &lt;span class="na"&gt;strokeLinejoin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
                        &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M5 13l4 4L19 7"&lt;/span&gt;
                      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-4 h-4 rounded-full border-2 border-gray-300 hover:border-gray-500 transition-colors"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Content */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1 min-w-0"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
                  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`text-sm &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
                    &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;
                      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line-through text-gray-400&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-gray-900&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs text-gray-400 truncate"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Delete */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
                &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleDelete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
                  &lt;span class="nx"&gt;actionLoading&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-delete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-300 hover:text-red-400 disabled:opacity-30 transition-colors flex-shrink-0"&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;
                  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-4 h-4"&lt;/span&gt;
                  &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
                  &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
                  &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
                    &lt;span class="na"&gt;strokeLinecap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
                    &lt;span class="na"&gt;strokeLinejoin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
                    &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M6 18L18 6M6 6l12 12"&lt;/span&gt;
                  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app lets users create, complete, and delete tasks by calling the backend methods like &lt;code&gt;createTask()&lt;/code&gt;, &lt;code&gt;completeTask()&lt;/code&gt;, and &lt;code&gt;deleteTask()&lt;/code&gt; Instead of using API requests via &lt;code&gt;fetch()&lt;/code&gt;. After each action, it refreshes the task list so the UI stays up to date. It also handles loading and error states, so the user gets feedback while actions are happening.&lt;/p&gt;

&lt;p&gt;After this, you can run your frontend in a separate terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have this UI in your browser and should be able to create tasks, delete them, and check if they are complete:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flx69lnw6lcukwo3bszul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flx69lnw6lcukwo3bszul.png" alt="Task Tracker basic image" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What really stands out here is how little friction there is between the frontend and backend. With Graftcode, the backend feels less like a separate system you have to manually integrate with and more like a typed extension of your app. That means less boilerplate, fewer moving parts, and a much smoother development experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Breakdown
&lt;/h2&gt;

&lt;p&gt;At a high level, the entire application follows a straightforward flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initialize the backend connection by setting the Graftcode host.&lt;/li&gt;
&lt;li&gt;Define the task shape with a TypeScript interface so the UI knows what data to expect.&lt;/li&gt;
&lt;li&gt;Call backend methods directly to create, complete, and delete tasks.&lt;/li&gt;
&lt;li&gt;Refresh the UI after each action so the displayed data always matches the backend state.&lt;/li&gt;
&lt;li&gt;Show loading and error feedback to keep the experience clear and responsive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What makes this approach compelling is that the frontend never has to manage API routes, write request wrappers, or keep track of endpoint URLs. Instead, it interacts with backend functionality in a much more direct way, which keeps the component focused on UI behavior rather than network plumbing.&lt;/p&gt;

&lt;p&gt;That’s a big deal if you’ve ever spent too much time stitching together frontend and backend code just to move data around. Graftcode removes a lot of that friction. For teams that want to move faster without sacrificing type safety, that’s a pretty attractive tradeoff.&lt;/p&gt;

&lt;p&gt;An interesting fact about using Graftcode is its developer experience: the fact that you’re able to select classes and methods from the IDE with the code completion feature in IDEs, which even makes it easy for people to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqmrzi2ptanlbho5vi1z8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqmrzi2ptanlbho5vi1z8.png" alt="Autocompletion in Graftcode" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that’s it; we’ve built a simple task tracker that shows how React can work directly with a TypeScript backend through Graftcode without the usual API layer in between.&lt;/p&gt;

&lt;p&gt;Instead of spending time creating routes, controllers, request handlers, and client-side &lt;code&gt;fetch()&lt;/code&gt; calls, we were able to expose backend functionality as methods and use them like a package. That makes the development experience feel direct, especially for applications where frontend and backend are tightly connected.&lt;/p&gt;

&lt;p&gt;What is incredible is how you don’t need much setup once the backend is exposed via Graftcode Gateway. As mentioned in this blog post, with Graftcode Vision, you can inspect the available methods, understand their inputs and outputs, and install the generated package into your frontend with strong typing and better discoverability. That means less guessing, fewer integration bugs, and a much nicer developer experience overall.&lt;/p&gt;

&lt;p&gt;By extending this project, you’ll get a better feel for how Graftcode fits into real-world development workflows and where it can simplify your stack. The more you use it, the more obvious the benefits become: less boilerplate, stronger typing, faster iteration, and a cleaner path from backend logic to frontend UI.&lt;/p&gt;

&lt;p&gt;If you found this useful, try building your own small app with Graftcode and see how it changes the way you connect frontend and backend logic. Once you experience how direct the workflow feels, it’s pretty hard to go back to writing fetch calls for everything.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Stop Using Fetch() in React: A Better Way To Call Your Backend</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Mon, 25 May 2026 08:44:57 +0000</pubDate>
      <link>https://dev.to/coderoflagos/stop-using-fetch-in-react-a-better-way-to-call-your-backend-2a2e</link>
      <guid>https://dev.to/coderoflagos/stop-using-fetch-in-react-a-better-way-to-call-your-backend-2a2e</guid>
      <description>&lt;p&gt;Developers have an ‘unspoken struggle’ when communicating with APIs. When working on an interactive application, developers constantly need to communicate their frontend to their backend logic. &lt;/p&gt;

&lt;p&gt;The hassle of writing logic, connecting routes, and defining endpoints is a huge part of building that developers would prefer to avoid. With tools like &lt;a href="https://graftcode.com/" rel="noopener noreferrer"&gt;Graftcode&lt;/a&gt;, developers can install a strongly-typed backend package that connects directly to their backend, instead of manually writing API clients, routes, and endpoint integration code.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You’ll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Why using &lt;code&gt;fetch()&lt;/code&gt; can be a complex approach&lt;/li&gt;
&lt;li&gt;How Graftcode removes the need for building APIs&lt;/li&gt;
&lt;li&gt;How to expose your own backend logic through Graftcode Gateway&lt;/li&gt;
&lt;li&gt;How to call backend modules can be used in React applications as dependencies without writing APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This tutorial assumes the reader has the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;&lt;strong&gt;Node&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;&amp;gt;= 22 or higher installed on their local development machine&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/npx" rel="noopener noreferrer"&gt;&lt;strong&gt;npx&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;7.2 or higher is installed on their local development machine&lt;/li&gt;
&lt;li&gt;Basic understanding of how to work with &lt;code&gt;fetch()&lt;/code&gt; or REST APIs&lt;/li&gt;
&lt;li&gt;A basic knowledge of JavaScript and React&lt;/li&gt;
&lt;li&gt;A Stripe account with in test mode&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you have these prerequisites, you’re ready to begin this tutorial. In this blog post, you’ll learn how Graftcode works and how to use Graftcode as a connector between your React frontend and Node.js backend without manually building an API. This blog post/tutorial includes a demo that shows how to build an interactive application by just building your application’s logic through an imported backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Do Developers Still Use &lt;code&gt;fetch()&lt;/code&gt; in React?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most applications still rely on the regular pattern of using &lt;code&gt;fetch()&lt;/code&gt; or other HTTP clients. Here’s the most common approach React applications use when communicating with their backend:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A4800%2Fformat%3Awebp%2F1%2AKU5lQ359umDpPfyJ6ao0lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A4800%2Fformat%3Awebp%2F1%2AKU5lQ359umDpPfyJ6ao0lw.png" alt="Image from “**Automating APIs with JavaScript: How I Stopped Writing Endless Boilerplate” -** [Babar saad](https://sa82912045.medium.com/?source=post_page---byline--cdfbcc930a48---------------------------------------)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image Credit: &lt;a href="https://sa82912045.medium.com/?source=post_page---byline--cdfbcc930a48---------------------------------------" rel="noopener noreferrer"&gt;Babar saad&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach works, but it increases workload and introduces friction, and, unknowingly to most developers, it creates problems such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeated boilerplate for every endpoint&lt;/li&gt;
&lt;li&gt;Manual serialization and parsing&lt;/li&gt;
&lt;li&gt;Increased workload when building new features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;API layers are not necessary for many applications, but it’s common practice and introduces the issues listed above. &lt;/p&gt;

&lt;p&gt;There is an alternate way to call your backend apart from using &lt;code&gt;fetch()&lt;/code&gt; and other HTTP-based clients. With this option, you don’t need to worry about creating requests, API routes, and managing them. An alternate option is to use &lt;a href="https://graftcode.com" rel="noopener noreferrer"&gt;Graftcode&lt;/a&gt;, which is what this blog post will be all about.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Graftcode?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://graftcode.com/" rel="noopener noreferrer"&gt;Graftcode&lt;/a&gt; is a tool that lets you call backend functions and methods from another runtime without manually building REST APIs, writing HTTP client code, or creating custom SDKs. Instead of treating your backend as a collection of endpoints, Graftcode packages backend logic as a strongly-typed, installable dependency.&lt;/p&gt;

&lt;p&gt;Graftcode uses its Gateway to expose selected backend classes and methods and generates a package, called a &lt;strong&gt;Graft&lt;/strong&gt;, that you can install directly in your application. Once installed, you can import backend modules and call their methods like regular functions, while Graftcode handles the communication between your application and the backend runtime.&lt;/p&gt;

&lt;p&gt;This works whether your frontend and backend are written in different languages or the same language. When they are different, Graftcode bridges runtimes so one side can call methods from the other. When they are the same, as in this React and Node.js example, the main benefit is removing the manual REST/API layer, routes, and &lt;code&gt;fetch()&lt;/code&gt; calls between them.&lt;/p&gt;

&lt;p&gt;In practice, Graftcode changes how interactive applications are built. Instead of configuring endpoints, maintaining client code, and managing API integration logic, you expose backend methods through Graftcode Gateway, install the generated Graft package, import the module you need, and call the method directly.&lt;/p&gt;

&lt;p&gt;For example,  here’s a traditional way to call Stripe’s SDK with React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/create-intent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Stripe&lt;/span&gt; &lt;span class="nx"&gt;SDK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using Graftcode to call Stripe’s SDK through React, here’s what you do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;StripeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPaymentIntent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Graftcode, you just call functions; you do not need Express, routes, or even &lt;code&gt;fetch()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case for Graftcode: Stripe Dashboard without a REST API
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll take a look at how to work with Graftcode and when you should use it.&lt;/p&gt;

&lt;p&gt;We will be building an interactive Stripe dashboard in React. Yes - without a single API! This isn’t just a simple example; this is an interactive application that does three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a payment intent with Stripe&lt;/li&gt;
&lt;li&gt;Generate payment links&lt;/li&gt;
&lt;li&gt;List your most recent transactions&lt;/li&gt;
&lt;li&gt;Displays your Stripe’s revenue summary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these will be done without using a single REST endpoint. However, since we’re using Stripe Node.js SDK, which requires a secret key and cannot run in the browser, we will have the SDK as a backend and expose it through Graftcode Gateway.&lt;/p&gt;

&lt;p&gt;This section has been broken down into different steps to make it easy to understand how to build applications with Graftcode using React. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a React Project
&lt;/h2&gt;

&lt;p&gt;Firstly, we’ll create a React application from scratch using Vite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest graftcode-demo &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react
&lt;span class="nb"&gt;cd &lt;/span&gt;graftcode-demo
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Install Hypertube NodeJS SDK
&lt;/h2&gt;

&lt;p&gt;Navigate to the project within your CLI and install &lt;code&gt;hypertube-nodejs-sdk&lt;/code&gt; - It’s needed for the Websocket transport layer as it uses Node.js built-in features that don’t exist in the browser. Vite needs to polyfill them; to do this, install the SDK and the polyfill plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;hypertube-nodejs-sdk vite-plugin-node-polyfills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, you need to update your &lt;code&gt;vite.config.js&lt;/code&gt; to enable the polyfills.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nodePolyfills&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-node-polyfills&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;nodePolyfills&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/crypto-shim.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, create a &lt;code&gt;crypto-shim.js&lt;/code&gt; file in the  &lt;code&gt;src/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomUUID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;randomUUID&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: &lt;strong&gt;Create the Backend Module&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, this is where the real work begins; we need to work on configuring the backend module, as we can’t import certain backend modules like the one we want to work with, for now (Graftcode is in its beta version).&lt;/p&gt;

&lt;p&gt;Inside the project folder, create a &lt;code&gt;backend/&lt;/code&gt; directory and initialize it as its own Node.js project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;backend
&lt;span class="nb"&gt;cd &lt;/span&gt;backend
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;stripe dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the directory, create an &lt;code&gt;index.js&lt;/code&gt; file inside the &lt;code&gt;backend/&lt;/code&gt; directory with a class that has your Stripe logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stripe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createPaymentIntent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gbp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentIntents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createPaymentLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gbp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;unit_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;product_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;listTransactions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentIntents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment intent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getRevenueSummary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentIntents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;succeeded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;succeeded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;totalRevenue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;totalRevenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;avgTransaction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;totalRevenue&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;successRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;succeeded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;succeeded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StripeService&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippet above, the plan was to create a normal Node.js class without decorators, frameworks, and special annotations. The pattern is a class with static methods ****exported by name. That is how Graftcode discovers and registers your backend logic.&lt;/p&gt;

&lt;p&gt;Note that the method returns &lt;code&gt;JSON.stringify()&lt;/code&gt; rather than plain objects. Graftcode's transport layer wraps the object return values as remote references and returns a JSON string as the platform requires it.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; in the same &lt;code&gt;backend&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;sk_test_your_key_here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get the Stripe secret key from your dashboard. To get this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to Stripe’s Test account Dashboard&lt;/li&gt;
&lt;li&gt;Hit the &lt;strong&gt;Developers&lt;/strong&gt; panel&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;API Keys&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Get your &lt;strong&gt;secret key&lt;/strong&gt; from the &lt;strong&gt;Standard Keys&lt;/strong&gt; panel&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Expose the Backend With Graftcode Gateway
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll be doing a bit more work on the backend - &lt;a href="https://academy.graftcode.com/quick-start/expose-backend/javascript" rel="noopener noreferrer"&gt;read this guide&lt;/a&gt; to learn more about exposing your backend with Graftcode’s gateway.&lt;/p&gt;

&lt;p&gt;To begin with, run it against your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gg ./package.json &lt;span class="nt"&gt;--projectKey&lt;/span&gt; YOUR_PROJECT_KEY &lt;span class="nt"&gt;--port&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get the project key, do the following in your Graftcode dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to the &lt;strong&gt;Vision&lt;/strong&gt; panel&lt;/li&gt;
&lt;li&gt;Create a new gateway&lt;/li&gt;
&lt;li&gt;In the deployment options section, hit the “&lt;strong&gt;I already have Graftcode Gateway&lt;/strong&gt;” button: This skips the download process and automatically generates a new project key for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejwtl7s79g0qv65slh4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejwtl7s79g0qv65slh4a.png" alt="Run and deploy logic" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The gateway reads your &lt;code&gt;package.json&lt;/code&gt;, finds the &lt;code&gt;main&lt;/code&gt; entry point, loads &lt;code&gt;StripeService&lt;/code&gt;, and registers all four methods automatically.&lt;/p&gt;

&lt;p&gt;Once running, the gateway prints the exact install command for your project. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--registry&lt;/span&gt; https://grft.dev/YOUR_PROJECT_ID__graftcode @graft/npm-backend@1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the command exactly as printed, alongside the project ID in the URL, which is specific to your account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Install the Configured Package
&lt;/h2&gt;

&lt;p&gt;In the project’s root, configure the &lt;code&gt;@graft&lt;/code&gt; registry so npm knows where to find the generated package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"@graft:registry=https://grft.dev/YOUR_PROJECT_ID__graftcode"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to always replace your actual project ID as shown in your Graftcode portal. Then install the generated package using the exact command the gateway printed when it started - so this is more like wrapped into Graftcode now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @graft/npm-backend@1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Import the Backend From Your React Application
&lt;/h2&gt;

&lt;p&gt;The next step after configuring your backend is to import it into your frontend. In your &lt;code&gt;App.jsx&lt;/code&gt;, import the generated package and configure the gateway host.&lt;/p&gt;

&lt;p&gt;You can retrieve the gateway host URL from &lt;strong&gt;Graftcode Vision&lt;/strong&gt;. Open your project in the Vision portal, navigate to your running gateway, and copy the &lt;strong&gt;WebSocket endpoint&lt;/strong&gt; shown for your deployment. When running locally, this will usually look like &lt;code&gt;ws://localhost:8080/ws&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StripeService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graft/npm-backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;GraftConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://localhost:8080/ws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippet above, the &lt;code&gt;GraftConfig.host&lt;/code&gt; is the WebSocket URL of your running gateway. Ensure the backend is currently running on a separate terminal. That is the entire connection setup you need to work with Graftcode. You don’t need any base URLs, HTTP clients, or middleware.&lt;/p&gt;

&lt;p&gt;All you need to call your backend methods like regular functions like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;StripeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPaymentIntent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gbp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;StripeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPaymentLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gbp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;demo Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;StripeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listTransactions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;StripeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRevenueSummary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each function call moves over WebSocket to the gateway, which runs it in Node.js, where the Stripe SDK is wrapped, and returns the result. What Graftcode eliminates is all the code you would normally write around it, and the direct contact the SDK has with your browser.&lt;/p&gt;

&lt;p&gt;You can compare this approach to the traditional approach. To work with Stripe traditionally, you’ll be working with endpoints directly, which is a stressful approach. Here’s an example of what you’ll be doing normally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/create-intent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gbp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, you need to ensure there’s a configured endpoint for the &lt;code&gt;create-intent&lt;/code&gt;. Whereas, in Graftcode, all you need to do is call functions. In fact, in your IDE, when you type your function, it raises suggestions based on the imported module; this way, it’s easy for you to use Graftcode.&lt;/p&gt;

&lt;p&gt;With the traditional approach, you would need the Express route, the request validation, the response shape, the error handling, and you would maintain them. With Graftcode, you write the function once and call it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Exploring Backend Methods with Graftcode Vision
&lt;/h2&gt;

&lt;p&gt;Now, the React application has been connected to a backend without writing any API routes. But there’s another part of the Graftcode experience that makes this workflow even more interesting: &lt;strong&gt;Graftcode Vision&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Unlike working with API workflows, where you rely on documentation, Swagger specs, or tools like Postman, Graftcode Vision lets you see your backend in modules. When you open it in the browser, you’re not looking at endpoints or routes. You are looking at actual classes and methods; the actual ones you imported. &lt;/p&gt;

&lt;p&gt;In the portal, you can inspect the module’s classes, see every method it exposes, understand the parameters it expects, and even test those methods live. It removes the guesswork that developers usually deal with when integrating APIs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbna14m7anfxjfpmfresz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbna14m7anfxjfpmfresz.png" alt="Graftcode Vision Dashboard" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Run Your Entire Application
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, you need to start the gateway from the &lt;code&gt;backend/&lt;/code&gt; directory in one terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend
gg ./package.json &lt;span class="nt"&gt;--projectKey&lt;/span&gt; YOUR_PROJECT_KEY &lt;span class="nt"&gt;--port&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start your React application from your project’s root in a separate terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run start OR npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click any button in the application - they perform different functions. When a button is clicked, a call goes over WebSocket to Node.js, hits the Stripe API, and returns a response without a REST API, endpoints, or &lt;code&gt;fetch()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fct0qczpu2u4edkvclpyt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fct0qczpu2u4edkvclpyt.png" alt="Graftcode demo with Stripe" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your Stripe dashboard, you should see recent interactions with your Stripe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firaza0ev6zz4gjqegvd8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firaza0ev6zz4gjqegvd8.png" alt="Stripe Dashboard" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Deeper Look at Graftcode
&lt;/h2&gt;

&lt;p&gt;The code looks simple and also looks like an easier path to making things work, but there’s a bigger change than the simplicity.&lt;/p&gt;

&lt;p&gt;In a normal setup, your frontend and backend communicate through an API that you manually built. &lt;/p&gt;

&lt;p&gt;The four methods we configured in &lt;code&gt;StripeService&lt;/code&gt;: &lt;code&gt;createPaymentIntent&lt;/code&gt;, &lt;code&gt;createPaymentLink&lt;/code&gt;, &lt;code&gt;listTransactions&lt;/code&gt;, &lt;code&gt;getRevenueSummary&lt;/code&gt; , would normally be an Express route. You would define the route, its request shape, response shape, and the error handling. You would write &lt;code&gt;fetch()&lt;/code&gt; calls on the React side and keep both in sync.&lt;/p&gt;

&lt;p&gt;Here, you expose them through the gateway, &lt;code&gt;gg&lt;/code&gt;. The auto-generated &lt;code&gt;@graft/npm-backend&lt;/code&gt; package is what React imports and calls. The most interesting thing is: instead of writing routes and &lt;code&gt;fetch()&lt;/code&gt; calls, you write functions and let Graftcode handle the communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you look back at the application you built in this tutorial, the most interesting part is the fact that none of it required an API.&lt;/p&gt;

&lt;p&gt;There were no routes to define or anything to write, and no requests to construct. The entire interaction between frontend and backend was reduced to a simple method call, without losing any capability.&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this blog post. If you enjoyed this blog post, you can do well to try out Graftcode and check out some of its resources that will be listed in the references section. &lt;/p&gt;

&lt;p&gt;If you have any questions, leave them in the comments section below. See you in the next blog post!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://academy.graftcode.com/quick-start/expose-backend/javascript" rel="noopener noreferrer"&gt;Expose your backend with Graftcode (JavaScript)&lt;/a&gt; - Learn how to expose backend logic and connect it to your frontend using Graftcode.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://modules.graftcode.com/" rel="noopener noreferrer"&gt;Graftcode Modules Portal&lt;/a&gt; - Browse and install backend modules that can be used directly in your applications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://academy.graftcode.com/" rel="noopener noreferrer"&gt;Graftcode Documentation&lt;/a&gt; - Explore detailed tutorials and explanations of how Graftcode works.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Are AI Observability Tools Actually Helping?</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Mon, 30 Mar 2026 13:03:35 +0000</pubDate>
      <link>https://dev.to/coderoflagos/are-ai-observability-tools-actually-helping-3337</link>
      <guid>https://dev.to/coderoflagos/are-ai-observability-tools-actually-helping-3337</guid>
      <description>&lt;p&gt;Observability tools have been feeling very different lately.&lt;/p&gt;

&lt;p&gt;Almost every platform now claims to offer some “AI-powered” feature, such as anomaly detection, root cause analysis, automated insights, and even suggested fixes.&lt;/p&gt;

&lt;p&gt;But I’m not sure how much of it is actually useful in workflows.&lt;/p&gt;

&lt;p&gt;From what I’ve seen, most teams still deal with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many alerts
&lt;/li&gt;
&lt;li&gt;Jumping between logs, metrics, and traces
&lt;/li&gt;
&lt;li&gt;Spending so much time figuring out root causes &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And even with AI features, a lot of tools still feel like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Here’s more data… just slightly reorganized”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the same time, there &lt;em&gt;are&lt;/em&gt; some interesting improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automatic correlation between signals
&lt;/li&gt;
&lt;li&gt;faster incident investigation
&lt;/li&gt;
&lt;li&gt;less manual digging in some cases
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So it’s not all hype, but it also doesn’t feel like a complete shift yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Curious about real usage
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Are you actually using AI features in your observability stack?
&lt;/li&gt;
&lt;li&gt;Has it reduced alert fatigue at all?
&lt;/li&gt;
&lt;li&gt;Or are you mostly ignoring those features?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recently looked into this while comparing a bunch of AI-powered observability tools and how they’re evolving.&lt;/p&gt;

&lt;p&gt;If anyone’s interested in the full breakdown, I put it here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://metoro.io/blog/best-observability-tools-with-ai" rel="noopener noreferrer"&gt;https://metoro.io/blog/best-observability-tools-with-ai&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Feels like we’re in that phase where:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The idea is solid, but the execution is still catching up&lt;br&gt;&lt;br&gt;
It would be interesting to hear what others are seeing in production.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Sat, 20 Dec 2025 13:45:53 +0000</pubDate>
      <link>https://dev.to/coderoflagos/-33bm</link>
      <guid>https://dev.to/coderoflagos/-33bm</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/coderoflagos" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F392943%2F708b2716-2bb6-45ee-9662-ddb0288e3079.JPG" alt="coderoflagos"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/coderoflagos/a-practical-guide-to-building-your-first-automation-workflow-4k7l" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A Practical Guide to Building Your First Automation Workflow&lt;/h2&gt;
      &lt;h3&gt;Opemipo Disu ・ Dec 19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ai&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>programming</category>
      <category>ai</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Practical Guide to Building Your First Automation Workflow</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Fri, 19 Dec 2025 11:38:08 +0000</pubDate>
      <link>https://dev.to/coderoflagos/a-practical-guide-to-building-your-first-automation-workflow-4k7l</link>
      <guid>https://dev.to/coderoflagos/a-practical-guide-to-building-your-first-automation-workflow-4k7l</guid>
      <description>&lt;p&gt;Recently, I’ve been exploring the world of automation basically because I got tired of working with tools and handling tasks manually by writing scripts to make things happen. However, I wanted an easier approach; something visual and flexible, and my search led me to the world of automation workflows.&lt;/p&gt;

&lt;p&gt;Along the way, I found a life-changing tool for workflow automation, ByteChef, that enabled me to integrate different tools and build workflows in a straightforward way. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is ByteChef?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://bytechef.io" rel="noopener noreferrer"&gt;Bytechef&lt;/a&gt; is an open-source workflow automation and integration tool that lets you work with APIs and tools; it’s a tool that visually and seamlessly orchestrates connections with your favorite tools. With ByteChef, you can easily work with your best tools without necessarily writing a single line of code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44sn2dpvbrofyjm1vgr6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44sn2dpvbrofyjm1vgr6.gif" alt="Easy GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, instead of manually working with data from different tools, or creating complex processes, ByteChef provides an interactive interface and robust capabilities to bring your automation ideas to life.&lt;/p&gt;

&lt;p&gt;ByteChef’s capabilities aren't just limited to building workflow automations, it also enables you to work with different APIs of your choice. For example, you can connect APIs into your application with ByteChef. In this blog post, we won’t be focusing on this feature as we will have a deep look into the workflow automation feature.&lt;/p&gt;

&lt;p&gt;ByteChef can be ran in two ways: &lt;strong&gt;cloud&lt;/strong&gt; (we manage it for you) and &lt;strong&gt;self-hosted&lt;/strong&gt; (you run it on Docker). Cloud is easier to start with. If you want to self-host, you can check the &lt;a href="https://github.com/bytechefhq/bytechef" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for setup steps. For this guide, we'll use the Cloud approach, but everything works the same on both.&lt;/p&gt;

&lt;p&gt;Before moving to the next section of this article, I just dropped a video on YouTube where you can see how to create your first workflow in ByteChef. In this video, you’ll learn about ByteChef and how to work with it - you can see it as a video version of this blog post.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/Bs_AnyxmcEk"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of ByteChef
&lt;/h3&gt;

&lt;p&gt;Even while ByteChef provides the workflow automation feature, there are other great features that work with the workflow automation feature. In this section of the article, we’ll have a look at features that makes up the workflow automation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Application Integration&lt;/strong&gt;: With ByteChef, you can work with over 200+ tools including Gmail, Slack, Google Drive, and OpenAI. The fun of this integration is that you're not locked into a single ecosystem. Whether you're using productivity tools like Google Workspace, communication platforms like Slack, or AI services like OpenAI, ByteChef connects them all seamlessly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visual Workflow Builder&lt;/strong&gt;: ByteChef lets you design and configure workflows using an interactive interface without writing code. This doesn’t mean you aren’t allowed to write code; while using Bytechef, you don’t need to write complex code - in fact, writing code is optional when you’re using ByteChef. The main work while using ByteChef is just adding components, triggers, and configuring them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flow Logic&lt;/strong&gt;: ByteChef enables you to create smart workflows with branching logic, conditions, and decision points. This is what transforms workflows from simple into smart automation. You can create complex decision trees with multiple conditions; in ByteChef, we have different flows:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Condition&lt;/strong&gt;: Here’s a very basic flow; it checks something (for example; if something is urgent or not) and goes left if true, right if false. Pretty simple.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Branch&lt;/strong&gt;: This flow is very similar to condition, but handles more than just true/false. You can have multiple different paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Each&lt;/strong&gt;: When you have a list of things, this flow runs the same steps for each item. For example, if you have 10 emails, it processes all 10 the same way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loop (In Progress)&lt;/strong&gt;: Repeats the same thing over and over until something changes. Useful if you need to keep trying until it works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Map (In Progress)&lt;/strong&gt;: It takes a list and transforms every item in it. Changes the format or adds information to each item.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fork/Join&lt;/strong&gt;: It helps run multiple things at the same time instead of one after another. Also help save time by doing parallel work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parallel&lt;/strong&gt;: This flow is quite similar to fork/join. It runs multiple tasks at once.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Handler&lt;/strong&gt;: If something breaks, this flow catches it and does something else instead of crashing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wait for Approval&lt;/strong&gt;: Pauses and waits for a user’s approval before moving forward. Good for important decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Subflow (In progress)&lt;/strong&gt;:  This flow calls another workflow from within your workflow and helps organize complex workflows into smaller pieces.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the conditions themselves, ByteChef uses &lt;a href="https://docs.spring.io/spring-framework/docs/3.0.x/reference/expressions.html" rel="noopener noreferrer"&gt;&lt;strong&gt;SpEL (Spring Expression Language&lt;/strong&gt;)&lt;/a&gt; to create and manage them. You can do simple stuff like checking if something equals something, or more complex stuff like math. An example of condition expressions are: &lt;code&gt;anthropic_1.urgent == true&lt;/code&gt; and &lt;code&gt;email.from == 'boss@company.com'&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trigger-Based Automation&lt;/strong&gt;: This compliments workflows to take actions automatically based on certain events for example; taking new emails, form submissions, or scheduled times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Transformation&lt;/strong&gt;: Process and transform data as it moves between applications using built-in tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Integration&lt;/strong&gt;: Leverage AI capabilities to make your workflows smarter and more intelligent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Concepts Of ByteChef
&lt;/h2&gt;

&lt;p&gt;Before building your first workflow, there are things you need to know about the basic pieces that makes up a workflow in ByteChef, let’s have a look at them in this section of the blog post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Triggers&lt;/strong&gt;: These are events that start your workflow; it’s the first thing after creating your workflow. An example of a trigger is when a new email arrives, a form being submitted, or a scheduled time is reached. Triggers are just like the "when" of your automation; it initiates automations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Actions&lt;/strong&gt;: Actions are similar to triggers, but these are tasks each component performs. An action could be sending a message, creating a file, analyzing text with AI, or updating a record. Actions are the specific task a component should perform. In ByteChef, the action you want depends on the component you’re working with. Some components even enable you to create custom actions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Components&lt;/strong&gt;: These are the building blocks, you can also refer to them as nodes. Each component connects to an external app (like OpenAI, Google Drive, or even Spotify) and lets you use that app within a workflow. Components have two parts: &lt;strong&gt;triggers&lt;/strong&gt; and &lt;strong&gt;actions&lt;/strong&gt;; to work with a component, you need to connect with the tool and configure properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Projects&lt;/strong&gt;: Projects are like folders that hold your workflows - it’s a place where you can keep all your workflows. A project can hold as many workflows as you want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workflows&lt;/strong&gt;: In ByteChef, workflows are the actual automation. A workflow is a series of steps and triggers that work together to automate something. It's the whole thing here, but the automation process itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connections&lt;/strong&gt;: ByteChef uses connections to work with services, they’re like authentication links to third-party applications, allowing ByteChef to interact with your accounts securely. With ByteChef, you can connect services once, and ByteChef remembers it so workflows can use them securely.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are are the major concepts of ByteChef and all you need to know before building your first workflow in ByteChef - now, let’s put what we know to work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your First Workflow: An Email and AI Triage Example
&lt;/h2&gt;

&lt;p&gt;Now, let’s build an actual workflow. In this guide, we will be building an automated email system that checks incoming emails for urgency and routes them to different Slack channels through the flows and Anthropic AI for smart decision making. This workflow will showcase the capabilities of the key concepts you'll use in building basic and complex automations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a New Project
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, a project in ByteChef is the folder where the workflow lives.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the dashboard, head over to the &lt;strong&gt;Projects&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Click on the &lt;strong&gt;New Project&lt;/strong&gt; button at the top right corner.&lt;/li&gt;
&lt;li&gt;Fill the necessary credentials such as its name, category, description, and tags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxur8gruhncyf0bewu1bx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxur8gruhncyf0bewu1bx.png" alt="Create project modal via ByteChef’s Dashboard."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create project modal via ByteChef’s Dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a New Workflow
&lt;/h3&gt;

&lt;p&gt;When done creating your project, you can create a new workflow by clicking the &lt;strong&gt;+ Workflow&lt;/strong&gt; button in the project’s pane. When clicked, a modal should pop up requesting for the name and description of your workflow - this workflow will be saved in the project where it was created. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7o65vs1yf60643jfw7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7o65vs1yf60643jfw7s.png" alt="Create new workflow modal via ByteChef’s Dashboard."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create new workflow modal via ByteChef’s Dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Set Up Your Trigger
&lt;/h3&gt;

&lt;p&gt;After creating the workflow, the first step is to configure the trigger in the workflow. The configurable &lt;strong&gt;manual trigger&lt;/strong&gt; is the first thing you see in the workflow, now the first thing to do is to change the trigger and make configurations.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click the replace icon when you hover on the trigger button&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because of what we’ll be working on, search for and select "Gmail" when you want to replace the trigger&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose the trigger type: "New Email"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect to Gmail’s OAuth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the trigger parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Format: Simple (for straightforward configuration)&lt;/li&gt;
&lt;li&gt;Topic Name: Based on what is configured in your Google Pub/Sub.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This setup means your workflow will be activated whenever a new email arrives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Add a new component
&lt;/h3&gt;

&lt;p&gt;Now that emails are triggering your workflow, let's add the Anthropic component to determine if each email is urgent.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the + icon button to add a new task&lt;/li&gt;
&lt;li&gt;Search for and select "&lt;strong&gt;Anthropic&lt;/strong&gt;" (the AI provider)&lt;/li&gt;
&lt;li&gt;Connect Anthropic using the your client ID (API Key)&lt;/li&gt;
&lt;li&gt;Select "Ask" as the action type&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the AI task in the properties pane:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model: Choose any Anthropic models of your choice&lt;/li&gt;
&lt;li&gt;Format: Simple&lt;/li&gt;
&lt;li&gt;Response Format: Structured Data&lt;/li&gt;
&lt;li&gt;Max Models: The maximum number of token to generate in the chat completion.&lt;/li&gt;
&lt;li&gt;User Prompt: Create an instruction like:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Analyze this email and determine if it is urgent with "This is urgent" or "This is not urgent"&lt;/span&gt;
&lt;span class="na"&gt;Email Subject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${trigger_1.subject}&lt;/span&gt;
&lt;span class="na"&gt;Email From&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${trigger_1.from}&lt;/span&gt;
&lt;span class="na"&gt;Email Body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${trigger_1.bodyPlain}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;${trigger_1}&lt;/code&gt; syntax references data from your Gmail trigger.&lt;/li&gt;
&lt;li&gt;In the Anthropic component, create a schema for the incoming conditional flow.&lt;/li&gt;
&lt;li&gt;Add a new data pill and select &lt;strong&gt;Boolean&lt;/strong&gt; as the pill type - give it a title.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dbhtcy3abcuwodz6vas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dbhtcy3abcuwodz6vas.png" alt="Add new data pill"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This action sends each email to Claude for analysis, which will respond with a clear classification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Add Conditional Flow
&lt;/h3&gt;

&lt;p&gt;With the urgency classified in the Anthropic component, now we need to route emails to different destinations based on the result.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the add icon in the workflow&lt;/li&gt;
&lt;li&gt;Select "Condition" in the flows tab as the flow type&lt;/li&gt;
&lt;li&gt;Configure the condition:

&lt;ul&gt;
&lt;li&gt;Set "Raw Expression" to TRUE to enable custom logic&lt;/li&gt;
&lt;li&gt;Enter the expression: &lt;code&gt;anthropic_1.isUrgent&lt;/code&gt; from what we created in the schema builder&lt;/li&gt;
&lt;li&gt;This checks if the AI response equals "URGENT".&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This creates a branch point in your workflow. Depending on whether the condition is true or false, different actions will execute.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Define the True Branch (Urgent Emails)
&lt;/h3&gt;

&lt;p&gt;Here’s for emails classified as urgent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under the "True" section, add a new component&lt;/li&gt;
&lt;li&gt;Search and select the "Slack" component&lt;/li&gt;
&lt;li&gt;Choose "Send Channel Message" for the action&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give the component a name&lt;/li&gt;
&lt;li&gt;Channel: Select your "urgent-emails" channel (or create a channel where you want urgent emails to be delivered)&lt;/li&gt;
&lt;li&gt;Message: Create an informative message like:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;URGENT EMAIL&lt;/span&gt;

&lt;span class="nv"&gt;*From&lt;/span&gt;&lt;span class="s"&gt;:* ${trigger_1.from}&lt;/span&gt;
&lt;span class="nv"&gt;*Subject&lt;/span&gt;&lt;span class="s"&gt;:* ${trigger_1.subject}&lt;/span&gt;
&lt;span class="nv"&gt;*Classification&lt;/span&gt;&lt;span class="s"&gt;:*&lt;/span&gt; 
&lt;span class="nv"&gt;*Reason&lt;/span&gt;&lt;span class="s"&gt;:*&lt;/span&gt; 

&lt;span class="s"&gt;Requires immediate attention&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 6: Define the False Branch (Non-Urgent Emails)
&lt;/h3&gt;

&lt;p&gt;For emails classified as not urgent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the "Case False" section, add a new task&lt;/li&gt;
&lt;li&gt;Select "Slack" and "Send Channel Message"&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give the component a name&lt;/li&gt;
&lt;li&gt;Channel: Select your "routine-emails" channel (or any other channel where you want unimportant messages to be delivered)&lt;/li&gt;
&lt;li&gt;Message: Create a message like:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;New Email Received&lt;/span&gt;

&lt;span class="nv"&gt;*From&lt;/span&gt;&lt;span class="s"&gt;:* ${trigger_1.from}&lt;/span&gt;
&lt;span class="nv"&gt;*Subject&lt;/span&gt;&lt;span class="s"&gt;:* ${trigger_1.subject}&lt;/span&gt;
&lt;span class="nv"&gt;*Classification&lt;/span&gt;&lt;span class="s"&gt;:*&lt;/span&gt; 
&lt;span class="nv"&gt;*Reason&lt;/span&gt;&lt;span class="s"&gt;:*&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, your workflow should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8gmc5z2n47o4hrfn6tt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8gmc5z2n47o4hrfn6tt.png" alt="Workflow result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: Test Your Workflow
&lt;/h3&gt;

&lt;p&gt;Before activating your workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Review the entire flow to ensure it makes sense&lt;/li&gt;
&lt;li&gt;Click the  "Test" button at the top-right corner of the workflow,  to test the workflow with sample data&lt;/li&gt;
&lt;li&gt;Check that the flow follows the correct path&lt;/li&gt;
&lt;li&gt;Verify that messages are formatted correctly&lt;/li&gt;
&lt;li&gt;When testing, you should see something like this in the Slack channel where you want non-urgent messages to be delivered:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;New Email Received&lt;/span&gt;
&lt;span class="na"&gt;From&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sample from&lt;/span&gt;
&lt;span class="na"&gt;Subject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sample subject&lt;/span&gt;
&lt;span class="na"&gt;Classification&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;Reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 8: Publish and Deploy
&lt;/h3&gt;

&lt;p&gt;Once you're satisfied with the workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;Publish&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Deployments&lt;/strong&gt; tab in the dashboard&lt;/li&gt;
&lt;li&gt;Click New Deployment&lt;/li&gt;
&lt;li&gt;Select the project you want to deploy, the version, and add other necessary credentials&lt;/li&gt;
&lt;li&gt;Ensure the connections are configured properly&lt;/li&gt;
&lt;li&gt;Enable the workflow&lt;/li&gt;
&lt;li&gt;Send a test urgent/non-urgent email to your configured email address&lt;/li&gt;
&lt;li&gt;Monitor the configured Slack channels to verify emails are being routed correctly&lt;/li&gt;
&lt;li&gt;Check the workflow logs to see execution history and identify any issues&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a message is urgent, it’ll drop in the expected channel in this format:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcht8t3rwot3kc3ibkw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcht8t3rwot3kc3ibkw3.png" alt="Result in Slack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, to monitor the deployment, you can check your logs in the workflow executions section of the dashboard&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3utq54lw7qfcfzoh8koz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3utq54lw7qfcfzoh8koz.png" alt="ByteChef logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have your first workflow running, there are ways to make the most of it. You can add error handling to catch failures, so if something breaks, your workflow knows what to do instead of just stopping. &lt;/p&gt;

&lt;p&gt;To achieve this, you can try creating a loop to process multiple emails at once if you want to batch operations, or even instruct your LLM to make sentiment detection and content categorization to make your workflow even smarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;ByteChef enables you to automate routine tasks and create smart workflows that save time and reduce errors. Your first workflow is just the beginning. You can create more workflows to be better with automation. In ByteChef, the best way to understand the platform better is by playing around with it - as you become more comfortable with the platform, you'll discover countless ways to streamline your work and work with your favourite applications.&lt;/p&gt;

&lt;p&gt;The best way to successful automation is starting simple, testing thoroughly, and gradually building more complex workflows as your confidence and needs grow.&lt;/p&gt;

&lt;p&gt;Thanks for taking the time to learn about workflow automation with ByteChef in this blog post. Please, do well to use &lt;a href="https://bytechef.io" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt; and &lt;a href="https://discord.com/invite/VKvNxHjpYx" rel="noopener noreferrer"&gt;join the community&lt;/a&gt;, can’t wait to have you join the community.&lt;/p&gt;

&lt;p&gt;Lastly, if you ever have any issues navigating ByteChef, refer to the &lt;a href="https://docs.bytechef.io" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw40fxsns9gfgvpkpbmh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw40fxsns9gfgvpkpbmh.gif" alt="Thank you for readinng"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy automating! 🛠️&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Incident Event Pipelines for Real-Time Notifications with Windmill and Checkly</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Fri, 17 Oct 2025 13:10:38 +0000</pubDate>
      <link>https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2b2h</link>
      <guid>https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2b2h</guid>
      <description>&lt;p&gt;When applications and APIs have a downtime, customers are usually affected as operations remain broken. However, engineers do their job by fixing the broken operation - but a big question often comes up in engineering teams is how to tell users what exactly is happening without spamming or sending duplicate messages. That's where building a well-structured incident notification pipeline comes in.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore how to build an event pipeline for real-time notifications using Windmill. There are a bunch of monitoring tools like Sentry, New Relic, and even Grafana, for generating raw incidents but turning alerts into clear and reliable alerts for users means you need to orchestrate the alerts, clean them up, and make sure they always gets delivered.&lt;/p&gt;

&lt;p&gt;We will show how to use Windmill to gather incident events from a monitoring tool, apply routing rules, and deliver notifications through various channels. With this piece, you'll know how to orchestrate a production-ready pattern for ensuring that updates are sent to users without duplications or delay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jbv817y01z2to4qd81r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jbv817y01z2to4qd81r.gif" alt="This is not an alert from Windmill, please. 😂" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not an alert from Windmill, please. 😂&lt;/p&gt;

&lt;h2&gt;
  
  
  System Architecture: From Incidents to Alerts
&lt;/h2&gt;

&lt;p&gt;Now that we’ve set the context and had a little laugh with that caption 😅, let’s get straight to the point and look at how this whole system fits together. The goal of this workflow is simple: when something breaks within an application, users should be able to get real-time alerts only once. To make this work, we will integrate a monitoring tool with Windmill for orchestration and notification delivery. Now, let's have a deeper look at the major components of this workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring Tool&lt;/strong&gt;: While there are many tools such as Grafana, Sentry, and Prometheus, we will be using&amp;nbsp;&lt;a href="https://checklyhq.com/" rel="noopener noreferrer"&gt;Checkly&lt;/a&gt;&amp;nbsp;to detect when something goes wrong within an application. These tools can fire a webhook or alert when things break.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windmill&lt;/strong&gt;: Windmill sits in the middle of the workflow as the orchestrator as it helps ingest incident events from the monitoring tool (Checkly, in this context), and normalize them into a consistent schema so all the alerts are in the right destination. Windmill will also decide the destination of each type of alerts (whether they're critical, warnings, or minor). Lastly, we'll be ensuring there's a high level of reliability and deduplication with alerts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notification Channels&lt;/strong&gt;: Once the orchestration with Windmill is done, it can deliver notifications through various channels like Slack, email, SMS, or webhook endpoints to other services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feedback Loop&lt;/strong&gt;: Some alerts might not appear at the expected destination the first time. Windmill allows you to implement retry flows to reattempt delivery or escalate the issue to another channel.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnnzhc5xf671i8p161x6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnnzhc5xf671i8p161x6.png" alt="Windmill flow" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Gathering Events From Checkly in Windmill
&lt;/h2&gt;

&lt;p&gt;The first step of this workflow is collecting incident events from the monitoring tool. Since we're using Checkly as our monitoring tool, we'll integrate Checkly with Windmill for orchestration and notification delivery whenever an error or downtime occurs within an application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Webhook in Windmill
&lt;/h3&gt;

&lt;p&gt;Windmill lets you expose a flow as a webhook, which Checkly can call whenever something breaks. We need to work with Windmill for the webhook trigger configuration as this we'll need the incident pipeline for Checkly's webhook configuration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a Windmill account and log into your Windmill workspace via&amp;nbsp;&lt;a href="https://app.windmill.dev/" rel="noopener noreferrer"&gt;Windmill Cloud&lt;/a&gt;&amp;nbsp;or the&amp;nbsp;&lt;a href="https://www.windmill.dev/docs/advanced/self_host" rel="noopener noreferrer"&gt;self-hosted versions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In your Windmill dashboard, create a new&amp;nbsp;&lt;strong&gt;Flow&lt;/strong&gt;&amp;nbsp;from the Home tab.&lt;/li&gt;
&lt;li&gt;In the flow editor, give the flow a name and add a trigger.&lt;/li&gt;
&lt;li&gt;Select the&amp;nbsp;&lt;strong&gt;Webhook Trigger&lt;/strong&gt;&amp;nbsp;option.

&lt;ul&gt;
&lt;li&gt;This automatically generates an endpoint that accepts&amp;nbsp;&lt;code&gt;POST&lt;/code&gt;&amp;nbsp;requests.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Next, inspect the incoming data and add a step to log the payload (so you can see what you want Checkly to send).&lt;/li&gt;
&lt;li&gt;Add a preprocessor module to handle incoming webhook events (click the "&lt;strong&gt;+&lt;/strong&gt;" button after the trigger node) - once this is done, select&amp;nbsp;&lt;strong&gt;TypeScript&lt;/strong&gt;&amp;nbsp;as the language.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faulo5wsuchnej1qbe3jv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faulo5wsuchnej1qbe3jv.png" alt="Preprocessor with TypeScript" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the preprocessor editor, you can access the webhook’s payload. In this case, we will be replacing the template with the following code to process the data to ensure that the webhook and payload are working properly:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;preprocessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;check_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;check_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;run_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script above receives JSON data from Checkly, logs them and returns a confirmation message. If you test the script, you should receive this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;preprocessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;check_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;check_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;run_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script above receives JSON data from Checkly, logs them and returns a confirmation message. If you test the script, you should receive this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dg2ub3yo90chxtk1vth.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dg2ub3yo90chxtk1vth.png" alt="Webhook's test step on Windmill" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy your Windmill webhook endpoint. Now, you have to reopen the Trigger node, then you’ll see a URL like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://app.windmill.dev/api/w/[workspace]/jobs/run_wait_result/[flow_path]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2: Configure Checkly to Send Incidents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.checklyhq.com/signup" rel="noopener noreferrer"&gt;Create a Checkly account&lt;/a&gt; and log into &lt;a href="https://app.checklyhq.com/" rel="noopener noreferrer"&gt;Checkly’s dashboard&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Head over to the &lt;strong&gt;Alerts Channels&lt;/strong&gt; tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the &lt;strong&gt;Add more channels&lt;/strong&gt; button and select the &lt;strong&gt;Webhook&lt;/strong&gt; option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give the Webhook instance a name and paste the Windmill webhook URL you created earlier (be sure to use the POST method).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the webhook instance on Checkly and you should get a JSON payload with different fields. If anything fails, Windmill will receive this payload instantly when you start capturing the issues with your monitored services.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fea77t4q4n6eilxo4o5ni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fea77t4q4n6eilxo4o5ni.png" alt="Checkly's Flow" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Orchestrating Incidents in Windmill
&lt;/h2&gt;

&lt;p&gt;Raw incidents aren’t enough, they’re often noisy and inconsistent and that’s why there’s a need to clean and route them properly. In Windmill’s environment, workflows  are like blocks for routing, and providing contexts to alerts. Once Checkly pushes an incident payload, Windmill takes over to make sense of it.&lt;/p&gt;

&lt;p&gt;A basic orchestration pattern includes the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normalization&lt;/strong&gt;: Convert Checkly’s raw JSON payload format into a consistent schema. Each monitoring tool has its own format of displaying schemas. Normalization in this context ensures every incident follows a predictable format like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"coderoflagos-check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"critical"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Timeout on /register route"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eu-west-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"incident_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run_8472"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach makes it easier to work with Slack notifications to process alerts without working with too much logic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deduplication&lt;/strong&gt;: Incidents can be disturbing. For example, if the same check fails 10 times within a minute, you don't want users to be sent 10 alerts on that. In Windmill, you can store or reference previous incidents in a temporary key-value store or even cache and check whether an identical incident already exists before sending another one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Routing Rules&lt;/strong&gt;: Not all incidents are the same; there are different classes they fall into. While there are different classes, you can build conditional logic in your Windmill flow to route alerts based on severity, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Critical&lt;/strong&gt;: Send immediately via SMS and urgent channels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warning&lt;/strong&gt;: Forward via email or Slack only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Info:&lt;/strong&gt;&amp;nbsp;Log silently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach ensures developers or end-users only get the right level of attention when something occurs.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retries and Recovery&lt;/strong&gt;: Delivery sometimes fails. For example, a notification service might return a network timeout. Windmill allows you to implement retry flows to reattempt delivery or escalate the issue to another channel.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example normalization step in Windmill
&lt;/h2&gt;

&lt;p&gt;Once your flow receives a payload from Checkly, the next step is to normalize it into your schema and prepare it for notification delivery. Here's how to achieve this:&lt;/p&gt;

&lt;p&gt;After your preprocessor, add a new code step that handles normalization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the&amp;nbsp;&lt;strong&gt;"+"&lt;/strong&gt;&amp;nbsp;button after your preprocessor.&lt;/li&gt;
&lt;li&gt;Select&amp;nbsp;&lt;strong&gt;Code&lt;/strong&gt;&amp;nbsp;option and choose&amp;nbsp;&lt;strong&gt;Python&lt;/strong&gt;&amp;nbsp;as the language.&lt;/li&gt;
&lt;li&gt;Give the step a unique name.&lt;/li&gt;
&lt;li&gt;After, you can apply the following code in the code step:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
    Normalize Checkly data into a consistent incident schema
    &lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Normalize&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;incident&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="nx"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;check_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unknown Service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;severity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;critical&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Check completed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;region&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;region&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;incident_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;flow_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Normalized incident: {normalized}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;normalized&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step takes the preprocessed Checkly data and normalizes it into a consistent format that can be used by downstream notification steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delivering Notifications
&lt;/h2&gt;

&lt;p&gt;After normalization, you can add steps to deliver notifications through various channels. Here's how Windmill transforms your Checkly incidents into actionable notifications:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add Notification Delivery Steps
&lt;/h3&gt;

&lt;p&gt;You can add multiple notification steps based on your needs. Each step receives the normalized incident data and delivers it through a specific channel:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slack Notification Step:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add another code step after your normalization step&lt;/li&gt;
&lt;li&gt;Choose Python as the language&lt;/li&gt;
&lt;li&gt;Add&amp;nbsp;&lt;code&gt;slack_webhook_url&lt;/code&gt;&amp;nbsp;as a parameter&lt;/li&gt;
&lt;li&gt;Here’s an example code snippet of what you should have in the code step trigger:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incident&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slack_webhook_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
    Send incident notification to Slack
    &lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
    &lt;span class="nx"&gt;severity_emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🚨&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;incident&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;severity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;critical&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;⚠️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

    &lt;span class="nx"&gt;slack_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{severity_emoji} Incident Alert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*{incident['service']}* is experiencing issues&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;*Error:* {incident['message']}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;*Severity:* {incident['severity']}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;*Region:* {incident['region']}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;*Incident ID:* {incident['incident_id']}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slack_webhook_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;slack_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;channel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;incident_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;incident&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;incident_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message_sent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Notified team about {incident['service']} incident&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that even non-critical incidents still reach your engineering team without repeating emails&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Windmill makes it easy to send alerts from Checkly to your team or product users. You can use it to recieve alerts, clean data, and send alerts via Slack, email, or any other destination you prefer. Everything works automatically, so your team can focus on fixing issues instead of managing notifications manually - however, note that with this approach, there are still some efforts you can apply to make things work more efficently.&lt;/p&gt;

&lt;p&gt;To get the best results, try using clear alert formats and test your flow often to make sure messages are sent correctly. You can also explore other Windmill features like custom logic and extra integrations to make your system stronger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before you go… 😂
&lt;/h3&gt;

&lt;p&gt;Thanks for reading! If this article helped you, check out &lt;a href="https://windmill.dev/docs" rel="noopener noreferrer"&gt;Windmill’s docs&lt;/a&gt; or join &lt;a href="https://discord.com/invite/V7PM2YHsPB" rel="noopener noreferrer"&gt;Windmill’s community&lt;/a&gt; to learn more. Sharing your feedback or building something cool with Windmill helps everyone in the developer community grow together.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Mon, 13 Oct 2025 13:36:23 +0000</pubDate>
      <link>https://dev.to/coderoflagos/-2e3l</link>
      <guid>https://dev.to/coderoflagos/-2e3l</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2290" class="crayons-story__hidden-navigation-link"&gt;Incident Event Pipelines for Real-Time Notifications with Windmill and Checkly&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/coderoflagos" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F392943%2F708b2716-2bb6-45ee-9662-ddb0288e3079.JPG" alt="coderoflagos profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/coderoflagos" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Opemipo Disu
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Opemipo Disu
                
              
              &lt;div id="story-author-preview-content-2915549" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/coderoflagos" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F392943%2F708b2716-2bb6-45ee-9662-ddb0288e3079.JPG" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Opemipo Disu&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2290" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 13 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2290" id="article-link-2915549"&gt;
          Incident Event Pipelines for Real-Time Notifications with Windmill and Checkly
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2290" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;8&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/coderoflagos/incident-event-pipelines-for-real-time-notifications-with-windmill-and-checkly-2290#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Amazon Bedrock and Retrieval-Augmented Generation (RAG): Building Smarter AI Systems with Context-Aware Responses</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Wed, 09 Apr 2025 12:25:38 +0000</pubDate>
      <link>https://dev.to/microtica/amazon-bedrock-and-retrieval-augmented-generation-rag-building-smarter-ai-systems-with-28lm</link>
      <guid>https://dev.to/microtica/amazon-bedrock-and-retrieval-augmented-generation-rag-building-smarter-ai-systems-with-28lm</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In&amp;nbsp;&lt;a href="https://dev.to/microtica/amazon-bedrock-a-practical-guide-for-developers-and-devops-engineers-kag"&gt;Part 1 of this series&lt;/a&gt;, we delved into Amazon Bedrock and how DevOps engineers and developers could build their first generative AI applications and deploy with AWS Lambda. In the last blog post, we also focused on use cases that could be built with Amazon Bedrock even best practices for working with Amazon Bedrock.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, we’ll take a step further by showcasing how to address a very important challenge in AI; providing context-aware responses for generating quality and relevant responses.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will learn how Amazon Bedrock works with RAG, its structure, and get a practical guide on integrating Amazon Bedrock and RAGs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Retrieval Augmented Generation?
&lt;/h2&gt;

&lt;p&gt;Retrieval Augmented Generation (RAG) is a technique used to improve the quality of responses from LLMs by adding relevant information from external sources. Normally, when working with a traditional LLM, you get responses based on what they’re trained to give back, but with RAG, you get responses from real-time data and more accurate information. Working with standard models can be static, whereas working with RAGs is super dynamic; that’s a major difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  RAG vs. Standard LLMs
&lt;/h3&gt;

&lt;p&gt;In this section of the tutorial, we will look at some of the differences in features between Standard LLMs and RAG-Enabled LLMs.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Standard LLM&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;RAG-Enabled LLM&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge Source&lt;/td&gt;
&lt;td&gt;Static / Fine-tuned data&lt;/td&gt;
&lt;td&gt;Dynamic / Real-time data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False Information Risk&lt;/td&gt;
&lt;td&gt;High (inaccurate or outdated)&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use of Private Data&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Large-scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost Efficiency&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;More efficient with caching&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the table above, you'll see that working with traditional LLMs can be very static, fixed, and inaccurate because they operate based on how humans fine-tune the model. However, RAG-Enabled LLMs work directly with data retrieved from external sources and real-time data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use-Cases of RAGs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chatbots:&lt;/strong&gt;&amp;nbsp;This is probably the most known use-case for RAGs. With RAGs, you get more accurate and current information as responses for better customer interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal Knowledge Search:&lt;/strong&gt;&amp;nbsp;RAG-enabled models enable users to easily access and utilize articles, guides, documentation, and even other public resources without any manual intervention or worrying if the information generated is relevant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support Automation:&lt;/strong&gt;&amp;nbsp;RAGs could also improve incident resolution by pulling from logs and past tickets. It helps provide quicker and accurate answers for resolving issues faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial Services:&lt;/strong&gt;&amp;nbsp;RAG-enabled models can also generate stats reports in different formats based on real-time market data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Does Retrieval Augmented Generation Work?
&lt;/h2&gt;

&lt;p&gt;RAG improves AI responses by using information retrieval with language models. For example; when a user submits a query, the system uses an existing knowledge base like S3, Elasticsearch, Pinecone, or OpenSearch to find relevant data. This data is added to the user’s query and sent to the AI model to make the response more accurate.&lt;/p&gt;

&lt;p&gt;Here’s an architectural diagram of how RAG works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ctgay2ciiju8sq09xw3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ctgay2ciiju8sq09xw3.webp" alt="Workflow Diagram" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Using RAG-Enabled LLMs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lower Risk of Inaccurate Information:&lt;/strong&gt;&amp;nbsp;Using RAG-Enabled LLMs generates responses based on reliable sources rather than making assumptions. Unlike using standard LLMs, where you have to provide models with data that might be inaccurate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Accuracy:&lt;/strong&gt;&amp;nbsp;Using them also ensures AI responses are more accurate and up-to-date by retrieving information from trusted external sources instead of relying on fine-tuned data. This reduces the risk of giving users incorrect information for responses, thereby improving the accuracy of generated content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Efficiency:&lt;/strong&gt;&amp;nbsp;They also help save money and reduce API calls by using existing data sources instead of making unnecessary requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Compliance:&lt;/strong&gt;&amp;nbsp;Using RAG-Enabled LLMs even helps provide data privacy by retrieving information only from authorized and secure sources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AWS Bedrock + RAG: The Perfect Match
&lt;/h2&gt;

&lt;p&gt;AWS Bedrock provides a solid base for RAG-enabled apps by offering various foundation models with built-in tools for storing and retrieving custom data.&lt;/p&gt;

&lt;p&gt;Its serverless setup ensures that there is security and compliance while integrating with services like &lt;strong&gt;Amazon OpenSearch&lt;/strong&gt; for search-based retrieval, &lt;strong&gt;Amazon S3&lt;/strong&gt; for storage, &lt;strong&gt;AWS RDS&lt;/strong&gt; for relational databases, and &lt;strong&gt;Amazon Bedrock&lt;/strong&gt; Knowledge Bases for vector-based retrieval. This setup allows developers to create scalable AI applications easily.&lt;/p&gt;

&lt;p&gt;Before delving into implementing RAG into Amazon Bedrock, lets have a look at Amazon Bedrock’s workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop6tf4bl9ls25v50amv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop6tf4bl9ls25v50amv4.png" alt="Image description" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement RAG with AWS Bedrock
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Store Your Custom Data
&lt;/h3&gt;

&lt;p&gt;Since we will be using Amazon S3 to store our data, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Head over to Amazon S3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbb2wx7w2o05dglj9kyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbb2wx7w2o05dglj9kyw.png" alt="Image" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create an&amp;nbsp;&lt;a href="https://us-east-1.console.aws.amazon.com/s3/get-started?region=us-east-1&amp;amp;bucketType=general" rel="noopener noreferrer"&gt;&lt;strong&gt;Amazon S3 Bucket&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;to store your data and make necessary configurations. Be sure to&amp;nbsp;&lt;strong&gt;enable&lt;/strong&gt;&amp;nbsp;Bucket Versioning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcj44ouy3la97buwa52j8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcj44ouy3la97buwa52j8.png" alt="Image" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upload to documents to your Amazon S3 bucket.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Choose an Embedding Model
&lt;/h3&gt;

&lt;p&gt;Choose any model to work with; your decision on selecting a model should be based on whether it fits the project you're working on.&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Refer to this guide&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;to find a list of models you can work with.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Create a Knowledge Base&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to Amazon Bedrock’s Console&lt;/li&gt;
&lt;li&gt;In the side navigation by the left, select "Knowledge bases".&lt;/li&gt;
&lt;li&gt;Click "Create knowledge base" and select the “Knowledge Base with Vector Store” option.&lt;/li&gt;
&lt;li&gt;Provide the knowledge base details&lt;/li&gt;
&lt;li&gt;When providing the knowledge base details, choose the S3 URI location as data source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fansi1b90ngv267qdt2fa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fansi1b90ngv267qdt2fa.png" alt="S3 URI" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Finally, select your embedding model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffke29lqjuxvpk6fhu5zk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffke29lqjuxvpk6fhu5zk.png" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure the vector store (Amazon OpenSearch Serverless will be used by default).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Chunking (Data Preparation):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Head over to the &lt;strong&gt;Knowledge Base&lt;/strong&gt; in the &lt;strong&gt;Amazon Bedrock&lt;/strong&gt; console.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select Your Knowledge Base&lt;/strong&gt;&amp;nbsp;From the Knowledge Bases section, choose the knowledge base you want to work with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add or Edit a Data Source&lt;/strong&gt;&amp;nbsp;If you haven't already, add a new data source pointing to your S3 bucket. If you have an existing S3 data source, select it for editing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Chunking Strategy&lt;/strong&gt;&amp;nbsp;In the data source settings, look for the "Chunking Configuration" section. Here, you'll find options to set your chunking strategy:

&lt;ul&gt;
&lt;li&gt;Fixed-size chunking.&lt;/li&gt;
&lt;li&gt;Hierarchical chunking.&lt;/li&gt;
&lt;li&gt;Semantic chunking.&lt;/li&gt;
&lt;li&gt;No chunking (treats each file as one chunk).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Here’s where to configure that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq038ukicnp1blqmobncx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq038ukicnp1blqmobncx.png" alt="Chunk" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose and Configure Your Chunking Strategy&lt;/strong&gt;&amp;nbsp;Select the strategy that fits your data and use case.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For Fixed-size&lt;/strong&gt;: Specify the number of tokens per chunk and overlap percentage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For Hierarchical&lt;/strong&gt;: Also define parent and child chunk sizes and overlap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For Semantic&lt;/strong&gt;: Set the maximum tokens, buffer size, and breakpoint percentile threshold.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Review and Save Changes&lt;/strong&gt;&amp;nbsp;After configuring your chunking strategy, review your settings and save the changes to your data source.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Test and Query the Knowledge Base
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Before testing, ensure the data is synced; &lt;strong&gt;syncing&lt;/strong&gt; means fetching the data from S3, chunking it, embedding it, and storing it in the vector database.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the knowledge base console, hit the&amp;nbsp;&lt;strong&gt;Test&lt;/strong&gt;&amp;nbsp;button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e229phecywfq59ejnq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e229phecywfq59ejnq2.png" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the panel pops out, enter a question related to your uploaded documents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click&amp;nbsp;&lt;strong&gt;Run&lt;/strong&gt;&amp;nbsp;to get AI-generated responses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 6: Verify the Retrieval Process&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If Bedrock correctly retrieves relevant data, your RAG setup is working! 🎉&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices &amp;amp; Tips for RAG Pipelines on AWS Bedrock
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimize Context Window:&lt;/strong&gt;&amp;nbsp;It's important to keep the context clear and focused on what's needed for the prompt. Too much information can confuse the model, so a great thing to do will be always try to provide only necessary data to get accurate responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balance Cost vs. Accuracy:&lt;/strong&gt;&amp;nbsp;Retrieving more data also helps improve accuracy, but it can also increase costs. Find a balance by fetching only the necessary data to reduce costs while maintaining the same quality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-Tune Retrieval Thresholds:&lt;/strong&gt;&amp;nbsp;Set limits for retrieval relevance to make sure you're only getting the most useful data. This helps prevent overwhelming the model with unnecessary information and keeps responses clear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Caching:&lt;/strong&gt;&amp;nbsp;Cache frequently used data to speed things up and reduce unnecessary API calls. This makes your pipeline more efficient and reduces costs, especially for common queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Data Sources:&lt;/strong&gt;&amp;nbsp;Protect your data by using IAM policies and encryption for sensitive sources. This practice ensures that only authorized users can access your data, keeping everything safe and compliant.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Use Cases for RAG
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps &amp;amp; Observability:&lt;/strong&gt;&amp;nbsp;You can use RAG for retrieving logs and metrics (in real-time) for automated incident resolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product Search &amp;amp; Recommendations:&lt;/strong&gt;&amp;nbsp;You can use RAG to refine personalized product recommendations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Document QA:&lt;/strong&gt;&amp;nbsp;You can also use RAG for employees to query company documents with chatbots and AI agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-Commerce:&lt;/strong&gt;&amp;nbsp;You can also use RAGs to fetch dynamic product descriptions and search results.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RAG vs. Fine-Tuning Decision Framework
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Best Approach&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Static Knowledge&lt;/td&gt;
&lt;td&gt;Fine-Tuning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic Data&lt;/td&gt;
&lt;td&gt;RAG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost-Sensitive&lt;/td&gt;
&lt;td&gt;RAG (less training required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Privacy&lt;/td&gt;
&lt;td&gt;RAG (retrieves private data)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What’s Next: RAG-Enabled AI Agents in Production
&lt;/h2&gt;

&lt;p&gt;Now, the next step for you is to create AI agents that automate workflows using Amazon Bedrock and integrate with RAG. To deploy your application, you can use AWS services like ECS, Lambda, or other Bedrock-managed services.&lt;/p&gt;

&lt;p&gt;In Part 3 of this series, we’ll explore how to scale RAG architectures in production, improve performance, and ensure seamless integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;RAG with AWS Bedrock makes models smarter by adding real-world context to its responses. That being said you’ll get more accurate answers, and reduce costs since you’re only pulling in the data you actually need. Anther thing is that AWS handles the backend, so you don’t have to stress about infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before you go… 🥹
&lt;/h3&gt;

&lt;p&gt;Thank you for taking the time to learn about integrating RAGs with AWS Bedrock. If you found this article helpful, please consider supporting Microtica by creating an account and&amp;nbsp;&lt;a href="https://discord.gg/N8WdXyXxZR" rel="noopener noreferrer"&gt;&lt;strong&gt;joining the community&lt;/strong&gt;&lt;/a&gt;. Your support helps us keep improving and offering valuable resources like this, for the developer community!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>10 Internal Developer Platforms to Improve Your Developer Workflow 🚀</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Fri, 28 Mar 2025 12:34:24 +0000</pubDate>
      <link>https://dev.to/microtica/10-internal-developer-platforms-to-improve-your-developer-workflow-55ee</link>
      <guid>https://dev.to/microtica/10-internal-developer-platforms-to-improve-your-developer-workflow-55ee</guid>
      <description>&lt;p&gt;&lt;strong&gt;Internal Developer Platforms&lt;/strong&gt; (IDPs) are essential tools in the software development process because they deliver the software faster and more efficiently. This means that it boosts the whole process's productivity. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtwr6vnyko7xkr0cdymw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtwr6vnyko7xkr0cdymw.gif" alt="let's go gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The need for these platforms is increasing because companies tend to find better solutions that will speed up software delivery. As businesses grow, the complexity of the development process is increasing too. That’s why IDPs can help to solve the challenges that a company may face.&lt;/p&gt;

&lt;p&gt;This ultimate guide will help you choose the best IDPs including their features, benefits, and functionalities. Understanding these platforms better will transform software development within a business.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is the Purpose of an Internal Developer Platform?
&lt;/h2&gt;

&lt;p&gt;Internal developer platforms (IDPs) are tools that help businesses streamline their development procedures. Compared with the traditional approach, IDPs provide a solution that simplifies processes, automates repetitive work, and allows developers to concentrate on what they do best - write code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsp6s3io1vzuihph831p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsp6s3io1vzuihph831p.gif" alt="relived gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These platforms ease the work of the developers, which means they can focus on their main job rather than manage the IT infrastructure. Tasks including configuration, provision, and deployment are all part of the self-services that IDPs offer. &lt;/p&gt;

&lt;p&gt;The main goal of an IDP is to increase developers' productivity. By providing enhanced technologies, developers are able to organize their time and focus on producing creative solutions. &lt;/p&gt;

&lt;p&gt;Because platform engineering creates an environment that helps both the business and the customers, developers can save time and effort while still providing value to clients. Using all these necessary tools ensures that your development procedures as well as the outcomes will be improved. &lt;/p&gt;

&lt;p&gt;Let’s take a closer look at the best platforms to use within your development workflow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Microtica
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foe0vrr3qonwurzqnftm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foe0vrr3qonwurzqnftm6.png" alt="Microtica image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://microtica.com/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;Microtica&lt;/a&gt; is an AI-powered platform that offers better cloud-native app deployment and management. It automates lots of activities, such as &lt;a href="https://www.microtica.com/blog/optimize-your-ci-cd-pipeline-for-faster-deployments" rel="noopener noreferrer"&gt;deployment pipelines&lt;/a&gt;, monitoring, and cost optimization, while providing ready templates for rapid implementation.&lt;/p&gt;

&lt;p&gt;In order to improve efficiency, save &lt;a href="https://www.microtica.com/blog/7-challenges-with-aws-costs" rel="noopener noreferrer"&gt;cloud expenses&lt;/a&gt;, and increase monitoring visibility, the platform offers developers the tools they need to manage apps on their cloud accounts. Microtica is suitable for all-size businesses because it also provides insights for operational and cost-saving improvements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://microtica.com/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Microtica For Free ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Qovery
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwdk2lxt9gglsxokg0oy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwdk2lxt9gglsxokg0oy9.png" alt="Qovery Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.qovery.com/" rel="noopener noreferrer"&gt;Qovery&lt;/a&gt; stands out as a powerful DevOps automation platform that aims to streamline the development process. It provides a comprehensive solution for provisioning, managing repetitive tasks, and maintaining a secure and compliant infrastructure to improve user experience and cost efficiency.&lt;/p&gt;

&lt;p&gt;Qovery streamlines deployment workflows while ensuring scalability, and compliance. It reduces the need for manual DevOps tasks by offering self-service tools that ensure the developers will manage and deploy cloud infrastructure efficiently. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.qovery.com/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Qovery ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  3. OpsLevel
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0i8igelkkm4zuvxfaib2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0i8igelkkm4zuvxfaib2.png" alt="OpsLevel Header"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://www.opslevel.com/" rel="noopener noreferrer"&gt;OpsLevel&lt;/a&gt;, developers can manage all of their tools, services, and systems from a single location using OpsLevel's standardized interface. As an internal developer portal, it offers automated services, helps to speed up the delivery of software quality, and enhances the visibility of the context. &lt;/p&gt;

&lt;p&gt;OpsLevel enables businesses to efficiently manage complex structures, while at the same time maintaining outstanding service with its user-friendly interface and powerful monitoring features. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.opslevel.com/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try OpsLevel ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Coherence
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7dgm3sn3anmefxsq34j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7dgm3sn3anmefxsq34j.png" alt="Coherence header"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.withcoherence.com/" rel="noopener noreferrer"&gt;Coherence&lt;/a&gt; is a platform that helps companies build a strong environment by testing, developing, and deploying web apps, and managing the full SDLC. It enables users to choose the features of the dataset, ensuring accuracy. &lt;/p&gt;

&lt;p&gt;Coherence is a helpful IDP because allows development tasks to be delivered faster and with greater accuracy than with conventional techniques.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.withcoherence.com/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Coherence ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Humanitec
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9bvk58j8s46qznzlxqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9bvk58j8s46qznzlxqb.png" alt="Humanitec Homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://humanitec.com/" rel="noopener noreferrer"&gt;Humanitec&lt;/a&gt; provides a platform that automates and standardizes infrastructure management for developers. It improves DevOps workflow by enhancing the collaboration between the operations and developers teams to achieve faster and better delivery. &lt;/p&gt;

&lt;p&gt;It also focuses on self-service tools that improve deployment automation, and environment management while cutting time and costs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://humanitec.com/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Humanitec ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Mia Platform
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3ytxlhhcg5r1hagujdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3ytxlhhcg5r1hagujdm.png" alt="Mia Platform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mia-platform.eu/" rel="noopener noreferrer"&gt;Mia Platform&lt;/a&gt; provides a variety of products for building digital platforms. The platform is associated with several international technological standards and focuses mostly on encouraging the use of Cloud Native and Open Source applications. &lt;/p&gt;

&lt;p&gt;Among its services is the main product, the Mia-Platform Console, which is a platform that improves developer experience, accelerates the creation of microservices architectures, and streamlines development procedures. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://mia-platform.eu/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Mia Platform ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Appvia
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox4gp8zf1jz1v2y3pe88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox4gp8zf1jz1v2y3pe88.png" alt="Appvia homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.appvia.io/" rel="noopener noreferrer"&gt;Appvia&lt;/a&gt; offers solutions that simplify and secure public cloud distribution. By offering solutions that are safe, affordable, and scalable, they enable businesses to proactively pursue cloud computing.&lt;/p&gt;

&lt;p&gt;Among its many features are infrastructure management, automated deployment, and integration with leading cloud providers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.appvia.io/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Appvia ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Portainer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4o3ablmvhj1lwrvwem1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4o3ablmvhj1lwrvwem1u.png" alt="Portainerr image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an open-source tool, &lt;a href="https://www.portainer.io/" rel="noopener noreferrer"&gt;Portainer&lt;/a&gt; makes it easier to deploy, monitor, and secure systems using Docker, Kubernetes, Swarm, and Podman. Everyone can use it, from small companies to big enterprises, by offering user-friendly interface automation, and developer self-service. &lt;/p&gt;

&lt;p&gt;The main goal of Portainer is to streamline operations, enforce best practices, and accelerate container adoption.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.portainer.io/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Portainer ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  9. WarpBuild
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2prv37lg7gj81dyq2bt9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2prv37lg7gj81dyq2bt9.png" alt="Warpbuild homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.warpbuild.com/" rel="noopener noreferrer"&gt;WarpBuild&lt;/a&gt; provides fast, cost-effective GitHub action runners that improve CI/CD performance. The main goal is to offer cloud-based deployment workflow automation and allow developers to manually handle activities like configuration and deployment. &lt;/p&gt;

&lt;p&gt;WarpBuild is designed for developers to accelerate deployments while reducing costs, with features such as automated testing and integration with any cloud provider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.warpbuild.com/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try WarpBuild ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Nullstone
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w7jwclpnuhu311uwlnq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w7jwclpnuhu311uwlnq.png" alt="Nullstone Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nullstone.io/" rel="noopener noreferrer"&gt;Nullstone&lt;/a&gt; helps developers faster deploy secure, full-stack applications on their own cloud infrastructure. It supports containers with self-service deployments, automated tools, and strong monitoring.&lt;/p&gt;

&lt;p&gt;Nullstone integrates with Terraform, Helm, and third-party services like Datadog and New Relic, providing flexibility and security while enabling faster software delivery, and better software development efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nullstone.io/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐️ Try Nullstone ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to Consider While Choosing the Best IDP
&lt;/h2&gt;

&lt;p&gt;Choosing the right platform for your business can be challenging due to many factors, such as the best features, procedures, and services they offer. By comparing their characteristics, and what they offer, you can easily find the best one that fits your business needs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgxrffa9lp9mp90vk999.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgxrffa9lp9mp90vk999.gif" alt="Multiple buttons gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, you should consider several factors, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ease of Use: An effective IDP should be easy to use and provide a smooth experience for developers. Find platforms that have a user-friendly interface, and self-service capabilities that will boost productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability: The IDP should support scalable infrastructure, especially if your team needs to deploy applications across multiple environments or clouds. A flexible platform allows teams to manage complex infrastructures that can easily scale and adapt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security: Analyze the security characteristics of each platform. The platform should provide robust compliance features to help teams manage risks, follow regulations, and ensure that only authorized people have access to sensitive resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration: Consider how well each platform integrates. A good platform integrates with tools, new technologies, and infrastructure. The integration speeds up the software delivery process and improves collaboration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost: It’s essential to evaluate the general and additional costs such as support, training, and other requirements. Each platform offers different features that come with different costs. Choose the one that best fits your company’s budget. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Suitability: All platforms offer different features that may be better for certain applications and processes. Consider platforms that better respond to your requirements and solve your business needs. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support: When choosing an IDP a main consideration is the quality of customer support they offer. The platform should have a responsive support team, providing 24/7 support, and comprehensive documentation. This will ensure your team will get timely assistance when facing challenges to reduce downtime. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the factors listed above are essential when choosing the best IDP for your business. By taking into account the cost, ease of use, security scalability, integration, sustainability, and support, you will find the best IDP that will fill your business requirements and bring greater productivity. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Finding the best internal developer platform involves several factors to consider. Each of these platforms provides different features and benefits that meet certain organizational requirements. By carefully evaluating each platform's advantages, disadvantages, and special features, your company may increase developer productivity, optimize processes, and maintain better security and compliance.   &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Amazon Bedrock: A Practical Guide for Developers and DevOps Engineers</title>
      <dc:creator>Opemipo Disu</dc:creator>
      <pubDate>Mon, 24 Mar 2025 13:05:12 +0000</pubDate>
      <link>https://dev.to/microtica/amazon-bedrock-a-practical-guide-for-developers-and-devops-engineers-kag</link>
      <guid>https://dev.to/microtica/amazon-bedrock-a-practical-guide-for-developers-and-devops-engineers-kag</guid>
      <description>&lt;p&gt;Once upon a time, building AI applications required deep experience with traditional technologies and some Machine Learning expertise. While that was the norm, developers had to configure models to their needs, provide GPUs, and manually optimize performance, which required a lot of effort and costs.&lt;/p&gt;

&lt;p&gt;While that approach seemed difficult, the AWS team built Amazon Bedrock, a tool that allows developers to easily create their AI applications through an API or the AWS Management Console using its embedded foundation models. Amazon Bedrock enables developers to build generative AI applications without the stress of directly managing the underlying stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4cj7cwuebobrrjpfsmc4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4cj7cwuebobrrjpfsmc4.gif" alt="Relax GIF" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, you’ll learn everything about Amazon Bedrock, the prerequisites of using Amazon Bedrock, how to get started with Amazon Bedrock, best practices for working with Amazon Bedrock, and even the core concepts of Amazon Bedrock. Other than that, you’ll also see some code samples of how you can work with AWS’s Bedrock API. So, this article will serve as an&amp;nbsp;&lt;strong&gt;A-Z guide&lt;/strong&gt;&amp;nbsp;for people who are interested in using Bedrock to build their generative AI applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Please, support Microtica 😅 🙏
&lt;/h2&gt;

&lt;p&gt;Before moving on, I’d love it if you could support our work at Microtica joining our community! ⭐️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://discord.gg/N8WdXyXxZR" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⭐️ Join Microtica’s Discord Community ⭐️&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpnhpxhp08zhpsuxqnzg.gif" alt="Thank you GIF" width="640" height="358"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What is Amazon Bedrock?
&lt;/h2&gt;

&lt;p&gt;Amazon Bedrock is a service that lets DevOps engineers and teams build gen AI applications. Instead of building or fine-tuning models manually, Amazon Bedrock uses foundational models from AI infrastructure providers to provide a ready-made API for developers to use easily. This approach removes the complexity that comes with building generative applications and working with underlying stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;Before getting in hands with Amazon Bedrock, I just thought it would be nice to share some benefits of Amazon Bedrock and include examples of how these benefits have a positive impact on your development workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quicker Development&lt;/strong&gt;: Compared to working manually, where you always have to work with models and fine-tune them, AWS lets you work with a single API. With this approach, you don’t have much to focus on. This approach saves a lot of time as it requires less effort than directly working with models.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: My colleague made an AI Assistant using Amazon Bedrock's text generation models without having to handle any ML models directly, which saved him time. He found this method quicker because he could add AI features in just a few days with an API call instead of spending months or weeks.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/U1mT6VjArKs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Amazon Bedrock is built on AWS’s Cloud Infrastructure and uses models from various companies, including AI21 Labs, Anthropic, Cohere, DeepSeek, Luma, Meta, Mistral AI, and Stability AI. This enables teams to scale their applications easily and under heavy workloads, Bedrock ensures excellent application performance without requiring manual intervention.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: An e-commerce service using Amazon Bedrock for product recommendations can easily scale resources during shopping seasons without compromising performance or experiencing downtime.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Integration with AWS Ecosystem&lt;/strong&gt;: As Amazon Bedrock is an AWS product, it seamlessly integrates with Amazon SageMaker, Lambda, and S3 for building, deploying, and managing applications.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: A bank using Amazon Bedrock for fraud detection can create automated workflows. For instance, AWS Lambda can identify suspicious transactions, save the reports in S3, and use SageMaker to check patterns.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cost-Effectiveness:&lt;/strong&gt;&amp;nbsp;Amazon Bedrock has flexible pricing, so you only pay for what you use. Instead of spending a lot on expensive servers and models, you can use any of Bedrock’s models that you think will help save costs while still getting powerful AI features. You can take a look at this page for Amazon Bedrock's pricing models.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: One of my colleagues automated blog posts with Amazon Bedrock and only paid for the API requests she used, saving money on monitoring and fine-tuning AI models.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started with Amazon Bedrock 🚀
&lt;/h2&gt;

&lt;p&gt;Now, it’s time to prepare to get our hands dirty. In this section, we will look into doing the real work and the things you should have before getting started. Even though Amazon Bedrock can be used to accomplish many tasks, this article is focused only on building generative AI applications easily with the AWS Management Console.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites For Using Amazon Bedrock
&lt;/h3&gt;

&lt;p&gt;Before getting started with Amazon Bedrock, here are some things you need to have ready:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic Python Knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An AWS Account&lt;/strong&gt;: This is primary: to get started, you need to&amp;nbsp;&lt;a href="https://aws.amazon.com/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;create an AWS account&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Management Console&lt;/strong&gt;: You need the console to interact with models if you don’t want to write code. Alternatively, you can use:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt;: You can use the CLI to create AWS CLI profiles using the API. For instructions on how to use this option, refer to this documentation. This option requires some basic Python knowledge.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;IAM Permissions&lt;/strong&gt;: You also need to assign the required IAM roles needed for Bedrock.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6td27syir0iz5jjb5q3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6td27syir0iz5jjb5q3.gif" alt="Lets go GIF" width="298" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will be using the AWS Management Console option for operations. You can use the CLI option to go a bit hands-on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic AI/ML Concepts
&lt;/h3&gt;

&lt;p&gt;Even though Amazon Bedrock helps with removing the complexities that come with building AI applications, a basic understanding of AI and ML is helpful because, even when using Amazon Bedrock, there are things you might encounter, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Foundational Models (FMs)&lt;/strong&gt;: These are the pre-built AI models that Amazon Bedrock provides for operations in generative applications. You might wonder if AWS owns the entire model, but some are from different companies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Engineering:&lt;/strong&gt;&amp;nbsp;This is the process of creating and improving input prompts to help AI models produce accurate and great responses. Good prompt engineering improves the model's understanding and ensures it aligns with the output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model fine-tuning&lt;/strong&gt;: With Amazon Bedrock, it’s possible to fine-tune models to your needs. You can always configure models to fit what you want; the approach for doing this is different from the manual approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Concepts of Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;Now, let’s take a look at some key concepts of Amazon Bedrock - by having a glance at them, you’ll have a deeper understanding of how Amazon Bedrock works and how to get the best out of it&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Foundation Models
&lt;/h3&gt;

&lt;p&gt;Let’s take a look at some foundation models that Amazon Bedrock uses and things to consider before using them.&lt;/p&gt;

&lt;p&gt;To find the list of models you could work with, their capabilities, and their availability in your region,&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;refer to this guide&lt;/a&gt;. In that guide, you’ll see everything about the models and the types of outputs they generate—for example, image, text, or code.&lt;/p&gt;

&lt;p&gt;Here are some things you should consider before using any of the models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: You should know if the model aligns with your application’s needs. For example, if you’re building a chatbot that generates text for responses, you need to work with one of the models that support text for their outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance vs. Cost&lt;/strong&gt;: Now, this is where the saying "quality over quantity" really matters. You need to think about two things: performance and cost. Some models work quickly but are usually expensive. If you want a model that fits your budget, you might have to find a balance between how well it performs and how much it costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt;: Amazon Bedrock lets you adjust models for some uses. Depending on your needs, you might want a model that can be customized to fit your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Amazon Bedrock API
&lt;/h2&gt;

&lt;p&gt;Now, let's explore Amazon Bedrock's API and SDK and learn how to use them. First, we'll have a look at the API and learn how to work with the foundational models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;Apart from interacting with the service, Amazon Bedrock API allows you to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work with the foundation models to generate text, create images, generate code&lt;/li&gt;
&lt;li&gt;Adjust the model’s behaviour with settings you can change.&lt;/li&gt;
&lt;li&gt;Get information about the model, including its ARN and ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Amazon Bedrock APIs use AWS's normal authentication and authorization methods, and that requires IAM roles and permissions for security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication &amp;amp; Access Control
&lt;/h3&gt;

&lt;p&gt;To use the Bedrock API, you need to install the&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;latest version of AWS CLI&lt;/a&gt;&amp;nbsp;and log in with AWS IAM credentials. Make sure your IAM user or role has the required permissions, too.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MarketplaceBedrock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="s2"&gt;"aws-marketplace:ViewSubscriptions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="s2"&gt;"aws-marketplace:Unsubscribe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="s2"&gt;"aws-marketplace:Subscribe"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This policy allows you to use the API to run models. To follow up with working with Amazon Bedrock’s APIs, you can refer to and read these guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/APIReference/welcome.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;&lt;strong&gt;Amazon Bedrock API Reference&lt;/strong&gt;&lt;/a&gt;: In this documentation, you’ll find the service endpoints you’ll likely work with.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;&lt;strong&gt;Getting Started With Amazon Bedrock API&lt;/strong&gt;&lt;/a&gt;: This documentation will walk you through everything you need to know about Amazon Bedrock’s API—from its installation requirements to the How-tos; it’s a more detailed guide for setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AWS SDK Integration
&lt;/h3&gt;

&lt;p&gt;AWS provides SDKs to integrate with your favourite programming languages, such as Python, Java, Go, JavaScript, Rust, etc. Now, let’s have a look at some examples of how they work with different languages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python (Boto3)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;botocore.exceptions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ClientError&lt;/span&gt;

    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_foundation_models&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bedrock_client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bedrock_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_foundation_models&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;modelSummaries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Got %s foundation models.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;ClientError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Couldn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t list foundation models.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

        &lt;span class="n"&gt;bedrock_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;fm_models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list_foundation_models&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bedrock_client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fm_models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;modelName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;---------------------------&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s a clear example of how to list the available Amazon Bedrock models with Python (Boto3). To learn more about how to the Python SDK works,&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/code-library/latest/ug/python_3_bedrock_code_examples.html" rel="noopener noreferrer"&gt;read this guide&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript Example (AWS SDK for JavaScript v3)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileURLToPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;BedrockClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;ListFoundationModelsCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-bedrock&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BedrockClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ListFoundationModelsCommand&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelSummaries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listing the available Bedrock foundation models:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

          &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Model: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Name: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Provider: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;providerName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Model ARN: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelArn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Input modalities: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputModalities&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Output modalities: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outputModalities&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Supported customizations: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customizationsSupported&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Supported inference types: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inferenceTypesSupported&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;` Lifecycle status: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ACTIVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;legacy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LEGACY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;`There are &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; active and &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;legacy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; legacy foundation models in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;

          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code snippet above also shows the listing of the available Bedrock foundation models. To learn more about how to use the JavaScript SDK,&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_bedrock_code_examples.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;read this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are code samples that showcase how to integrate Bedrock SDKs into your favorite programming languages. You can find them in&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/code-library/latest/ug/bedrock-runtime_code_examples.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Amazon Bedrock API Responses
&lt;/h3&gt;

&lt;p&gt;Now, lets have a look at the main API operations that Amazon Bedrock provides for model prediction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;InvokeModel&lt;/strong&gt;&amp;nbsp;– Sends one prompt and gets a response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Converse&lt;/strong&gt;&amp;nbsp;– Allows ongoing conversations by including previous messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, Amazon Bedrock supports streaming responses with&amp;nbsp;&lt;code&gt;InvokeModelWithResponseStream&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;ConverseStream&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To see the type of responses you’ll get when you submit a single prompt with&amp;nbsp;&lt;code&gt;InvokeModel&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;Converse&lt;/code&gt;, check the following guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-call.html?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;&lt;strong&gt;Converse API&lt;/strong&gt;&lt;/a&gt;: This guide showcases how to use Amazon Bedrock using the Converse API. It also includes how you can make a request with an&amp;nbsp;&lt;a href="https://docs.aws.amazon.com/general/latest/gr/bedrock.html#br-rt" rel="noopener noreferrer"&gt;Amazon Bedrock runtime endpoint&lt;/a&gt;&amp;nbsp;and examples of the response you’ll get with either&amp;nbsp;&lt;code&gt;Converse&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;ConverseStream&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html" rel="noopener noreferrer"&gt;&lt;strong&gt;InvokeModel&lt;/strong&gt;&lt;/a&gt;:&amp;nbsp;This guide explains how to use the&amp;nbsp;&lt;code&gt;InvokeModel&lt;/code&gt;&amp;nbsp;operation in Amazon Bedrock. It also covers how to send requests to foundation models, set parameters for the best results, and manage responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building A Conversational AI Application With Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;Now, let's start building our first application in Amazon Bedrock using the AWS Management Console. For this first project, we'll create a conversational AI assistant that works only with text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Get started with Amazon Bedrock in the AWS Management Console
&lt;/h3&gt;

&lt;p&gt;Firstly, sign into the AWS Management Console from the main AWS sign-in URL. When, you’re signed in, you’ll be redirected to the Dashboard. In the dashboard, select the&amp;nbsp;&lt;strong&gt;Amazon Bedrock&lt;/strong&gt;&amp;nbsp;option (search for "Bedrock" in the AWS search bar).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqzmug543vdcmic3m926.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqzmug543vdcmic3m926.png" alt="Searching AWS Bedrock from Console" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting Amazon Bedrock, head over to the&amp;nbsp;&lt;strong&gt;Model Access&lt;/strong&gt;&amp;nbsp;tab and ensure you have access to any&amp;nbsp;&lt;strong&gt;Amazon Titan&lt;/strong&gt;&amp;nbsp;text generation models by requesting access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fethhnpez4mjz74kfppu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fethhnpez4mjz74kfppu4.png" alt="Request Access Models" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting the model you'd like to work with, hit the&amp;nbsp;&lt;strong&gt;Next&lt;/strong&gt;&amp;nbsp;button. Afterwards, you'll be redirected to a tab where you should submit a request to access the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Building the Chatbot Using Amazon Titan
&lt;/h3&gt;

&lt;p&gt;Head over to the&amp;nbsp;&lt;strong&gt;Playgrounds&lt;/strong&gt;&amp;nbsp;section in the side navigation and select the&amp;nbsp;&lt;strong&gt;Chat / Text&lt;/strong&gt;&amp;nbsp;section. Enter a prompt in the playground. Click the&amp;nbsp;&lt;strong&gt;Run&lt;/strong&gt;&amp;nbsp;button to generate a response from Titan’s text model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpn9wkt5wgg6pbpzjlins.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpn9wkt5wgg6pbpzjlins.png" alt="Single Prompt AWS" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Deploy the Chatbot with AWS Lambda
&lt;/h3&gt;

&lt;p&gt;Now, let’s deploy the chatbot with&amp;nbsp;&lt;a href="https://aws.amazon.com/lambda/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;&amp;nbsp;as a serverless application! First, we need to create an AWS Lambda Function. Here are some steps to follow to create an AWS Lambda Function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to AWS Lambda and Create a Function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx4ojl0m9xfbq915r5ip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx4ojl0m9xfbq915r5ip.png" alt="AWS Lambda Homepage" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the&amp;nbsp;&lt;strong&gt;Author from Scratch&lt;/strong&gt;&amp;nbsp;tab and make deployment configurations. Note that the runtime should be&amp;nbsp;&lt;strong&gt;Python 3.10&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnwrp2wa31d28iw9trc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnwrp2wa31d28iw9trc0.png" alt="Author from Scratch selection" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a role with full access to the&amp;nbsp;&lt;strong&gt;Bedrock and CloudWatch permissions&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhc54don0leobdqjle5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhc54don0leobdqjle5u.png" alt="Creating Role" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create function! 🚀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add some code to the Lambda function and hit the&amp;nbsp;&lt;strong&gt;Deploy&lt;/strong&gt;&amp;nbsp;button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;bedrock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bedrock-runtime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;queryStringParameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bedrock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxTokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amazon.titan-text-lite-v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;model_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;model_output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Deploy the API with API Gateway
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Under the&amp;nbsp;&lt;strong&gt;Function Overview&lt;/strong&gt;, click the&amp;nbsp;&lt;strong&gt;Add Trigger&lt;/strong&gt;&amp;nbsp;button and select the&amp;nbsp;&lt;strong&gt;API gateway&lt;/strong&gt;&amp;nbsp;option.&lt;/li&gt;
&lt;li&gt;Create HTTP API and configure the security method for your API endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Deploy the API! 🤘&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjia8esazc8mtjy13dqfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjia8esazc8mtjy13dqfj.png" alt="Deploying HTTP API" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Note down your&amp;nbsp;&lt;strong&gt;Invoke URL&lt;/strong&gt;&amp;nbsp;to interact with the chatbot! 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sa9rcznwfc4yraoie4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sa9rcznwfc4yraoie4k.png" alt="Invoking URL" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Finally, you can interact with your API’s endpoint and build with it. 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Code Generation Tool Using Amazon Bedrock and Anthropic Bedrock
&lt;/h2&gt;

&lt;p&gt;Now, let’s build something more fun and technical. In this section, we will be building a code generation tool using Amazon Bedrock and Anthropic Claude’s 2.0 Model (a model that generates code as its form of response). Don’t fret, we’ll still be working with the AWS Management Console but a basic Python knowledge is required for this use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Navigate to Bedrock and Select the Anthropic Claude 2.0 Model
&lt;/h3&gt;

&lt;p&gt;Just like we did in the chatbot use case, access Amazon Bedrock in the AWS Management Console. Go to the&amp;nbsp;&lt;strong&gt;Chat/Text&lt;/strong&gt;&amp;nbsp;section under the&amp;nbsp;&lt;strong&gt;Playground&lt;/strong&gt;&amp;nbsp;section.&lt;/p&gt;

&lt;p&gt;Under the&amp;nbsp;&lt;strong&gt;Select Model&lt;/strong&gt;&amp;nbsp;dropdown, select the Anthropic Claude 2.0 Model. Once done, you can now enter a code-related prompt in the chat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskq8wrpq4vnkuwsdifrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskq8wrpq4vnkuwsdifrt.png" alt="Selecting Model from Dropdown in Chat." width="800" height="669"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s a super great model to work with as it doesn’t just generate code; it also explains what the code does and how it works. It’s a super fast and effective model to work with!&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the Code Generation Use-Case With AWS Lambda
&lt;/h3&gt;

&lt;p&gt;Also just as we did in the first use-case, we will also deploy code generation using AWS Lambda.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a New Lambda Function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add some Python code to Lambda Function (Runtime: 3.9):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;bedrock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bedrock-runtime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

  &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;queryStringParameters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bedrock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;k&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frequency_penalty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;presence_penalty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arn:aws:bedrock::account:model/claude-v2-20221215&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generated_text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Deploy an API for Code Generation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to&amp;nbsp;&lt;strong&gt;API Gateway&lt;/strong&gt;&amp;nbsp;and select the&amp;nbsp;&lt;strong&gt;HTTP API&lt;/strong&gt;&amp;nbsp;option.&lt;/li&gt;
&lt;li&gt;Integrate it with the code generator.&lt;/li&gt;
&lt;li&gt;Deploy the API and get the&amp;nbsp;&lt;strong&gt;Invoke URL&lt;/strong&gt;&amp;nbsp;for interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices For Working With Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;When working with&amp;nbsp;&lt;strong&gt;Amazon Bedrock&lt;/strong&gt;&amp;nbsp;you need pay attention to security, cost, and performance. By following these best practices, you can make sure your AI applications are secure, efficient, and cost-effective.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Data Security and Privacy
&lt;/h3&gt;

&lt;p&gt;Ideally, you want to keep your data private because AI models often handle sensitive user data, so security is very important in this case. To protect data when using AWS Bedrock, here some practices to follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use IAM Roles and Policies:&lt;/strong&gt;&amp;nbsp;Follow the&amp;nbsp;&lt;a href="https://community.aws/content/2dsQs3aTnwV3LKeUDFkXNSndHjp/understanding-the-principle-of-least-privilege-in-aws?lang=en&amp;amp;utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;least privilege principle&lt;/a&gt;&amp;nbsp;to limit access to Bedrock APIs and data storage. This means only giving people the permissions they need and nothing more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypt Data:&lt;/strong&gt;&amp;nbsp;You use&amp;nbsp;&lt;strong&gt;AWS Key Management Service (KMS)&lt;/strong&gt;&amp;nbsp;to protect sensitive data both when it's stored and when it's being sent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor and Audit Access:&lt;/strong&gt;&amp;nbsp;Enable&amp;nbsp;&lt;strong&gt;CloudWatch&lt;/strong&gt;&amp;nbsp;and&amp;nbsp;&lt;strong&gt;AWS Config&lt;/strong&gt;&amp;nbsp;to keep track of who accesses AI models, data, and logs; and how they’re being accessed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mask Data:&lt;/strong&gt;&amp;nbsp;Before sending data to Bedrock, remove any personally identifiable information to reduce the risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Cost Optimization (Managing Bedrock Usage and Expenses) 💸
&lt;/h3&gt;

&lt;p&gt;AWS Bedrock uses a&amp;nbsp;&lt;strong&gt;pay-per-use&lt;/strong&gt;&amp;nbsp;pricing model, so it's important to manage costs well. You get billed based on what you use. Here's how can optimize cost using AWS Bedrock:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose the Right Foundation Model:&lt;/strong&gt;&amp;nbsp;Different models cost different amounts; select the one that best fits your needs and budget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize API Calls:&lt;/strong&gt;&amp;nbsp;Cut down on unnecessary API requests by using caching and batching when you can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Usage:&lt;/strong&gt;&amp;nbsp;Use&amp;nbsp;&lt;a href="https://aws.amazon.com/aws-cost-management/aws-cost-explorer/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;AWS Cost Explorer&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="https://aws.amazon.com/aws-cost-management/aws-budgets/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;AWS Budgets&lt;/a&gt;&amp;nbsp;to track your spending and set up alerts for any unexpected cost increases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Auto Scaling:&lt;/strong&gt;&amp;nbsp;When using Bedrock with AWS Lambda, adjust the number of requests to reduce unnecessary API calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Bias and Fairness
&lt;/h3&gt;

&lt;p&gt;AI models can pick up biases based on the data they are trained on, which can cause problems. To make sure things are fair:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check Model Responses:&lt;/strong&gt;&amp;nbsp;Regularly test the model's outputs with prompts to identify any biases or errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Diverse Data for Fine-Tuning:&lt;/strong&gt;&amp;nbsp;When adjusting models, make sure the data includes various groups and viewpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Performance Tuning
&lt;/h3&gt;

&lt;p&gt;To enhance response times and overall performance, follow these practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tune API Parameters:&lt;/strong&gt;&amp;nbsp;Adjust settings like&amp;nbsp;&lt;code&gt;temperature&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;maxTokens&lt;/code&gt;&amp;nbsp;to get the best results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use an GPU-Optimized Infrastructure:&lt;/strong&gt;&amp;nbsp;If you are deploying custom models, use&amp;nbsp;&lt;a href="https://aws.amazon.com/ai/machine-learning/inferentia/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;AWS Inferentia&lt;/a&gt;&amp;nbsp;to boost performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balance Requests:&lt;/strong&gt;&amp;nbsp;If you have a lot of traffic, use&amp;nbsp;&lt;a href="https://aws.amazon.com/elasticloadbalancing/application-load-balancer/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;AWS Application Load Balancer&lt;/a&gt;&amp;nbsp;to distribute requests more efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce Latency:&lt;/strong&gt;&amp;nbsp;Place applications closer to users with&amp;nbsp;&lt;a href="https://aws.amazon.com/global-accelerator/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" rel="noopener noreferrer"&gt;AWS Global Accelerator&lt;/a&gt;&amp;nbsp;or AWS edge services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AWS Bedrock makes it easier to integrate AI by offering scalable foundation models from Amazon and other infrastructures without the stress of training models and managing infrastructure. To get the best results, developers should focus more on security, cost-effectiveness, and performance improvements without working manually.&lt;/p&gt;

&lt;p&gt;To keep exploring AWS Bedrock, developers should try out different models, adjust outputs, and connect with other AWS services. Keeping up with Amazon Bedrock’s guides, blogs and other resources will help make the most of Bedrock and encourage new ideas in AI-powered applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before you go… 🥹
&lt;/h3&gt;

&lt;p&gt;Thank you for taking the time to learn about building AI applications with AWS Bedrock. If you found this article helpful, please consider supporting Microtica by creating an account and&amp;nbsp;&lt;a href="https://discord.gg/N8WdXyXxZR" rel="noopener noreferrer"&gt;joining the community&lt;/a&gt;. Your support helps us keep improving and offering valuable resources for the developer community!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://app.microtica.com/?utm_source=DEV&amp;amp;utm_medium=post&amp;amp;utm_campaign=devrel" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Join Microtica for free! 🚀&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5i3lvc9gaht4vyuljyme.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5i3lvc9gaht4vyuljyme.gif" alt="Thank You GIF Minions" width="498" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
