<?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>Forem: Alexander Attoh</title>
    <description>The latest articles on Forem by Alexander Attoh (@alexander-attoh).</description>
    <link>https://forem.com/alexander-attoh</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3593783%2F6561572a-4764-4a60-b2d7-52b401ce8662.png</url>
      <title>Forem: Alexander Attoh</title>
      <link>https://forem.com/alexander-attoh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alexander-attoh"/>
    <language>en</language>
    <item>
      <title>Medical Service API - v1.0</title>
      <dc:creator>Alexander Attoh</dc:creator>
      <pubDate>Tue, 23 Dec 2025 15:11:33 +0000</pubDate>
      <link>https://forem.com/alexander-attoh/medical-service-api-v10-44b0</link>
      <guid>https://forem.com/alexander-attoh/medical-service-api-v10-44b0</guid>
      <description>&lt;h2&gt;
  
  
  Medical Service API
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Project Name
&lt;/h4&gt;

&lt;p&gt;Medical Service API&lt;/p&gt;

&lt;h4&gt;
  
  
  Description
&lt;/h4&gt;

&lt;p&gt;Medical Service API is a Java-based RESTful application designed to manage and track the full lifecycle of patient appointments, from initial visits to follow-up appointments and recorded results of each appointment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Author
&lt;/h4&gt;

&lt;p&gt;ATTOH ALEXANDER IFEANYICHUKWU&lt;/p&gt;

&lt;h4&gt;
  
  
  Version
&lt;/h4&gt;

&lt;p&gt;1.0&lt;/p&gt;

&lt;h4&gt;
  
  
  Date
&lt;/h4&gt;

&lt;p&gt;21st December 2025&lt;/p&gt;




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Medical Service API is a Java-based RESTful application designed to manage and track the complete lifecycle of patient appointments, including initial consultations, follow-up appointments, and associated medical results.&lt;/p&gt;

&lt;p&gt;The system addresses common challenges in medical appointment management such as tracking appointment history, maintaining patient–appointment relationships, and ensuring consistent state transitions throughout an appointment’s lifecycle.&lt;/p&gt;

&lt;p&gt;It is intended for medical institutions and healthcare systems that require a structured, scalable, and secure backend service for managing patient appointments and related workflows.&lt;/p&gt;

&lt;p&gt;At a high level, the API provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patient and appointment lifecycle management&lt;/li&gt;
&lt;li&gt;Support for follow-up appointment chaining&lt;/li&gt;
&lt;li&gt;Enforced business rules for appointment status transitions&lt;/li&gt;
&lt;li&gt;A RESTful interface suitable for integration with web or mobile client applications&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  API Documentation
&lt;/h2&gt;

&lt;p&gt;This section documents the REST endpoints exposed by the medical service.&lt;br&gt;
Each endpoint is defined by its HTTP method, URL, request body, response format, error cases, and example usage.&lt;/p&gt;
&lt;h4&gt;
  
  
  Appointment APIs
&lt;/h4&gt;
&lt;h5&gt;
  
  
  Book Appointment
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;POST&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/appointments&lt;/code&gt;&lt;br&gt;
Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "patientId": "uuid",
  "doctorId": "uuid",
  "appointmentTime": "2025-01-20T10:00",
  "followUpAppointmentType": "CONSULTATION"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Appointment booked",
  "data": {
    "id": "uuid",
    "appointmentTime": "2025-01-20T10:00",
    "status": "AWAITING",
    "result": null,
    "appointmentType": "CONSULTATION",
    "followUpAppointmentId": null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patient not found&lt;/li&gt;
&lt;li&gt;Doctor not found&lt;/li&gt;
&lt;li&gt;Appointment time not within doctor availability&lt;/li&gt;
&lt;li&gt;Appointment time conflicts with existing bookings
Notes&lt;/li&gt;
&lt;li&gt;Appointment is always created in AWAITING state.&lt;/li&gt;
&lt;li&gt;Appointment duration is inferred from AppointmentType.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Cancel Appointment
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;PATCH&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/appointments/{appointmentId}/cancel/{doctorId}&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appointmentId – Appointment UUID
doctorId – Doctor UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Appointment cancelled",
  "data": {
    "id": "uuid",
    "appointmentTime": "2025-01-20T10:00",
    "status": "CANCELLED",
    "result": null,
    "appointmentType": "CONSULTATION",
    "followUpAppointmentId": null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appointment not found&lt;/li&gt;
&lt;li&gt;Doctor not authorized for this appointment&lt;/li&gt;
&lt;li&gt;Appointment can no longer be updated
Rules&lt;/li&gt;
&lt;li&gt;Only AWAITING appointments can be cancelled.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Begin Appointment
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;PATCH&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/appointments/{appointmentId}/begin&lt;/code&gt;&lt;br&gt;
Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "doctorId": "uuid"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Appointment started",
  "data": {
    "id": "uuid",
    "appointmentTime": "2025-01-20T10:00",
    "status": "IN_PROGRESS",
    "result": null,
    "appointmentType": "CONSULTATION",
    "followUpAppointmentId": null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appointment not found&lt;/li&gt;
&lt;li&gt;Doctor does not match appointment&lt;/li&gt;
&lt;li&gt;Appointment not in AWAITING&lt;/li&gt;
&lt;li&gt;Appointment time has not arrived&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Complete Appointment
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;PATCH&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/appointments/{appointmentId}/complete/{doctorId}&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appointmentId – Appointment UUID
doctorId – Doctor UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "doctorId": "uuid",
  "result": "Patient diagnosed with mild hypertension"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Appointment completed",
  "data": {
    "id": "uuid",
    "appointmentTime": "2025-01-20T10:00",
    "status": "COMPLETED",
    "result": "Patient diagnosed with mild hypertension",
    "appointmentType": "CONSULTATION",
    "followUpAppointmentId": null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appointment not found&lt;/li&gt;
&lt;li&gt;Doctor does not match appointment&lt;/li&gt;
&lt;li&gt;Appointment not in progress&lt;/li&gt;
&lt;li&gt;Result is required
Rules&lt;/li&gt;
&lt;li&gt;Result must be provided before completion.&lt;/li&gt;
&lt;li&gt;Only doctors can complete appointments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Book Follow-Up Appointment
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;POST&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/appointments/{appointmentId}/follow-up&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;appointmentId – Appointment UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "patientId": "uuid",
  "doctorId": "uuid",
  "appointmentTime": "2025-01-30T09:00",
  "followUpAppointmentType": "SCAN"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Follow-up booked",
  "data": {
    "id": "uuid",
    "appointmentTime": "2025-01-30T09:00",
    "status": "AWAITING",
    "result": null,
    "appointmentType": "SCAN",
    "followUpAppointmentId": null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appointment not found.&lt;/li&gt;
&lt;li&gt;Follow-up requires completed appointment&lt;/li&gt;
&lt;li&gt;Patient not found.&lt;/li&gt;
&lt;li&gt;Doctor not found.&lt;/li&gt;
&lt;li&gt;Appointment mismatch&lt;/li&gt;
&lt;li&gt;Doctor does not have free time&lt;/li&gt;
&lt;li&gt;Selected time is not within the free range
Rules&lt;/li&gt;
&lt;li&gt;Only completed appointments can have follow-ups.&lt;/li&gt;
&lt;li&gt;Follow-up is linked via followUpAppointmentId, forming an appointment chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Doctor APIs
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Register Doctor
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;POST&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/doctors&lt;/code&gt;&lt;br&gt;
Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "fullName": "Dr John Doe",
  "email": "john@example.com",
  "phone": "+123456789",
  "specialization": "CARDIOLOGY",
  "bio": "Senior cardiologist with 10 years experience"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Doctor registered",
  "data": {
    "id": "uuid",
    "fullName": "Dr John Doe",
    "email": "john@example.com",
    "phone": "+123456789",
    "specialization": "CARDIOLOGY",
    "bio": "Senior cardiologist with 10 years experience",
    "doctorAvailabilities": [],
    "appointments": []
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doctor ID is system generated&lt;/li&gt;
&lt;li&gt;Full name required&lt;/li&gt;
&lt;li&gt;Email required&lt;/li&gt;
&lt;li&gt;Phone required&lt;/li&gt;
&lt;li&gt;Specialization required&lt;/li&gt;
&lt;li&gt;Bio required&lt;/li&gt;
&lt;li&gt;This email is already registered to a doctor&lt;/li&gt;
&lt;li&gt;This phone is already registered to a doctor&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Add Doctor Availability
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;POST&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/doctors/{doctorId}/availability&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doctorId – Doctor UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "day": "MONDAY",
  "startTime": "09:00",
  "endTime": "14:00"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Availability added",
  "data": {
    "id": "uuid",
    "day": "MONDAY",
    "startTime": "09:00",
    "endTime": "14:00"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doctor availability ID is system generated&lt;/li&gt;
&lt;li&gt;Doctor not found&lt;/li&gt;
&lt;li&gt;Day of the week is required&lt;/li&gt;
&lt;li&gt;Start time is required&lt;/li&gt;
&lt;li&gt;End time is required and should be after start time&lt;/li&gt;
&lt;li&gt;Selected time conflicts with existing availability&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Get Doctor Appointments
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/doctors/{doctorId}/appointments&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doctorId – Doctor UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Doctor appointments",
  "data": [
    {
      "id": "uuid",
      "appointmentTime": "2025-01-20T10:00",
      "status": "AWAITING",
      "result": null,
      "appointmentType": "CONSULTATION",
      "followUpAppointmentId": null
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Get Next Appointment
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/doctors/{doctorId}/appointments/next&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doctorId – Doctor UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Next appointment",
  "data": {
    "id": "uuid",
    "appointmentTime": "2025-01-20T10:00",
    "status": "AWAITING",
    "result": null,
    "appointmentType": "CONSULTATION",
    "followUpAppointmentId": null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Patient APIs
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Register Patient
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;POST&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/patients&lt;/code&gt;&lt;br&gt;
Request Body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "fullName": "Jane Doe",
  "email": "jane@example.com",
  "phone": "+2348012345678",
  "dob": "1998-05-12",
  "gender": "FEMALE",
  "address": "Lagos, Nigeria"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Patient registered",
  "data": {
    "id": "uuid",
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+2348012345678",
    "dob": "1998-05-12",
    "gender": "FEMALE",
    "address": "Lagos, Nigeria",
    "appointments": []
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patient ID is system generated&lt;/li&gt;
&lt;li&gt;Full name required&lt;/li&gt;
&lt;li&gt;Email required&lt;/li&gt;
&lt;li&gt;Phone required&lt;/li&gt;
&lt;li&gt;Invalid DOB&lt;/li&gt;
&lt;li&gt;Gender required&lt;/li&gt;
&lt;li&gt;Address required&lt;/li&gt;
&lt;li&gt;This email is already registered to a patient&lt;/li&gt;
&lt;li&gt;This phone is already registered to a patient&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Get Patient Details
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/patients/{patientId}&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patientId – Patient UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Patient fetched",
  "data": {
    "id": "uuid",
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+2348012345678",
    "dob": "1998-05-12",
    "gender": "FEMALE",
    "address": "Lagos, Nigeria",
    "appointments": []
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patient with this ID is not registered&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Get Patient Appointments
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/patients/{patientId}/appointments&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patientId – Patient UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Appointments fetched",
  "data": [
    {
      "id": "uuid",
      "appointmentTime": "2025-01-20T10:00",
      "status": "AWAITING",
      "result": null,
      "appointmentType": "CONSULTATION",
      "followUpAppointmentId": null
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Get Appointment Trail
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/patients/{patientId}/appointments/{appointmentId}/trail&lt;/code&gt;&lt;br&gt;
Request Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;patientId – Patient UUID
appointmentId – Appointment UUID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Appointment trail",
  "data": [
    {
      "id": "uuid",
      "appointmentTime": "2025-01-20T10:00",
      "status": "COMPLETED",
      "result": "Patient diagnosed with mild hypertension",
      "appointmentType": "CONSULTATION",
      "followUpAppointmentId": "follow-up-uuid"
    },
    {
      "id": "follow-up-uuid",
      "appointmentTime": "2025-01-30T09:00",
      "status": "AWAITING",
      "result": null,
      "appointmentType": "SCAN",
      "followUpAppointmentId": null
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rules&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Returns the full follow-up chain.&lt;/li&gt;
&lt;li&gt;Prevents circular references.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Get Available Doctors
&lt;/h5&gt;

&lt;p&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;br&gt;
URL: &lt;code&gt;/api/patients/doctors&lt;/code&gt;&lt;br&gt;
Query Parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;specialization (required)
day (optional)
doctorFullName (optional)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": true,
  "message": "Doctors fetched",
  "data": [{
    "date": "2025-01-21",
    "doctors": [
      {
        "doctorId": "uuid",
        "fullName": "Dr John Doe",
        "totalBookedHours": 2,
        "freeRanges": [
          { "start": "09:00", "end": "11:00" },
          { "start": "15:00", "end": "19:00" }
        ]
      }
    ]
  }]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specialization required&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>java</category>
    </item>
    <item>
      <title>How I Built "Backend Mentor" My First Hands-On Integration with Mastra</title>
      <dc:creator>Alexander Attoh</dc:creator>
      <pubDate>Mon, 03 Nov 2025 17:32:24 +0000</pubDate>
      <link>https://forem.com/alexander-attoh/how-i-built-backend-mentor-my-first-hands-on-integration-with-mastra-nog</link>
      <guid>https://forem.com/alexander-attoh/how-i-built-backend-mentor-my-first-hands-on-integration-with-mastra-nog</guid>
      <description>&lt;p&gt;🚀 &lt;/p&gt;

&lt;p&gt;You know that feeling when you find a new tool that just &lt;strong&gt;clicks&lt;/strong&gt;?&lt;br&gt;
That’s exactly how I felt when I discovered &lt;strong&gt;Mastra&lt;/strong&gt; — a new framework for building AI agents that actually &lt;strong&gt;feels like engineering&lt;/strong&gt;, not just prompt hacking.&lt;/p&gt;

&lt;p&gt;Over the past week, I’ve been experimenting with Mastra to build something I’ve always wanted:&lt;br&gt;
a friendly, always-available &lt;strong&gt;AI mentor&lt;/strong&gt; that helps developers learn backend concepts in bite-sized, conversational lessons.&lt;/p&gt;

&lt;p&gt;I called it &lt;strong&gt;Backend Mentor&lt;/strong&gt;, and in this post, I’ll walk you through how I built it, what worked, what didn’t, and what I learned along the way.&lt;/p&gt;


&lt;h2&gt;
  
  
  💡 The Idea: An AI That Teaches Like a Developer Friend
&lt;/h2&gt;

&lt;p&gt;I’ve always wanted to have a mentor that I could go to always and learn something new each day, but not just a blogger who may already post constantly, but someone who I could ask questions and would know my strengths and weaknesses.&lt;br&gt;
So I thought: &lt;em&gt;What if I could train an AI to do that instead?&lt;/em&gt;&lt;br&gt;
Something that doesn’t just spit out definitions, but &lt;strong&gt;teaches concepts like a senior dev explaining things over coffee&lt;/strong&gt; — using relatable examples, some Node.js code, and a clear flow.&lt;/p&gt;

&lt;p&gt;I didn’t want a chatbot.&lt;br&gt;
I wanted a &lt;strong&gt;teacher&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧱 Setting Up the Foundation
&lt;/h2&gt;

&lt;p&gt;I started with a basic Node.js setup and installed Mastra:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-mastra@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I created a structure that looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
 └── mastra/
     ├── agents/
     ├── a2a/
     └── index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty neat.&lt;br&gt;
Each folder has a clear purpose:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;agents/&lt;/strong&gt; → where the AI logic lives&lt;br&gt;
&lt;strong&gt;a2a/&lt;/strong&gt; → where I expose API routes&lt;br&gt;
&lt;strong&gt;index.ts&lt;/strong&gt; → bootstrapping Mastra itself&lt;/p&gt;

&lt;p&gt;It instantly felt more like setting up Express — but for AI logic.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 Building the “Backend Mentor” Agent
&lt;/h2&gt;

&lt;p&gt;At first, I thought I needed multiple tools — one for picking topics, another for generating lessons, another for Q&amp;amp;A.&lt;/p&gt;

&lt;p&gt;But then I realized: I was over-engineering it.&lt;br&gt;
The LLM is already capable of reasoning through those steps — I just needed to tell it &lt;strong&gt;what role it’s playing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So I scrapped the tools and wrote a really clear instruction prompt instead, just to start simple, and we could improve as we go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;backendMentorAgent&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;Agent&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;Backend Mentor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
You are "Backend Mentor" — an AI teacher and learning companion for backend developers.

Your mission:
- Teach backend development in a structured yet conversational way.
- Choose relevant or new backend topics when asked to learn something.
- Generate clear, well-explained lessons (10–20 minute reads) that balance theory and real-world examples.
- Answer user questions, clarify concepts, and expand on related subtopics naturally.
- Track recently covered topics to avoid unnecessary repetition, but revisit them strategically for reinforcement.

Tone and style:
- Professional yet friendly — think "senior developer mentoring a junior."
- Concise, precise, and technically correct.
- Avoid unnecessary filler or hype — focus on clarity and insight.
- Use examples in JavaScript/Node.js when appropriate.

Behavior:
- If the user is unsure what to learn, suggest a few backend topics.
- When asked a question, answer it directly with explanation and optional examples.
- When teaching, use short sections, headings, and code snippets.
- Assume persistence of short-term context (you remember recent lessons).

Output format:
- Respond in Markdown for readability.
- Include brief code samples where useful.
- Do not stop after the intro or preamble. Always include the full lesson in your next response.
`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google/gemini-2.5-pro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;

    &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LibSQLStore&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file:../mastra.db&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;That’s it.&lt;br&gt;
No complex tool chains — just a clear identity, purpose, and tone.&lt;/p&gt;

&lt;p&gt;And honestly? That one instruction block changed everything.&lt;br&gt;
It made the agent feel &lt;strong&gt;coherent&lt;/strong&gt; — it had a voice, a personality, and an agenda.&lt;/p&gt;


&lt;h2&gt;
  
  
  💾 Adding Memory (Because Context Matters)
&lt;/h2&gt;

&lt;p&gt;Mastra has built-in support for memory through different storage backends.&lt;br&gt;
I used the &lt;strong&gt;LibSQLStore&lt;/strong&gt;, which runs locally and persists data between runs — perfect for lightweight projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;Agent&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;@mastra/core/agent&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;Memory&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;@mastra/memory&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;LibSQLStore&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;@mastra/libsql&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;backendMentorAgent&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;Agent&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;Backend Mentor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;instructions&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="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google/gemini-2.5-pro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;

    &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LibSQLStore&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file:../mastra.db&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;Now my agent can remember what topics it has already taught —&lt;br&gt;
so if it explained “Caching Strategies” yesterday, it won’t repeat it today.&lt;/p&gt;

&lt;p&gt;That’s the kind of continuity that makes learning feel human.&lt;/p&gt;


&lt;h2&gt;
  
  
  🌐 Making It Accessible with A2A (Agent-to-Agent) API
&lt;/h2&gt;

&lt;p&gt;Mastra’s &lt;strong&gt;registerApiRoute&lt;/strong&gt; function is such a win.&lt;br&gt;
It basically lets you turn your agent into a callable API without any boilerplate.&lt;/p&gt;

&lt;p&gt;Here’s what my A2A route looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;registerApiRoute&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;@mastra/core/server&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;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;MessagePart&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;text&lt;/span&gt;&lt;span class="dl"&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;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&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;text&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;data&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&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;ArtifactPart&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;text&lt;/span&gt;&lt;span class="dl"&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;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;text&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;data&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Artifact&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;artifactId&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;name&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;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ArtifactPart&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;const&lt;/span&gt; &lt;span class="nx"&gt;a2aAgentRoute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;registerApiRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/a2a/agent/:agentId&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;handler&lt;/span&gt;&lt;span class="p"&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;c&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;const&lt;/span&gt; &lt;span class="nx"&gt;mastra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&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;mastra&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;agentId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agentId&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;body&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;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;jsonrpc&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;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&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;jsonrpc&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;requestId&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;c&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;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;jsonrpc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.0&lt;/span&gt;&lt;span class="dl"&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;requestId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&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="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid Request: "jsonrpc" must be "2.0" and "id" is required&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="mi"&gt;400&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;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mastra&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agentId&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;agent&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;c&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;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;jsonrpc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.0&lt;/span&gt;&lt;span class="dl"&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;requestId&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="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32602&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Agent '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' not found`&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="mi"&gt;404&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;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contextId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;messagesList&lt;/span&gt; &lt;span class="o"&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;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;messagesList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &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;messages&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;messagesList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messages&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;mastraMessages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messagesList&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="na"&gt;msg&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MessagePart&lt;/span&gt;&lt;span class="p"&gt;[])&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="na"&gt;part&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MessagePart&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&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;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;part&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="k"&gt;return&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;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&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="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;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;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mastraMessages&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;agentText&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;text&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="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Artifact&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="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;artifactId&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="na"&gt;name&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;agentId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;Response`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&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;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agentText&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;if &lt;/span&gt;&lt;span class="p"&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;toolResults&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="nx"&gt;artifacts&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="na"&gt;artifactId&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="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;ToolResults&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&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;toolResults&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;r&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;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;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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;const&lt;/span&gt; &lt;span class="nx"&gt;history&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="nx"&gt;messagesList&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;msg&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;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;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messageId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&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;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;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&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;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agentText&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
                    &lt;span class="na"&gt;messageId&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="na"&gt;taskId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&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;return&lt;/span&gt; &lt;span class="nx"&gt;c&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;span class="na"&gt;jsonrpc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.0&lt;/span&gt;&lt;span class="dl"&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;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;result&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="nx"&gt;taskId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;contextId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contextId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&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="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;"&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="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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;messageId&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="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&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;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;agentText&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
                            &lt;span class="na"&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;message&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="nx"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&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;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="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;error&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;Router 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;error&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;c&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;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;jsonrpc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.0&lt;/span&gt;&lt;span class="dl"&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="kc"&gt;null&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="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32603&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Internal error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;details&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;message&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="mi"&gt;500&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;Once this was running, I could literally POST a message to the endpoint&lt;br&gt;
and the agent would respond like a mini AI service — ready for integration into any platform.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔍 Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Finally, I registered everything inside &lt;code&gt;index.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;mastra&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;Mastra&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;backendMentorAgent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LibSQLStore&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:memory:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createLogger&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;BackendMentorAgent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;openAPIDocs&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="na"&gt;swaggerUI&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="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;apiRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a2aAgentRoute&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;And when I ran the project…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ Connected to Centrifugo
✅ Agent workflow found
✅ Backend Mentor is ready to teach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That first successful response — a 15-minute blog lesson on database indexing — honestly felt magical.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚖️ What Worked Amazingly Well
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Mastra’s modularity&lt;/strong&gt;&lt;br&gt;
Everything has a place. You’re not hacking things together — you’re &lt;em&gt;building a system.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Simplicity of defining agents&lt;/strong&gt;&lt;br&gt;
Just give it a name, a model, and some instructions.&lt;br&gt;
That’s all you need to spin up an agent that behaves consistently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Built-in A2A server&lt;/strong&gt;&lt;br&gt;
Being able to treat an agent like a microservice out of the box was a big plus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Developer ergonomics&lt;/strong&gt;&lt;br&gt;
The API design is clean, the logging is thoughtful, and the defaults are sane.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ The Rough Edges
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;❌ Package version mismatches&lt;/strong&gt;&lt;br&gt;
Mastra is evolving fast, so keeping versions in sync across packages can be tricky.&lt;br&gt;
Deleting &lt;code&gt;node_modules&lt;/code&gt; and reinstalling from scratch helped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ Overusing tools early on&lt;/strong&gt;&lt;br&gt;
My first version had three separate tools for every task.&lt;br&gt;
It worked — but it was overkill. The simpler, instruction-driven setup was way better.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 What I Learned Along the Way
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prompt clarity beats complex code.&lt;/strong&gt;
A well-written instruction can replace 50 lines of glue logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory adds realism.&lt;/strong&gt;
Even basic persistence makes your agent feel “alive.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs are your best friend.&lt;/strong&gt;
Mastra’s logger saved me more debugging time than I’d like to admit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start simple, evolve later.&lt;/strong&gt;
It’s tempting to over-abstract early, but AI agents benefit from clarity first.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 What’s Next for Backend Mentor
&lt;/h2&gt;

&lt;p&gt;Now that the basics work, here’s what I’m planning next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Daily lesson scheduler&lt;/strong&gt; — automatically publish a new topic every morning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend dashboard&lt;/strong&gt; — a clean UI for reading lessons and tracking progress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple learning paths&lt;/strong&gt; — e.g., REST APIs, databases, DevOps fundamentals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personalized feedback&lt;/strong&gt; — where the agent gives tailored exercises&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mastra makes this expansion surprisingly easy — I can add these features without rewriting the core logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Mastra Features I Used
&lt;/h2&gt;

&lt;p&gt;Before wrapping up, I wanted to highlight the Mastra features that powered Backend Mentor — and where you can actually try it out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧩 Mastra Features I Used&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s what my setup relied on:&lt;/p&gt;

&lt;p&gt;✅*&lt;em&gt;Agent *&lt;/em&gt;— the heart of the system. Defines the mentor’s personality, model, and behavior.&lt;/p&gt;

&lt;p&gt;✅*&lt;em&gt;Memory *&lt;/em&gt;— stores what the agent has already taught, keeping lessons relevant and avoiding repetition.&lt;/p&gt;

&lt;p&gt;✅*&lt;em&gt;LibSQLStore *&lt;/em&gt;— lightweight, file-based database for persisting memory locally.&lt;/p&gt;

&lt;p&gt;✅*&lt;em&gt;registerApiRoute *&lt;/em&gt;— turns the agent into a callable HTTP endpoint (A2A).&lt;/p&gt;

&lt;p&gt;✅*&lt;em&gt;Logger *&lt;/em&gt;— clean, structured logging for debugging and observability.&lt;/p&gt;

&lt;p&gt;These features together made the project feel like building a real, production-ready AI service — not just an experiment.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌍 Meet Backend Mentor on Telex
&lt;/h2&gt;

&lt;p&gt;You can check out Backend Mentor live on Telex here:&lt;br&gt;
👉 Backend Mentor Agent on &lt;a href="https://telex.im/telex-ai-intergration/home/colleagues/019a4695-a110-7111-b097-c65964c9e086/019a4695-532e-7110-944b-634bf0e82444" rel="noopener noreferrer"&gt;Telex&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
Backend Mentor is an AI teacher that helps developers learn backend development concepts in a conversational way.&lt;br&gt;
It creates structured lessons (about 10–20 minutes long), answers follow-up questions, and tracks what you’ve already learned — so every new session builds on the last.&lt;/p&gt;

&lt;p&gt;If you’re a backend developer trying to level up, it’s like having a senior dev in your browser — available 24/7.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌍 See It Live on Telex
&lt;/h2&gt;

&lt;p&gt;You can try Backend Mentor right now on &lt;a href="https://telex.im/telex-ai-intergration/home/channels" rel="noopener noreferrer"&gt;Telex&lt;/a&gt;&lt;br&gt;
an AI agent platform where you can deploy and chat with custom agents.&lt;/p&gt;

&lt;p&gt;Think of Telex as a Slack alternative for learning communities and bootcamps —&lt;br&gt;
but with AI agents that teach, moderate, and collaborate.&lt;/p&gt;

&lt;p&gt;Mastra and Telex together make it ridiculously easy to go from idea → AI service → real users in hours.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❤️ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Mastra feels like &lt;strong&gt;Express.js for AI&lt;/strong&gt; — light, flexible, and surprisingly fun to build with.&lt;br&gt;
It doesn’t fight you; it guides you toward good structure and readable code.&lt;/p&gt;

&lt;p&gt;Building Backend Mentor reminded me why I love this field.&lt;br&gt;
It’s not just about making things smarter — it’s about making learning &lt;strong&gt;more accessible&lt;/strong&gt;, &lt;strong&gt;more human&lt;/strong&gt;, and honestly… a little more fun.&lt;/p&gt;

&lt;p&gt;If you’re looking to experiment with agents or bring AI into your existing stack,&lt;br&gt;
&lt;strong&gt;Mastra is absolutely worth your weekend.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
