<?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: Miodrag Vilotijević</title>
    <description>The latest articles on DEV Community by Miodrag Vilotijević (@mijura).</description>
    <link>https://dev.to/mijura</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%2F3818142%2F3098a7e7-1463-495b-9f64-117ffa2a145f.png</url>
      <title>DEV Community: Miodrag Vilotijević</title>
      <link>https://dev.to/mijura</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mijura"/>
    <language>en</language>
    <item>
      <title>With this MCP, Notion is becoming a vibe-coding platform turning its pages into applications. Its two-way binding enables users to generate applications and store data in Notion databases, with Notion acting as the backend for collecting and fetching data.</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Wed, 25 Mar 2026 16:04:31 +0000</pubDate>
      <link>https://dev.to/mijura/with-this-mcp-notion-is-becoming-a-vibe-coding-platform-turning-its-pages-into-applications-its-20ki</link>
      <guid>https://dev.to/mijura/with-this-mcp-notion-is-becoming-a-vibe-coding-platform-turning-its-pages-into-applications-its-20ki</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/lotus015/vizion-vibe-coding-without-leaving-notion-write-it-in-notion-click-a-button-get-a-live-react-1m58" class="crayons-story__hidden-navigation-link"&gt;Vizion: Vibe-coding without leaving Notion. Write it in Notion. Click a button. Get a live React app — with two-way sync.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/lotus015/vizion-vibe-coding-without-leaving-notion-write-it-in-notion-click-a-button-get-a-live-react-1m58" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Notion MCP Challenge Submission 🧠&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/lotus015" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3818300%2F87e73f06-f589-414d-abb8-57543676e9e8.jpeg" alt="lotus015 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/lotus015" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Miodrag Todorovic
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Miodrag Todorovic
                
              
              &lt;div id="story-author-preview-content-3403777" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/lotus015" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3818300%2F87e73f06-f589-414d-abb8-57543676e9e8.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Miodrag Todorovic&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/lotus015/vizion-vibe-coding-without-leaving-notion-write-it-in-notion-click-a-button-get-a-live-react-1m58" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/lotus015/vizion-vibe-coding-without-leaving-notion-write-it-in-notion-click-a-button-get-a-live-react-1m58" id="article-link-3403777"&gt;
          Vizion: Vibe-coding without leaving Notion. Write it in Notion. Click a button. Get a live React app — with two-way sync.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/notionchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;notionchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mcp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mcp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/lotus015/vizion-vibe-coding-without-leaving-notion-write-it-in-notion-click-a-button-get-a-live-react-1m58" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/lotus015/vizion-vibe-coding-without-leaving-notion-write-it-in-notion-click-a-button-get-a-live-react-1m58#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>From Monolith to Microservices: How Bounded Context Improves AI-Driven Development</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Fri, 20 Mar 2026 17:44:03 +0000</pubDate>
      <link>https://dev.to/jigjoy/from-monolith-to-microservices-how-bounded-context-improves-ai-driven-development-382f</link>
      <guid>https://dev.to/jigjoy/from-monolith-to-microservices-how-bounded-context-improves-ai-driven-development-382f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When we first launched our vibe coding platform, the architecture started as a single monolithic application. Initially this approach allowed us to move quickly and ship features fast.&lt;/p&gt;

&lt;p&gt;But as the platform grew, the warning signs appeared.&lt;/p&gt;

&lt;p&gt;The codebase became increasingly complex, new features were harder to implement, and development velocity began to slow down. What once felt manageable started to evolve into a tightly coupled system that was difficult to reason about.&lt;/p&gt;

&lt;p&gt;To solve this, we made a strategic decision: refactor the platform from a monolith into a microservices architecture.&lt;/p&gt;

&lt;p&gt;In this article we explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Why monolithic architectures struggle in AI-driven systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How Domain-Driven Design (DDD) helps define system boundaries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why bounded contexts are critical for AI agents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How we split our platform into eight microservices&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architectural shift significantly improved both developer productivity and AI agent performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Domain-Driven Design
&lt;/h2&gt;

&lt;p&gt;The concept of Domain-Driven Design (DDD) was introduced by Eric Evans in the influential book Domain‑Driven Design: Tackling Complexity in the Heart of Software.&lt;/p&gt;

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

&lt;p&gt;Although the book was published in 2003, its ideas remain extremely relevant today. Many modern architectural patterns—including microservices—are heavily inspired by DDD principles.&lt;/p&gt;

&lt;p&gt;DDD focuses on one core idea:&lt;/p&gt;

&lt;p&gt;Software architecture should mirror the structure of the business domain. Instead of organizing systems purely around technical layers, DDD encourages teams to structure software around real business capabilities and concepts.&lt;/p&gt;

&lt;p&gt;While doing domain distillation, we detected the 6 main bounded contexts that can act as independent services: project planning, AI coding, project deployment, version control, observability, account and billing.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Monolith vs Microservices Debate
&lt;/h2&gt;

&lt;p&gt;For years developers have debated a fundamental architectural question:&lt;/p&gt;

&lt;p&gt;Should applications remain monolithic, or should they be broken into microservices?&lt;/p&gt;

&lt;p&gt;Monoliths have advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Simpler deployments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easier early development&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fewer distributed systems challenges&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, as systems scale, monoliths often become harder to maintain. Large codebases accumulate complexity and eventually turn into what developers often call a "Big Ball of Mud."&lt;/p&gt;

&lt;p&gt;Today the conversation has evolved even further. We are no longer building systems only for human developers. We are building systems that AI agents interact with, modify, and reason about. And this introduces a new challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Monolithic Architectures Confuse AI Agents
&lt;/h2&gt;

&lt;p&gt;AI agents rely heavily on clear context boundaries.When a system grows into a large monolithic repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Domain concepts overlap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terminology becomes ambiguous&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architectural boundaries blur&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it harder for AI systems to correctly interpret intent. For example, an AI agent might receive a command such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a large monolith, the term project might refer to several different things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A planning workspace&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A source code repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A deployment environment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without clear boundaries, the AI agent must guess the meaning. And guessing leads to errors. This is why architectural clarity matters even more in AI-driven development environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Bounded Context?
&lt;/h2&gt;

&lt;p&gt;A Bounded Context is a central concept in Domain-Driven Design. It defines a clear boundary within which a specific domain model applies and terminology has a single meaning.&lt;/p&gt;

&lt;p&gt;Inside a bounded context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Language is consistent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concepts are clearly defined&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Domain logic belongs only to that context&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a shared understanding between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Developers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Domain experts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI agents&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each context effectively becomes its own mini-world with well-defined rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Bounded Contexts Improve AI Development
&lt;/h3&gt;

&lt;p&gt;In large software systems, the same word can mean different things in different domains. While building our AI coding platform, we encountered this problem quickly. Consider the word project.&lt;/p&gt;

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

&lt;p&gt;When both meanings existed in the same codebase, confusion spread. Not only for engineers—but for AI agents operating within the platform. By introducing bounded contexts, we ensured that each domain defines its own terminology and behavior. This dramatically improved the reliability of both human workflows and AI-generated development tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Microservices Architecture
&lt;/h2&gt;

&lt;p&gt;After refactoring the platform using Domain-Driven Design principles, we divided the system into eight bounded contexts, each implemented as a separate microservice.&lt;/p&gt;

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

&lt;p&gt;This allowed each domain to evolve independently while maintaining clear system boundaries.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project Planning Context&lt;/strong&gt; - manages planning activities. Within this domain we store: tasks, projects, agent which generate tasks...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI Coding Context&lt;/strong&gt; - this is where development actually happens. AI coding agents operate in this domain and perform tasks such as: writing code, committing changes, managing development workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project Deployment Context&lt;/strong&gt; - manages the infrastructure and pipelines required to deploy software built by AI agents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Control Context&lt;/strong&gt; - while platforms like GitHub provide robust version control, we chose to build a lightweight internal system optimized specifically for AI-driven development workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observability Context&lt;/strong&gt; - collects events and analytics from across the platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Account and Billing Context&lt;/strong&gt; - manages user accounts, platform credits, payments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API Gateway&lt;/strong&gt; - acts as the central entry point into the platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Platform UI&lt;/strong&gt; - provides the user interface that connects all services together.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Avoiding the Big Ball of Mud
&lt;/h2&gt;

&lt;p&gt;Without clear architectural boundaries, complex systems eventually degrade into tightly coupled codebases that are difficult to maintain. Developers often describe this situation as a "Big Ball of Mud."&lt;/p&gt;

&lt;p&gt;Symptoms typically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Spaghetti code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Increasing bugs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slower development cycles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Poor onboarding experience&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confusing system behavior&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For AI-driven platforms, the consequences are even worse because agents lose the contextual clarity required to generate reliable code.&lt;/p&gt;

&lt;p&gt;By organizing our platform around bounded contexts and microservices, we achieved several key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Clear domain ownership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster feature development&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better system scalability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved AI agent performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More maintainable architecture&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;As AI agents become increasingly involved in software development, architecture design must evolve alongside them. Bounded contexts and microservices are no longer just about scaling engineering teams—they also help AI systems reason about complex software platforms. For us, adopting Domain-Driven Design and microservices architecture transformed a growing monolith into a scalable platform designed for the future of AI-assisted development.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Multiple models are in play on any large project. Yet when code based on distinct models is combined, software becomes buggy, unreliable, and difficult to understand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— Eric Evans&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>ai</category>
      <category>vibecoding</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why a Single Interface for Multiple LLM Providers Is a Bad Design Decision</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Thu, 19 Mar 2026 06:29:02 +0000</pubDate>
      <link>https://dev.to/jigjoy/dont-write-frameworks-for-dummies-100l</link>
      <guid>https://dev.to/jigjoy/dont-write-frameworks-for-dummies-100l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Don't write frameworks for dummies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence stuck with me while reading Domain-Driven Design: Tackling Complexity in the Heart of Software. I didn't fully understand it at first - but after building (and then redesigning) an AI orchestration framework, I do now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where We Started
&lt;/h2&gt;

&lt;p&gt;When we began building a framework for orchestrating AI agents, one of the first features we introduced was a unified request interface across multiple LLM providers.&lt;/p&gt;

&lt;p&gt;At first, it felt like a great design decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean abstraction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But that simplicity turned out to be misleading.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Problem with "Unified" Abstractions
&lt;/h2&gt;

&lt;p&gt;Over time, cracks started to show:&lt;/p&gt;

&lt;h3&gt;
  
  
  All models looked the same to developers
&lt;/h3&gt;

&lt;p&gt;By flattening everything into a single interface, we erased the differences between models. Developers stopped thinking about capabilities and limitations - which is exactly what they should be thinking about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding new models became harder, not easier
&lt;/h3&gt;

&lt;p&gt;New models come with new capabilities, parameters, and behaviors. A "unified" interface either ignores those features, or becomes bloated trying to support everything. Neither is good design.&lt;/p&gt;

&lt;h3&gt;
  
  
  The ubiquitous language was wrong
&lt;/h3&gt;

&lt;p&gt;The API didn't reflect the domain. It reflected our attempt to simplify it. That meant the language of the library didn't express real model capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  We enabled misuse by design
&lt;/h3&gt;

&lt;p&gt;The worst part: the abstraction allowed developers to make mistakes easily - and only discover them at runtime.&lt;/p&gt;

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

&lt;p&gt;passing &lt;code&gt;reasoning_effort="high"&lt;/code&gt; to a model that doesn't support reasoning.&lt;/p&gt;

&lt;p&gt;The system didn't prevent it. It allowed it.&lt;/p&gt;

&lt;p&gt;That's not just a bad developer experience - it's a failure in design. The abstraction wasn't helping developers. It was hiding the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Redesign
&lt;/h2&gt;

&lt;p&gt;So we changed direction.&lt;/p&gt;

&lt;p&gt;Instead of forcing a unified interface, we started modeling each LLM separately, along with its capabilities and constraints.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Why This Is the Right Move
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Advanced users can extract more value
&lt;/h3&gt;

&lt;p&gt;Power users are no longer limited by a lowest-common-denominator API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Models are not the same - and that matters
&lt;/h3&gt;

&lt;p&gt;Treating them as identical leads to misuse. Embracing differences leads to better outcomes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invalid configurations are caught early
&lt;/h3&gt;

&lt;p&gt;Instead of runtime surprises, errors are surfaced immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better developer experience (DX)
&lt;/h3&gt;

&lt;p&gt;Clear APIs, explicit capabilities, fewer hidden assumptions.&lt;/p&gt;

&lt;p&gt;Most importantly: the library expresses domain knowledge correctly&lt;br&gt;
The design now reflects reality - not an oversimplified version of it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Looking Forward
&lt;/h2&gt;

&lt;p&gt;We're not done yet.&lt;/p&gt;

&lt;p&gt;We haven't fully committed the redesign - but we've started moving in this direction, and the changes will roll out in the next versions of Mozaik.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;make model capabilities explicit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;prevent invalid usage early&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;and let developers actually use the power of each model instead of hiding it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is still evolving, and we'll likely learn more (and fix more mistakes) along the way.&lt;/p&gt;

&lt;p&gt;But one thing is already clear:&lt;/p&gt;

&lt;p&gt;We're no longer trying to hide the complexity of LLMs. We're designing for it.&lt;/p&gt;

&lt;p&gt;Source:&lt;br&gt;


&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://jigjoy.ai/blog/single-interface-for-multiple-llms" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjigjoy.ai%2Fblog%2Fsingle-interface-for-multiple-llms%2Fthumbnail-og.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://jigjoy.ai/blog/single-interface-for-multiple-llms" rel="noopener noreferrer" class="c-link"&gt;
            Why a Single Interface for Multiple LLM Providers Is a Bad Design Decision
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Why unified LLM abstractions fail and how modeling each LLM separately improves developer experience. A lesson in Domain-Driven Design.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
          jigjoy.ai
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
    <item>
      <title>How to Build an Autonomous AI Agent That Executes Terminal Commands</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Sun, 15 Mar 2026 18:54:33 +0000</pubDate>
      <link>https://dev.to/jigjoy/how-to-build-an-autonomous-ai-agent-that-executes-terminal-commands-23ke</link>
      <guid>https://dev.to/jigjoy/how-to-build-an-autonomous-ai-agent-that-executes-terminal-commands-23ke</guid>
      <description>&lt;h2&gt;
  
  
  What Makes an Agent Autonomous?
&lt;/h2&gt;

&lt;p&gt;An autonomous agent is an agent that can make independent decisions to accomplish tasks-without constant human guidance.&lt;/p&gt;

&lt;p&gt;But how do we measure the level of autonomy an agent has?&lt;/p&gt;

&lt;p&gt;The answer lies in the variety of tasks an agent can perform on its own.&lt;/p&gt;

&lt;p&gt;Consider an agent that has a single tool-the ability to write files. That's one degree of autonomy. It can create content, save it, and that's about it.&lt;/p&gt;

&lt;p&gt;Now consider an agent with access to a terminal. Suddenly, the possibilities explode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;List files in any directory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read and write files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute scripts and programs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install packages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interact with git repositories&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make network requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And much more...&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a high degree of autonomy-which, as we'll discuss, comes with both incredible power and important security considerations.&lt;/p&gt;

&lt;p&gt;This is basically the idea behind modern coding tools like Claude Code—or even better, OpenClaw.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Concept: Tool Execution Loop
&lt;/h2&gt;

&lt;p&gt;The main thing we need to enable is an implementation for executing tools in a loop.&lt;/p&gt;

&lt;p&gt;I'll use a library I built for this- &lt;code&gt;@mozaik-ai/core&lt;/code&gt; - a TypeScript framework for orchestrating AI agents.&lt;/p&gt;

&lt;p&gt;With Mozaik, we can easily equip an agent with tools. So we just need to create a terminal tool for executing commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Terminal Tool
&lt;/h2&gt;

&lt;p&gt;First, let's define the terminal class that will give our agent the ability to execute shell commands:&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;spawn&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;child_process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Terminal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;runCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cwd&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CommandResult&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;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;shell&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stdout&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="nx"&gt;stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;

            &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;on&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;on&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

            &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;exitCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="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 we define the tool that will give our agent the ability to execute shell commands:&lt;/p&gt;

&lt;p&gt;The tool is straightforward: it takes a command string, executes it using Node.js's child_process module, and returns the output.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;terminal&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;Terminal&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;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tool&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;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;run_command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Run a command in the terminal.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The command to run in the terminal.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The current working directory.&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;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cwd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cwd&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Running command: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; in directory: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--------------------------------&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;terminal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cwd&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;result&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;h2&gt;
  
  
  Attaching the Tool to an Agent
&lt;/h2&gt;

&lt;p&gt;Now we attach the terminal tool to our agent:&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="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MozaikRequest&lt;/span&gt; &lt;span class="o"&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;gpt-5-mini&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="nx"&gt;tools&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;userRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Analyze the github respository and update the README.md file with a high level description of the project.`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are a terminal agent. 

You can run commands in the terminal to help the user with their request. 
Do not ask any questions to the user. Just run the commands and return the result.

Tools:
- run_command: Run a command in the terminal. You can use this tool to run any command in the terminal.

User Request:
- &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userRequest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MozaikAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Watching the Agent Work
&lt;/h2&gt;

&lt;p&gt;Let's give the agent a task and watch it work. Below you can see what happens step by step - the terminal commands the agent autonomously executes to get the job done.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Look at this folder and tell me in one sentence what it does 
                    — like you're explaining it to someone who has never written a line of code.`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The agent breaks it down on its own. It runs two commands to get the job done. The first command lists the files in the current directory, and the second command reads README.md to figure out the purpose of the project.&lt;/p&gt;

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

&lt;p&gt;We can see which commands the agent executed to get the job done. No instructions on how to do it. Just the goal—and the agent figures out the rest.&lt;/p&gt;

&lt;p&gt;Now, let's give the agent a more complex task:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Analyze this directory and write 
                    a detailed description of the project 
                    in a file called purpose.md.`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We see the agent executed multiple commands to get the job done, and finally wrote the purpose.md file with the description of the project.&lt;/p&gt;

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

&lt;p&gt;With great autonomy comes great responsibility. Terminal access is powerful—but it can also be dangerous if not properly controlled.&lt;/p&gt;

&lt;p&gt;The balance between autonomy and safety is a spectrum. Start with tighter controls and expand as you build confidence in your agent's behavior.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building an autonomous agent with terminal access is surprisingly straightforward—the core pattern is just a tool execution loop.&lt;/p&gt;

&lt;p&gt;What makes these agents powerful isn't the complexity of the implementation, but the emergent capabilities that arise from giving an LLM access to a shell.&lt;/p&gt;

&lt;p&gt;The agent doesn't need to be explicitly programmed for every scenario. Give it a goal, give it tools, and it will find a way.&lt;/p&gt;

&lt;p&gt;GitHub Repo:&lt;br&gt;


&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jigjoy-ai" rel="noopener noreferrer"&gt;
        jigjoy-ai
      &lt;/a&gt; / &lt;a href="https://github.com/jigjoy-ai/terminal-agent" rel="noopener noreferrer"&gt;
        terminal-agent
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A minimal AI-powered terminal agent that can execute shell commands and interact with the local system to automate tasks and workflows.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;@mozaik-ai/terminal&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A small terminal-agent project that lets an AI act as a terminal operator. It exposes a tool for running shell commands programmatically and returning structured results (stdout, stderr, exit code). The agent is built on top of Mozaik AI core primitives and is intended for automation tasks where an AI needs to inspect the repository, run commands, and modify files.&lt;/p&gt;

&lt;p&gt;Key points&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project name: @mozaik-ai/terminal&lt;/li&gt;
&lt;li&gt;Purpose: Provide a terminal tool that an AI agent can use to run commands in a shell and capture results.&lt;/li&gt;
&lt;li&gt;Language: TypeScript (Node.js)&lt;/li&gt;
&lt;li&gt;Entry point: src/index.ts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run arbitrary shell commands via a typed tool (run_command)&lt;/li&gt;
&lt;li&gt;Captures stdout, stderr, and exit code&lt;/li&gt;
&lt;li&gt;Simple Terminal class that spawns child processes and returns CommandResult objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How it works (high level)&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;src/index.ts wires up a MozaikAgent with a single tool: run_command&lt;/li&gt;

&lt;li&gt;The tool schema requires { command, cwd } and invokes Terminal.runCommand&lt;/li&gt;

&lt;li&gt;Terminal.runCommand uses child_process.spawn (with shell…&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jigjoy-ai/terminal-agent" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;





&lt;p&gt;Source:&lt;br&gt;


&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://jigjoy.ai/blog/autonomous-terminal-agent" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjigjoy.ai%2Fblog%2Fautonomous-terminal-agent%2Fthumbnail-og.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://jigjoy.ai/blog/autonomous-terminal-agent" rel="noopener noreferrer" class="c-link"&gt;
            Building an Autonomous Agent That Can Run Terminal Commands
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Learn how to build an autonomous AI agent with terminal access. Discover how tool-equipped agents can execute shell commands and accomplish complex tasks.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
          jigjoy.ai
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>ai</category>
      <category>agents</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
