<?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: Miodrag Vilotijević</title>
    <description>The latest articles on Forem by Miodrag Vilotijević (@mijura).</description>
    <link>https://forem.com/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>Forem: Miodrag Vilotijević</title>
      <link>https://forem.com/mijura</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mijura"/>
    <language>en</language>
    <item>
      <title>Create Event-Driven Agentic Systems with Mozaik</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Tue, 05 May 2026 14:43:29 +0000</pubDate>
      <link>https://forem.com/mijura/structured-context-context-memory-context-item-generators-and-the-agentic-environment-496l</link>
      <guid>https://forem.com/mijura/structured-context-context-memory-context-item-generators-and-the-agentic-environment-496l</guid>
      <description>&lt;p&gt;Mozaik started as a multi-provider library. With version 3.0.0, we are evolving it into a full TypeScript framework for building non-blocking AI agents.&lt;/p&gt;

&lt;p&gt;This release introduces an event-based architecture designed around inversion of control. Instead of forcing developers into rigid, sequential pipelines, Mozaik enables humans, agents, observers, and tools to collaborate inside a shared agentic environment. Participants can emit, observe, and react to typed context items in real time, making multi-agent orchestration more flexible, composable, and concurrent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured Context
&lt;/h2&gt;

&lt;p&gt;Mozaik 3 introduces a structured, multi-provider context model compatible with the OpenResponses specification.&lt;/p&gt;

&lt;p&gt;Instead of treating prompts as plain strings, Mozaik models context as typed items, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SystemMessageItem&lt;/li&gt;
&lt;li&gt;DeveloperMessageItem&lt;/li&gt;
&lt;li&gt;UserMessageItem&lt;/li&gt;
&lt;li&gt;FunctionCallItem&lt;/li&gt;
&lt;li&gt;FunctionCallOutputItem&lt;/li&gt;
&lt;li&gt;ReasoningItem&lt;/li&gt;
&lt;li&gt;ModelMessageItem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flubvgnallo6rn7bou4z5.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%2Flubvgnallo6rn7bou4z5.png" alt=" " width="800" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These context items help developers provide clearer, more precise instructions to language models. For example, combining system, developer, and user messages gives the model a better-organized context than placing everything into a single user message.&lt;/p&gt;

&lt;p&gt;This structure also makes model interactions easier to inspect, store, replay, and adapt across providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context Memory
&lt;/h2&gt;

&lt;p&gt;Mozaik now models context as an aggregate of ordered context items through ModelContext.&lt;/p&gt;

&lt;p&gt;This gives developers a structured foundation for both short-term working memory and long-term persistence. The framework includes a repository interface, allowing context to be saved and retrieved through different storage backends.&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%2Fov1vfczklc3tk1czx8sx.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%2Fov1vfczklc3tk1czx8sx.png" alt=" " width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mozaik provides an in-memory implementation for working memory, while developers can implement their own repositories for file systems, databases, or other persistence layers.&lt;/p&gt;

&lt;p&gt;This approach keeps memory explicit, portable, and provider-independent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context Item Generators
&lt;/h2&gt;

&lt;p&gt;Mozaik 3 introduces asynchronous context item generators for key parts of the framework, including input handling, inference, and function call execution.&lt;/p&gt;

&lt;p&gt;Instead of relying on blocking await chains, runners can produce context items over time through async iterables. This enables items to be generated and delivered in real time while giving developers control over when and how those streams are consumed.&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%2F0bgzezru9u3hdu85be1w.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%2F0bgzezru9u3hdu85be1w.png" alt=" " width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mozaik provides default implementations for function call execution and OpenAI inference. Developers can also create their own implementations, which is especially useful for testing, mocking runners, customizing tool execution, or adding support for additional model providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Environment
&lt;/h2&gt;

&lt;p&gt;The main goal of Mozaik 3 is to enable AI agents to collaborate in a non-blocking way.&lt;/p&gt;

&lt;p&gt;We believe that truly agentic systems should not be limited to sequential chains. In many real-world use cases, agents need to observe, react, and contribute concurrently.&lt;/p&gt;

&lt;p&gt;To support this, Mozaik introduces the Participant abstraction and the AgenticEnvironment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Participants join the same environment and react to typed context items as they arrive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Participants, including humans and agents, join the same environment and subscribe to context items generated by other participants. When one participant emits a context item, other participants can observe it, react to it, ignore it, or use it to update their own internal context.&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%2Ft0hpel8ikevbx9ae4km4.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%2Ft0hpel8ikevbx9ae4km4.png" alt=" " width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or example, a human can send a UserMessageItem into the environment. One or more agents can react by running inference, producing model messages, requesting function calls, or incorporating the new item into their own context. Other agents can observe those outputs and respond with their own contributions.&lt;/p&gt;

&lt;p&gt;This enables agents to work in parallel and remain aware of what other participants are doing during inference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Participants
&lt;/h2&gt;

&lt;p&gt;To make multi-agent development faster, Mozaik 3 also includes default participant implementations:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;BaseAgentParticipant&lt;br&gt;
BaseHumanParticipant&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These base classes provide common capabilities for generating, receiving, and reacting to context items, so developers can set up multi-agent systems with less boilerplate while still keeping full control over the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Foundation for Multi-Agent Systems
&lt;/h2&gt;

&lt;p&gt;Mozaik 3 moves beyond simple provider abstraction.&lt;/p&gt;

&lt;p&gt;It introduces a framework-level architecture for building reactive, non-blocking, context-aware AI systems. By combining structured context, explicit memory, async context item generation, and a shared agentic environment, Mozaik gives developers the building blocks for more flexible and scalable multi-agent applications.&lt;/p&gt;

&lt;p&gt;With version 3.0.0, Mozaik becomes a foundation for building agents that do not just run in sequence, but collaborate through shared context in real time.&lt;/p&gt;

&lt;p&gt;Star on GitHub: &lt;a href="https://github.com/jigjoy-ai/mozaik" rel="noopener noreferrer"&gt;https://github.com/jigjoy-ai/mozaik&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>My Story of Building a TypeScript Framework for Event-Driven AI Agents</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Thu, 30 Apr 2026 08:11:58 +0000</pubDate>
      <link>https://forem.com/mijura/my-story-of-building-a-typescript-framework-for-event-driven-ai-agents-2k76</link>
      <guid>https://forem.com/mijura/my-story-of-building-a-typescript-framework-for-event-driven-ai-agents-2k76</guid>
      <description>&lt;p&gt;While working on agentic systems my co-founder early on detected the core limitation of agentic systems. They are doing this sequentially, so AI agent need to wait other agent to start the work. And they are blocking in nature - if you are building agentic system you probably know that almost any SDK or library has agents with blocking run method (await).&lt;/p&gt;

&lt;p&gt;So we decided to start addressing this problem and open up new possibilities - if we manage to make agents act more like humans: work autonomously, in parallel, interrupt, react to others and environment.&lt;/p&gt;

&lt;p&gt;For me it was hard to structure this agent communication. At first it was hard to detect from where to start - but after days of reading white papers, documentation of LLM providers I found the clue.&lt;/p&gt;

&lt;p&gt;It was OpenResponses documentation by OpenAI, Vercel, OpenRouter, Hugging Face - they unite to specify unified structure of context.&lt;/p&gt;

&lt;p&gt;They describe all context items in depth - I will cover just the basic idea:&lt;/p&gt;

&lt;p&gt;DeveloperMessage&lt;br&gt;
SystemMessage&lt;br&gt;
UserMessage&lt;br&gt;
Reasoning&lt;br&gt;
FunctionCall&lt;br&gt;
FunctionCallOutput&lt;br&gt;
ModelMessage&lt;/p&gt;

&lt;p&gt;All those items are streamable using semantic events.&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%2Fch48r2xtj7keo7clwykx.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%2Fch48r2xtj7keo7clwykx.png" alt=" " width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That was starting point for my framework.&lt;/p&gt;

&lt;p&gt;Only after that I realized I need stronger foundation.&lt;/p&gt;

&lt;p&gt;I started with building multi-provider library - but in order to go further and to decouple infrastructure for my code library I needed to create higher degree of abstraction than just mapping request to LLM providers.&lt;/p&gt;

&lt;p&gt;So I turned this specification into objects - enabling easy population of context, persistence, and streaming.&lt;/p&gt;

&lt;p&gt;Now I wanted to create interceptor while those context items generate in real-time.&lt;/p&gt;

&lt;p&gt;My second decision was to model agent loop as state machine with following states:&lt;/p&gt;

&lt;p&gt;user message received&lt;br&gt;
inference pending&lt;br&gt;
function call pending&lt;br&gt;
model message received&lt;br&gt;
Switching states based on probability of LLM response. I added hooks for each state so developers can write logic to control loop:&lt;/p&gt;

&lt;p&gt;onUserMessage&lt;br&gt;
beforeInference&lt;br&gt;
afterInference&lt;br&gt;
beforeFunctionCall&lt;br&gt;
afterFunctionCall&lt;br&gt;
onModelMessage&lt;/p&gt;

&lt;p&gt;It was good progress - but it was still modeling runtime of a single agent.&lt;/p&gt;

&lt;p&gt;After that I realized - to structure agent communication they probably need to share context items and semantic events. That was a mini insight I discovered down the road. But I soon realized that agent loop is just one concrete implementation of agent workflow with automated switching from one state to another.&lt;/p&gt;

&lt;p&gt;I needed more abstract solution - where developers can write logic to control the agent’s stream of context items that are generating in real time.&lt;/p&gt;

&lt;p&gt;So I removed agent loop abstraction. And came up with new idea. I will make agents and humans abstract - and model environment where they operate together. Participants subscribe to environment for listening context items. Every time new context item arrives - each participant will be notified so they can react on other participants work.&lt;/p&gt;

&lt;p&gt;Also I introduced generators for:&lt;/p&gt;

&lt;p&gt;FunctionCallRunner&lt;br&gt;
InferenceRunner&lt;br&gt;
InputStream&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%2Fycgrcdptc5odhcr55gpk.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%2Fycgrcdptc5odhcr55gpk.png" alt=" " width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Participants need to provide those generators during initialization.&lt;/p&gt;

&lt;p&gt;That was important decision - because with abstract generators which are isolated from communication we can easily mock LLM calls and test framework even before we send any real request.&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%2Fmy0ic86ayzrj0l0havlm.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%2Fmy0ic86ayzrj0l0havlm.png" alt=" " width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And voilà - we created environment where agents can naturally connect and react on the stream of context items they are producing. Not sequential. Not blocking. But event-driven. More like how humans actually work.&lt;/p&gt;

&lt;p&gt;That’s my story of building a TypeScript framework. I am excited to see what possibilities and challenges will emerge when using multiple agents at once.&lt;/p&gt;

&lt;p&gt;Check it out:&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/mozaik" rel="noopener noreferrer"&gt;
        mozaik
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Mozaik is a TypeScript framework for building non-blocking AI agents.
    &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&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Mozaik&lt;/strong&gt; is a TypeScript framework for building AI agents that share an &lt;strong&gt;agentic environment&lt;/strong&gt; instead of being orchestrated through rigid pipelines.&lt;/p&gt;
&lt;p&gt;In Mozaik, humans, agents, observers, and tools are all &lt;code&gt;Participant&lt;/code&gt;s of the same &lt;code&gt;AgenticEnvironment&lt;/code&gt;. Each participant runs &lt;strong&gt;non-blocking&lt;/strong&gt; and streams typed &lt;code&gt;ContextItem&lt;/code&gt;s into the environment. Every other participant sees those items in real time and can react, intercept, or stay silent — without any central scheduler.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn add @mozaik-ai/core&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Key Configuration&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-dotenv notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; .env&lt;/span&gt;
&lt;span class="pl-v"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;your-openai-key-here&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The agentic environment&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;AgenticEnvironment&lt;/code&gt; is a broadcast bus for typed context items. &lt;code&gt;Participant&lt;/code&gt;s &lt;code&gt;join()&lt;/code&gt; it, and any item produced by one participant is delivered to every subscriber's &lt;code&gt;onContextItem(source, item)&lt;/code&gt; callback.&lt;/p&gt;

  &lt;div class="js-render-enrichment-target"&gt;
    &lt;div class="render-plaintext-hidden"&gt;
      &lt;pre&gt;flowchart LR
    Human[BaseHumanParticipant] --&amp;gt;|streamInput| Env(("AgenticEnvironment"))
    Agent[BaseAgentParticipant] --&amp;gt;|"runInference / executeFunctionCall"| Env
    Observer[Custom Participant] --&amp;gt;|join| Env
    Env --&amp;gt;|onContextItem| Human
    Env --&amp;gt;|onContextItem| Agent
    Env --&amp;gt;|onContextItem| Observer
&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;span class="js-render-enrichment-loader d-flex flex-justify-center flex-items-center width-full"&gt;
    &lt;span&gt;
  
    
    
    &lt;span class="sr-only"&gt;Loading&lt;/span&gt;
&lt;/span&gt;
  &lt;/span&gt;



&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Non-blocking participants&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Mozaik ships two ready-to-use participants:&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Participant&lt;/th&gt;
&lt;th&gt;Capabilities&lt;/th&gt;
&lt;th&gt;Pulls from&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BaseHumanParticipant&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jigjoy-ai/mozaik" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>agents</category>
      <category>ai</category>
      <category>showdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>I mapped the OpenResponses specification into domain objects to make context, context items, and streaming events explicit and usable across multiple providers - check it out.</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Fri, 17 Apr 2026 08:38:28 +0000</pubDate>
      <link>https://forem.com/mijura/i-mapped-the-openresponses-specification-into-domain-objects-to-make-context-context-items-and-56kl</link>
      <guid>https://forem.com/mijura/i-mapped-the-openresponses-specification-into-domain-objects-to-make-context-context-items-and-56kl</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9" class="crayons-story__hidden-navigation-link"&gt;Why Agent Frameworks End Up As SDK Wrappers - And How To Overcome It&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/jigjoy"&gt;
            &lt;img alt="JigJoy logo" 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%2Forganization%2Fprofile_image%2F12673%2F0815940b-2b5b-4cdd-9626-9dd0bf5f8be4.png" class="crayons-logo__image" width="492" height="474"&gt;
          &lt;/a&gt;

          &lt;a href="/mijura" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&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%2F3818142%2F3098a7e7-1463-495b-9f64-117ffa2a145f.png" alt="mijura profile" class="crayons-avatar__image" width="240" height="240"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mijura" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Miodrag Vilotijević
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Miodrag Vilotijević
                
              
              &lt;div id="story-author-preview-content-3508869" 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="/mijura" 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%2F3818142%2F3098a7e7-1463-495b-9f64-117ffa2a145f.png" class="crayons-avatar__image" alt="" width="240" height="240"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Miodrag Vilotijević&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;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/jigjoy" class="crayons-story__secondary fw-medium"&gt;JigJoy&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 16&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/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9" id="article-link-3508869"&gt;
          Why Agent Frameworks End Up As SDK Wrappers - And How To Overcome It
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agents&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&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/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9" 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="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&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/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              4&lt;span class="hidden s:inline"&gt; comments&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;
            4 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>
    </item>
    <item>
      <title>Why Agent Frameworks End Up As SDK Wrappers - And How To Overcome It</title>
      <dc:creator>Miodrag Vilotijević</dc:creator>
      <pubDate>Thu, 16 Apr 2026 07:48:43 +0000</pubDate>
      <link>https://forem.com/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9</link>
      <guid>https://forem.com/jigjoy/why-agent-frameworks-end-up-as-sdk-wrappers-and-how-to-overcome-it-51j9</guid>
      <description>&lt;p&gt;Today, most frameworks for building AI agents are missing something fundamental. If you look closely at the language they use, you'll notice a pattern: their domain models are anemic. They give you abstractions like "agent", "tool", "step", but they don't actually model the thing that matters most - context. Because of that, developers are left on their own to deal with problems like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;context window overflow&lt;/li&gt;
&lt;li&gt;context bloating&lt;/li&gt;
&lt;li&gt;loss of structure across multiple model calls&lt;/li&gt;
&lt;li&gt;messy handling of tool outputs and reasoning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And where does all of that logic end up? In your application layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Cost: Polluting Your Domain
&lt;/h2&gt;

&lt;p&gt;Instead of focusing on your actual domain (finance, healthcare, internal tooling, etc.), you start writing code like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;guessing what the model "needs to see" next&lt;/li&gt;
&lt;li&gt;use your own way and schema to persist context&lt;/li&gt;
&lt;li&gt;load context with schema which is not most efficient way to do it&lt;/li&gt;
&lt;li&gt;and so on...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not your domain. It's not even context engineering. In the absence of the right abstractions, developers are pushed to reimplement core LLM concepts themselves - while mixing them with their own domain logic. And this is where complexity arises. We experienced these issues firsthand. That’s what pushed us to address them—so engineers like us can extract more from LLMs and open up new possibilities.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Enable developers to use a rich domain model for handling context in agentic applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So instead of letting LLM concerns leak into your domain, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep your domain logic isolated and aligned with best practices&lt;/li&gt;
&lt;li&gt;use standardized building blocks to build your own context model&lt;/li&gt;
&lt;li&gt;don't spend time reinventing the wheel&lt;/li&gt;
&lt;li&gt;and hopefully, enjoy the process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, this is a space we're actively learning in. LLMs are still evolving, and we want to both learn and share what we discover while working on these problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Point: OpenResponses
&lt;/h2&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%2Fzysv7moyuo16voti82b5.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%2Fzysv7moyuo16voti82b5.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We didn't start from scratch.&lt;/p&gt;

&lt;p&gt;Our starting point is the OpenResponses specification, published by companies like OpenAI, OpenRouter, Vercel and others in January this year. Their goal is to standardize how we work with LLM providers. They define a shared structure that reflects how models actually operate.&lt;/p&gt;

&lt;p&gt;At its core:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Context is composed of context items.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-created items
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;user message&lt;/li&gt;
&lt;li&gt;developer message&lt;/li&gt;
&lt;li&gt;function call output&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Model-generated items
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;reasoning&lt;/li&gt;
&lt;li&gt;function call&lt;/li&gt;
&lt;li&gt;model message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They also introduce an important idea:&lt;/p&gt;

&lt;p&gt;Model-generated items are state machines that can be streamed with semantic events.&lt;/p&gt;

&lt;p&gt;Those are the fundamental building blocks of the OpenResponses specification and how major LLM providers implement them. For a deeper dive, you can check: &lt;a href="https://www.openresponses.org/" rel="noopener noreferrer"&gt;https://www.openresponses.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3g16u5ulj76jvqh2fq8.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%2Fv3g16u5ulj76jvqh2fq8.png" alt=" " width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Take on This
&lt;/h2&gt;

&lt;p&gt;OpenResponses gives us the source of truth for how LLMs work today. These building blocks should not be ignored. But the specification itself is not enough. Developers still need a way to work with it in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Mozaik
&lt;/h2&gt;

&lt;p&gt;Our approach is to take this specification and turn it into a rich object domain model. The goal is not to abstract everything away, but to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make context explicit&lt;/li&gt;
&lt;li&gt;make it composable&lt;/li&gt;
&lt;li&gt;make it persistent&lt;/li&gt;
&lt;li&gt;make it evolvable across multiple steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With our base implementation, developers can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build structured context from typed items&lt;/li&gt;
&lt;li&gt;manage model-generated items (reasoning, function calls, outputs)&lt;/li&gt;
&lt;li&gt;persist context&lt;/li&gt;
&lt;li&gt;restore it and continue execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without leaking context engineering concerns into their core domain logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Leads
&lt;/h2&gt;

&lt;p&gt;We see this as a starting point.&lt;/p&gt;

&lt;p&gt;By introducing a richer domain model for context, new opportunities open up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;better strategies for context compression&lt;/li&gt;
&lt;li&gt;smarter handling of long-running interactions&lt;/li&gt;
&lt;li&gt;clearer debugging and observability&lt;/li&gt;
&lt;li&gt;more predictable and controllable multi-agent systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic Example
&lt;/h2&gt;

&lt;p&gt;Here's a minimal example of building and storing context using Mozaik:&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;contextRepository&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;InMemoryContextRepository&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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UserMessage&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tell me a joke about birds&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;developerMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DeveloperMessage&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a joke teller. You will be given a joke and you will need to tell it to the user.&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;projectId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`pr-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;developerMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addItem&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;await&lt;/span&gt; &lt;span class="nx"&gt;contextRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GPT54Model&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;generatedItems&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;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generatedItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contextRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&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;restoredContexts&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;contextRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByProjectId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectId&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="nx"&gt;restoredContexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This uses an in-memory repository, but in real applications you can plug in your own persistence layer.&lt;/p&gt;

&lt;p&gt;You can find more working examples in the GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jigjoy-ai/mozaik-examples" rel="noopener noreferrer"&gt;github.com/jigjoy-ai/mozaik-examples&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The industry is moving fast. But if we keep ignoring context as a core primitive, we'll keep rebuilding the same fragile systems. Mozaik is our attempt to fix that - by giving context the place it actually deserves. And this is just the beginning. We're excited to see where this journey takes us.&lt;/p&gt;

&lt;p&gt;If you like what we’re building, give Mozaik a ⭐ on GitHub.&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/mozaik" rel="noopener noreferrer"&gt;
        mozaik
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Mozaik is a TypeScript library for building, managing, and evolving LLM context.
    &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&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Mozaik&lt;/strong&gt; is a TypeScript library for building, managing, and evolving &lt;strong&gt;LLM context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of focusing on agents themselves, Mozaik provides a structured way to &lt;strong&gt;model, manipulate, persist, and restore the context&lt;/strong&gt; that drives language model behavior. It implements a clean object model aligned with the &lt;strong&gt;OpenResponses specification&lt;/strong&gt;, enabling developers to work with LLM inputs and outputs as composable, typed entities.&lt;/p&gt;

&lt;p&gt;With Mozaik, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure interactions as ordered &lt;strong&gt;context items&lt;/strong&gt; (messages, reasoning steps, function calls, etc.)&lt;/li&gt;
&lt;li&gt;Append and evolve context across multiple model calls&lt;/li&gt;
&lt;li&gt;Persist and reload context from storage&lt;/li&gt;
&lt;li&gt;Manage context size and avoid overflow&lt;/li&gt;
&lt;li&gt;Build complex workflows through &lt;strong&gt;context composition&lt;/strong&gt;, not ad-hoc prompt strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mozaik treats context as a &lt;strong&gt;first-class primitive&lt;/strong&gt;, making it easier to design scalable, maintainable, and provider-agnostic LLM applications.&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://private-user-images.githubusercontent.com/17992401/548975496-0fdc15a8-3778-4d0e-bd13-143d04090b9e.jpeg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzYzMjY0NDYsIm5iZiI6MTc3NjMyNjE0NiwicGF0aCI6Ii8xNzk5MjQwMS81NDg5NzU0OTYtMGZkYzE1YTgtMzc3OC00ZDBlLWJkMTMtMTQzZDA0MDkwYjllLmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwNDE2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDQxNlQwNzU1NDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04NDdlNjMxMmM3MDBlNjMzYTdiYjc5YmM2Yjk3MjBkZTE4ZGM4MGU2Njg2NWNhNTUyZTBkZmM1YTBkNjM4OWNiJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZqcGVnIn0.dw8mInBMyCycjVsEiae_QiPzuRRpSudoVcs7YJsMf_0"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F17992401%2F548975496-0fdc15a8-3778-4d0e-bd13-143d04090b9e.jpeg%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzYzMjY0NDYsIm5iZiI6MTc3NjMyNjE0NiwicGF0aCI6Ii8xNzk5MjQwMS81NDg5NzU0OTYtMGZkYzE1YTgtMzc3OC00ZDBlLWJkMTMtMTQzZDA0MDkwYjllLmpwZWc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwNDE2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDQxNlQwNzU1NDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04NDdlNjMxMmM3MDBlNjMzYTdiYjc5YmM2Yjk3MjBkZTE4ZGM4MGU2Njg2NWNhNTUyZTBkZmM1YTBkNjM4OWNiJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZqcGVnIn0.dw8mInBMyCycjVsEiae_QiPzuRRpSudoVcs7YJsMf_0" alt="mozaik"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📦 Installation&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn add @mozaik-ai/core&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;API Key Configuration&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Make sure to set your API keys in a &lt;code&gt;.env&lt;/code&gt; file at the…&lt;/p&gt;
&lt;/div&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/mozaik" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>llm</category>
      <category>ai</category>
      <category>agents</category>
      <category>javascript</category>
    </item>
    <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://forem.com/mijura/with-this-mcp-notion-is-becoming-a-vibe-coding-platform-turning-its-pages-into-applications-its-20ki</link>
      <guid>https://forem.com/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;14&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://forem.com/jigjoy/from-monolith-to-microservices-how-bounded-context-improves-ai-driven-development-382f</link>
      <guid>https://forem.com/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://forem.com/jigjoy/dont-write-frameworks-for-dummies-100l</link>
      <guid>https://forem.com/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://forem.com/jigjoy/how-to-build-an-autonomous-ai-agent-that-executes-terminal-commands-23ke</link>
      <guid>https://forem.com/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>
