<?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: Mohammad Joud Julius</title>
    <description>The latest articles on DEV Community by Mohammad Joud Julius (@judejulius).</description>
    <link>https://dev.to/judejulius</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%2F4154463%2Fece703f7-aea2-44bb-aa66-bc89008e0ddd.jpg</url>
      <title>DEV Community: Mohammad Joud Julius</title>
      <link>https://dev.to/judejulius</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/judejulius"/>
    <language>en</language>
    <item>
      <title>I Built an Open-Source Studio for Building, Testing, and Deploying AI Agents</title>
      <dc:creator>Mohammad Joud Julius</dc:creator>
      <pubDate>Thu, 01 Oct 2026 10:38:09 +0000</pubDate>
      <link>https://dev.to/judejulius/i-built-an-open-source-studio-for-building-testing-and-deploying-ai-agents-1l7d</link>
      <guid>https://dev.to/judejulius/i-built-an-open-source-studio-for-building-testing-and-deploying-ai-agents-1l7d</guid>
      <description>&lt;h1&gt;
  
  
  I Built an Open-Source Studio for Building and Shipping AI Agents
&lt;/h1&gt;

&lt;p&gt;Building an AI chatbot is easy.&lt;/p&gt;

&lt;p&gt;Shipping one that has tools, knowledge, memory, observability, evaluations, human handoff, multiple model providers, workflows, and an actual interface your users can interact with is a different problem.&lt;/p&gt;

&lt;p&gt;That gap is what led me to build &lt;strong&gt;Chatbot Studio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's an open-source platform for building AI agents and then publishing those agents as website chatbots or connecting them to channels such as WhatsApp.&lt;/p&gt;

&lt;p&gt;This isn't a SaaS announcement or a sales pitch. The project is MIT licensed, self-hostable, and available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/judejulius/ChatbotStudio" rel="noopener noreferrer"&gt;https://github.com/judejulius/ChatbotStudio&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I wanted to solve
&lt;/h2&gt;

&lt;p&gt;A lot of AI projects begin with something like this:&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="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&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="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then reality arrives.&lt;/p&gt;

&lt;p&gt;You need tools.&lt;/p&gt;

&lt;p&gt;Then retrieval.&lt;/p&gt;

&lt;p&gt;Then credentials.&lt;/p&gt;

&lt;p&gt;Then streaming.&lt;/p&gt;

&lt;p&gt;Then conversation state.&lt;/p&gt;

&lt;p&gt;Then rate limits.&lt;/p&gt;

&lt;p&gt;Then evaluations.&lt;/p&gt;

&lt;p&gt;Then traces because something went wrong in production.&lt;/p&gt;

&lt;p&gt;Then a UI.&lt;/p&gt;

&lt;p&gt;Then somebody asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can we put this on the website?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And someone else asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can customers talk to a human if the AI gets stuck?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that point you're no longer building a prompt around an LLM.&lt;/p&gt;

&lt;p&gt;You're building an &lt;strong&gt;agent platform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is the problem Chatbot Studio is trying to explore.&lt;/p&gt;




&lt;h2&gt;
  
  
  The core design: the agent and the chatbot are different things
&lt;/h2&gt;

&lt;p&gt;One architectural decision became especially important while building this.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;agent&lt;/strong&gt; should not be the same object as its presentation layer.&lt;/p&gt;

&lt;p&gt;The agent owns things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;model provider&lt;/li&gt;
&lt;li&gt;model&lt;/li&gt;
&lt;li&gt;system instructions&lt;/li&gt;
&lt;li&gt;tools&lt;/li&gt;
&lt;li&gt;MCP servers&lt;/li&gt;
&lt;li&gt;knowledge&lt;/li&gt;
&lt;li&gt;memory&lt;/li&gt;
&lt;li&gt;skills&lt;/li&gt;
&lt;li&gt;guardrails&lt;/li&gt;
&lt;li&gt;sandbox settings&lt;/li&gt;
&lt;li&gt;human-in-the-loop behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A published chatbot owns the things that belong to the channel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;appearance&lt;/li&gt;
&lt;li&gt;allowed domains&lt;/li&gt;
&lt;li&gt;usage limits&lt;/li&gt;
&lt;li&gt;launcher configuration&lt;/li&gt;
&lt;li&gt;welcome experience&lt;/li&gt;
&lt;li&gt;suggested prompts&lt;/li&gt;
&lt;li&gt;publishing state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model + Knowledge + Tools
          |
          v
        Agent
          |
     test / evaluate
          |
          v
   Published Chatbot
          |
   Website / Channel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The chatbot isn't a duplicated agent configuration.&lt;/p&gt;

&lt;p&gt;It's a channel sitting on top of the agent.&lt;/p&gt;

&lt;p&gt;That means I can improve an agent's instructions, knowledge, model, or tools without recreating every chatbot using it.&lt;/p&gt;

&lt;p&gt;The agent remains the source of truth.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building agents
&lt;/h1&gt;

&lt;p&gt;The main Agent Studio lets you configure and test an agent before publishing it.&lt;/p&gt;

&lt;p&gt;Currently the platform supports provider families including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI&lt;/li&gt;
&lt;li&gt;Anthropic&lt;/li&gt;
&lt;li&gt;Google Gemini&lt;/li&gt;
&lt;li&gt;Groq&lt;/li&gt;
&lt;li&gt;OpenRouter&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;OpenAI-compatible endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An agent can then be connected to knowledge bases, tools, MCP servers, memory, skills, guardrails, and other runtime controls.&lt;/p&gt;

&lt;p&gt;The test chat runs against the saved agent configuration.&lt;/p&gt;

&lt;p&gt;That part matters.&lt;/p&gt;

&lt;p&gt;I didn't want a playground where the test environment was secretly different from the thing that eventually gets deployed.&lt;/p&gt;

&lt;p&gt;The goal is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;configure -&amp;gt; test -&amp;gt; evaluate -&amp;gt; publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prototype -&amp;gt; rewrite everything -&amp;gt; deploy something different
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  MCP support
&lt;/h1&gt;

&lt;p&gt;One part I've been particularly interested in is &lt;strong&gt;Model Context Protocol&lt;/strong&gt; support.&lt;/p&gt;

&lt;p&gt;Chatbot Studio can connect agents to MCP servers using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stdio&lt;/li&gt;
&lt;li&gt;SSE&lt;/li&gt;
&lt;li&gt;streamable HTTP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes external capabilities much easier to attach to an agent without baking every integration directly into the application.&lt;/p&gt;

&lt;p&gt;The broader architecture becomes something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 +----------------+
                 | Knowledge Base |
                 +-------+--------+
                         |
+----------+      +------v------+
| MCP Tool +-----&amp;gt;+             |
+----------+      |    Agent    |
                  |             |
+----------+      +------+------+
| API Tool +------------+
+----------+             |
                         v
                  Conversation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For me, MCP is interesting because it moves agent tooling toward a more interoperable ecosystem instead of every project inventing its own tool interface.&lt;/p&gt;




&lt;h1&gt;
  
  
  RAG and knowledge bases
&lt;/h1&gt;

&lt;p&gt;Agents can also be connected to reusable knowledge bases.&lt;/p&gt;

&lt;p&gt;The backend currently handles sources including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;text&lt;/li&gt;
&lt;li&gt;URLs&lt;/li&gt;
&lt;li&gt;PDF&lt;/li&gt;
&lt;li&gt;DOCX&lt;/li&gt;
&lt;li&gt;Markdown&lt;/li&gt;
&lt;li&gt;CSV&lt;/li&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documents are processed into chunks and embeddings that can be retrieved during conversations.&lt;/p&gt;

&lt;p&gt;The important idea here was making knowledge a reusable platform resource rather than stuffing documents directly into one chatbot implementation.&lt;/p&gt;

&lt;p&gt;One knowledge base can therefore become part of a broader agent configuration.&lt;/p&gt;




&lt;h1&gt;
  
  
  The chatbot is an actual Web Component
&lt;/h1&gt;

&lt;p&gt;For deployment on websites, I wanted the exported chatbot to be as framework-independent as possible.&lt;/p&gt;

&lt;p&gt;So the primary integration is a browser-native custom element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://your-domain.com/widget.esm.js?widget=wgt_..."&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;chatbot-widget&amp;gt;&amp;lt;/chatbot-widget&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component uses a Shadow DOM so the host website's CSS doesn't unexpectedly destroy the chatbot UI—and the chatbot doesn't leak its styles back into the host application.&lt;/p&gt;

&lt;p&gt;The element also exposes a small JavaScript API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatbot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chatbot-widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;chatbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;chatbot&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I need help with an order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;chatbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;chatbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it emits events such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chatbot-ready
chatbot-error
chatbot-handoff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the core is a Web Component, framework integrations can stay fairly thin.&lt;/p&gt;

&lt;p&gt;Chatbot Studio can generate integrations for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;native HTML&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Vue&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;WordPress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of maintaining five completely different chatbot implementations, they all revolve around the same browser-native element.&lt;/p&gt;




&lt;h1&gt;
  
  
  The visual chatbot customizer
&lt;/h1&gt;

&lt;p&gt;I also wanted customization to use the &lt;strong&gt;real renderer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The editor therefore mounts the same widget implementation that gets exported.&lt;/p&gt;

&lt;p&gt;You can customize things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;launcher&lt;/li&gt;
&lt;li&gt;window&lt;/li&gt;
&lt;li&gt;header&lt;/li&gt;
&lt;li&gt;greeting&lt;/li&gt;
&lt;li&gt;suggested prompts&lt;/li&gt;
&lt;li&gt;agent message bubbles&lt;/li&gt;
&lt;li&gt;visitor message bubbles&lt;/li&gt;
&lt;li&gt;composer&lt;/li&gt;
&lt;li&gt;loading indicator&lt;/li&gt;
&lt;li&gt;scroll controls&lt;/li&gt;
&lt;li&gt;footer&lt;/li&gt;
&lt;li&gt;dark/light behavior&lt;/li&gt;
&lt;li&gt;lead capture&lt;/li&gt;
&lt;li&gt;knowledge citations&lt;/li&gt;
&lt;li&gt;streamed reasoning&lt;/li&gt;
&lt;li&gt;human handoff&lt;/li&gt;
&lt;li&gt;usage limits&lt;/li&gt;
&lt;li&gt;allowed domains&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This avoids a problem I've seen in visual builders where the editor preview looks one way and the actual embedded component behaves differently.&lt;/p&gt;

&lt;p&gt;The preview and the shipped widget share the same rendering path.&lt;/p&gt;




&lt;h1&gt;
  
  
  Human handoff
&lt;/h1&gt;

&lt;p&gt;AI shouldn't have to pretend it can solve every problem.&lt;/p&gt;

&lt;p&gt;So Chatbot Studio also has human handoff.&lt;/p&gt;

&lt;p&gt;Instead of handing a conversation off to an undefined "human", conversations can be routed into queues such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;General Support
Technical Support
Sales
Billing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Administrators control which users belong to which queues.&lt;/p&gt;

&lt;p&gt;The AI can hand the conversation to an appropriate queue, after which a person can take ownership of it.&lt;/p&gt;

&lt;p&gt;Once handed over, the assistant stops trying to answer the conversation as though nothing happened.&lt;/p&gt;

&lt;p&gt;This required treating handoff as application state rather than just another tool response.&lt;/p&gt;




&lt;h1&gt;
  
  
  Agent teams and visual workflows
&lt;/h1&gt;

&lt;p&gt;Not every task belongs inside one large agent.&lt;/p&gt;

&lt;p&gt;The project therefore also supports agent teams and visual workflows.&lt;/p&gt;

&lt;p&gt;The workflow side supports concepts including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DAG execution&lt;/li&gt;
&lt;li&gt;conditional paths&lt;/li&gt;
&lt;li&gt;input mapping&lt;/li&gt;
&lt;li&gt;human approval&lt;/li&gt;
&lt;li&gt;persisted runs&lt;/li&gt;
&lt;li&gt;scheduled execution&lt;/li&gt;
&lt;li&gt;execution traces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The UI uses XYFlow for the visual workflow editor.&lt;/p&gt;

&lt;p&gt;This lets you move from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User -&amp;gt; Agent -&amp;gt; Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;toward workflows such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    -&amp;gt; Research Agent -----
                   /                       \
Input -&amp;gt; Classifier                          -&amp;gt; Final Agent
                   \                       /
                    -&amp;gt; Internal Data Tool --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because workflow runs are persisted and traced, there is something to inspect when an orchestration path doesn't behave as expected.&lt;/p&gt;




&lt;h1&gt;
  
  
  Evals and observability
&lt;/h1&gt;

&lt;p&gt;One lesson from working with LLM applications is that manually chatting with an agent is not a sufficient testing strategy.&lt;/p&gt;

&lt;p&gt;You eventually need repeatable evaluations.&lt;/p&gt;

&lt;p&gt;Chatbot Studio includes evaluation suites so test cases can be run repeatedly instead of relying only on intuition.&lt;/p&gt;

&lt;p&gt;There is also observability around things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;token usage&lt;/li&gt;
&lt;li&gt;cost&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;tool calls&lt;/li&gt;
&lt;li&gt;traces&lt;/li&gt;
&lt;li&gt;errors&lt;/li&gt;
&lt;li&gt;sessions&lt;/li&gt;
&lt;li&gt;visitor feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also a prompt optimization workflow where generated improvements can be reviewed before being accepted.&lt;/p&gt;

&lt;p&gt;I deliberately wanted that last step to stay human-controlled.&lt;/p&gt;

&lt;p&gt;An optimizer can propose a prompt change.&lt;/p&gt;

&lt;p&gt;It shouldn't silently decide that production needs a new personality at 3 AM.&lt;/p&gt;




&lt;h1&gt;
  
  
  WhatsApp
&lt;/h1&gt;

&lt;p&gt;The project has also grown beyond browser chatbots.&lt;/p&gt;

&lt;p&gt;There is a WhatsApp channel implementation using a Node.js bridge around Baileys.&lt;/p&gt;

&lt;p&gt;It handles things including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QR pairing&lt;/li&gt;
&lt;li&gt;authentication persistence&lt;/li&gt;
&lt;li&gt;inbound messages&lt;/li&gt;
&lt;li&gt;outbound messages&lt;/li&gt;
&lt;li&gt;quoted replies&lt;/li&gt;
&lt;li&gt;typing state&lt;/li&gt;
&lt;li&gt;debounce windows&lt;/li&gt;
&lt;li&gt;audio transcription&lt;/li&gt;
&lt;li&gt;optional generated voice replies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the architecture is increasingly becoming:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                      +--&amp;gt; Website Widget
                      |
Provider -&amp;gt; Agent -----+--&amp;gt; WhatsApp
           |
           +-------------&amp;gt; Workflows
           |
           +-------------&amp;gt; Agent Teams
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The channel shouldn't define the intelligence.&lt;/p&gt;

&lt;p&gt;The agent should.&lt;/p&gt;




&lt;h1&gt;
  
  
  Under the hood
&lt;/h1&gt;

&lt;p&gt;Chatbot Studio isn't built as one giant application.&lt;/p&gt;

&lt;p&gt;The main pieces are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend/
backend/
widget/
wa-bridge/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;The Studio UI is built with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js 16
React 19
TypeScript
Tailwind CSS
Zustand
XYFlow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;The API and agent runtime use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python 3.12+
FastAPI
Pydantic
Motor
MongoDB
APScheduler
MCP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Widget
&lt;/h3&gt;

&lt;p&gt;The embeddable chatbot is a separate JavaScript package built with esbuild.&lt;/p&gt;

&lt;h3&gt;
  
  
  WhatsApp bridge
&lt;/h3&gt;

&lt;p&gt;WhatsApp transport runs as a separate Node.js service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure
&lt;/h3&gt;

&lt;p&gt;The default Docker setup brings together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js
FastAPI
MongoDB
WhatsApp bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with an optional nginx SSL profile.&lt;/p&gt;

&lt;p&gt;This separation has made it much easier to reason about where functionality actually belongs.&lt;/p&gt;




&lt;h1&gt;
  
  
  Running it locally
&lt;/h1&gt;

&lt;p&gt;The project is designed to be self-hosted.&lt;/p&gt;

&lt;p&gt;You'll need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Node.js 20+
Python 3.12+
uv
MongoDB 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clone the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/judejulius/ChatbotStudio.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ChatbotStudio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your environment configuration:&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;cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install everything:&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 &lt;span class="nb"&gt;install&lt;/span&gt;:all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start MongoDB:&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 mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the development stack:&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 dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend will be available on:&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:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and FastAPI's API documentation on:&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:8000/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a Docker Compose setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you replace the placeholder secrets in &lt;code&gt;.env&lt;/code&gt; before running a real deployment.&lt;/p&gt;




&lt;h1&gt;
  
  
  Security became part of the architecture
&lt;/h1&gt;

&lt;p&gt;Once a platform stores model-provider credentials, MCP credentials, visitor conversations, and authentication data, security can no longer be an afterthought.&lt;/p&gt;

&lt;p&gt;The project includes mechanisms around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;encrypted provider credentials&lt;/li&gt;
&lt;li&gt;encrypted MCP secrets&lt;/li&gt;
&lt;li&gt;JWT authentication&lt;/li&gt;
&lt;li&gt;optional TOTP two-factor authentication&lt;/li&gt;
&lt;li&gt;short-lived widget sessions&lt;/li&gt;
&lt;li&gt;domain allowlists&lt;/li&gt;
&lt;li&gt;rate limiting&lt;/li&gt;
&lt;li&gt;visitor IP hashing&lt;/li&gt;
&lt;li&gt;role-based access&lt;/li&gt;
&lt;li&gt;queue-based conversation access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is still always more security work to do in a project like this, but I've tried to make those concerns architectural rather than something added after everything else.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I learned building this
&lt;/h1&gt;

&lt;p&gt;The biggest lesson was that building an AI agent is usually not the hardest part.&lt;/p&gt;

&lt;p&gt;The hard part is everything surrounding it.&lt;/p&gt;

&lt;p&gt;A useful agent system needs answers to questions like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Where do credentials live?

How are tools registered?

How is knowledge retrieved?

How do I test changes?

How do I inspect failures?

How do I embed this into another application?

What happens when the AI gets stuck?

Who takes over?

How do I control usage?

Can I change providers?

Can I run it myself?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you start answering those questions, you're no longer writing a chatbot script.&lt;/p&gt;

&lt;p&gt;You're designing infrastructure around intelligent software.&lt;/p&gt;

&lt;p&gt;That's the space I want Chatbot Studio to explore.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why open source it?
&lt;/h1&gt;

&lt;p&gt;Because I think the interesting part of AI agents right now isn't another closed chat interface.&lt;/p&gt;

&lt;p&gt;It's figuring out the infrastructure patterns that make agents useful outside demos.&lt;/p&gt;

&lt;p&gt;Things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP&lt;/li&gt;
&lt;li&gt;agent orchestration&lt;/li&gt;
&lt;li&gt;reusable knowledge&lt;/li&gt;
&lt;li&gt;evaluations&lt;/li&gt;
&lt;li&gt;observability&lt;/li&gt;
&lt;li&gt;human escalation&lt;/li&gt;
&lt;li&gt;portable widgets&lt;/li&gt;
&lt;li&gt;multiple providers&lt;/li&gt;
&lt;li&gt;self-hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are problems developers should be able to inspect, modify, argue about, and improve.&lt;/p&gt;

&lt;p&gt;Chatbot Studio is MIT licensed, so you can clone it, study it, change it, break it, rebuild parts of it, or use ideas from it in your own projects.&lt;/p&gt;




&lt;h1&gt;
  
  
  I'd like developer feedback
&lt;/h1&gt;

&lt;p&gt;The project has become much larger than the original chatbot-widget idea, and there are plenty of areas I want to keep improving.&lt;/p&gt;

&lt;p&gt;If you work with LLM applications, MCP, agent orchestration, RAG, frontend infrastructure, FastAPI, or self-hosted AI systems, I'd especially like feedback on the architecture.&lt;/p&gt;

&lt;p&gt;I'm interested in hearing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What would you change?&lt;/li&gt;
&lt;li&gt;What integrations are missing?&lt;/li&gt;
&lt;li&gt;Which parts should be separated further?&lt;/li&gt;
&lt;li&gt;Where would you simplify the architecture?&lt;/li&gt;
&lt;li&gt;What features would make it more useful for your own agent projects?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you find something broken, opening an issue is even better.&lt;/p&gt;

&lt;p&gt;The repository is here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/judejulius/ChatbotStudio" rel="noopener noreferrer"&gt;https://github.com/judejulius/ChatbotStudio&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the project is useful or the architecture gives you ideas, a GitHub star is appreciated.&lt;/p&gt;

&lt;p&gt;More importantly, I'd like to see what other developers build with it.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>github</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
