<?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: Arindam Majumder </title>
    <description>The latest articles on DEV Community by Arindam Majumder  (@arindam_1729).</description>
    <link>https://dev.to/arindam_1729</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F965723%2F8c3a1bb4-eb47-4302-a280-09eedb8bc785.png</url>
      <title>DEV Community: Arindam Majumder </title>
      <link>https://dev.to/arindam_1729</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arindam_1729"/>
    <language>en</language>
    <item>
      <title>Building a Debate Council of LLMs to Stress-Test NVIDIA Cosmos 3</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Wed, 24 Jun 2026 13:19:01 +0000</pubDate>
      <link>https://dev.to/arindam_1729/building-a-debate-council-of-llms-to-stress-test-nvidia-cosmos-3-2ihc</link>
      <guid>https://dev.to/arindam_1729/building-a-debate-council-of-llms-to-stress-test-nvidia-cosmos-3-2ihc</guid>
      <description>&lt;p&gt;A benchmark score tells you how a model did on a test. It does not tell you whether the model can hold a position, take a punch, and adjust without falling apart.&lt;/p&gt;

&lt;p&gt;That second thing is what I wanted to know about &lt;a href="https://nvidianews.nvidia.com/news/nvidia-launches-cosmos-3-the-open-frontier-foundation-model-for-physical-ai" rel="noopener noreferrer"&gt;NVIDIA Cosmos 3&lt;/a&gt;, which NVIDIA had just shipped. So instead of running yet another eval, I did something more fun. I built the model an arena and made it argue with itself.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2061515414837100955-54" src="https://platform.twitter.com/embed/Tweet.html?id=2061515414837100955"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2061515414837100955-54');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2061515414837100955&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;Cosmos Arena&lt;/strong&gt;, a multi-agent debate council. You hand it a motion, something like "This house believes AGI will arrive before 2035," and five roles fight it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Advocate argues for, a Skeptic argues against&lt;/li&gt;
&lt;li&gt;They trade rebuttals across several rounds&lt;/li&gt;
&lt;li&gt;An optional Pragmatist pokes holes in both sides&lt;/li&gt;
&lt;li&gt;An Arbiter scores everything and hands down a verdict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the catch that makes it a real test: every seat runs on the same model. The only thing that changes is the role.&lt;/p&gt;

&lt;p&gt;That is surprisingly hard to fake. A model that just knows how to sound smart will produce two confident speeches that never touch. A model that can actually reason opens round two by answering the exact weakness the other side exposed in round one. You watch the difference happen, turn by turn.&lt;/p&gt;

&lt;p&gt;This tutorial is the full build. By the end you will have a working Streamlit app, you will get why the orchestration uses LangGraph instead of one model pretending to be everyone, and you will know how to serve Cosmos 3 through Nebius Token Factory.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, what Cosmos 3 actually is
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6nzmi6610jdumq1iq93u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6nzmi6610jdumq1iq93u.png" alt="Cosmos 3" width="690" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me be honest about the model up front, because it is not a normal chat model, and the name can mislead you.&lt;/p&gt;

&lt;p&gt;NVIDIA built Cosmos 3 for &lt;strong&gt;Physical AI&lt;/strong&gt;: robots, autonomous vehicles, factory floors, anything that has to understand motion, causality, and physics in the real world. NVIDIA &lt;a href="https://blogs.nvidia.com/blog/cosmos-3-physical-ai-open-world-foundation-model/" rel="noopener noreferrer"&gt;launched it on June 1, 2026 at GTC Taipei&lt;/a&gt; and calls it the first fully open omnimodel with native vision reasoning.&lt;/p&gt;

&lt;p&gt;Under the hood it is a Mixture-of-Transformers that pairs a &lt;strong&gt;reasoning transformer&lt;/strong&gt; with an &lt;strong&gt;expert generation transformer&lt;/strong&gt;. One half thinks about object interactions, motion, and space. The other half generates video and action trajectories.&lt;/p&gt;

&lt;p&gt;The whole point is to let a robot reason before it acts, which cuts physical AI training cycles from months down to days. The &lt;a href="https://developer.nvidia.com/blog/develop-physical-ai-reasoning-world-and-action-models-with-nvidia-cosmos-3/" rel="noopener noreferrer"&gt;NVIDIA technical blog&lt;/a&gt; goes deep if you want the full picture.&lt;/p&gt;

&lt;p&gt;So why use a robotics world model to run a debate? Because that reasoning transformer is the interesting part. NVIDIA trained it to reason about the physical world, and I wanted to see how well that transfers to something it was never sold for: a pure-language argument, no images, no video, just ideas. That transfer tells you far more than a single-prompt score ever will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cosmos 3 specs at a glance
&lt;/h2&gt;

&lt;p&gt;Here are the details that matter for this project.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Cosmos 3 Super&lt;/th&gt;
&lt;th&gt;Cosmos 3 Nano&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total parameters&lt;/td&gt;
&lt;td&gt;64B&lt;/td&gt;
&lt;td&gt;16B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Split&lt;/td&gt;
&lt;td&gt;32B reasoner + 32B generator&lt;/td&gt;
&lt;td&gt;8B reasoner + 8B generator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture&lt;/td&gt;
&lt;td&gt;Mixture-of-Transformers (reasoning + generation)&lt;/td&gt;
&lt;td&gt;Mixture-of-Transformers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built for&lt;/td&gt;
&lt;td&gt;Post-training robotics and AV models at the highest physics accuracy&lt;/td&gt;
&lt;td&gt;Fast video and action reasoning in a fraction of a second&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;OpenMDW (open for commercial and non-commercial use)&lt;/td&gt;
&lt;td&gt;OpenMDW&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Released&lt;/td&gt;
&lt;td&gt;June 1, 2026 (GTC Taipei)&lt;/td&gt;
&lt;td&gt;June 1, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few more things worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is genuinely &lt;strong&gt;omnimodal&lt;/strong&gt;. It takes in and generates text, images, video, ambient sound, and action sequences, all in one model.&lt;/li&gt;
&lt;li&gt;It was trained on one of the largest multimodal physical AI datasets out there, billions of samples across text, image, video, sound, and action.&lt;/li&gt;
&lt;li&gt;It shipped with a &lt;strong&gt;Cosmos Coalition&lt;/strong&gt; of robotics and AI labs (Agile Robots, Black Forest Labs, Runway, Skild AI, and others) building on top of it.&lt;/li&gt;
&lt;li&gt;NVIDIA is upfront about the limits: generation can drift over time, and the reasoning can still hallucinate, since there is no physics simulator actually running in the loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our build, the parts that matter are the reasoner tower and how well the model holds a role. The debate leans hard on both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it runs: Nebius Token Factory
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjna6go4f9akbn41spv07.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjna6go4f9akbn41spv07.png" alt="Image2" width="799" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A 64B omni-model is not something I want to babysit on my own GPUs. So every model call in this project goes through &lt;a href="https://dub.sh/nebius" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Token Factory is Nebius's production inference platform. It takes open and partner models, including NVIDIA's, and serves them behind one fast, OpenAI-compatible API, with the posttraining and governance pieces handled for you.&lt;/p&gt;

&lt;p&gt;NVIDIA models like Nemotron already run there, and Nebius has been &lt;a href="https://nebius.com/newsroom/nebius-teams-with-nvidia-to-build-cloud-for-robotics-and-physical-ai" rel="noopener noreferrer"&gt;building cloud infrastructure with NVIDIA specifically for robotics and physical AI&lt;/a&gt;. That makes it a natural home for Cosmos.&lt;/p&gt;

&lt;p&gt;Why it fits this project so well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-compatible API.&lt;/strong&gt; Anything built for OpenAI works with a base-URL swap. The base URL is &lt;code&gt;https://api.tokenfactory.nebius.com/v1/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drop-in LangChain support.&lt;/strong&gt; The &lt;a href="https://pypi.org/project/langchain-nebius/" rel="noopener noreferrer"&gt;&lt;code&gt;langchain-nebius&lt;/code&gt;&lt;/a&gt; package gives you a &lt;code&gt;ChatNebius&lt;/code&gt; model that slots straight into LangGraph.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No GPUs to provision.&lt;/strong&gt; You point at a model name and pay per token. That is the whole setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One key for five seats.&lt;/strong&gt; Every council member shares a single &lt;code&gt;NEBIUS_API_KEY&lt;/code&gt;, so there are no per-agent credentials to juggle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grab a key from the &lt;a href="https://tokenfactory.nebius.com/" rel="noopener noreferrer"&gt;Nebius Token Factory console&lt;/a&gt; and you are ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are building
&lt;/h2&gt;

&lt;p&gt;The council has five roles. Four of them are model calls. The fifth, the Moderator, is the graph itself, and that turns out to be the decision that makes everything work.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The Advocate&lt;/td&gt;
&lt;td&gt;&lt;code&gt;proponent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Argues for the motion, rebuts the Skeptic each round&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Skeptic&lt;/td&gt;
&lt;td&gt;&lt;code&gt;opponent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Argues against the motion, rebuts the Advocate each round&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Pragmatist&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pragmatist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Independent member who stress-tests both sides (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Arbiter&lt;/td&gt;
&lt;td&gt;&lt;code&gt;judge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Scores logic, evidence, and rebuttal, then gives a verdict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Moderator&lt;/td&gt;
&lt;td&gt;the graph&lt;/td&gt;
&lt;td&gt;Routes turns, threads the transcript, decides when to stop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The flow goes from opening statements, through alternating rebuttal rounds, to an optional reality check, and finally a scored verdict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        +--------------+      +-------------+
START -&amp;gt;|  proponent   | ---&amp;gt; |  opponent   | --&amp;gt; (more rounds?)
        +--------------+      +-------------+         |
              ^  more rounds: next_round              | no
              +---------------------------------------+
                                                      v
                                  (pragmatist?) -&amp;gt; judge -&amp;gt; END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why a graph and not one clever prompt
&lt;/h2&gt;

&lt;p&gt;You could try the lazy version: one prompt that says "argue both sides of X, then judge it." It reads fine and proves nothing.&lt;/p&gt;

&lt;p&gt;The problem is that the model writes the "for" case and the "against" case in a single breath. They do not respond to each other, because they were written together. There is no exchange, just a model acting out the idea of a debate.&lt;/p&gt;

&lt;p&gt;A real debate needs structure that a prompt cannot promise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each side gets its own turn, so each argument is a focused generation&lt;/li&gt;
&lt;li&gt;A rebuttal sees what the other side actually just said&lt;/li&gt;
&lt;li&gt;Rounds stack up, so later the Advocate answers a real objection instead of repeating its opener&lt;/li&gt;
&lt;li&gt;The judge reads the full transcript and scores it on fixed criteria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a state machine, not a prompt, which is exactly what LangGraph is for. Putting the structure in code means each role gets its own isolated call, rebuttals genuinely see the prior turn, and the round count is enforced rather than left to the model's mood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.11 or higher&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://dub.sh/nebius" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt; account and API key&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/astral-sh/uv" rel="noopener noreferrer"&gt;&lt;code&gt;uv&lt;/code&gt;&lt;/a&gt; for dependencies (&lt;code&gt;pip install uv&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dependency list is short on purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;"langgraph&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;    &lt;span class="py"&gt;"langchain-nebius&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;    &lt;span class="py"&gt;"langchain-core&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;    &lt;span class="py"&gt;"python-dotenv&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;    &lt;span class="py"&gt;"streamlit&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.47&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;",&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Project layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cosmos_arena_debate_council/
  app.py              # Streamlit UI and live debate streaming
  cosmos_council.py   # LangGraph debate graph: nodes, routing, model
  pyproject.toml      # Dependencies
  .env.example        # Environment variable template
  assets/             # NVIDIA and Nebius logos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Arindam200/awesome-ai-apps.git
&lt;span class="nb"&gt;cd &lt;/span&gt;awesome-ai-apps/advance_ai_agents/cosmos_arena_debate_council
uv &lt;span class="nb"&gt;sync
cp&lt;/span&gt; .env.example .env   &lt;span class="c"&gt;# then add your NEBIUS_API_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEBIUS_API_KEY=your_api_key_here
# Optional overrides
COSMOS_MODEL=nvidia/Cosmos3-Super-Reasoner
NEBIUS_BASE_URL=https://api.tokenfactory.nebius.com/v1/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Wire up Cosmos 3 and handle the reasoning channel
&lt;/h2&gt;

&lt;p&gt;This is the one gotcha that will trip you up, so it goes first.&lt;/p&gt;

&lt;p&gt;The stock &lt;code&gt;ChatNebius&lt;/code&gt; integration reads the answer from &lt;code&gt;message.content&lt;/code&gt;, the usual OpenAI shape. But Cosmos, served as a reasoner, often puts its answer in a non-standard &lt;code&gt;reasoning&lt;/code&gt; field and leaves &lt;code&gt;content&lt;/code&gt; empty. Use the integration as-is and every council member comes back blank.&lt;/p&gt;

&lt;p&gt;The fix is a small subclass that folds the reasoning field back in. If &lt;code&gt;content&lt;/code&gt; is empty, the reasoning is the answer. If both are there, the reasoning becomes separate chain-of-thought for the UI to show.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.outputs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatResult&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_nebius&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatNebius&lt;/span&gt;

&lt;span class="n"&gt;DEFAULT_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.tokenfactory.nebius.com/v1/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;DEFAULT_MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nvidia/Cosmos3-Super-Reasoner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CosmosChatNebius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChatNebius&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;ChatNebius that surfaces the non-standard `reasoning` field.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_create_chat_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation_info&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ChatResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;_create_chat_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_dump&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
            &lt;span class="n"&gt;reasoning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;
            &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="c1"&gt;# Real answer present, keep reasoning as separate chain-of-thought.
&lt;/span&gt;                &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;additional_kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning_content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Empty content, so the reasoning is the answer.
&lt;/span&gt;                &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cosmos can also do it the other way, wrapping its reasoning in &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; tags inside the content. A small splitter pulls the two apart so the UI never mixes thinking into the actual argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="n"&gt;_THINK_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;think&amp;gt;(.*?)&amp;lt;/think&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DOTALL&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IGNORECASE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;split_reasoning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Separate the visible answer from the model&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s &amp;lt;think&amp;gt; reasoning.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;reasoning_parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_THINK_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_THINK_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;think&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;  &lt;span class="c1"&gt;# unclosed reasoning block
&lt;/span&gt;        &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;think&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;reasoning_parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;think&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reasoning_parts&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A shared factory ties it together. Every seat calls this same function, so the model never changes, only the prompt does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ChatNebius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Create the shared Cosmos reasoner backed by Nebius Token Factory.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CosmosChatNebius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COSMOS_MODEL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_MODEL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBIUS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBIUS_BASE_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;temperature&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;
  
  
  Step 2: Give each seat a persona
&lt;/h2&gt;

&lt;p&gt;The roles are just system prompts, but they are written to force genuinely different behavior. The Advocate and Skeptic are told to rebut the other side point by point before adding anything new. The Pragmatist takes no side. The Arbiter has to produce a fixed scorecard. Here are two of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PROPONENT_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are The Advocate, a council member in the Cosmos Arena debate.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your role: argue persuasively and rigorously IN FAVOR of the motion.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Guidelines:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- Make the strongest honest case for the motion.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- Ground claims in reasoning, evidence, and concrete examples.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- If you are given the opposition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s prior argument, directly REBUT it &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;point by point before adding new arguments.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- Be sharp and confident, but never fabricate facts.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- Keep it focused: 3-5 tight paragraphs in markdown. End with your &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;single strongest line.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- Output ONLY your argument. Do not narrate your process.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;JUDGE_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are The Arbiter, the impartial judge of the Cosmos Arena debate.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You will be given the full debate transcript.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deliver your verdict as markdown with EXACTLY these sections:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### Scorecard&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A markdown table scoring each side (Proponent, Opponent) from 0-10 on &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**Logic**, **Evidence**, and **Rebuttal**, with a **Total** column.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### Verdict&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;State the winner (or an honest draw) in one bold sentence, then 2-3 &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentences justifying it based strictly on the arguments made.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### Strongest Argument&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Quote or paraphrase the single most decisive point.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;### What Would Change the Outcome&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;One short paragraph on the evidence or reasoning that would flip the result.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where you find out if Cosmos 3 can really be five different people. Weaker models leak. The Skeptic starts agreeing, or the Arbiter picks a winner before it reads anything. A strong reasoner keeps the seats clean all the way through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Model the debate as state
&lt;/h2&gt;

&lt;p&gt;The whole debate lives in one typed state object. The trick is &lt;code&gt;transcript&lt;/code&gt;, an append-only list. Each node returns only its single new turn, and LangGraph's reducer, &lt;code&gt;operator.add&lt;/code&gt;, tacks it onto the running transcript. That means each streamed update is exactly one new turn, which is perfect for a live UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Turn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;speaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;   &lt;span class="c1"&gt;# proponent | opponent | pragmatist | judge
&lt;/span&gt;    &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;     &lt;span class="c1"&gt;# debate round (0 for judge and pragmatist)
&lt;/span&gt;    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;      &lt;span class="c1"&gt;# the visible argument
&lt;/span&gt;    &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="c1"&gt;# the model's chain-of-thought, if any
&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DebateState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;current_round&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="c1"&gt;# operator.add makes each node APPEND its turn to the transcript.
&lt;/span&gt;    &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Turn&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One small helper grabs the other side's most recent turn. This is the piece that makes rebuttals real instead of generic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_latest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Turn&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;speaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speaker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;speaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Write the nodes
&lt;/h2&gt;

&lt;p&gt;Each council member is a node: one model call with a role prompt and a user prompt built from the live transcript. Watch how the proponent's prompt changes between the opening round and later rounds. From round two on, it gets handed the Skeptic's latest argument and told to rebut it point by point. That is the whole difference between a debate and two people talking past each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_prompt&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inline_reasoning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;split_reasoning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;reasoning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;additional_kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning_content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;inline_reasoning&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;proponent_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DebateState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;rnd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rnd&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="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The motion before the council:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;motion&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deliver your OPENING case in favor of the motion.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The motion before the council:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;motion&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The Skeptic&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s most recent argument was:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;_latest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transcript&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;opponent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is round &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rnd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Rebut the Skeptic point by point, then &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;press your strongest new arguments for the motion.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROPONENT_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transcript&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Turn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speaker&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;)]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The judge node works the same way but reads the entire transcript and produces the scorecard. Since the transcript is already clean and structured, there is no fragile report parsing. Clean text in, verdict out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Let the graph moderate
&lt;/h2&gt;

&lt;p&gt;Here is the payoff. The Moderator is not a model deciding what comes next, it is plain deterministic routing. START to proponent to opponent, then a conditional edge decides: run another round, or wrap up? If rounds remain, bump the counter and loop back. If not, run the optional Pragmatist, then the Arbiter, then end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_debate_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_pragmatist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# ... node definitions: proponent, opponent, pragmatist, judge ...
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route_after_opponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DebateState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;increment_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pragmatist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;use_pragmatist&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DebateState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proponent_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;opponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opponent_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;increment_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;increment_round_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;judge_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;use_pragmatist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pragmatist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pragmatist_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;opponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;opponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;route_after_opponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;increment_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pragmatist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;use_pragmatist&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;increment_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;increment_round&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proponent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;use_pragmatist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pragmatist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Stream it live in Streamlit
&lt;/h2&gt;

&lt;p&gt;The UI streams with &lt;code&gt;stream_mode="updates"&lt;/code&gt;, so each member's argument shows up the moment its node finishes. Color-coded card, correct round, and a collapsible panel that exposes Cosmos 3's chain-of-thought.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;motion&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recursion_limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;stream_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;updates&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="n"&gt;new_turns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transcript&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;new_turns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="c1"&gt;# skip the increment_round bookkeeping step
&lt;/span&gt;        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;turn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_turns&lt;/span&gt;&lt;span class="p"&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="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run streamlit run app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8501&lt;/code&gt;, pick your number of rounds (1 to 4) and whether to seat the Pragmatist, type in a motion, and hit "Convene the Council."&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like in action
&lt;/h2&gt;

&lt;p&gt;Let me run the motion "This house believes AGI will arrive before 2035."&lt;/p&gt;

&lt;p&gt;The Advocate opens strong on compute scaling curves, efficiency gains, and the money pouring into the field. Confident, concrete, ends on a sharp line.&lt;/p&gt;

&lt;p&gt;The Skeptic does not blink. A trend line is not a mechanism, benchmark progress is not general capability, and "before 2035" is a specific claim that needs a specific argument the other side has not made.&lt;/p&gt;

&lt;p&gt;Round two is where it gets good. The Advocate opens by quoting the Skeptic's "no mechanism" point and answering it head-on before pressing forward. The rebuttal threading is working. This is now an actual exchange.&lt;/p&gt;

&lt;p&gt;The Pragmatist steps outside the fight and calls it: both sides are arguing definitions. What would really settle it is a measurable capability threshold tied to a date. Name it, or you are just debating vibes.&lt;/p&gt;

&lt;p&gt;Then the Arbiter closes with a scorecard:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Side&lt;/th&gt;
&lt;th&gt;Logic&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;th&gt;Rebuttal&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Proponent&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opponent&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It gives the win to the Skeptic, narrowly. The Advocate argued well and rebutted directly, but leaned on extrapolation where the Skeptic demanded a mechanism, and that hard 2035 deadline raised a bar the Advocate never quite cleared.&lt;/p&gt;

&lt;p&gt;The fun part is not who won. It is that the round-two rebuttal genuinely engaged the round-one objection. That only happens if the model can hold a position, absorb a counter, and adjust, which is exactly the reasoning I was trying to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this tells you about Cosmos 3
&lt;/h2&gt;

&lt;p&gt;Running a few motions through the arena surfaces things a benchmark never will.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role discipline.&lt;/strong&gt; Does the Skeptic stay skeptical for four straight rounds, or quietly start agreeing? Cosmos held its seats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebuttal quality.&lt;/strong&gt; Do later rounds answer the specific prior point, or just restate the opener with new adjectives? This is the clearest signal of real reasoning, and you can see it live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Judgment calibration.&lt;/strong&gt; Does the Arbiter's verdict actually follow from the transcript, or does it pick a side and backfill? Read the scorecard against what was said and you will know fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A debate is really a reasoning stress test in disguise: adversarial, multi-turn, and either self-consistent across rounds or not. For a model whose reasoner was trained mostly on physical and spatial problems, watching it carry that reasoning into abstract language debate is a genuinely interesting result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-offs, honestly
&lt;/h2&gt;

&lt;p&gt;This is not free. A two-round debate with the Pragmatist is six full reasoning-model calls: the Advocate twice, the Skeptic twice, the Pragmatist, and the Arbiter. Reasoning models also emit a lot of thinking tokens. More rounds means more cost and more waiting.&lt;/p&gt;

&lt;p&gt;For this use case it is worth it, because the structure is the product and watching the reasoning unfold is the whole point. For a plain question-and-answer task, it would be massive overkill. Match the architecture to the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;You now have a working multi-agent debate council. It models a structured debate as an explicit LangGraph state machine instead of a prompt, threads real rebuttals through a shared append-only transcript, runs every seat on NVIDIA Cosmos 3 while surfacing its chain-of-thought, and serves the whole thing through one &lt;a href="https://dub.sh/nebius" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt; key over an OpenAI-compatible API.&lt;/p&gt;

&lt;p&gt;From here the graph makes it easy to keep going. Add seats like a Historian or a Domain Expert. Let the Arbiter call a tie-breaker round. Wire in retrieval so arguments cite real sources. Or run a tournament of motions and chart which side the model tends to favor. Each one is just a few more nodes and edges.&lt;/p&gt;

&lt;p&gt;Want to try it? Clone the &lt;a href="https://github.com/Arindam200/awesome-ai-apps" rel="noopener noreferrer"&gt;repo&lt;/a&gt;, grab a &lt;a href="https://tokenfactory.nebius.com/" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt; key, and convene your own council. Pick a motion you genuinely cannot call, and see how Cosmos 3 reasons its way through it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by Arindam Majumder. Part of the &lt;a href="https://github.com/Arindam200/awesome-ai-apps" rel="noopener noreferrer"&gt;awesome-ai-apps&lt;/a&gt; collection, powered by &lt;a href="https://langchain-ai.github.io/langgraph/" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt;, &lt;a href="https://developer.nvidia.com/blog/develop-physical-ai-reasoning-world-and-action-models-with-nvidia-cosmos-3/" rel="noopener noreferrer"&gt;NVIDIA Cosmos 3&lt;/a&gt;, and &lt;a href="https://dub.sh/nebius" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nvidia</category>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
    </item>
    <item>
      <title>The Best Vercel Analytics Alternative When You Outgrow the Free Tier</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Sat, 13 Jun 2026 20:16:35 +0000</pubDate>
      <link>https://dev.to/raah/the-best-vercel-analytics-alternative-when-you-outgrow-the-free-tier-2e0l</link>
      <guid>https://dev.to/raah/the-best-vercel-analytics-alternative-when-you-outgrow-the-free-tier-2e0l</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vercel Analytics is a convenient starting point for Vercel-hosted projects, especially when you only need simple traffic analytics.&lt;/li&gt;
&lt;li&gt;The Hobby plan includes a capped monthly Web Analytics allowance. If your site grows beyond that allowance, you may need to upgrade or move to another analytics setup.&lt;/li&gt;
&lt;li&gt;Speed Insights is separate from Web Analytics and has its own data-point limits and pricing model.&lt;/li&gt;
&lt;li&gt;Raah is a strong Vercel Analytics alternative when you want traffic analytics, Core Web Vitals, network performance, third-party script monitoring, frontend errors, and user journeys in one dashboard.&lt;/li&gt;
&lt;li&gt;You do not need to move your app away from Vercel to use Raah. Add one lightweight beacon and keep your existing hosting workflow.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Vercel Analytics is one of the easiest ways to add traffic analytics to a Vercel-hosted site. If you already deploy with Vercel, the setup is simple, the dashboard is clean, and the data is useful enough for many early projects.&lt;/p&gt;

&lt;p&gt;But the free tier has limits.&lt;/p&gt;

&lt;p&gt;On the Hobby plan, Vercel Analytics includes a capped amount of monthly Web Analytics events. Once your site grows beyond that allowance, tracking can stop until the next billing cycle unless you upgrade. Vercel also prices additional Web Analytics events on paid plans, and Speed Insights has its own separate usage model.&lt;/p&gt;

&lt;p&gt;That is fine for some teams. But if you want predictable analytics, privacy-friendly tracking, Web Vitals, network performance, and user behavior insights in one place, you may want a Vercel Analytics alternative.&lt;/p&gt;

&lt;p&gt;That is where &lt;a href="https://raah.dev/" rel="noopener noreferrer"&gt;Raah&lt;/a&gt; fits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why people look for a Vercel Analytics alternative
&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%2F8ptj0jq7vvzapl7aarbo.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%2F8ptj0jq7vvzapl7aarbo.png" alt="Vercel Analytics dashboard with visitor charts and event tracking" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most people do not start looking for an alternative because Vercel Analytics is hard to use. They start looking because their needs change.&lt;/p&gt;

&lt;p&gt;Common reasons include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your site is growing beyond the Hobby analytics allowance.&lt;/li&gt;
&lt;li&gt;You do not want analytics tied to your hosting provider.&lt;/li&gt;
&lt;li&gt;You want traffic analytics and performance monitoring in one dashboard.&lt;/li&gt;
&lt;li&gt;You need deeper frontend observability than pageviews alone.&lt;/li&gt;
&lt;li&gt;You want cookie-free analytics without consent banner complexity.&lt;/li&gt;
&lt;li&gt;You want to monitor Core Web Vitals, API calls, third-party scripts, and user journeys together.&lt;/li&gt;
&lt;li&gt;You deploy across Vercel, Netlify, Cloudflare, custom servers, or multiple platforms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vercel Analytics is convenient if your whole world lives inside Vercel. Raah is built for teams that want analytics to follow the product, not the hosting provider.&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%2Fcdn.raah.dev%2Fimages%2Fblog%2Fvercel-analytics-alternative%2Fvisitor-chart-dark.avif" 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%2Fcdn.raah.dev%2Fimages%2Fblog%2Fvercel-analytics-alternative%2Fvisitor-chart-dark.avif" alt="Vercel Analytics visitor chart showing traffic activity" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vercel Analytics free tier: what to know
&lt;/h2&gt;

&lt;p&gt;Vercel's Hobby plan includes a free Web Analytics allowance, but it is capped. Vercel's public pricing also lists paid Web Analytics usage at a per-event rate on paid plans.&lt;/p&gt;

&lt;p&gt;Speed Insights is separate from Web Analytics. On the Hobby plan, Vercel provides a free Speed Insights allowance for one project, with its own data-point limits.&lt;/p&gt;

&lt;p&gt;That means your actual analytics setup may involve more than one usage bucket:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web Analytics events&lt;/li&gt;
&lt;li&gt;Speed Insights data points&lt;/li&gt;
&lt;li&gt;Add-ons if you are on a paid plan&lt;/li&gt;
&lt;li&gt;Usage-based pricing as traffic grows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For small personal projects, this may be enough. For a growing product, SaaS app, content site, or startup landing page, those limits can become part of your analytics decision.&lt;/p&gt;

&lt;p&gt;For the exact current numbers, always check the official &lt;a href="https://vercel.com/pricing" rel="noopener noreferrer"&gt;Vercel pricing page&lt;/a&gt; and &lt;a href="https://vercel.com/docs/speed-insights/limits-and-pricing" rel="noopener noreferrer"&gt;Speed Insights limits and pricing documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to use instead: Raah
&lt;/h2&gt;

&lt;p&gt;Raah is a privacy-first website analytics and frontend observability platform for developers.&lt;/p&gt;

&lt;p&gt;You add one lightweight script to your site, and Raah gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pageviews and visitor analytics&lt;/li&gt;
&lt;li&gt;Referrers and UTM campaign tracking&lt;/li&gt;
&lt;li&gt;Device, browser, country, and city breakdowns&lt;/li&gt;
&lt;li&gt;Core Web Vitals monitoring&lt;/li&gt;
&lt;li&gt;Network request performance&lt;/li&gt;
&lt;li&gt;API and endpoint timing&lt;/li&gt;
&lt;li&gt;Third-party script performance&lt;/li&gt;
&lt;li&gt;User journey visibility&lt;/li&gt;
&lt;li&gt;Frontend error tracking&lt;/li&gt;
&lt;li&gt;Performance alerts&lt;/li&gt;
&lt;li&gt;Cookie-free tracking without fingerprinting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Raah is built for teams that want to understand both traffic and user experience.&lt;/p&gt;

&lt;p&gt;Traditional analytics tools tell you what pages people visit. Raah also helps you understand whether those pages are fast, which APIs are slow, which third-party scripts are hurting performance, and where users are coming from.&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%2Flfymbj9hf2jp1zfl5z7w.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%2Flfymbj9hf2jp1zfl5z7w.png" alt="Raah user analytics dashboard showing visitor trends and traffic breakdowns" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vercel Analytics vs Raah
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Vercel Analytics&lt;/th&gt;
&lt;th&gt;Raah&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic pageview analytics&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works outside Vercel&lt;/td&gt;
&lt;td&gt;Limited by setup and use case&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cookie-free analytics&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core Web Vitals&lt;/td&gt;
&lt;td&gt;Via Speed Insights&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network request monitoring&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API performance from the browser&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-party script performance&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User journey insights&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy-friendly by default&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting-provider independent&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Vercel Analytics is a good fit if you want simple analytics for a Vercel project.&lt;/p&gt;

&lt;p&gt;Raah is a better fit if you want a fuller picture of what users experience after they land on your site.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you switch from Vercel Analytics?
&lt;/h2&gt;

&lt;p&gt;You should consider switching when analytics becomes part of how you run the product, not just something you occasionally check.&lt;/p&gt;

&lt;p&gt;For example, switch when you want to answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which marketing campaigns are bringing users who actually engage?&lt;/li&gt;
&lt;li&gt;Which pages are slow for real users?&lt;/li&gt;
&lt;li&gt;Are API calls slowing down the user journey?&lt;/li&gt;
&lt;li&gt;Which third-party scripts are hurting load time?&lt;/li&gt;
&lt;li&gt;Where are users dropping off?&lt;/li&gt;
&lt;li&gt;Are performance issues happening for specific countries, browsers, or networks?&lt;/li&gt;
&lt;li&gt;Can I monitor analytics and frontend reliability in one dashboard?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only need a simple pageview counter, Vercel Analytics may be enough.&lt;/p&gt;

&lt;p&gt;If you need traffic analytics plus real-user performance monitoring, Raah gives you a broader view.&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%2F85m3seotmr0n87r6qz3l.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%2F85m3seotmr0n87r6qz3l.png" alt="Raah Web Vitals dashboard showing real user performance metrics" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add Raah to a Vercel site
&lt;/h2&gt;

&lt;p&gt;You do not need to move your app away from Vercel to use Raah.&lt;/p&gt;

&lt;p&gt;Raah works with Vercel-hosted sites, Next.js apps, React apps, Astro sites, Vue apps, Nuxt apps, SvelteKit apps, and other frontend frameworks.&lt;/p&gt;

&lt;p&gt;The setup is usually one script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://t.raah.dev/script.js"&lt;/span&gt;
  &lt;span class="na"&gt;data-pid=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_PROJECT_ID"&lt;/span&gt;
  &lt;span class="na"&gt;data-domain=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_DOMAIN"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deployment, open your Raah dashboard and visit your site. Data usually starts appearing within a few minutes.&lt;/p&gt;

&lt;p&gt;If you use Next.js, you can also follow the framework-specific setup in the &lt;a href="https://raah.dev/docs/getting-started/install-the-beacon" rel="noopener noreferrer"&gt;Raah beacon installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Raah is a strong Vercel Analytics alternative
&lt;/h2&gt;

&lt;p&gt;The biggest reason to use Raah is that it combines analytics and frontend observability.&lt;/p&gt;

&lt;p&gt;You do not just see that a page received traffic. You can see whether the experience was good.&lt;/p&gt;

&lt;p&gt;That matters because traffic without performance context can be misleading. A campaign may bring users, but if the landing page has poor LCP, slow API calls, or a blocking third-party script, those users may leave before converting.&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%2Fmdrdlk2go086qw3dhpi9.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%2Fmdrdlk2go086qw3dhpi9.png" alt="Raah observability dashboard showing frontend performance and reliability signals" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Raah helps you connect those dots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Acquisition:&lt;/strong&gt; Where users came from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavior:&lt;/strong&gt; What pages and journeys they followed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experience:&lt;/strong&gt; How fast the site felt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; Which requests, scripts, or errors affected the session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes Raah useful not only for marketers, but also for founders, developers, and product teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final verdict
&lt;/h2&gt;

&lt;p&gt;Vercel Analytics is a convenient starting point for Vercel projects. The free Hobby allowance is useful for small sites, but growing products often need more flexibility, deeper visibility, and analytics that are not tied to one hosting platform.&lt;/p&gt;

&lt;p&gt;If you are looking for a Vercel Analytics alternative that gives you privacy-friendly web analytics, Core Web Vitals, network performance, third-party script monitoring, and user journey insights in one dashboard, Raah is built for that.&lt;/p&gt;

&lt;p&gt;You can keep hosting on Vercel.&lt;/p&gt;

&lt;p&gt;Just use Raah to understand what your users are actually experiencing.&lt;/p&gt;

</description>
      <category>observability</category>
      <category>vercel</category>
      <category>webdev</category>
      <category>web</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Tue, 09 Jun 2026 16:13:29 +0000</pubDate>
      <link>https://dev.to/arindam_1729/-43l1</link>
      <guid>https://dev.to/arindam_1729/-43l1</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/raah/introducing-raah-4mng" class="crayons-story__hidden-navigation-link"&gt;Introducing Raah&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="/raah"&gt;
            &lt;img alt="Raah 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%2F13422%2F850915c3-efdf-4c9d-9f56-06e1f7fd4f13.png" class="crayons-logo__image" width="128" height="128"&gt;
          &lt;/a&gt;

          &lt;a href="/arindam_1729" 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%2F965723%2F8c3a1bb4-eb47-4302-a280-09eedb8bc785.png" alt="arindam_1729 profile" class="crayons-avatar__image" width="800" height="678"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/arindam_1729" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Arindam Majumder 
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Arindam Majumder 
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3722391" 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="/arindam_1729" 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%2F965723%2F8c3a1bb4-eb47-4302-a280-09eedb8bc785.png" class="crayons-avatar__image" alt="" width="800" height="678"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Arindam Majumder &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="/raah" class="crayons-story__secondary fw-medium"&gt;Raah&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/raah/introducing-raah-4mng" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 9&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/raah/introducing-raah-4mng" id="article-link-3722391"&gt;
          Introducing Raah
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webanalytics"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webanalytics&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&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/raah/introducing-raah-4mng" 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;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/raah/introducing-raah-4mng#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;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 crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&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>Introducing Raah</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Tue, 09 Jun 2026 14:30:00 +0000</pubDate>
      <link>https://dev.to/raah/introducing-raah-4mng</link>
      <guid>https://dev.to/raah/introducing-raah-4mng</guid>
      <description>&lt;p&gt;Today, we are introducing Raah, a privacy-first analytics and frontend observability platform for teams that need a clearer view of what real users experience in production.&lt;/p&gt;

&lt;p&gt;Most products treat analytics, performance, errors, and uptime as separate problems. In practice, they are the same question from different angles: are people finding your product, using it, and getting a fast, reliable experience?&lt;/p&gt;

&lt;p&gt;Raah answers that from one lightweight beacon. You get traffic analytics, Core Web Vitals, browser errors, API timing, third-party script impact, alerts, and status pages in one dashboard, without cookies or fingerprinting.&lt;/p&gt;

&lt;p&gt;The goal is simple: help small teams move from scattered signals to production truth.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Why we built Raah
&lt;/h2&gt;

&lt;p&gt;Most teams stitch together analytics, Web Vitals tooling, error tracking, uptime checks, and backend monitoring. Each tool is useful on its own, but the complete picture is still hard to read.&lt;/p&gt;

&lt;p&gt;You may know a page received traffic, but not whether it loaded slowly. You may know an API was healthy from your server logs, but not whether users on a regional network saw high latency. You may know conversion dropped, but not whether a third-party script, JavaScript error, or poor INP contributed to the problem.&lt;/p&gt;

&lt;p&gt;Raah is built around a simple belief: product and engineering teams should be able to see user behavior and user experience together.&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%2Fmdrdlk2go086qw3dhpi9.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%2Fmdrdlk2go086qw3dhpi9.png" alt="Raah observability dashboard showing frontend performance and reliability signals" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Raah gives you
&lt;/h2&gt;

&lt;p&gt;Raah starts with the questions teams ask every week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many people visited, where did they come from, and which pages mattered?&lt;/li&gt;
&lt;li&gt;Which pages are slow for real users, not just in a lab test?&lt;/li&gt;
&lt;li&gt;Which API endpoints are creating the worst p95 or p99 experience?&lt;/li&gt;
&lt;li&gt;Are errors concentrated in a browser, region, ISP, or release?&lt;/li&gt;
&lt;li&gt;Did a marketing campaign bring traffic that actually engaged?&lt;/li&gt;
&lt;li&gt;Can we explain an incident with real user evidence?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of forcing those answers across several dashboards, Raah brings the main signals into one workflow.&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%2Flfymbj9hf2jp1zfl5z7w.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%2Flfymbj9hf2jp1zfl5z7w.png" alt="Raah user analytics dashboard showing traffic, referrers, and visitor trends" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Analytics without the usual privacy baggage
&lt;/h2&gt;

&lt;p&gt;Raah tracks visits, pageviews, referrers, UTM campaigns, devices, geography, sessions, and engagement without setting cookies or fingerprinting users.&lt;/p&gt;

&lt;p&gt;That makes it a practical alternative for teams that want useful product analytics without turning a simple website into a consent and tracking project.&lt;/p&gt;

&lt;p&gt;The goal is not to recreate every enterprise marketing analytics feature. The goal is to give developers, founders, and product teams a clear read on what is happening and what deserves attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend observability built in
&lt;/h2&gt;

&lt;p&gt;Traffic alone does not tell you whether the experience was good. Raah also captures frontend reliability and performance signals from real browsers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core Web Vitals including LCP, CLS, INP, FCP, and TTFB&lt;/li&gt;
&lt;li&gt;Browser-level network timing including DNS, TCP, TLS, TTFB, and download phases&lt;/li&gt;
&lt;li&gt;API endpoint latency, error rate, and percentile breakdowns&lt;/li&gt;
&lt;li&gt;JavaScript errors and unhandled promise rejections&lt;/li&gt;
&lt;li&gt;Third-party script performance&lt;/li&gt;
&lt;li&gt;Session-level context for debugging what happened&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%2F85m3seotmr0n87r6qz3l.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%2F85m3seotmr0n87r6qz3l.png" alt="Raah Web Vitals dashboard showing real user performance metrics" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real user network monitoring
&lt;/h2&gt;

&lt;p&gt;Synthetic checks are useful, but they run from known locations under controlled conditions. They do not show what every user saw from their own browser, device, ISP, and geography.&lt;/p&gt;

&lt;p&gt;Raah captures browser-level network telemetry from live traffic, so you can compare API and page performance by endpoint, country, ISP, status code, and timing phase.&lt;/p&gt;

&lt;p&gt;That matters when a service looks healthy from your infrastructure but feels slow to customers in a specific region or network.&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%2F79x36wlu105n3l9ivpl7.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%2F79x36wlu105n3l9ivpl7.png" alt="Raah network report showing DNS, TCP, TLS, TTFB, and download timing" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for small teams that need production truth
&lt;/h2&gt;

&lt;p&gt;Raah is designed for teams that need practical visibility without a heavyweight rollout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SaaS teams debugging inconsistent endpoint latency&lt;/li&gt;
&lt;li&gt;Founders watching traffic, campaigns, performance, and reliability from one place&lt;/li&gt;
&lt;li&gt;Agencies managing client websites without cookie-heavy analytics setups&lt;/li&gt;
&lt;li&gt;Product teams connecting user behavior to frontend experience&lt;/li&gt;
&lt;li&gt;Engineering teams that want alerts and evidence before users complain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can start with a single script tag and let real traffic populate the dashboard.&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%2F2irb2dr7ju01tr5f0tzi.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%2F2irb2dr7ju01tr5f0tzi.png" alt="Raah install snippet showing the beacon script setup" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a project in the Raah dashboard.&lt;/li&gt;
&lt;li&gt;Install the lightweight script.&lt;/li&gt;
&lt;li&gt;Let live traffic populate metrics.&lt;/li&gt;
&lt;li&gt;Use breakdowns by endpoint, ISP, geography, and session context to investigate outliers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Raah was built to help teams move from “we think it is fine” to “we know what users are seeing.”&lt;/p&gt;

</description>
      <category>web</category>
      <category>webanalytics</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Claude Opus 4.8: Effort Controls, Dynamic Workflows, and an Honest-by-Default Coding Agent</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Fri, 29 May 2026 04:51:37 +0000</pubDate>
      <link>https://dev.to/arindam_1729/claude-opus-48-effort-controls-dynamic-workflows-and-an-honest-by-default-coding-agent-3eao</link>
      <guid>https://dev.to/arindam_1729/claude-opus-48-effort-controls-dynamic-workflows-and-an-honest-by-default-coding-agent-3eao</guid>
      <description>&lt;p&gt;The frontier model race has been moving in fits and starts. OpenAI shipped GPT-5.5 and a new Codex line. Google pushed Gemini 3.1 Pro and a faster Gemini Flash. xAI keeps iterating on Grok. And now Anthropic has shipped &lt;strong&gt;Claude Opus 4.8&lt;/strong&gt;, only 41 days after Opus 4.7, which is an unusually short release cycle for them and a clear signal about how the rest of 2026 is going to feel.&lt;/p&gt;

&lt;p&gt;Opus 4.8 is not a flashy rebrand. The headline numbers are real (SWE-bench Pro at 69.2%, USAMO 2026 at 96.7%, GraphWalks at 1M tokens jumping from 40.3% to 68.1%), but the more interesting story is structural: effort controls you can dial per request, dynamic workflows that orchestrate hundreds of parallel subagents, a fast mode that is roughly three times cheaper than it used to be, and a measurable drop in the kind of overconfident, slightly-deceptive coding behavior that makes agents annoying to trust.&lt;/p&gt;

&lt;p&gt;In this article, I will walk you through everything you need to know about Opus 4.8. We will cover the release details, the new effort tiers, the Dynamic Workflows feature in Claude Code, the pricing changes, the honesty and alignment improvements, two practical things you can build with it today, and an honest assessment of where it still falls short. By the end, you should have a clear mental model of when to upgrade, when to wait, and how to actually use the new controls.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Claude Opus 4.8?
&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%2Fqm6wknvmtui944x7frta.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%2Fqm6wknvmtui944x7frta.png" alt="Image1" width="800" height="954"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Opus 4.8 is Anthropic's new flagship model, released on &lt;strong&gt;May 28, 2026&lt;/strong&gt; and available immediately across the Claude API, Amazon Bedrock, Google Cloud Vertex AI, and Microsoft Foundry. The API model ID is &lt;code&gt;claude-opus-4-8&lt;/code&gt;. It ships at the same headline price as Opus 4.7, keeps the 1M-token context window, and is positioned squarely at agentic coding, long-horizon reasoning, and multi-day workflows.&lt;/p&gt;

&lt;p&gt;Here is what makes Opus 4.8 stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Effort controls everywhere&lt;/strong&gt;: low, high (default), extra (&lt;code&gt;xhigh&lt;/code&gt;), and max tiers you can pick per request, with high tuned to spend roughly the same tokens as Opus 4.7's default while doing better work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Workflows in Claude Code&lt;/strong&gt;: a research preview that lets the model plan a job, spin up hundreds of parallel subagents, verify their outputs adversarially, and resume across multi-day runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheaper fast mode&lt;/strong&gt;: 2.5× output speed at $10/$50 per million tokens, roughly three times cheaper than the previous Opus fast mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honesty by default&lt;/strong&gt;: a four-fold reduction in unreported code flaws versus Opus 4.7, a 0% rate of uncritically reporting flawed results (the first Claude model to hit zero on that test), and a ten-fold reduction in overconfidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Big agentic coding gains&lt;/strong&gt;: SWE-bench Pro at 69.2%, leading every published competitor on that benchmark.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-context retrieval breakthrough&lt;/strong&gt;: GraphWalks BFS at 1M tokens jumps from 40.3% to 68.1% F1, the biggest single benchmark gain of the release.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New API ergonomics&lt;/strong&gt;: the Messages API now accepts &lt;code&gt;system&lt;/code&gt; entries inside the &lt;code&gt;messages&lt;/code&gt; array, letting you update instructions mid-task without breaking the prompt cache.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pricing and Availability
&lt;/h2&gt;

&lt;p&gt;Opus 4.8 launches at the same standard rate as Opus 4.7, which keeps the upgrade math simple.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standard&lt;/strong&gt;: $5 per million input tokens, $25 per million output tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast mode&lt;/strong&gt;: $10 / $50 per million tokens for roughly 2.5× the output speed. Anthropic describes this as "three times cheaper than fast mode for previous models," which is the real story here: latency-sensitive workloads that were borderline on the old Opus fast mode become economically reasonable on 4.8.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context window&lt;/strong&gt;: 1,000,000 tokens, unchanged from 4.7.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access&lt;/strong&gt;: Claude API, Amazon Bedrock, Google Cloud Vertex AI, Microsoft Foundry, claude.ai, Claude Code, Cowork, and (as of release day) GitHub Copilot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because price did not move, the upgrade decision for most teams is just a function of whether the benchmark and reliability gains help your specific workload.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmark Performance
&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%2F33ou1941paeimxarbee8.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%2F33ou1941paeimxarbee8.png" alt="Image2" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The benchmark deltas are the cleanest part of the release.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SWE-bench Pro&lt;/strong&gt;: &lt;strong&gt;69.2%&lt;/strong&gt; (up from 64.3% on Opus 4.7). For comparison, GPT-5.5 sits at 58.6% and the next competitor at 54.2%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SWE-bench Verified&lt;/strong&gt;: 88.6% (up from 87.6%).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SWE-bench Multilingual&lt;/strong&gt;: 84.4% (up from 80.5%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Opus 4.8 leads every SWE-bench variant. This is the most useful headline number for anyone building a coding agent today.&lt;/p&gt;

&lt;h3&gt;
  
  
  Math and Reasoning
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;USAMO 2026&lt;/strong&gt;: &lt;strong&gt;96.7%&lt;/strong&gt; (up from 69.3% on 4.7). A 27.4-point jump in one model cycle is not a normal benchmark delta. Anthropic is describing this as a qualitative change in mathematical reasoning depth, not a tuning win.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Long-Context Retrieval
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GraphWalks BFS at 1M tokens&lt;/strong&gt;: &lt;strong&gt;68.1% F1&lt;/strong&gt; (up from 40.3%).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphWalks Parents at 1M tokens&lt;/strong&gt;: &lt;strong&gt;83.3% F1&lt;/strong&gt; (up from 56.6%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the release's biggest relative lead. If your application leans hard on long-context retrieval (legal review, large repo navigation, research synthesis), 4.8 is a different model than 4.7 for that work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Notable Scores
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;HLE with tools: 57.9%&lt;/li&gt;
&lt;li&gt;OSWorld-Verified (computer use): 83.4%&lt;/li&gt;
&lt;li&gt;MCP-Atlas: 82.2%&lt;/li&gt;
&lt;li&gt;Finance Agent v2: 53.9%&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Where It Regressed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPQA Diamond&lt;/strong&gt;: 93.6% vs 94.2% on 4.7. Near-saturated benchmark, so variance at the top is expected, but worth flagging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminal-Bench 2.1&lt;/strong&gt;: 74.6%, behind GPT-5.5's 78.2%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual tasks&lt;/strong&gt;: trails Gemini 3.1 Pro and GPT-5.5 in several languages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take the benchmarks as directional. The honesty and reliability deltas below matter more for production use.&lt;/p&gt;




&lt;h2&gt;
  
  
  Effort Control: The Knob You Have Been Waiting For
&lt;/h2&gt;

&lt;p&gt;Opus 4.8 exposes four effort tiers, and you can set them per request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Low&lt;/strong&gt;: fast responses, minimal token use. Best for summarization, classification, and simple Q&amp;amp;A.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High&lt;/strong&gt; (default): Anthropic's "best balance" tier. Tuned to spend similar tokens to Opus 4.7's default while outperforming it on coding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extra&lt;/strong&gt; (&lt;code&gt;xhigh&lt;/code&gt;): recommended for difficult tasks and long-running async workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max&lt;/strong&gt;: maximum token depth. Reserve for quality-only priorities where you do not care about cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The effort knob is exposed in claude.ai and Cowork (all plans), in Claude Code via the existing effort menu, and in the API. Claude Code's rate limits have been raised to accommodate the new high default. This is the kind of control that used to live behind enterprise sales conversations, and getting it as a first-class request parameter is a quiet but meaningful win.&lt;/p&gt;

&lt;p&gt;A practical migration heuristic: move to Opus 4.8 on the default high tier first, then sample representative tasks at xhigh to model the token-cost delta before turning it on in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dynamic Workflows: Hundreds of Subagents, Multi-Day Jobs
&lt;/h2&gt;

&lt;p&gt;The biggest new feature in this release is &lt;strong&gt;Dynamic Workflows&lt;/strong&gt;, a research preview inside Claude Code that lets Opus 4.8 orchestrate work normally reserved for a small engineering team.&lt;/p&gt;

&lt;p&gt;The capability, in short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model plans a job.&lt;/li&gt;
&lt;li&gt;It spins up tens or hundreds of parallel subagents to execute pieces of it.&lt;/li&gt;
&lt;li&gt;Other agents adversarially try to refute the findings before they are reported.&lt;/li&gt;
&lt;li&gt;State is checkpointed, so jobs survive interruptions and resume across multi-day runs.&lt;/li&gt;
&lt;li&gt;Coordination happens outside the conversation thread, so the main session stays responsive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The use cases Anthropic is pointing at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Codebase-wide bug hunts and dead-code discovery.&lt;/li&gt;
&lt;li&gt;Security and hardening audits.&lt;/li&gt;
&lt;li&gt;Large migrations: framework swaps, language ports, API deprecations.&lt;/li&gt;
&lt;li&gt;Verification-heavy tasks where you want independent attempts plus an adversarial reviewer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The canonical case study is &lt;strong&gt;Bun's Zig-to-Rust port&lt;/strong&gt;, run by Jarred Sumner: 750,000 lines of Rust generated, 99.8% of the test suite passing, eleven days from first commit to merge. The workflow first mapped lifetime requirements, then parallel writers generated every &lt;code&gt;.rs&lt;/code&gt; file with two reviewers per file, and an overnight fix loop addressed a data-copy optimization. That is a real-world result, not a benchmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  Activation
&lt;/h3&gt;

&lt;p&gt;Inside Claude Code, you turn it on in any of three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable auto mode in Claude Code.&lt;/li&gt;
&lt;li&gt;Ask explicitly: "create a workflow."&lt;/li&gt;
&lt;li&gt;Toggle the &lt;code&gt;ultracode&lt;/code&gt; setting, which sets effort to &lt;code&gt;xhigh&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first trigger shows you a preview and requires confirmation. Dynamic Workflows is available on Max, Team, and Enterprise (admin-enabled), and via the APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Cost Warning
&lt;/h3&gt;

&lt;p&gt;Workflows consume substantially more tokens than standard sessions. Plan your budgets before flipping this on in production. The same feature that finishes a quarter's worth of work in days will also spend a quarter's worth of tokens in the same window if you do not watch it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honesty, Reliability, and Alignment
&lt;/h2&gt;

&lt;p&gt;This is the part of the release that does not show up cleanly in a benchmark table but matters most for anyone shipping agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Honesty
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Four-fold reduction&lt;/strong&gt; in unreported code flaws versus Opus 4.7.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code summary honesty&lt;/strong&gt;: fails to flag important events only 3.7% of the time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uncritically reporting flawed results&lt;/strong&gt;: &lt;strong&gt;0%&lt;/strong&gt;. First Claude model to score zero on that test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overconfidence&lt;/strong&gt;: more than ten-fold improvement over Opus 4.7.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy investigation&lt;/strong&gt;: perfect score. Opus 4.7 gave incorrect answers 25% of the time on the same probe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read those as one trend: Opus 4.8 is significantly less likely to hand you a confident-sounding summary that papers over a real problem. Bridgewater Associates' testimonial in Anthropic's launch coverage explicitly calls out "Opus 4.8's tendency to proactively flag issues with the inputs and outputs of an analysis" as the differentiator.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alignment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stronger prosocial behavior and user-autonomy support.&lt;/li&gt;
&lt;li&gt;Substantially lower deceptive and misuse-enabling behaviors than 4.7.&lt;/li&gt;
&lt;li&gt;Reckless or destructive actions reduced significantly.&lt;/li&gt;
&lt;li&gt;Overall alignment risk rated "very low."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Agentic Security Caveat
&lt;/h3&gt;

&lt;p&gt;One regression worth taking seriously: prompt-injection robustness dropped. &lt;strong&gt;Gray Swan attack success rate climbed to roughly 9.6%, up from 6.0% on Opus 4.7.&lt;/strong&gt; If your pipeline ingests untrusted external content (scraped web pages, user-submitted documents, third-party tool output) review your sandboxing approach before upgrading.&lt;/p&gt;




&lt;h2&gt;
  
  
  API Enhancements You Should Actually Notice
&lt;/h2&gt;

&lt;p&gt;The Messages API now accepts &lt;code&gt;system&lt;/code&gt; entries inside the &lt;code&gt;messages&lt;/code&gt; array. In practice that means you can update instructions mid-task without breaking the prompt cache, which has been a real pain point for long-horizon agents.&lt;/p&gt;

&lt;p&gt;Concrete use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjusting tool permissions partway through a session.&lt;/li&gt;
&lt;li&gt;Reallocating a token budget after a planning step.&lt;/li&gt;
&lt;li&gt;Injecting environment context (the user just switched repos, a long-running job finished) without restarting the whole conversation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For long-running agentic workflows, this single change is more useful than it sounds.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Opus 4.8 Compares to the Field
&lt;/h2&gt;

&lt;p&gt;A short read on where 4.8 sits today:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vs. GPT-5.5:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opus 4.8 leads on SWE-bench Pro (69.2% vs 58.6%) and on GDPval-AA ELO by roughly 121 points.&lt;/li&gt;
&lt;li&gt;GPT-5.5 still leads Terminal-Bench 2.1 (78.2% vs 74.6%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;vs. Gemini 3.1 Pro:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opus 4.8 leads on SWE-bench variants and long-context retrieval.&lt;/li&gt;
&lt;li&gt;Gemini 3.1 Pro leads on GPQA Diamond (94.3% vs 93.6%) and on several multilingual tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read those numbers as "Opus 4.8 is the strongest agentic coding model right now, but the multilingual and terminal-harness wins are not universal."&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest Assessment: Strengths and Limitations
&lt;/h2&gt;

&lt;p&gt;Opus 4.8 is the most useful coding model Anthropic has shipped, but it is worth going in with calibrated expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it shines:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentic coding gains are real. The SWE-bench Pro lead over GPT-5.5 is large enough to matter on real workloads.&lt;/li&gt;
&lt;li&gt;The honesty improvements (four-fold drop in unreported flaws, zero rate on uncritical reporting, ten-fold drop in overconfidence) translate directly into less time spent double-checking the agent.&lt;/li&gt;
&lt;li&gt;Dynamic Workflows is a genuine shift, not a gimmick. The Bun port is the kind of result that would have been a quarter of work and is now eleven days.&lt;/li&gt;
&lt;li&gt;Effort control as a first-class parameter is the right primitive for cost-aware agent design.&lt;/li&gt;
&lt;li&gt;Fast mode at roughly one-third the previous price unlocks latency-sensitive workloads that were borderline before.&lt;/li&gt;
&lt;li&gt;Same pricing as 4.7 makes the upgrade decision easy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where to be careful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt-injection robustness regressed (Gray Swan ~9.6% vs 6.0%). If you handle untrusted content, audit your sandbox before upgrading.&lt;/li&gt;
&lt;li&gt;Terminal-Bench 2.1 still trails GPT-5.5. If your workload is shell-heavy, benchmark both.&lt;/li&gt;
&lt;li&gt;Multilingual tasks remain a relative weakness. Gemini 3.1 Pro and GPT-5.5 win in several languages.&lt;/li&gt;
&lt;li&gt;Dynamic Workflows can burn tokens fast. Budget carefully or you will discover the cost on your invoice.&lt;/li&gt;
&lt;li&gt;Vending-Bench 2 regressed, hinting at potential issues with highly structured, multi-step transactional interactions. Worth testing if that is your domain.&lt;/li&gt;
&lt;li&gt;Pipelines tightly tuned to 4.7 prompts will need re-validation. The honesty improvements change how the model communicates uncertainty, which can ripple through downstream parsing.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When to Upgrade and When to Wait
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Upgrade from Opus 4.7 if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run agentic coding workflows and want the honesty improvements.&lt;/li&gt;
&lt;li&gt;Long-context retrieval is core to your product (the GraphWalks delta is the biggest gain in the release).&lt;/li&gt;
&lt;li&gt;You have been hitting silent failures or overconfident outputs.&lt;/li&gt;
&lt;li&gt;You want fast mode at the new lower price.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stay on Opus 4.7 if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your production pipeline is meticulously prompt-tuned to 4.7 and you do not have a re-validation window.&lt;/li&gt;
&lt;li&gt;You rely on the GPQA Diamond delta at the top of the curve.&lt;/li&gt;
&lt;li&gt;You ingest untrusted external content and cannot tighten sandboxing right now.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A safe default migration path: switch the model ID, leave effort at &lt;code&gt;high&lt;/code&gt;, validate a representative sample of tasks, then experiment with &lt;code&gt;xhigh&lt;/code&gt; for the hardest workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to Learn Next
&lt;/h2&gt;

&lt;p&gt;A few directions worth exploring once you have Opus 4.8 running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Effort tuning per workload&lt;/strong&gt;: profile token spend at each tier on real traffic. The right tier is almost never the same across your app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Workflows playbooks&lt;/strong&gt;: build templates for codebase audits, migrations, and dead-code sweeps. The reusable bit is the workflow shape, not the prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mid-task system messages&lt;/strong&gt;: refactor your long-horizon agents to use the new in-array &lt;code&gt;system&lt;/code&gt; entries instead of restarting threads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mythos preview&lt;/strong&gt;: Anthropic has hinted that Mythos-class models will reach general availability in the coming weeks, with the same same-price upgrade pattern. Worth tracking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheaper-with-Opus-capability tier&lt;/strong&gt;: Anthropic also signaled cheaper models with Opus-level capability are in the works, which will reshape which tier you run by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anthropic's documentation, the Claude API release notes, and the model card for Opus 4.8 are the best primary sources for any of this.&lt;/p&gt;




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

&lt;p&gt;Opus 4.8 is not a rebrand and it is not a victory lap. It is a focused release that pushes on the parts of agentic coding that actually slow teams down: silent failures, overconfident summaries, single-thread workflows, and a coarse effort model. The benchmark wins are real, but the more durable shift is structural. Effort controls give you a cost dial. Dynamic Workflows give you a way to run multi-day jobs. The honesty improvements give you a model you can trust to flag its own mistakes.&lt;/p&gt;

&lt;p&gt;The 41-day cycle from 4.7 to 4.8, the Mythos hints, and the cheaper-fast-mode pricing together signal that Anthropic is racing. That is good for everyone building on top of these models, but it also means the right play is to upgrade incrementally, measure what changed, and keep your prompts and sandboxes loose enough to absorb the next jump.&lt;/p&gt;

&lt;p&gt;If you are building agents right now, switch the model ID, leave effort at high, test your hardest workloads at xhigh, and try one Dynamic Workflow on something you have been putting off. That is enough to see why this release matters.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>opus</category>
      <category>anthropic</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building AI Agents That Actually Remember: Memory Systems Explained</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Thu, 28 May 2026 14:39:46 +0000</pubDate>
      <link>https://dev.to/arindam_1729/building-ai-agents-that-actually-remember-memory-systems-explained-4078</link>
      <guid>https://dev.to/arindam_1729/building-ai-agents-that-actually-remember-memory-systems-explained-4078</guid>
      <description>&lt;p&gt;You built an AI agent. It calls tools, plans multi-step workflows, and the first time you run it, the demo feels magical. Then you run it again the next day, and it greets you like a stranger. Same clarifying questions. Same mistakes. Same steps reconstructed from scratch.&lt;/p&gt;

&lt;p&gt;That is not a tooling problem. That is a memory problem.&lt;/p&gt;

&lt;p&gt;Most agents shipping today are stateless. They execute inside a loop, but they do not accumulate knowledge across runs. Every session starts at zero, which means every improvement they appeared to make last time is gone. If agents are going to automate real work, they have to get better the longer you use them. That only happens with memory, and not just stored data, but structured, evolving memory that compresses experience into knowledge.&lt;/p&gt;

&lt;p&gt;In this article, I will break down what memory really means inside an agent, where the standard implementations fall short, how to design memory as a first-class layer in your agent loop, and finally how a system like &lt;strong&gt;Engram&lt;/strong&gt; handles this in practice. By the end, you should have a clear mental model for adding real long-term memory to whatever you are building.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you like Video more, You can watch this:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/hrciMR7e7Fk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What "Memory" Actually Means in an Agent
&lt;/h2&gt;

&lt;p&gt;When people say "memory" in AI, they usually mean storing chat history and pulling it back later. That is not memory. That is replay.&lt;/p&gt;

&lt;p&gt;An agent already has context during execution. The system prompt, the tools, the intermediate tool calls, the partial outputs, all of it sits inside the model's context window for the duration of a single run. The moment the run ends, that context evaporates.&lt;/p&gt;

&lt;p&gt;The common patch is to dump everything into a vector database, then retrieve the chunks that look semantically similar to the next prompt. This keeps the agent informed, but it does not make it smarter. It is the equivalent of handing someone a transcript of a meeting they never attended and hoping they get up to speed.&lt;/p&gt;

&lt;p&gt;Real memory does something more interesting. It compresses raw experience into reusable knowledge. Humans do not remember entire conversations word for word. We remember conclusions, preferences, and patterns. Agents need the same transformation layer between raw execution and stored memory, or they will keep drowning in their own logs.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Most Agents Are Built Today
&lt;/h2&gt;

&lt;p&gt;The default agent loop looks roughly like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user gives the agent a task.&lt;/li&gt;
&lt;li&gt;The agent plans a sequence of steps.&lt;/li&gt;
&lt;li&gt;It calls tools, observes results, and produces an output.&lt;/li&gt;
&lt;li&gt;The whole transcript is dumped into a database, often a vector store.&lt;/li&gt;
&lt;li&gt;On the next run, similar chunks are retrieved and injected back into the prompt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At a glance, this feels like memory. In practice it builds a system that can &lt;strong&gt;recall&lt;/strong&gt; but cannot &lt;strong&gt;learn&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The agent never refines what it knows. It never resolves contradictions. It never updates outdated information. It just accumulates. Over time, the store fills with multiple versions of the same idea, conflicting preferences, and abandoned half-thoughts. Retrieval gets noisier, irrelevant context starts crowding the prompt, token usage climbs, and accuracy drops.&lt;/p&gt;

&lt;p&gt;This is the reason so many agents feel stuck at the same level no matter how many sessions you put through them.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Missing Piece: A Learning Loop
&lt;/h2&gt;

&lt;p&gt;The gap is a learning step between execution and storage.&lt;/p&gt;

&lt;p&gt;Most loops look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input → plan → execute → store → end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A real long-term-memory loop should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input → plan → execute → learn → update memory → next run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That learning step is where transformation happens. Instead of saving raw logs, the system pulls out structured insights and writes those. If a user says they prefer Postgres over MySQL, that is a stable preference, not a line buried in a chat log. If an agent tried three approaches and only one worked, the successful path is a reusable strategy, not noise mixed in with two failures.&lt;/p&gt;

&lt;p&gt;Without this step, the agent keeps rediscovering the same things on every run, and you pay for it in tokens, latency, and user trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Types of Memory Inside an Agent
&lt;/h2&gt;

&lt;p&gt;It helps to split memory into layers, the same way cognitive science does. Most current systems collapse all three into one bucket, which is exactly why they get confused.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Episodic memory&lt;/strong&gt;: events. Tool calls, inputs, outputs, failures, timestamps. Useful for traceability and debugging, but rarely the right thing to inject back into a prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic memory&lt;/strong&gt;: distilled knowledge. Preferences, facts, constraints, decisions. This is what the agent should actually carry across sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Procedural memory&lt;/strong&gt;: how to do things. Sequences of steps that worked before. This is where agents start becoming efficient, because they can reuse solutions instead of recomputing them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good memory system treats these differently. Episodes get logged and mostly left alone. Semantic facts get reconciled and updated in place. Procedures get versioned, scored, and promoted when they keep working.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Real Memory System Needs
&lt;/h2&gt;

&lt;p&gt;A working memory layer for agents needs three core operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extraction&lt;/strong&gt;: take raw input and decide what is worth remembering. Most of what an agent sees is noise. Extraction is the filter that separates a durable fact ("user is on macOS Sonoma, prefers pnpm") from disposable chatter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reconciliation&lt;/strong&gt;: compare new information with what already exists. Update when the facts have changed. Resolve when they conflict. Merge when they are redundant. This is the step that keeps memory clean instead of letting it sprawl.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval&lt;/strong&gt;: when the agent runs again, hand it the relevant pieces, not the whole archive. The goal is precision, not volume. A 200-token answer with the right three facts beats a 4,000-token dump every time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pipeline is what turns memory into something the agent can rely on instead of something it has to sift through every turn.&lt;/p&gt;




&lt;h2&gt;
  
  
  How This Changes Agent Behavior
&lt;/h2&gt;

&lt;p&gt;Once a memory layer like this is in place, the agent's behavior changes in ways the user actually notices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It stops asking the same clarifying questions because it already has the answers.&lt;/li&gt;
&lt;li&gt;It avoids paths it has already tried and failed on.&lt;/li&gt;
&lt;li&gt;It adapts to the user because preferences are stored and continuously updated.&lt;/li&gt;
&lt;li&gt;It gets faster because it reuses successful strategies instead of recomputing them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point the agent stops being a pure execution engine and starts being something closer to an accumulating knowledge system. That is the line between "impressive demo" and "tool I actually use every day."&lt;/p&gt;




&lt;h2&gt;
  
  
  Engram: A Memory System for Agents
&lt;/h2&gt;

&lt;p&gt;This brings us to &lt;strong&gt;Engram&lt;/strong&gt;, an open-source memory layer designed to sit alongside your agent rather than inside it. The project bills itself as "persistent cognitive memory for AI agents" and is built around exactly the extract → reconcile → retrieve pipeline above.&lt;/p&gt;

&lt;p&gt;Here is what makes Engram worth a look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory pipeline, not a bucket&lt;/strong&gt;: incoming data flows through an extraction step that classifies items as facts, preferences, events, or decisions and assigns an importance score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reconciliation built in&lt;/strong&gt;: new memories are checked against existing ones. Duplicates are merged, conflicts are resolved, and stale entries get pruned instead of piling up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dream Cycle&lt;/strong&gt;: a background consolidation job that runs on a schedule (the docs describe a nightly cadence). It refreshes scores, dedupes, extracts patterns across memories, and prunes things that have gone stale. The biological analogy is not a coincidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensemble retrieval&lt;/strong&gt;: multiple embedding models are queried in parallel and combined with Reciprocal Rank Fusion. Recency is weighted so fresh context wins ties.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory pools&lt;/strong&gt;: shared memory spaces with access control, so multiple agents can read and write into the same knowledge base without trampling each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open and self-hostable&lt;/strong&gt;: Apache 2.0 licensed, runs locally on Apple Silicon or CUDA, with an optional hybrid mode that mixes in cloud embeddings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Engram exposes itself through a TypeScript SDK, a REST API, and an MCP server, which means it slots into Claude Desktop, Cursor, Windsurf, and anything else that speaks the Model Context Protocol.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing Engram
&lt;/h2&gt;

&lt;p&gt;The Python core is a single pip install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;engram-core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional extras cover the server, the MCP integration, embedding backends, or the full bundle. For the TypeScript SDK, install the client package alongside whatever agent framework you are already using.&lt;/p&gt;

&lt;p&gt;The self-hosted version of openengram.ai ships a setup wizard that walks you through account creation and model configuration, and all features unlock locally at no cost. If you want to start with the cloud-hosted control plane, you grab an API key (&lt;code&gt;ek_...&lt;/code&gt;) and point the SDK at it.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Minimal Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;Here is the smallest end-to-end example using the Python SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;engram&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Memory&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User prefers Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;preference&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project uses Postgres, not MySQL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;programming language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&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="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;store&lt;/code&gt; is the extraction entry point. You tag each memory with a type and an importance score so the consolidation pass can reason about it later. &lt;code&gt;search&lt;/code&gt; runs full-text and semantic retrieval. &lt;code&gt;recall&lt;/code&gt; pulls the top-N most relevant memories for prompt injection.&lt;/p&gt;

&lt;p&gt;The TypeScript flavor is just as light:&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;Engram&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="s1"&gt;@engram/client&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;engram&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;Engram&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ek_...&lt;/span&gt;&lt;span class="dl"&gt;'&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;engram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User prefers dark mode&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;memories&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;engram&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UI preferences&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both SDKs share the same mental model: write through &lt;code&gt;remember&lt;/code&gt; / &lt;code&gt;store&lt;/code&gt;, read through &lt;code&gt;recall&lt;/code&gt; / &lt;code&gt;search&lt;/code&gt;, and let the consolidation pipeline keep the underlying store clean in the background.&lt;/p&gt;

&lt;p&gt;You can also link memories explicitly to build a small knowledge graph the agent can walk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;bug_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Login fails on Safari&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error_fix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fix_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Added WebKit prefix to CSS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error_fix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bug_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fix_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;caused_by&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bug_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;link&lt;/code&gt; call is what turns a flat collection of facts into procedural memory the agent can actually follow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 1: Give a Developer Agent a Real Long-Term Memory
&lt;/h2&gt;

&lt;p&gt;Let us put this together with a concrete scenario. You are building a developer agent that helps scaffold and maintain a project. Without memory, every new session restarts the same conversation about your stack.&lt;/p&gt;

&lt;p&gt;Bootstrap a tiny project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;agent-with-memory &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;agent-with-memory
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;engram-core openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wire memory into a basic loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;engram&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Memory&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Known about the user:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;

    &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;importance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Set up a new Node service. I prefer Postgres and pnpm.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Add a users table to the project.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the first call, the agent has nothing to recall, so it answers from scratch and writes two events to memory. On the second call, &lt;code&gt;mem.context()&lt;/code&gt; returns the relevant prior decisions (Postgres, pnpm) and injects them into the system prompt. The agent never has to ask "what package manager do you use" again, and you never have to repeat yourself.&lt;/p&gt;

&lt;p&gt;If you then say "actually, switch this project to Bun," Engram's reconciliation step updates the existing preference rather than appending a contradicting one. That is the difference between a memory system and a log.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 2: Wire Engram Into Your Coding Agent Over MCP
&lt;/h2&gt;

&lt;p&gt;The second project shows how to plug Engram into an existing coding agent without writing client code at all. Most modern coding agents (Claude Desktop, Cursor, Windsurf, the Antigravity CLI, and others) speak MCP, and Engram ships an MCP server out of the box.&lt;/p&gt;

&lt;p&gt;Start the MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"engram-core[mcp]"&lt;/span&gt;
engram mcp serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add it to your agent's MCP config. For Claude Desktop, edit &lt;code&gt;claude_desktop_config.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"engram"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"engram"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the agent. From inside any session you can now ask things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Remember that this project uses Drizzle ORM, not Prisma.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What have I told you about my testing setup?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent calls Engram's MCP tools to write and read memories, and the consolidation loop keeps the store tidy in the background. The same memory pool is now visible to every MCP-aware agent you use, which is the part most people underestimate the first time they try it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Think About Memory While Building Agents
&lt;/h2&gt;

&lt;p&gt;When you sit down to design an agent, the first question is usually "which model?" or "which tools?" That is the wrong starting point. The first question should be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What does this agent need to remember, and how should that memory evolve?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Decide what qualifies as durable knowledge for your domain. Decide what should never be stored (raw PII, transient state, things that age out fast). Decide how updates and conflicts are resolved. Then design your loop so that every execution contributes back to that memory, not just consumes from it.&lt;/p&gt;

&lt;p&gt;A few practical heuristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Store conclusions, not transcripts.&lt;/strong&gt; A summarized decision is worth ten chat logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score importance at write time.&lt;/strong&gt; Future-you needs a signal for what to keep when the store gets crowded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reconcile, do not append.&lt;/strong&gt; When the same fact shows up twice, the system should update, not duplicate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve narrowly.&lt;/strong&gt; A small, precise context wins over a giant relevant-ish blob.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is what turns a collection of tools into a system that actually improves over time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest Assessment: Strengths and Limitations
&lt;/h2&gt;

&lt;p&gt;Engram is one of the most thoughtful entries in the agent-memory space right now, but it is worth going in with calibrated expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it shines:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The extract → reconcile → retrieve pipeline matches the way memory should work, not just the way it is easiest to ship.&lt;/li&gt;
&lt;li&gt;The Dream Cycle is the right idea. Background consolidation is what keeps memory stores from rotting over weeks of use.&lt;/li&gt;
&lt;li&gt;Ensemble retrieval with RRF is a meaningful step up from single-model vector search. Recall stays high even when the query phrasing drifts from how the memory was originally written.&lt;/li&gt;
&lt;li&gt;MCP support means it works with the agent you are already using today, not just a bespoke SDK.&lt;/li&gt;
&lt;li&gt;Apache 2.0 and self-hostable. Your memories live where you want them to live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where to be careful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extraction is LLM-driven, which means it can occasionally classify the wrong thing as a durable fact. Importance scoring helps, but you should still spot-check what is being written.&lt;/li&gt;
&lt;li&gt;"Memory" is only as good as your write discipline. If you treat it as a dump-everything store, you will recreate the noisy-vector-DB problem inside a nicer wrapper.&lt;/li&gt;
&lt;li&gt;The ecosystem around agent memory is moving fast, and Engram is one of several real implementations (some Go, some Rust, some Python). Pick the one whose architecture and license match your deployment, and expect interfaces to keep evolving for the next year.&lt;/li&gt;
&lt;li&gt;Hybrid cloud mode is convenient but read the data-handling policy if you are working with sensitive content. Self-hosting is the safer default for regulated workloads.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What to Learn Next
&lt;/h2&gt;

&lt;p&gt;Once you have a memory layer wired in, there are a few directions worth exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory pools&lt;/strong&gt;: share a single store across multiple agents (a researcher, a writer, a reviewer) and watch them coordinate without you writing any glue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Procedural memory&lt;/strong&gt;: start storing successful tool-call sequences as reusable strategies, not just facts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eval your memory&lt;/strong&gt;: write tests that check whether your agent remembers the right things across sessions. Memory regressions are real and they are easy to miss without a harness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP everywhere&lt;/strong&gt;: once memory is exposed as MCP, every agent you use can read and write into the same brain. That is when things actually get interesting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Engram documentation at &lt;code&gt;engram.to&lt;/code&gt; and &lt;code&gt;openengram.ai&lt;/code&gt; is the best place to go deeper, and the GitHub organizations behind the various implementations are active and worth tracking.&lt;/p&gt;




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

&lt;p&gt;Most agents today feel powerful in the moment and forget everything afterward. That is the ceiling on what they can become.&lt;/p&gt;

&lt;p&gt;Memory raises that ceiling. It lets agents accumulate knowledge, refine behavior, and adapt with use instead of resetting every session. Engram is one good implementation of this idea, but the larger shift is architectural. Agents are not just reasoning systems anymore. They are learning systems, and memory is the layer that makes the learning stick.&lt;/p&gt;

&lt;p&gt;If you are building agents right now, focus less on making them smarter inside a single run. Focus on making them better across many runs.&lt;/p&gt;

&lt;p&gt;That is where the real leverage is. Give it a try in your next project and see how quickly the dynamic changes.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>memory</category>
      <category>ai</category>
      <category>rag</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Mon, 25 May 2026 19:28:42 +0000</pubDate>
      <link>https://dev.to/arindam_1729/-1d23</link>
      <guid>https://dev.to/arindam_1729/-1d23</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7" class="crayons-story__hidden-navigation-link"&gt;Antigravity CLI: A Hands-On Guide to Google's Terminal Coding Agent&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 href="/arindam_1729" 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%2F965723%2F8c3a1bb4-eb47-4302-a280-09eedb8bc785.png" alt="arindam_1729 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/arindam_1729" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Arindam Majumder 
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Arindam Majumder 
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3720002" 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="/arindam_1729" 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%2F965723%2F8c3a1bb4-eb47-4302-a280-09eedb8bc785.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Arindam Majumder &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/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 21&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/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7" id="article-link-3720002"&gt;
          Antigravity CLI: A Hands-On Guide to Google's Terminal Coding Agent
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/antigravity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;antigravity&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/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&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/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7" 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;26&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              4&lt;span class="hidden s:inline"&gt;&amp;nbsp;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;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&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>Antigravity CLI: A Hands-On Guide to Google's Terminal Coding Agent</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Thu, 21 May 2026 19:52:44 +0000</pubDate>
      <link>https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7</link>
      <guid>https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7</guid>
      <description>&lt;p&gt;The AI coding agent space has been reshuffling fast. Anthropic has Claude Code, OpenAI has Codex CLI, xAI has Grok CLI, and now Google has retired Gemini CLI and replaced it with something bigger: &lt;strong&gt;Antigravity CLI&lt;/strong&gt;, a Go-based terminal agent that shares its engine with the Antigravity 2.0 desktop application.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will walk you through everything you need to know to get started with Antigravity CLI. We will cover the installation process, authentication, the agent and command modes, and build two practical projects that show what this tool can actually do. By the end, you will have a solid foundation for using Antigravity CLI in your real development workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Antigravity CLI?
&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%2Fxtl1z3by4rl2tunkhbnh.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%2Fxtl1z3by4rl2tunkhbnh.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antigravity CLI is Google's command-line coding agent powered by the Gemini family of models (with optional support for Claude and open-source backends). Unlike a simple chat wrapper, it is designed to reason across your project, edit multiple files at once, spawn subagents for parallel work, and call tools on your behalf.&lt;/p&gt;

&lt;p&gt;Google describes it as a lightweight Terminal User Interface (TUI) that brings the core capabilities of Antigravity 2.0 (multi-step reasoning, multi-file editing, tool calling, and persistent history) directly to your terminal. It is the official replacement for Gemini CLI, which sunsets for individual Google AI Pro and Ultra users on &lt;strong&gt;June 18, 2026&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is a quick look at what makes Antigravity CLI stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Built in Go&lt;/strong&gt;: snappier startup and lower memory footprint than the Node-based Gemini CLI it replaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared agent engine with Antigravity 2.0&lt;/strong&gt;: the desktop app and the CLI use the same runtime, so updates land everywhere at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bidirectional sync with the GUI&lt;/strong&gt;: preferences, permissions, and even active sessions can be exported from the terminal into the desktop app and back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async subagents&lt;/strong&gt;: long-running refactors and research tasks run in parallel without blocking your prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-class extensibility&lt;/strong&gt;: Agent Skills, Hooks, Subagents, MCP servers, and Plugins (the rebrand of Gemini CLI Extensions) are all supported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH-aware authentication&lt;/strong&gt;: detects remote sessions and gives you an auth URL to open on your local browser.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you get started, make sure you have the following in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operating system&lt;/strong&gt;: macOS, Linux, or Windows (native PowerShell, no WSL required).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curl&lt;/strong&gt; (macOS/Linux) or PowerShell 5+ (Windows): used by the installer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Google account&lt;/strong&gt;: any Google AI Pro, Ultra, or free-tier account works. Code Assist Standard/Enterprise customers can use their existing license.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic terminal comfort&lt;/strong&gt;: you do not need to be a shell expert, but knowing how to navigate directories and run commands will help.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Installing Antigravity CLI
&lt;/h2&gt;

&lt;p&gt;Installation is a single command. Open your terminal and run the one that matches your OS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS / Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://antigravity.google/cli/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows (PowerShell):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;irm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://antigravity.google/cli/install.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer detects your environment, drops the binary (named &lt;code&gt;agy&lt;/code&gt;, not &lt;code&gt;antigravity&lt;/code&gt;) into &lt;code&gt;~/.local/bin/&lt;/code&gt; on Unix or &lt;code&gt;%LOCALAPPDATA%\Antigravity\&lt;/code&gt; on Windows, and prints the line you need to add to your shell profile if the directory is not already on &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once it finishes, restart your terminal and verify the installation worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the version number printed. If the command is not found, double-check that the install directory is on your &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;The first time you run &lt;code&gt;agy&lt;/code&gt;, it kicks off a Google Sign-In flow. On a desktop machine it opens your browser automatically and walks you through the OAuth grant. Credentials are then cached in your system keyring (Keychain on macOS, Credential Manager on Windows, libsecret on Linux).&lt;/p&gt;

&lt;p&gt;If you are working over SSH or in a headless server environment, Antigravity CLI detects the remote session and prints an authorization URL plus a one-time code. Open the URL on your local machine, paste the code, and the CLI completes the handshake. This fixes one of the more painful flows in the old Gemini CLI.&lt;/p&gt;

&lt;p&gt;If you would rather use an API key (for CI or scripting), set it before running any command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTIGRAVITY_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make this permanent, add the export line to your &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt; file, then source it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Understanding the Operating Modes
&lt;/h2&gt;

&lt;p&gt;Antigravity CLI gives you three distinct ways to interact with it, each suited to a different context.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Interactive Agent Mode
&lt;/h3&gt;

&lt;p&gt;This is the default mode. Running &lt;code&gt;agy&lt;/code&gt; from any project directory launches the full TUI: a scrollable conversation pane, a &lt;code&gt;&amp;gt;&lt;/code&gt; prompt, and a status bar showing the active model, token usage, and any running subagents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fxlpmgn1u109d77m9b0fo.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%2Fxlpmgn1u109d77m9b0fo.png" alt="Image11" width="713" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once inside, you can type natural language prompts. A few starter prompts to try in any repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain this repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What does @src/main.go do and where is it called from?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@&lt;/code&gt; syntax pulls a file into context without you having to paste it. You can also reference whole directories (&lt;code&gt;@src/&lt;/code&gt;) or glob patterns (&lt;code&gt;@**/*.ts&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;You can switch models mid-session using the &lt;code&gt;/model&lt;/code&gt; slash command. Antigravity CLI ships with access to Gemini 3.5 Flash, Gemini 3.1 Pro, Claude Sonnet, Claude Opus, and GPT-OSS 120B (subject to your plan):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/model gemini-3.1-pro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful built-in slash commands inside the TUI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/help&lt;/code&gt;: list every command and keyboard shortcut.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/context&lt;/code&gt;: show token usage broken down by category and manage checkpoints.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/usage&lt;/code&gt;: quota and rate-limit status across all available models.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/export&lt;/code&gt;: push the current session into Antigravity 2.0 so you can keep working in the GUI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Command Mode
&lt;/h3&gt;

&lt;p&gt;Command mode is designed for quick, inline assistance: getting a one-shot completion or a terminal command without leaving whatever you were doing. Trigger it with &lt;strong&gt;Cmd + I&lt;/strong&gt; on macOS or &lt;strong&gt;Ctrl + I&lt;/strong&gt; on Windows/Linux from inside the TUI, or invoke it headlessly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Write a Go function that reads a CSV and returns a summary struct"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For structured output that you can pipe into other tools, add &lt;code&gt;--output-format&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"List all TODOs in this codebase"&lt;/span&gt; &lt;span class="nt"&gt;--output-format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the mode you reach for from shell scripts, Git hooks, or CI jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Async Subagent Mode
&lt;/h3&gt;

&lt;p&gt;Antigravity CLI's headline upgrade over Gemini CLI is asynchronous subagents. From inside the TUI you can dispatch a long-running task to a background agent and keep prompting in the foreground:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/agent refactor "Convert all callback-based handlers in @internal/api to use context.Context"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subagent reports progress in the status bar and posts its diff back into the conversation when finished. You can run several in parallel, which is handy for splitting a big refactor across packages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Inspecting Your Project Context
&lt;/h2&gt;

&lt;p&gt;When you drop Antigravity CLI into a new project, the most useful command to run is &lt;code&gt;agy inspect&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy inspect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints a summary of everything the agent has discovered, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuration files it has loaded (&lt;code&gt;.agents/&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, project-level instructions).&lt;/li&gt;
&lt;li&gt;Agent Skills available globally (&lt;code&gt;~/.gemini/antigravity-cli/skills/&lt;/code&gt;) and per-workspace (&lt;code&gt;.agents/skills/&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Plugins loaded (including any Gemini CLI extensions you imported).&lt;/li&gt;
&lt;li&gt;Hooks registered for the project.&lt;/li&gt;
&lt;li&gt;MCP servers connected from &lt;code&gt;mcp_config.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Antigravity CLI is not behaving the way you expect, &lt;code&gt;agy inspect&lt;/code&gt; is your first debugging step. It shows you exactly what context the agent is working with.&lt;/p&gt;




&lt;h2&gt;
  
  
  Migrating From Gemini CLI
&lt;/h2&gt;

&lt;p&gt;If you were already using Gemini CLI, Antigravity CLI ships a one-shot importer that pulls your old extensions, model preferences, and auth state across:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy plugin import gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It walks the legacy &lt;code&gt;~/.gemini/&lt;/code&gt; directory, converts each extension into a Plugin, and rewrites your &lt;code&gt;settings.json&lt;/code&gt; into the new schema. Original files are left untouched until you confirm.&lt;/p&gt;

&lt;p&gt;The official migration guide lives at &lt;code&gt;antigravity.google/docs/gcli-migration&lt;/code&gt; and covers edge cases like custom auth providers and air-gapped enterprise installs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing Antigravity CLI for Your Project
&lt;/h2&gt;

&lt;p&gt;Antigravity CLI supports project-level customization through a few mechanisms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AGENTS.md&lt;/strong&gt;: drop a plain-English instruction file at the root of your project. Anything you write here gets prepended to every prompt processed inside that directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Always use TypeScript. Prefer functional patterns over class-based ones. Never use `any` as a type.
Run `pnpm test` after every change that touches src/.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Agent Skills&lt;/strong&gt;: reusable slash commands. Place a Markdown file at &lt;code&gt;.agents/skills/lint.md&lt;/code&gt; and it becomes &lt;code&gt;/lint&lt;/code&gt; inside the TUI. Skills can include their own prompts, allowed tools, and even nested subagent definitions. Global skills live at &lt;code&gt;~/.gemini/antigravity-cli/skills/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks&lt;/strong&gt;: JSON-defined lifecycle interceptors that fire before a tool call, after a file edit, or on session start. Use them for things like auto-running &lt;code&gt;gofmt&lt;/code&gt; after every write or blocking edits to &lt;code&gt;vendor/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP servers&lt;/strong&gt;: both local (stdio) and remote (HTTP) Model Context Protocol servers are supported, configured in a dedicated &lt;code&gt;mcp_config.json&lt;/code&gt;. Remote servers require a &lt;code&gt;serverUrl&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;agy inspect&lt;/code&gt; any time to confirm which of these are active in the current directory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Custom Model Configuration
&lt;/h2&gt;

&lt;p&gt;If you want to pin the CLI to a specific model or point it at a self-hosted or third-party endpoint, edit your config file (&lt;code&gt;~/.config/antigravity/config.toml&lt;/code&gt;). The configuration accepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;model&lt;/code&gt;: the model identifier (e.g. &lt;code&gt;gemini-3.1-pro&lt;/code&gt;, &lt;code&gt;claude-opus&lt;/code&gt;, &lt;code&gt;gpt-oss-120b&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;base_url&lt;/code&gt;: the API base URL, useful for proxies or self-hosted Gemma deployments&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: a human-readable label shown in the TUI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;env_key&lt;/code&gt;: the environment variable that holds the API key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After adding a custom model, select it with the &lt;code&gt;-m&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy &lt;span class="nt"&gt;-m&lt;/span&gt; my-custom-model &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Summarize the changes in the last 5 commits"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or switch to it inside the TUI with &lt;code&gt;/model my-custom-model&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest Assessment: Strengths and Limitations
&lt;/h2&gt;

&lt;p&gt;Antigravity CLI is the most polished launch of a Google developer tool in a while, but it is worth going in with calibrated expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it shines:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Go rewrite is noticeably faster than Gemini CLI. Startup feels instant and the TUI stays responsive even under long sessions.&lt;/li&gt;
&lt;li&gt;Async subagents are a genuine workflow upgrade. Splitting a refactor across three background agents and watching their diffs land one by one is genuinely useful, not a gimmick.&lt;/li&gt;
&lt;li&gt;SSH-aware auth fixes the single biggest pain point of Gemini CLI for remote developers.&lt;/li&gt;
&lt;li&gt;Bidirectional sync with Antigravity 2.0 means you can switch between the terminal and the GUI without losing context.&lt;/li&gt;
&lt;li&gt;Built-in support for multiple model families (Gemini, Claude, GPT-OSS) lets you pick the right tool for each task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where to be careful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Like every LLM-based coding agent, it can produce plausible-looking code with subtle bugs. Always review generated output before running it in production.&lt;/li&gt;
&lt;li&gt;The plugin ecosystem is essentially Gemini CLI's extension ecosystem with a coat of paint. Many extensions work but a few have not been re-tested against the new runtime.&lt;/li&gt;
&lt;li&gt;Async subagents are powerful but they consume your quota in parallel. Watch &lt;code&gt;/usage&lt;/code&gt; if you are on a metered plan.&lt;/li&gt;
&lt;li&gt;Enterprise (Code Assist Standard/Enterprise) users can stay on Gemini CLI indefinitely, but everyone else needs to migrate before &lt;strong&gt;June 18, 2026&lt;/strong&gt; or lose access entirely.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What to Learn Next
&lt;/h2&gt;

&lt;p&gt;Now that you have Antigravity CLI running and you have seen what it can do, here are some directions worth exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent Skills&lt;/strong&gt;: write a small Markdown file to turn a common prompt into a reusable slash command for your team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers&lt;/strong&gt;: connect Antigravity CLI to your database, internal docs, or issue tracker so the agent can pull live context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent recipes&lt;/strong&gt;: experiment with patterns like "researcher + writer" or "scout + fixer" pairs that run async.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity 2.0 desktop&lt;/strong&gt;: use &lt;code&gt;/export&lt;/code&gt; to push a hard problem from the terminal into the GUI when you want richer file diffs and graph views.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity SDK&lt;/strong&gt;: if you want to embed agent capabilities inside your own apps, the SDK exposes the same runtime that powers the CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The official Antigravity documentation at &lt;code&gt;antigravity.google/docs&lt;/code&gt; is the best place to go deeper on all of these topics.&lt;/p&gt;




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

&lt;p&gt;Antigravity CLI is more than a rebrand of Gemini CLI. The Go rewrite, async subagents, shared runtime with the desktop app, and SSH-aware auth add up to a genuinely different product. It is fast to install, thoughtfully designed around extensibility, and its mix of interactive, command, and async modes covers a wide range of real development scenarios.&lt;/p&gt;

&lt;p&gt;The fact that Google built it as a peer of the Antigravity 2.0 desktop application, not a stripped-down companion, is a sign that the terminal is being treated as a first-class surface, not an afterthought.&lt;/p&gt;

&lt;p&gt;Give it a try in your next project and see where it fits.&lt;/p&gt;

</description>
      <category>antigravity</category>
      <category>ai</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Scaling Karpathy’s AutoResearch Using Nebius Token Factory</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Sun, 03 May 2026 13:50:44 +0000</pubDate>
      <link>https://dev.to/studio1hq/scaling-karpathys-autoresearch-using-nebius-token-factory-81a</link>
      <guid>https://dev.to/studio1hq/scaling-karpathys-autoresearch-using-nebius-token-factory-81a</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We ran about 250 prompt optimization experiments overnight using a small AI agent loop. The idea was simple: let an AI system propose an experiment, run it, evaluate the result, and then try again with a better idea. Instead of manually testing prompts one by one, the system keeps improving its own attempts over multiple iterations.&lt;/p&gt;

&lt;p&gt;This idea comes from &lt;a href="https://github.com/karpathy/autoresearch" rel="noopener noreferrer"&gt;Andrej Karpathy’s AutoResearch&lt;/a&gt;, where an AI agent can automate the typical machine learning research cycle. In a normal workflow, researchers adjust parameters, run experiments, observe the results, and repeat the process many times before reaching a good configuration. AutoResearch shows that this repetitive process can be handled by an intelligent agent.&lt;/p&gt;

&lt;p&gt;In this article, we will walk through how we built a cloud-native AutoResearch loop using &lt;a href="https://tokenfactory.nebius.com/" rel="noopener noreferrer"&gt;Nebius Token Factory for LLM inference&lt;/a&gt;, allowing the agent to run hundreds of experiments automatically while keeping structured records of every attempt. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pitfalls in the Original AutoResearch Implementation
&lt;/h2&gt;

&lt;p&gt;Karpathy’s AutoResearch project is a very interesting idea and a great starting point to understand how AI agents can run experiments automatically. &lt;/p&gt;

&lt;p&gt;The repository mainly consists of simple files such as &lt;strong&gt;&lt;code&gt;program.md&lt;/code&gt;&lt;/strong&gt; (which defines the research goal), &lt;strong&gt;&lt;code&gt;train.py&lt;/code&gt;&lt;/strong&gt; (which runs the experiment), and a lightweight results log that records experiment outcomes. The agent reads the goal, modifies the experiment code, runs it, and stores the results, demonstrating how an AI system can iterate through experiments automatically.&lt;/p&gt;

&lt;p&gt;It was built as a research prototype to demonstrate the concept, not as a full system for running large-scale experiments in real workflows. &lt;/p&gt;

&lt;p&gt;As a result, a few limitations arise when we try to scale the idea.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Experiment tracking using TSV files:&lt;/strong&gt; In the original implementation, experiment results are stored in a simple TSV (tab-separated values) file. This file usually contains basic fields like experiment ID, score, and parameters. While this is easy to implement, it becomes difficult to manage as the number of experiments grows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited structure for experiment metadata:&lt;/strong&gt; A flat TSV file does not provide structured storage for experiment details such as prompts, responses, timestamps, or reasoning steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local model dependency:&lt;/strong&gt; The original workflow usually depends on running models locally. This means developers often need access to local GPUs or preconfigured environments to run inference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Difficulty scaling experiment loops:&lt;/strong&gt; Because of the local infrastructure and simple logging system, running hundreds of experiments in a controlled way becomes harder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-2030371219518931079-421" src="https://platform.twitter.com/embed/Tweet.html?id=2030371219518931079"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2030371219518931079-421');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2030371219518931079&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Are Going to Build
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The use case for this project is prompt optimization. In many real workflows, developers often try multiple prompts manually to get the best response from a language model. This usually involves repeated trial-and-error, where prompts are slightly modified, tested, and evaluated before arriving at a good result. When the number of experiments increases, managing and tracking these attempts becomes difficult.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this tutorial, we will build a small system that keeps the same AutoResearch idea while addressing a few of those practical limitations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AutoResearch-style experiment loop:&lt;/strong&gt; We implement the same research cycle where an agent proposes an experiment, runs it, evaluates the result, stores the outcome, and then proposes the next attempt based on previous results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud-based reasoning using Nebius Token Factory:&lt;/strong&gt; Instead of relying on local models, the agent uses &lt;a href="https://nebius.com/services/token-factory" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt; to generate experiment ideas and responses. This removes the dependency on local GPUs and makes the research loop easier to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured experiment tracking using JSON:&lt;/strong&gt; Instead of logging experiments in a flat TSV file, each experiment is stored as a structured JSON record. This allows us to track prompts, responses, scores, and timestamps more clearly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt optimization as the experiment domain:&lt;/strong&gt; For this tutorial, the system will try to generate the best explanation for vector databases. Each experiment proposes a different prompt and evaluates how well the response matches our criteria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running a large experiment loop:&lt;/strong&gt; The system runs around 250 iterations, allowing the agent to gradually improve prompts by learning from previous experiment results.&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%2Fcw0wg1ee8ap9foj7bz73.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%2Fcw0wg1ee8ap9foj7bz73.png" alt="Image1" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Nebius Token Factory
&lt;/h2&gt;

&lt;p&gt;To run the AutoResearch loop properly, the agent needs a reliable way to generate experiment ideas and responses. Instead of running models locally, we use Nebius Token Factory as the inference layer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Managed model inference:&lt;/strong&gt; Nebius Token Factory lets us run open models through an API. We do not need to download models or manage GPUs locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access to open models:&lt;/strong&gt; The platform provides models such as &lt;strong&gt;Llama, DeepSeek, and Qwen&lt;/strong&gt;, which can be used for reasoning, prompt generation, and experiment responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-compatible API:&lt;/strong&gt; The API follows the same structure used in the OpenAI SDK. This makes integration simple in Python applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent reasoning backend:&lt;/strong&gt; In our system, the AutoResearch agent calls Nebius Token Factory to analyze previous experiments and propose the next prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports large experiment loops:&lt;/strong&gt; Because inference runs in the cloud, we can run &lt;strong&gt;hundreds of experiment iterations&lt;/strong&gt; without worrying about local compute limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No local GPU requirement:&lt;/strong&gt; Developers can run the experiment loop directly from their machine while the model inference happens in Nebius infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more demos, &lt;a href="https://github.com/nebius/token-factory-cookbook" rel="noopener noreferrer"&gt;refer to the cookbooks here&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%2Fulamywlxs830ejq8z7jz.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%2Fulamywlxs830ejq8z7jz.png" alt="Image2" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial: Building an AutoResearch-like System with Nebius Token Factory
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Clone the Project Repository
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Clone the repository.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/studio1hq/Nebius_autoresearch.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install required dependencies.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set up a working environment.&lt;/li&gt;
&lt;li&gt;Review the Project Structure&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;What it Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;program.md&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines the research goal&lt;/td&gt;
&lt;td&gt;Contains the task the agent is trying to optimize. In this project, the goal is to generate the best prompt for explaining vector databases.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;agent.py&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generates the next experiment&lt;/td&gt;
&lt;td&gt;Uses &lt;strong&gt;Nebius Token Factory&lt;/strong&gt; to analyze previous experiment results and propose the next prompt to test.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;experiment.py&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs the experiment&lt;/td&gt;
&lt;td&gt;Sends the generated prompt to &lt;strong&gt;Nebius Token Factory&lt;/strong&gt; and retrieves the model’s response.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;scorer.py&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Evaluates experiment output&lt;/td&gt;
&lt;td&gt;Scores the response based on simple rules such as response length and presence of relevant keywords. Returns a numeric score.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;main.py&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Controls the AutoResearch loop&lt;/td&gt;
&lt;td&gt;Loads previous experiment history, runs the experiment cycle, logs results, and repeats the process for multiple iterations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;results.json&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stores experiment history&lt;/td&gt;
&lt;td&gt;Saves structured experiment records including prompt, response, score, and timestamp. Easier to analyze compared to flat TSV logs.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 2 — Configure Nebius Token Factory
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Create a Nebius Token Factory API key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open the Token Factory dashboard:&lt;br&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%2Fow50jbq72jik3e8s4qtk.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%2Fow50jbq72jik3e8s4qtk.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the API Keys section in the left sidebar and click Get API key.&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%2F56f26yl8o3d1q49p70ev.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%2F56f26yl8o3d1q49p70ev.png" alt="Image6" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new key for your project. This key will be used by the application to authenticate API requests sent to &lt;a href="https://docs.tokenfactory.nebius.com/quickstart" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Store the API key as an environment variable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the root of the project and store the key as an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;NEBIUS_API_KEY&lt;/span&gt;=&lt;span class="n"&gt;your_api_key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4x13035f1ohr3vqhe76v.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%2F4x13035f1ohr3vqhe76v.png" alt="Image9" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure the Token Factory client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tokenfactory.nebius.com/cookbook/overview" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt; provides an OpenAI-compatible API, so we can use the same client structure used for OpenAI integrations.&lt;/p&gt;

&lt;p&gt;Initialize the client using the Nebius API base URL and the API key stored in the environment variable.&lt;/p&gt;

&lt;p&gt;The request sends the prompt to the selected model (for example, &lt;code&gt;llama-3-70b-instruct&lt;/code&gt;) and receives the generated response.&lt;/p&gt;

&lt;p&gt;In this system, these API calls power two parts of the AutoResearch loop:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent reasoning: W&lt;/strong&gt;here the agent proposes the next experiment prompt (&lt;a href="http://agent.pyhttps://github.com/Studio1HQ/Nebius_autoresearch/blob/main/nebius_autoresearch/agent.py" rel="noopener noreferrer"&gt;agent.py&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;typing&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Any&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;generate_response&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;propose_experiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="nx"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
    Proposes a new system prompt based on the research goal and experiment history.

    Args:
        history: List of previous experiment results (dicts with 'prompt' and 'score').
        goal: The research goal string.

    Returns:
        str: The proposed system prompt for the next experiment.
    &lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Format&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;history_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No previous experiments.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nx"&gt;experiments&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;provide&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="nx"&gt;without&lt;/span&gt; &lt;span class="nx"&gt;overflowing&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;
        &lt;span class="nx"&gt;recent_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="nx"&gt;history_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Attempt {i+1}:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Prompt: {r.get('prompt', 'Unknown')}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Score: {r.get('score', 0)}/10&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recent_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="nx"&gt;system_instruction&lt;/span&gt; &lt;span class="o"&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;You are an expert AI researcher optimizing a system prompt to achieve a specific goal.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Analyze the previous attempts and their scores. Identify what worked and what didn't.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Then, generate a NEW, improved system prompt that is likely to achieve a higher score.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do not repeat previous prompts. Be creative and precise.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Format your response exactly as follows:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;THOUGHT: &amp;lt;your analysis and plan&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PROMPT: &amp;lt;the actual system prompt text&amp;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;user_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Research Goal:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;{goal}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Experiment History:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;{history_text}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Based on the above, generate the next system prompt to test.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ensure you include your thought process before the prompt.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The agent builds a context using the &lt;strong&gt;goal + past experiments&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;This prompt is sent to Nebius using &lt;code&gt;generate_response()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The model suggests the &lt;strong&gt;next experiment (new prompt)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;This is where the &lt;strong&gt;“thinking” of the agent happens&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Experiment execution:&lt;/strong&gt; where the prompt is sent to the model, and the response is evaluated. (&lt;a href="http://experiment.pyhttps://github.com/Studio1HQ/Nebius_autoresearch/blob/main/nebius_autoresearch/experiment.py" rel="noopener noreferrer"&gt;experiment.py&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;generate_response&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_experiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
    Runs the experiment by using the proposed system prompt to explain vector databases.
    &lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
    &lt;span class="nx"&gt;test_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{system_prompt}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;Explain vector databases. Respond in under 120 words.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generate_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test_prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The generated prompt is sent again to Nebius.&lt;/li&gt;
&lt;li&gt;The model produces the &lt;strong&gt;actual output&lt;/strong&gt; for evaluation.&lt;/li&gt;
&lt;li&gt;This response is later scored and stored.&lt;/li&gt;
&lt;li&gt;This is the &lt;strong&gt;execution step of the experiment&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this configuration in place, the AutoResearch loop can use Nebius Token Factory as its inference backend. &lt;/p&gt;

&lt;p&gt;For example, (refer to &lt;a href="http://client.pyhttps://github.com/Studio1HQ/Nebius_autoresearch/blob/main/nebius_autoresearch/client.py" rel="noopener noreferrer"&gt;client.py&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBIUS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBIUS_API_KEY environment variable not set&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Nebius Token Factory OpenAI-compatible endpoint
&lt;/span&gt;    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.tokenfactory.nebius.com/v1/chat/completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-3.3-70B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="c1"&gt;# Optional parameters for generation control
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;You can also use an OpenAI-compatible API interface. The same client patterns used in OpenAI-based applications can be used here with minimal changes, making integration into existing workflows straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.tokenfactory.nebius.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEBIUS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;completion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama-3-70b-instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the answer to all questions?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 — Understanding the AutoResearch Loop
&lt;/h2&gt;

&lt;p&gt;The system follows a simple research loop where the agent proposes experiments, evaluates the results, and improves the next attempt based on previous runs.&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%2Fp7m0hqwbqifrqje6w2e1.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%2Fp7m0hqwbqifrqje6w2e1.png" alt="Image7" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Load the research goal:&lt;/strong&gt; The system reads the task defined in &lt;code&gt;program.md&lt;/code&gt;. In this case, the goal is to generate the best prompt for explaining vector databases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load previous experiment history:&lt;/strong&gt; The program reads &lt;code&gt;results.json&lt;/code&gt; to understand what prompts were already tested and how they performed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent proposes the next experiment:&lt;/strong&gt; The agent uses Nebius Token Factory to analyze the previous results and suggest a new prompt to try.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the experiment:&lt;/strong&gt; The new prompt is sent to the model through the Token Factory API, and the response is generated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score the result:&lt;/strong&gt; The response is evaluated using the scoring function defined in &lt;code&gt;scorer.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store the experiment record:&lt;/strong&gt; The prompt, response, score, and timestamp are saved in &lt;code&gt;results.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeat the loop:&lt;/strong&gt; The system continues this cycle for around &lt;strong&gt;250 experiment iterations&lt;/strong&gt;, allowing the agent to gradually improve the prompts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4 — Run the System
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5eootoe4iotf9g8ccvsb.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%2F5eootoe4iotf9g8ccvsb.png" alt="Image8" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terminal output shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iteration number&lt;/li&gt;
&lt;li&gt;proposed prompt&lt;/li&gt;
&lt;li&gt;generated response&lt;/li&gt;
&lt;li&gt;score.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every 25 experiments, the system prints a short report in the terminal showing the number of experiments completed, the best score so far, and the prompt that produced the best result. This helps track how the agent is improving over time.&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%2Fgaryev8vat5we4yqxjbb.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%2Fgaryev8vat5we4yqxjbb.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each experiment is stored as a structured record in results.json. The record contains the prompt used, the response generated by the model, the score assigned by the evaluation function, and the timestamp of the run. This structured format makes it easier to inspect and analyze experiment history later.&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%2Fup5ejurslni6g2hfc0r8.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%2Fup5ejurslni6g2hfc0r8.png" alt="Image11" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of starting from scratch every time, the system loads the existing results.json file when the program starts. It detects the last completed experiment and continues from the next iteration. This allows the experiment loop to resume without losing previous results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;AutoResearch shows how an AI agent can run experiments automatically by proposing ideas, testing them, and learning from the results. &lt;/p&gt;

&lt;p&gt;In this tutorial, we extended that idea by using Nebius Token Factory for cloud-based model inference and structured experiment logging for better tracking. This makes the research loop easier to run, easier to observe, and more practical for developers experimenting with AI workflows.&lt;/p&gt;

&lt;p&gt;If you want to try similar experimentation workflows, you can start with &lt;a href="https://tokenfactory.nebius.com/" rel="noopener noreferrer"&gt;Nebius Token Factory&lt;/a&gt; to run open models through a simple API without managing GPUs. The broader &lt;a href="https://nebius.com/" rel="noopener noreferrer"&gt;Nebius Cloud platform&lt;/a&gt; also provides GPU infrastructure, scalable inference, and tools for building AI applications. &lt;/p&gt;

&lt;p&gt;Explore the available services, experiment with different models, and build your own AI-driven systems using the Nebius ecosystem.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nebius</category>
      <category>machinelearning</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Build a HackMD-Style Collaborative Markdown Editor with React, Antigravity IDE &amp; Velt</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Mon, 27 Apr 2026 07:21:30 +0000</pubDate>
      <link>https://dev.to/studio1hq/build-a-hackmd-style-collaborative-markdown-editor-with-react-antigravity-ide-velt-5gfj</link>
      <guid>https://dev.to/studio1hq/build-a-hackmd-style-collaborative-markdown-editor-with-react-antigravity-ide-velt-5gfj</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Building real-time collaboration from scratch takes significant effort. You need sync logic, presence, comments, and infrastructure before you even ship the feature.&lt;/p&gt;

&lt;p&gt;In this guide, we generate a pixel perfect HackMD style editor UI using Antigravity, connect live markdown preview in React, and then use Velt to add presence, live sync, and comments in just a few steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’re Building
&lt;/h2&gt;

&lt;p&gt;We are building a HackMD style markdown editor with a clean two pane layout. On the left, users can write markdown. On the right, they see a live rendered preview. The interface follows a dark theme and mirrors the structure and layout of HackMD closely.&lt;/p&gt;

&lt;p&gt;This is not just a static clone. The final result will support real time collaboration, allowing multiple users to edit, comment, and stay aware of each other inside the same document.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/TAVQnzl7YOk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;We use a focused, minimal stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React with Vite and TypeScript:&lt;/strong&gt; Provides a fast development setup and a clean component-based architecture.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://antigravity.google/" rel="noopener noreferrer"&gt;**Antigravity&lt;/a&gt;:** Used to generate a pixel-accurate editor UI directly from a reference image. This allows us to replicate the layout precisely without manual design iteration.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://velt.dev/" rel="noopener noreferrer"&gt;**Velt React SDK&lt;/a&gt;:** Adds the collaboration layer. We use it to enable presence, live state sync, and contextual comments without building real-time infrastructure from scratch.&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%2F7y75lx2zb0ozmfw66d02.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%2F7y75lx2zb0ozmfw66d02.png" alt="Image1" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Generating a Pixel-Perfect UI with Antigravity
&lt;/h2&gt;

&lt;p&gt;Antigravity is an AI-powered development platform and “agent-first” IDE where AI agents assist with coding tasks across your editor, terminal, and browser, moving beyond simple code completion toward autonomous execution of complex software workflows. &lt;/p&gt;

&lt;p&gt;It lets you generate and modify real code based on high-level instructions, orchestrating planning, editing, and validation with minimal manual effort.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Antigravity?
&lt;/h3&gt;

&lt;p&gt;Cloning an interface like HackMD manually is time-consuming. Matching spacing, typography, layout, and dark mode details takes careful iteration.&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%2Fbtl1dxi959wckm4y742a.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%2Fbtl1dxi959wckm4y742a.png" alt="Image2" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We used Antigravity to generate the editor UI directly from the reference image. The prompt enforced strict visual fidelity. No redesign. No interpretation.&lt;/p&gt;

&lt;p&gt;This gave us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rapid UI cloning:&lt;/strong&gt; Full split layout with header, editor, preview, and status bar in minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pixel-accurate output:&lt;/strong&gt; Layout and styling matched the reference closely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No design drift&lt;/strong&gt;: The UI stayed consistent with the original.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the UI ready, we could move straight to functionality and collaboration.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Prompt Strategy
&lt;/h3&gt;

&lt;p&gt;The prompt was written with strict visual constraints. Every layout detail, spacing rule, and styling decision had to follow the reference image exactly.&lt;/p&gt;

&lt;p&gt;We enforced a simple rule: the image always wins. If there was any conflict between best practice and the screenshot, the screenshot was treated as the authority.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;expert&lt;/span&gt; &lt;span class="nx"&gt;frontend&lt;/span&gt; &lt;span class="nx"&gt;engineer&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;pixel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;perfect&lt;/span&gt; &lt;span class="nx"&gt;implementer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;HackMD&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;exactly&lt;/span&gt; &lt;span class="nx"&gt;matching&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;provided&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;redesign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;interpretation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;approximation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;visual&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;behavioral&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;CRITICAL&lt;/span&gt; &lt;span class="nc"&gt;INSTRUCTIONS &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;IGNORE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="nx"&gt;assumptions&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;about&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;typography&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sizing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;invent&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;omit&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;restyle&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;improve&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;anything&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;DO&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;guess&lt;/span&gt; &lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;responsiveness&lt;/span&gt; &lt;span class="nx"&gt;strictly&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;standard&lt;/span&gt; &lt;span class="nx"&gt;proportional&lt;/span&gt; &lt;span class="nx"&gt;scaling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;Follow&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="nx"&gt;exactly&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;unclear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;replicate&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;faithfully&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;possible&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;visual&lt;/span&gt; &lt;span class="nx"&gt;evidence&lt;/span&gt; &lt;span class="nx"&gt;alone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;INPUT&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;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;working&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;basic&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;building&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;authentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;real&lt;/span&gt; &lt;span class="nx"&gt;GitHub&lt;/span&gt; &lt;span class="nx"&gt;integration&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="nx"&gt;consists&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;Left&lt;/span&gt; &lt;span class="nx"&gt;pane&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;Right&lt;/span&gt; &lt;span class="nx"&gt;pane&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Live&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;provided&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;single&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;truth&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;REQUIRED&lt;/span&gt; &lt;span class="nx"&gt;OUTPUT&lt;/span&gt;

&lt;span class="nx"&gt;Produce&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;production&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;recreates&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;pixel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;perfectly&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;You&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="nx"&gt;functional&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nc"&gt;CSS &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;CSS&lt;/span&gt; &lt;span class="nx"&gt;Modules&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;precisely&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Ensure&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;fully&lt;/span&gt; &lt;span class="nx"&gt;responsive&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="nx"&gt;sizes&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nx"&gt;preserving&lt;/span&gt; &lt;span class="nx"&gt;proportions&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Background&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Pane&lt;/span&gt; &lt;span class="nx"&gt;widths&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Divider&lt;/span&gt; &lt;span class="nx"&gt;behavior&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Toolbar&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;placement&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Font&lt;/span&gt; &lt;span class="nx"&gt;family&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;weight&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Line&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Hover&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;focus&lt;/span&gt; &lt;span class="nf"&gt;states &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;implied&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Spacing&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;margins&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Implement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;
   &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Live&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt; &lt;span class="nx"&gt;rendering&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Match&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;dark&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="nx"&gt;styling&lt;/span&gt; &lt;span class="nx"&gt;exactly&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;shown&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Match&lt;/span&gt; &lt;span class="nx"&gt;scrollbar&lt;/span&gt; &lt;span class="nx"&gt;appearance&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;closely&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;possible&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;external&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;libraries&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;strictly&lt;/span&gt; &lt;span class="nx"&gt;necessary&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="nx"&gt;parsing&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;semantic&lt;/span&gt; &lt;span class="nx"&gt;HTML&lt;/span&gt; &lt;span class="nx"&gt;where&lt;/span&gt; &lt;span class="nx"&gt;applicable&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;LAYOUT&lt;/span&gt; &lt;span class="nx"&gt;REQUIREMENTS&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Two&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;column&lt;/span&gt; &lt;span class="nx"&gt;split&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;editable&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rendered&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Divider&lt;/span&gt; &lt;span class="nx"&gt;exactly&lt;/span&gt; &lt;span class="nx"&gt;positioned&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;shown&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Toolbar&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="nx"&gt;exactly&lt;/span&gt; &lt;span class="nx"&gt;matching&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;alignment&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Bottom&lt;/span&gt; &lt;span class="nx"&gt;GitHub&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;appear&lt;/span&gt; &lt;span class="nx"&gt;exactly&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nf"&gt;shown &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visual&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;RESPONSIVENESS&lt;/span&gt; &lt;span class="nx"&gt;REQUIREMENTS&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;On&lt;/span&gt; &lt;span class="nx"&gt;smaller&lt;/span&gt; &lt;span class="nx"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Maintain&lt;/span&gt; &lt;span class="nx"&gt;proportional&lt;/span&gt; &lt;span class="nx"&gt;scaling&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Preserve&lt;/span&gt; &lt;span class="nx"&gt;visual&lt;/span&gt; &lt;span class="nx"&gt;hierarchy&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Do&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;collapse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;redesign&lt;/span&gt; &lt;span class="nx"&gt;panes&lt;/span&gt; &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;explicitly&lt;/span&gt; &lt;span class="nx"&gt;shown&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;mobile&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;specific&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;clearly&lt;/span&gt; &lt;span class="nx"&gt;implied&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;FUNCTIONAL&lt;/span&gt; &lt;span class="nx"&gt;REQUIREMENTS&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="nx"&gt;typing&lt;/span&gt; &lt;span class="nx"&gt;updates&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;real&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Toolbar&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;need&lt;/span&gt; &lt;span class="nx"&gt;real&lt;/span&gt; &lt;span class="nx"&gt;functionality&lt;/span&gt; &lt;span class="nx"&gt;unless&lt;/span&gt; &lt;span class="nx"&gt;explicitly&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;GitHub&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;visual&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;persistence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="nx"&gt;calls&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;DELIVERY&lt;/span&gt; &lt;span class="nx"&gt;FORMAT&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Return&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CSS&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Brief&lt;/span&gt; &lt;span class="nx"&gt;explanation&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;structure&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Code&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;paste&lt;/span&gt; &lt;span class="nx"&gt;ready&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;FINAL&lt;/span&gt; &lt;span class="nx"&gt;RULE&lt;/span&gt;

&lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;there&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;ever&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;conflict&lt;/span&gt; &lt;span class="nx"&gt;between&lt;/span&gt; &lt;span class="nx"&gt;best&lt;/span&gt; &lt;span class="nx"&gt;practices&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;THE&lt;/span&gt; &lt;span class="nx"&gt;IMAGE&lt;/span&gt; &lt;span class="nx"&gt;ALWAYS&lt;/span&gt; &lt;span class="nx"&gt;WINS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;

&lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;provided&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;absolute&lt;/span&gt; &lt;span class="nx"&gt;authority&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;replicate&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;exactly&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generated Component Structure
&lt;/h3&gt;

&lt;p&gt;Antigravity generated a clean, modular React structure instead of a single large file. The UI was split into focused components, each responsible for one section of the editor. This made the layout easy to reason about and ready for collaboration features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Header.tsx&lt;/code&gt; — Top navigation and toolbar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Editor.tsx&lt;/code&gt; — Left pane markdown input&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Preview.tsx&lt;/code&gt; — Right pane rendered markdown&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;StatusBar.tsx&lt;/code&gt; — Bottom metadata bar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Layout.tsx&lt;/code&gt; — Structural wrapper composing the editor layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure is accurate based on the repo you shared. It matches the actual &lt;code&gt;src/components&lt;/code&gt; breakdown and reflects how the UI is assembled in &lt;code&gt;App.tsx&lt;/code&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%2F9qe6e34wsi5ysd4xhmuu.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%2F9qe6e34wsi5ysd4xhmuu.png" alt="Image3" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Markdown + Live Preview
&lt;/h3&gt;

&lt;p&gt;The editor follows a simple two-pane model. The left pane is a controlled textarea where users write markdown. The right pane renders the parsed markdown in real time.&lt;/p&gt;

&lt;p&gt;State is lifted to a shared parent component so that every keystroke updates both the editor and the preview instantly. This keeps the UI predictable and ensures the preview always reflects the latest content.&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%2F98ce85j4tfyflully52f.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%2F98ce85j4tfyflully52f.png" alt="Image4" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Making the Editor Collaborative with Velt
&lt;/h2&gt;

&lt;p&gt;Once the local markdown editor was working, the next step was to make it collaborative. Instead of building real-time infrastructure from scratch, we integrated Velt to handle sync, presence, and comments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Velt?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://velt.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;Velt&lt;/strong&gt; is a collaboration SDK&lt;/a&gt; that lets developers embed real-time collaboration features into web products quickly and efficiently. It provides fully managed components and backend support so you can add multiplayer-style experiences without building real-time infrastructure from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features of Velt:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Sync&lt;/strong&gt; – Real-time shared state across users so everyone sees updates instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comments&lt;/strong&gt; – Contextual commenting components like those in Figma, Google Docs, and spreadsheet tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Presence &amp;amp; Cursors&lt;/strong&gt; – Shows active users and cursor positions in shared sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiplayer Editing&lt;/strong&gt; – Multiple users can edit content concurrently with conflict resolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notifications&lt;/strong&gt; – Built-in support for alerts and updates (mentions, replies).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recording &amp;amp; Huddles&lt;/strong&gt; – audio/video/screen recording and in-app collaborative sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable SDK&lt;/strong&gt; – Components and behavior can be styled and extended to match your product.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent Skills and MCP Integration&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Velt recently introduced &lt;a href="https://docs.velt.dev/get-started/skills" rel="noopener noreferrer"&gt;Agent Skills&lt;/a&gt; and an &lt;a href="https://docs.velt.dev/get-started/mcp-installer" rel="noopener noreferrer"&gt;implementation MCP&lt;/a&gt; that allow collaboration features to be integrated using AI agents. Instead of manually wiring presence, comments, and live sync, agents can now orchestrate much of the integration flow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing &amp;amp; Setting Up Velt
&lt;/h3&gt;

&lt;p&gt;We started by &lt;a href="https://docs.velt.dev/get-started/quickstart" rel="noopener noreferrer"&gt;installing the Velt React SDK&lt;/a&gt; and adding it to the project. This gives us access to collaboration primitives such as live state, presence, and comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @veltdev/react
&lt;span class="c"&gt;# Optional: npm install --save-dev @veltdev/types&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we wrapped the root of the application with the Velt provider. This initializes the collaboration layer and connects the app to Velt using an API key.&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%2F0l6s9gg51bhki5pgd6j5.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%2F0l6s9gg51bhki5pgd6j5.png" alt="Image5" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From this point on, collaboration features can be layered into existing components without restructuring the entire application.&lt;/p&gt;

&lt;p&gt;Since Velt also supports &lt;a href="https://docs.velt.dev/get-started/skills" rel="noopener noreferrer"&gt;Agent Skills&lt;/a&gt; and &lt;a href="https://docs.velt.dev/get-started/mcp-installer" rel="noopener noreferrer"&gt;MCP-based implementations&lt;/a&gt; &lt;strong&gt;i&lt;/strong&gt;n an agent-enabled environment, collaboration features can be scaffolded automatically, without manually wiring every component. The agent can configure provider setup, inject components, and connect live state with minimal manual steps.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Manual SDK setup → Explicit integration in code&lt;/li&gt;
&lt;li&gt;Agent Skills / MCP → AI-assisted integration with reduced setup effort&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this project, we used the manual SDK approach. But teams using agent driven workflows can accelerate collaboration integration even further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Text Comments
&lt;/h3&gt;

&lt;p&gt;With Velt initialized, the next step was &lt;a href="https://docs.velt.dev/async-collaboration/comments/overview" rel="noopener noreferrer"&gt;enabling inline comments&lt;/a&gt; inside the document.&lt;/p&gt;

&lt;p&gt;We wrapped the editor layout with the VeltComments component in text mode. This attaches a collaborative comment layer directly to the markdown content without changing the editor’s internal logic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contextual inline comments:&lt;/strong&gt; Users can select text and leave feedback directly within the document.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anchored collaboration:&lt;/strong&gt; Comments stay attached to specific sections even as content evolves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-user discussion:&lt;/strong&gt; Multiple users can comment and reply in the same document in real time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the editor moves from being a single user tool to a shared workspace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_VELT_API_KEY&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;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentUser&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;switchUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&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;setCurrentUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hackmd-current-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Load user preference on app start&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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="nx"&gt;storedUserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hackmd-current-user&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;storedUserId&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;u&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;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;storedUserId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nf"&gt;setCurrentUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;VeltProvider&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;VeltComments&lt;/span&gt; &lt;span class="na"&gt;textMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AppContent&lt;/span&gt;
        &lt;span class="na"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onSwitchUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;switchUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;VeltProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enabling Live Sync
&lt;/h3&gt;

&lt;p&gt;Comments make the document collaborative, but the content itself is still local. To enable true multi-user editing, we replaced local React state with &lt;a href="https://docs.velt.dev/realtime-collaboration/live-state-sync/overview" rel="noopener noreferrer"&gt;Velt’s shared live state&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of managing markdown with &lt;code&gt;useState&lt;/code&gt;, we switched to &lt;code&gt;useLiveState&lt;/code&gt;. This hook stores the document content in a shared real time layer managed by Velt.&lt;/p&gt;

&lt;p&gt;Every update to the markdown now propagates instantly across connected users. No WebSockets, no manual sync logic, no conflict resolution setup.&lt;/p&gt;

&lt;p&gt;The rest of the component structure remains unchanged. Only the state source is replaced.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi user editing&lt;/strong&gt; — Multiple users can type in the same document simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant shared updates&lt;/strong&gt; — Changes appear in real time across all active sessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the moment where the editor becomes fully collaborative.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLiveState&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="s1"&gt;@veltdev/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Editor&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Preview&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;StatusBar&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./StatusBar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&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="s1"&gt;../types/veltUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defaultMarkdown&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="s1"&gt;../constants/defaultTemplate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LayoutProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nl"&gt;onSwitchUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;Layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LayoutProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onSwitchUser&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;markdown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMarkdown&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLiveState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hackmd-clone-markdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultMarkdown&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;column&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&lt;/span&gt; &lt;span class="na"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onSwitchUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onSwitchUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;relative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Editor&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;markdown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setMarkdown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Preview&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;markdown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatusBar&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Presence Awareness
&lt;/h3&gt;

&lt;p&gt;Editing and commenting are core collaboration features, but &lt;a href="https://docs.velt.dev/realtime-collaboration/presence/overview" rel="noopener noreferrer"&gt;presence&lt;/a&gt; adds awareness. It lets users see who else is currently active inside the document.&lt;/p&gt;

&lt;p&gt;With Velt, presence is automatically tracked once the provider is configured. Active users can be identified in the session, enabling visual indicators such as avatars or active participant signals.&lt;/p&gt;

&lt;p&gt;This creates a collaborative awareness layer. Users know when others are viewing or editing the same document, which reduces overlap and improves coordination.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VeltPresence&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="s1"&gt;@veltdev/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&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="s1"&gt;../types/veltUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;HeaderProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nl"&gt;onSwitchUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VeltUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HeaderProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;staticUsers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onSwitchUser&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;showUserMenu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowUserMenu&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var(--toolbar-height)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#2f3136&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Darker gray for toolbar&lt;/span&gt;
            &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;space-between&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 16px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid #111&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;14px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#b9bbbe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Left Section */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
                    &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;marginRight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;50%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#3370b7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Power&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My workspace&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#4f545c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Editor Mode Buttons */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#333&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px 8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#444&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Pencil&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px 8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#888&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Columns&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px 8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#888&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Eye&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Plus&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HelpCircle&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Search&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

...

export default Header;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What We Didn’t Have to Build
&lt;/h2&gt;

&lt;p&gt;Using Velt removed the need to build and maintain a complex collaboration infrastructure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No WebSocket layer for managing real-time connections&lt;/li&gt;
&lt;li&gt;No CRDT or conflict resolution system for concurrent edits&lt;/li&gt;
&lt;li&gt;No custom backend service for syncing document state&lt;/li&gt;
&lt;li&gt;No notification engine for mentions and updates&lt;/li&gt;
&lt;li&gt;No database layer for storing and anchoring comments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allowed us to ship faster, reduce engineering overhead, and keep the codebase focused on core product functionality rather than infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;You can &lt;a href="https://github.com/Studio1HQ/hackmd-clone/" rel="noopener noreferrer"&gt;run the full demo&lt;/a&gt; locally and explore the collaborative features in action.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the repository&lt;/li&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Add your Velt API key&lt;/li&gt;
&lt;li&gt;Start the development server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once running, &lt;a href="https://hackmd-velt.vercel.app/" rel="noopener noreferrer"&gt;open the app&lt;/a&gt; in two different browsers or devices. You will see live sync, comments, and presence working in real time.&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%2F6kiq98fa3lve4he7uuby.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%2F6kiq98fa3lve4he7uuby.png" alt="Image5" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Modern tooling changes how fast we can ship collaborative software. AI can drastically accelerate UI replication, allowing you to move from design to production-ready components in minutes. At the same time, collaboration infrastructure no longer needs to be built from scratch. By layering Velt on top of a clean React architecture, you can enable live sync, comments, and presence without managing real-time systems yourself.&lt;/p&gt;

&lt;p&gt;If you’re building collaborative features into your product, explore Velt and see how quickly you can turn a single user interface into a shared workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.velt.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;Velt Documentation&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Studio1HQ/coda.io-velt" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hackmd-velt.vercel.app/" rel="noopener noreferrer"&gt;&lt;strong&gt;Live Demo&lt;/strong&gt;&lt;/a&gt;: Try the application yourself&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>antigravity</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Claude Opus 4.7 seems to use way more tokens than expected</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Wed, 22 Apr 2026 04:35:24 +0000</pubDate>
      <link>https://dev.to/arindam_1729/claude-opus-47-seems-to-use-way-more-tokens-than-expected-2mhd</link>
      <guid>https://dev.to/arindam_1729/claude-opus-47-seems-to-use-way-more-tokens-than-expected-2mhd</guid>
      <description>&lt;p&gt;While playing with Opus 4.7 over the last few days, I noticed that prompts were filling context much faster than I expected.&lt;/p&gt;

&lt;p&gt;I also came across a few measurements from others testing it with real developer inputs like project instructions, git logs, stack traces, and long coding prompts.&lt;/p&gt;

&lt;p&gt;Claude Opus 4.7 seems to use way more tokens than expected&lt;br&gt;
Anthropic mentions the updated tokenizer may produce around 1.0–1.35× more tokens compared to previous models.&lt;/p&gt;

&lt;p&gt;But a lot of the real-world measurements seem closer to ~1.4–1.47× more tokens. Which becomes noticeable pretty quickly if you're running larger contexts.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;context budgets disappear faster&lt;/li&gt;
&lt;li&gt;long-running sessions accumulate tokens much quicker&lt;/li&gt;
&lt;li&gt;effective cost per workflow goes up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not necessarily a bad thing, though.&lt;/p&gt;

&lt;p&gt;I mean, Tokenizer changes are usually made to improve how the model handles code, markdown, structured text, and other developer-heavy inputs. So there’s probably a capability tradeoff happening here.&lt;/p&gt;

&lt;p&gt;I made a short video here walking through the measurements, the tokenizer changes, and what it means in practice, if you want to explore more&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>anthropic</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Claude’s new Advisor Strategy is pretty interesting</title>
      <dc:creator>Arindam Majumder </dc:creator>
      <pubDate>Wed, 15 Apr 2026 20:07:17 +0000</pubDate>
      <link>https://dev.to/arindam_1729/claudes-new-advisor-strategy-is-pretty-interesting-9nb</link>
      <guid>https://dev.to/arindam_1729/claudes-new-advisor-strategy-is-pretty-interesting-9nb</guid>
      <description>&lt;p&gt;A lot of people building AI agents run into the same problem sooner or later.&lt;/p&gt;

&lt;p&gt;If you run the entire agent on a powerful model, it works well but the costs grow quickly. If you run everything on a cheaper model, the system stays fast and affordable but it sometimes makes weak decisions, especially when planning complex tasks or choosing tools.&lt;/p&gt;

&lt;p&gt;Anthropic recently introduced something called Advisor Strategy that tries to solve this in a simple way.&lt;/p&gt;

&lt;p&gt;Instead of using one model for everything, the agent runs on a smaller executor model like Sonnet or Haiku. That model handles the normal workflow such as calling tools, executing steps, and moving the task forward. When the agent reaches something more complex, it can consult a stronger model like Opus for guidance. The advisor reads the full context, suggests what to do next, and the executor continues the workflow.&lt;/p&gt;

&lt;p&gt;So most of the work stays cheap and fast, but the agent can still get strong reasoning when it actually needs it. It feels a lot like how a junior engineer works most of the time but occasionally asks a senior engineer for advice.&lt;/p&gt;

&lt;p&gt;I found this architecture interesting because it pushes agent systems toward multi-model setups instead of relying on a single model for everything, which seems like a direction many frameworks will probably move toward.&lt;/p&gt;

&lt;p&gt;I made a short video breaking down how the advisor strategy works and how developers can implement it in their own agents&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
