<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marcel Wege</title>
    <description>The latest articles on DEV Community by Marcel Wege (@weegy).</description>
    <link>https://dev.to/weegy</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%2F3969430%2F3cccd057-011c-4fcb-bbd0-3fe55b4828d8.jpeg</url>
      <title>DEV Community: Marcel Wege</title>
      <link>https://dev.to/weegy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/weegy"/>
    <language>en</language>
    <item>
      <title>What building a multi-agent runtime taught me about isolation and data leaks</title>
      <dc:creator>Marcel Wege</dc:creator>
      <pubDate>Fri, 05 Jun 2026 08:00:05 +0000</pubDate>
      <link>https://dev.to/weegy/4-hard-lessons-from-building-a-self-hostable-open-source-ai-agent-runtime-2dgb</link>
      <guid>https://dev.to/weegy/4-hard-lessons-from-building-a-self-hostable-open-source-ai-agent-runtime-2dgb</guid>
      <description>&lt;p&gt;The model was the easy part.&lt;/p&gt;

&lt;p&gt;Prompting, tool-calling, getting usable output back: mostly solved, mostly boring. What cost me weeks was everything around the model. Where memory lives. What a tool is allowed to hand back. Whether a non-engineer can build any of it without me.&lt;/p&gt;

&lt;p&gt;This is from building omadia, an agent runtime we run in production and ship as open source. The point of it isn't "more AI magic." It's the control layer under the magic. Your data stays on your own infrastructure, you can audit what the agents do, and you decide what they are allowed to touch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory between agents bleeds, and you notice too late
&lt;/h2&gt;

&lt;p&gt;One agent, no problem. Several agents sharing one memory store, and context starts crossing wires: agent A "knows" something only agent B was ever told. It is intermittent, it looks like a hallucination, and it quietly burns trust once different agents serve different people.&lt;/p&gt;

&lt;p&gt;What fixed it was access-aware memory. Each agent and each orchestrator gets its own namespace and its own slice of the graph, and the routing decision happens where the channel binding resolves, not five layers deep in the agent. An agent reads its own context or nothing.&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="c1"&gt;// scope every read/write to the agent that owns the turn&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memoryFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// isolated namespace + graph slice&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;turn&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;context&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;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cost: sharing on purpose is now the harder path. That is the right trade. Isolation should be the default you opt out of, not the thing you remember to add.&lt;/p&gt;

&lt;h2&gt;
  
  
  The leak is in the tool output, not the prompt
&lt;/h2&gt;

&lt;p&gt;Everybody guards the prompt. The leak that actually got me came out the other side, in tool results.&lt;/p&gt;

&lt;p&gt;A tool returns a tidy "summary plus details" object. Buried in the details is a field, sometimes PII, that the current agent has no business seeing. Nobody injected anything. The data just rode along in the response and the model repeated it.&lt;/p&gt;

&lt;p&gt;So tool output became an untrusted boundary, the same way user input is. omadia redacts results per record before the model sees them and restores the full data only where the access actually allows it. If you build around Claude or ChatGPT, this is the piece people skip and then regret.&lt;/p&gt;

&lt;h2&gt;
  
  
  The builder I was proud of was the one people abandoned
&lt;/h2&gt;

&lt;p&gt;This is the part I got wrong. I built a full agent builder, every option exposed, and handed it to the non-engineers it was meant for. They opened it once and left.&lt;/p&gt;

&lt;p&gt;The version that worked was smaller. Describe the agent in plain language, connect a couple of tools, watch it run in a live preview next to the description. Same engine underneath. The power-user surface still exists for people who want it. It just stopped being the front door.&lt;/p&gt;

&lt;p&gt;For a builder, the default screen is a product decision, not a config flag. Aim it at the least technical person you actually want to keep.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plugin seams decide whether any of this scales
&lt;/h2&gt;

&lt;p&gt;omadia is built from plugins, and the seam that earns its keep is the channel: where the agent actually talks. A conversation starts in Telegram, moves to MS Teams, and the agent keeps its context across the jump. In an enterprise that handoff matters more than any single feature, because Teams is where the work already happens. Integrations and capability providers like graph memory plug onto the same seams.&lt;/p&gt;

&lt;p&gt;Get those seams wrong early and everything downstream is rework. I know, because I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two questions I am still arguing with myself about
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;How would you scope memory between orchestrators? Strict per-orchestrator namespaces stay clean but make deliberate sharing the awkward case.&lt;/li&gt;
&lt;li&gt;Do you redact tool output before or after expanding the record? I expand first, then gate per field. The ordering has real consequences.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you build self-hosted agents, I would rather hear where this breaks than where it shines. The runtime is open source (MIT) and runs on your own infrastructure, in containers or straight on the Node stack. More at omadia.ai, and the design discussion is here: &lt;a href="https://github.com/byte5ai/omadia/discussions/216" rel="noopener noreferrer"&gt;https://github.com/byte5ai/omadia/discussions/216&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
