<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="https://blog.veladan.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.veladan.org/" rel="alternate" type="text/html" /><updated>2026-07-09T09:22:42+00:00</updated><id>https://blog.veladan.org/feed.xml</id><title type="html">Veladan Programming Blog</title><subtitle>...for all the programming issues I found.</subtitle><entry><title type="html">The Inverted Cost Model: Why Your Orchestrator Should Be the Cheapest Agent</title><link href="https://blog.veladan.org/2026/07/09/inverted-cost-model-opencode.html" rel="alternate" type="text/html" title="The Inverted Cost Model: Why Your Orchestrator Should Be the Cheapest Agent" /><published>2026-07-09T08:00:00+00:00</published><updated>2026-07-09T08:00:00+00:00</updated><id>https://blog.veladan.org/2026/07/09/inverted-cost-model-opencode</id><content type="html" xml:base="https://blog.veladan.org/2026/07/09/inverted-cost-model-opencode.html"><![CDATA[<blockquote>
  <p>I had my multi-agent cost strategy backwards. The orchestrator is your heaviest token consumer, so it should be the cheapest model — not the smartest one.</p>
</blockquote>

<h2 id="the-problem-with-the-obvious-approach">The problem with the obvious approach</h2>

<p>When I first started using orchestration plugins in OpenCode, my instinct was straightforward: use expensive, capable models for the main agents and reserve my local model for simple tasks like search or quick edits.</p>

<p>It makes sense on paper. The orchestrator coordinates everything, so it should be the best model, right?</p>

<p>Wrong. The orchestrator is the model that sees the most tokens. Every subagent response, every file read, every intermediate result passes through it. It consumes orders of magnitude more tokens than any specialist agent because it is always in the loop.</p>

<h2 id="the-inverted-cost-model">The inverted cost model</h2>

<p>The insight is simple: <strong>run your heaviest token consumer locally, and use paid models only where they earn it.</strong></p>

<p>The orchestrator does not need deep reasoning. It needs to plan, delegate, track progress, and reconcile results. A 27B local model handles that surprisingly well. The agents that actually need capability — the ones doing deep analysis, architecture review, or documentation research — consume far fewer tokens because they are called selectively for specific tasks.</p>

<h2 id="real-numbers-from-a-real-session">Real numbers from a real session</h2>

<p>I resolved a complex issue recently. Here are the actual metrics:</p>

<ul>
  <li><strong>342 API calls</strong></li>
  <li><strong>36.7M tokens processed</strong></li>
  <li><strong>Total cost: $0.31</strong></li>
</ul>

<p>The setup: OpenCode with Oh-My-Opencode-slim, running Qwen3.6-27B locally as the orchestrator and fixer. The specialist agents used GLM-5.2 (Oracle), DeepSeek-V4-Flash (Librarian, Explorer), and Kimi K2.7-Code (Designer) through OpenCode Go.</p>

<p>The same session with GLM-5.2 as the orchestrator would have cost <strong>$16.56</strong>.</p>

<p>That is a <strong>53x cost reduction</strong> for the same result. 95% of all tokens were processed locally at zero cost.</p>

<h2 id="how-oh-my-opencode-slim-makes-this-work">How Oh-My-Opencode-slim makes this work</h2>

<p>Oh-My-Opencode-slim is an agent orchestration plugin for OpenCode by Boring Dystopia Development. It defines six specialized agents, each with its own model assignment:</p>

<table>
  <thead>
    <tr>
      <th>Agent</th>
      <th>Role</th>
      <th>My model</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Orchestrator</strong></td>
      <td>Planning, delegation, reconciliation</td>
      <td>Qwen3.6-27B (local)</td>
    </tr>
    <tr>
      <td><strong>Oracle</strong></td>
      <td>Architecture review, deep reasoning</td>
      <td>GLM-5.2 (OpenCode Go)</td>
    </tr>
    <tr>
      <td><strong>Librarian</strong></td>
      <td>Documentation, web research</td>
      <td>DeepSeek-V4-Flash (OpenCode Go)</td>
    </tr>
    <tr>
      <td><strong>Explorer</strong></td>
      <td>Codebase search, grep</td>
      <td>DeepSeek-V4-Flash (OpenCode Go)</td>
    </tr>
    <tr>
      <td><strong>Designer</strong></td>
      <td>UI/UX work</td>
      <td>Kimi K2.7-Code (OpenCode Go)</td>
    </tr>
    <tr>
      <td><strong>Fixer</strong></td>
      <td>Focused implementation tasks</td>
      <td>Qwen3.6-27B (local)</td>
    </tr>
  </tbody>
</table>

<p>The Orchestrator stays in the main session loop, coordinating work and delegating to specialists. The specialists run as background agents — they get their specific context, do the work, and return results. The Orchestrator never sees the full token payload of each specialist’s work; it only sees the summary.</p>

<p>This is the key mechanism that makes the inverted model work: the orchestrator sees everything, but the specialists see only what they need.</p>

<h2 id="why-a-local-27b-model-works-as-orchestrator">Why a local 27B model works as orchestrator</h2>

<p>Qwen3.6-27B running on my RTX PRO 6000 (96 GB VRAM) via vLLM handles the orchestration role well for three reasons:</p>

<ol>
  <li>
    <p><strong>Planning is not the same as reasoning.</strong> The orchestrator’s job is to decompose tasks, track state, and route work. It does not need to solve hard problems — it needs to coordinate people who do.</p>
  </li>
  <li>
    <p><strong>Latency matters.</strong> The orchestrator is called on every turn. A local model responds in milliseconds. A remote API call adds seconds of round-trip time, and that compounds across hundreds of calls in a session.</p>
  </li>
  <li>
    <p><strong>Context window is sufficient.</strong> The orchestrator needs to maintain session state, not reason about a full codebase. 262K context (reduced from 1M for stability) is more than enough.</p>
  </li>
</ol>

<h2 id="adapting-the-opencode-go-preset">Adapting the opencode-go preset</h2>

<p>Oh-My-Opencode-slim ships with an <code class="language-plaintext highlighter-rouge">opencode-go</code> preset designed for cost-efficient setups using OpenCode Go’s low-cost models. The default configuration uses GLM-5.2 for the orchestrator, Qwen3.7-Max for Oracle, DeepSeek-V4-Flash for Librarian/Explorer/Fixer, and Kimi K2.7-Code for Designer.</p>

<p>My configuration adapts it by routing the orchestrator and fixer to my local model — the two biggest token consumers:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"opencode-go"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"orchestrator"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"model"</span><span class="p">:</span><span class="w"> </span><span class="s2">"vllm-pro6000/Qwen3.6-27B"</span><span class="p">,</span><span class="w"> </span><span class="nl">"skills"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"*"</span><span class="p">],</span><span class="w"> </span><span class="nl">"mcps"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"*"</span><span class="p">,</span><span class="w"> </span><span class="s2">"!context7"</span><span class="p">]</span><span class="w"> </span><span class="p">},</span><span class="w">
    </span><span class="nl">"oracle"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"model"</span><span class="p">:</span><span class="w"> </span><span class="s2">"opencode-go/glm-5.2"</span><span class="p">,</span><span class="w"> </span><span class="nl">"skills"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"simplify"</span><span class="p">],</span><span class="w"> </span><span class="nl">"mcps"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">},</span><span class="w">
    </span><span class="nl">"librarian"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"model"</span><span class="p">:</span><span class="w"> </span><span class="s2">"opencode-go/deepseek-v4-flash"</span><span class="p">,</span><span class="w"> </span><span class="nl">"mcps"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"websearch"</span><span class="p">,</span><span class="w"> </span><span class="s2">"context7"</span><span class="p">,</span><span class="w"> </span><span class="s2">"gh_grep"</span><span class="p">]</span><span class="w"> </span><span class="p">},</span><span class="w">
    </span><span class="nl">"explorer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"model"</span><span class="p">:</span><span class="w"> </span><span class="s2">"opencode-go/deepseek-v4-flash"</span><span class="p">,</span><span class="w"> </span><span class="nl">"mcps"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">},</span><span class="w">
    </span><span class="nl">"designer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"model"</span><span class="p">:</span><span class="w"> </span><span class="s2">"opencode-go/kimi-k2.7-code"</span><span class="p">,</span><span class="w"> </span><span class="nl">"mcps"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">},</span><span class="w">
    </span><span class="nl">"fixer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"model"</span><span class="p">:</span><span class="w"> </span><span class="s2">"vllm-pro6000/Qwen3.6-27B"</span><span class="p">,</span><span class="w"> </span><span class="nl">"mcps"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>The change is minimal — two model assignments swapped from remote to local. The effect is dramatic: the orchestrator alone accounts for the majority of token consumption in a session, so making it local eliminates the bulk of the cost.</p>

<p>If you do not have a local GPU, the same principle applies: use the cheapest capable model for the orchestrator. DeepSeek-V4-Flash through OpenCode Go is an excellent option — fast, cheap, and surprisingly competent at planning.</p>

<h2 id="the-rule">The rule</h2>

<p><strong>The orchestrator should be your cheapest, fastest model. The specialists should be your most capable ones.</strong></p>

<p>The orchestrator is a project manager, not an engineer. It delegates, tracks, and reconciles. The Oracle, Librarian, and Designer are the engineers who do the actual work. Give them the best tools. Give the project manager the cheapest desk.</p>

<h2 id="what-i-got-wrong-initially">What I got wrong initially</h2>

<p>My first setup used GLM-5.2 and DeepSeek-V4-Pro as the orchestrator with local models for simple tasks. It worked well but cost $0.71 per session. Flipping the model assignments — local orchestrator, paid specialists — brought it down to $0.31 while actually improving the workflow.</p>

<p>The orchestrator was the bottleneck all along. Not in capability, but in token volume. Every tool call, every file read, every agent response went through it. Making it local eliminated the cost entirely.</p>

<h2 id="setup-requirements">Setup requirements</h2>

<p>This approach needs:</p>

<ul>
  <li><strong>A GPU that can run a 27B model.</strong> My RTX PRO 6000 has 96 GB VRAM, but even a consumer GPU with 24 GB (like the 7900 XTX) can run a 27B model in Q4 quantization.</li>
  <li><strong>vLLM serving the model locally.</strong> I run it via Docker with <code class="language-plaintext highlighter-rouge">gpu-memory-utilization</code> tuned to leave room for KV cache.</li>
  <li><strong>OpenCode with Oh-My-Opencode-slim installed.</strong> The plugin handles all the orchestration logic — you just configure which model goes where.</li>
  <li><strong>OpenCode Go account</strong> for the specialist models (pay-as-you-go, low-cost models).</li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li><a href="https://opencode.ai">OpenCode</a> — The terminal-based coding agent</li>
  <li><a href="https://github.com/alvinunreal/oh-my-opencode-slim">Oh-My-Opencode-slim</a> — Multi-agent orchestration plugin (6.7k stars)</li>
  <li><a href="/2026/06/01/opencode-setup">My previous OpenCode setup post</a> — Full configuration walkthrough</li>
  <li><a href="/2026/06/18/max-blackwell-vllm">RTX PRO 6000 Blackwell setup</a> — Hardware and vLLM configuration</li>
</ul>]]></content><author><name>Daniel Vela</name></author><summary type="html"><![CDATA[I had my multi-agent cost strategy backwards. The orchestrator is your heaviest token consumer, so it should be the cheapest model — not the smartest one.]]></summary></entry><entry><title type="html">Why FP8: Choosing the Right Qwen3.6 Quant for Agentic Coding</title><link href="https://blog.veladan.org/2026/06/29/fp8-quant-choice.html" rel="alternate" type="text/html" title="Why FP8: Choosing the Right Qwen3.6 Quant for Agentic Coding" /><published>2026-06-29T08:00:00+00:00</published><updated>2026-06-29T08:00:00+00:00</updated><id>https://blog.veladan.org/2026/06/29/fp8-quant-choice</id><content type="html" xml:base="https://blog.veladan.org/2026/06/29/fp8-quant-choice.html"><![CDATA[<blockquote>
  <p>I replaced my local model in OpenCode from Qwen3.6-27B to Qwen3.6-35B-A3B in FP8. Here is why, and why the other two options — the smaller 27B and the NVIDIA NVFP4 variant — lost.</p>
</blockquote>

<h1 id="benchmark-setup">Benchmark Setup</h1>

<p>Measured with <a href="https://github.com/danieltvela/llm-race">llm-race</a> using the <strong>multi-agent parallel</strong> workflow:</p>

<blockquote>
  <p>Multiple independent agents running in parallel — 4 agents, 12 queries, 256 prefill tokens, 4096 output tokens. Independent parallel agents with user queries and tool context.</p>
</blockquote>

<p>My homelab workstation (“Tesla”) runs vLLM on a single <strong>NVIDIA RTX PRO 6000 Blackwell</strong> with 96 GB of VRAM, dedicated to me. I use OpenCode with the Oh-My-OpenAgent plugin for agentic coding — multi-step, autonomous, terminal-driven development.</p>

<p>The question was: which Qwen3.6 quant to run locally?</p>

<p><img src="https://blog.veladan.org/assets/benchmarks/qwen3.6/speed.png" alt="Benchmark comparison" /></p>

<h1 id="option-1-qwen36-27b-fp8">Option 1: Qwen3.6-27B-FP8</h1>

<p>The smaller model. Closer to what I already had.</p>

<p><strong>Quality:</strong> marginally lower than 35B on coding benchmarks. Not a dramatic difference, but measurable.</p>

<p><strong>Speed:</strong> roughly <strong>one fifth</strong> the throughput of the 35B. On agentic workflows where the model generates 1000+ token responses, this means waiting three times longer for each turn. In interactive coding, that adds up fast.</p>

<p><strong>Verdict:</strong> slower and not much different in quality. The 35B is worth the extra VRAM.</p>

<h1 id="option-2-nvidias-nvfp4-variant">Option 2: NVIDIA’s NVFP4 Variant</h1>

<p>Theoretically, NVFP4 offers ~2x bandwidth efficiency over FP8. Weights are smaller, transfer is faster. On paper it makes perfect sense.</p>

<p>In practice on Blackwell with vLLM:</p>

<ul>
  <li>The <strong>marlin dequantization kernel consumes exactly what the smaller weights save in transfer</strong>. The theoretical bandwidth advantage evaporates at the dequant step.</li>
  <li>The resulting <strong>TPS difference is ~6%</strong> — roughly 1.26s vs 1.19s for a 1000-token turn. That is invisible in interactive use.</li>
  <li>There is a <strong>measurable quality loss</strong> in coding benchmarks compared to FP8. NVFP4 is a real quant, and even a good one, it still quantizes.</li>
  <li>The <strong>17 GB of VRAM savings</strong> are irrelevant with 96 GB dedicated to a single user. You are not squeezing models onto a shared H100 server — you have the room.</li>
  <li>The <strong>NVIDIA kernels for sm_120 (Blackwell)</strong> are not yet mature. The NVFP4 kernels in vLLM nightly still require dequantization workarounds. The FP8 backend, by contrast, uses native Triton with real hardware FP8 support on Blackwell. Simpler, more mature, fewer edge cases.</li>
</ul>

<p><strong>Verdict:</strong> the 2x bandwidth advantage is theoretical. It does not materialize on Blackwell today, it costs quality, and the kernels are not ready.</p>

<h1 id="option-3-qwen36-35b-a3b-in-fp8">Option 3: Qwen3.6-35B-A3B in FP8</h1>

<p><strong>Quality:</strong> highest of the three. The 35B A3B (active 3B sparse) gives the best coding performance in the family.</p>

<p><strong>Speed:</strong> good. On my hardware it generates tokens at a pace that feels instantaneous during agentic workflows. The ~6% TPS advantage NVFP4 <em>theoretically</em> has over FP8 is not perceptible in practice.</p>

<p><strong>Backend maturity:</strong> FP8 on Blackwell uses Triton natively with real hardware FP8 support. No dequantization workarounds. No nightly kernel hacks. It just works.</p>

<p><strong>VRAM:</strong> 96 GB is plenty for a 35B A3B in FP8. No squeezing, no swapping, no patience-testing context limits.</p>

<h1 id="the-conclusion">The Conclusion</h1>

<p>For this specific setup — <strong>RTX PRO 6000 Blackwell, single-user, agentic coding workflow</strong> — <strong>FP8 is the correct choice</strong>.</p>

<p>NVFP4 makes sense on HBM-equipped hardware (H100/H200) where the bandwidth equation is genuinely different, or when you have native NVFP4 kernels without dequantization in vLLM. Neither condition applies here.</p>

<p>The 27B is slower. The NVFP4 has no real speed advantage and loses quality. The 35B FP8 is the sweet spot — best quality, good speed, mature backend, and VRAM to spare.</p>

<p>I went back to the FP8 recipe I started with. Sometimes the simple answer is the right one.</p>

<p><img src="https://blog.veladan.org/assets/benchmarks/qwen3.6/stats.png" alt="stats comparison" /></p>

<hr />

<p><strong>See also:</strong> <a href="https://blog.veladan.org/2026/06/12/qwen3-6-benchmarks-vllm-recipe.html">Qwen3.6 Benchmarks &amp; vLLM Recipe</a> — the full benchmark suite and Docker setup behind these numbers.</p>]]></content><author><name>Daniel Vela</name></author><summary type="html"><![CDATA[I replaced my local model in OpenCode from Qwen3.6-27B to Qwen3.6-35B-A3B in FP8. Here is why, and why the other two options — the smaller 27B and the NVIDIA NVFP4 variant — lost.]]></summary></entry><entry><title type="html">Pipeline vs S2S: Architecting for Control in Voice Local AI</title><link href="https://blog.veladan.org/2026/06/21/pipeline-vs-s2s.html" rel="alternate" type="text/html" title="Pipeline vs S2S: Architecting for Control in Voice Local AI" /><published>2026-06-21T00:00:00+00:00</published><updated>2026-06-21T00:00:00+00:00</updated><id>https://blog.veladan.org/2026/06/21/pipeline-vs-s2s</id><content type="html" xml:base="https://blog.veladan.org/2026/06/21/pipeline-vs-s2s.html"><![CDATA[<h1 id="why-the-modular-pipeline-is-the-engine-of-production-voice-ai">Why the Modular Pipeline is the Engine of Production Voice AI</h1>

<p>In the rapidly evolving landscape of Speech-to-Speech (S2S) models, the temptation to move toward “native” multimodal models is strong. However, for building robust, production-ready systems, the Modular Pipeline (STT -&gt; LLM -&gt; TTS) remains an engineering powerhouse.</p>

<p>While S2S offers a glimpse into the future of natural interaction, the Modular Pipeline provides the control, flexibility, and hardware-agnosticism required to build professional software.</p>

<div class="container">
  <img src="/assets/pipeline/pipeline.jpg" class="img-fluid border rounded-3 shadow-lg mb-4 img-rounded overflow: hidden; display: inline-block; vertical-align: middle;" alt="Architecture diagram of a modular Voice AI pipeline" width="384" height="576" loading="lazy" />
</div>

<hr />

<h2 id="the-power-of-modular-flexibility">The Power of Modular Flexibility</h2>

<p>The primary reason for choosing a <strong>Pipeline</strong> architecture is the ability to decouple components. In AI, the “state-of-the-art” changes every week. A modular approach allows for:</p>

<ul>
  <li><strong>Hot-swappable Models:</strong> Need a faster STT for a specific region? Swap it. Want to use a smaller, local MoE model for low-latency reasoning? Swap the LLM.</li>
  <li><strong>Hardware Heterogeneity:</strong> AI is not a monolith. A production environment might span from Mac Minis (optimized for different architectures) to DGX clusters with high-end CUDA support. A pipeline allows you to optimize each step for the specific hardware it runs on.</li>
</ul>

<h2 id="resource-efficiency-the-key-to-local-deployment">Resource Efficiency: The Key to Local Deployment</h2>

<p>One of the most critical advantages of the <strong>Pipeline</strong> is its footprint. A native S2S model must handle voice decoding, LLM reasoning, and audio synthesis simultaneously, often resulting in a model size and compute requirement nearly equal to the sum of all three components.</p>

<p>In a Pipeline, tasks are decoupled. The STT can run independently while the LLM and TTS are idle, significantly lowering the hardware overhead for that specific task. While the LLM and TTS may overlap during generation, this can be minimized by using short-response prompts.</p>

<p>This surgical separation of concerns is what makes running a high-quality Voicebot on your own hardware—privately and locally—feasible. It allows for a level of optimization that monolithic models simply cannot match.</p>

<div class="container">
  <img src="/assets/pipeline/resource-efficiency.jpg" class="img-fluid border rounded-3 shadow-lg mb-4 img-rounded overflow: hidden; display: inline-block; vertical-align: middle;" alt="Visualizing the hardware efficiency of decoupled tasks" width="350" height="250" loading="lazy" />
</div>

<h2 id="the-intermediate-space-the-hidden-superpower">The “Intermediate Space”: The Hidden Superpower</h2>

<p>One of the most overlooked advantages of the Pipeline is the “space” between the STT and the LLM. This isn’t just a latency cost; it’s a processing opportunity. By intercepting the text stream, we can perform:</p>

<ol>
  <li><strong>Speaker Identification:</strong> Knowing <em>who</em> is talking before the LLM even sees the prompt.</li>
  <li><strong>Keyword Forcing:</strong> Identifying specific triggers (like “search” or “investigate”) to force specific tool calls or logic paths.</li>
  <li><strong>Wakeword Management:</strong> Implementing robust wake-up logic that is nearly impossible to handle reliably in a continuous S2S stream.</li>
</ol>

<h2 id="engineering-for-immediacy-beating-the-latency-gap">Engineering for Immediacy: Beating the Latency Gap</h2>

<p>To compete with native S2S latency, we employ three specific engineering tactics that maximize the efficiency of the Pipeline:</p>

<h3 id="1-concurrent-transcription">1. Concurrent Transcription</h3>
<p>For the STT to be truly efficient, transcription must occur <strong>while</strong> the user is speaking. The objective is to have the text ready by the moment the Voice Activity Detection (VAD) identifies the end of speech. This requires an STT model capable of keeping pace with human speech in real-time, ensuring the system doesn’t feel like it’s “waiting” for the user to finish.</p>

<h3 id="2-prioritizing-time-to-first-token-tftt">2. Prioritizing Time to First Token (TFTT)</h3>
<p>In our architecture, the paramount metric for the LLM is <strong>TFTT</strong>. Because user prompts are typically concise, high throughput (Tokens Per Second) is less critical than starting the response immediately. A steady 50 tokens/s is more than sufficient because we don’t need to generate massive paragraphs instantly; we just need to start the “flow” of conversation as quickly as possible.</p>

<h3 id="3-the-immediacy-tricks">3. The Immediacy Tricks</h3>
<p>We use two clever tricks to create a sense of instantaneity:</p>
<ul>
  <li><strong>Prompt Engineering:</strong> We instruct the LLM to begin its responses with short, affirmative anchors like <em>“Yes,”</em> <em>“Agreed,”</em> or <em>“Let’s go.”</em> This provides an immediate conversational hook.</li>
  <li><strong>Sentence Parsing:</strong> We implement a parser that splits the LLM’s text stream by punctuation (commas and periods). As soon as the parser detects a complete phrase, it fires the TTS engine. This allows the system to start speaking the first part of the answer while the LLM is still generating the remainder of the message.</li>
</ul>

<div class="container">
  <img src="/assets/pipeline/ai-agent.jpg" class="img-fluid border rounded-3 shadow-lg mb-4 img-rounded overflow: hidden; display: inline-block; vertical-align: middle;" alt="A conceptual visualization of an AI agent processing keywords to trigger specific tools" width="384" height="576" loading="lazy" />
</div>

<h2 id="handling-the-human-side-barge-in-and-emotion">Handling the “Human” Side: Barge-in and Emotion</h2>

<p>A common critique of the Pipeline is the loss of emotional prosody and the latency of sequential steps. However, these are solvable engineering problems:</p>

<ul>
  <li><strong>Barge-in:</strong> Because we manage the threads, we can instantly kill a TTS playback or an LLM generation the moment the STT detects the user has started speaking again. This is crucial for natural flow.</li>
  <li><strong>Emotion Tagging:</strong> We don’t need a native S2S model to “feel” emotion. By using an STT that detects sentiment and passing that as a metadata tag (e.g., <code class="language-plaintext highlighter-rouge">[User](sad) I don't know what to do today</code>), the LLM can still generate a contextually aware, empathetic response.</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>S2S is a marvel of research, but the <strong>Pipeline</strong> is a masterclass in engineering. It trades a small amount of native latency for a massive amount of control, debuggability, and production reliability. For anyone building a Voicebot that needs to do more than just “chat”—that needs to <em>act</em>—the Pipeline is the way to go.</p>

<hr />

<p><strong>Follow the project on Twitter:</strong> <a href="https://x.com/danieltvela/status/2033972678197997743">Voicebot updates</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Why the Modular Pipeline remains the king of production local Voicebots over native Speech-to-Speech.]]></summary></entry><entry><title type="html">Maximizing the NVIDIA PRO 6000 Blackwell for Multi-Agent Workflows</title><link href="https://blog.veladan.org/ai,/hardware/2026/06/18/max-blackwell-vllm.html" rel="alternate" type="text/html" title="Maximizing the NVIDIA PRO 6000 Blackwell for Multi-Agent Workflows" /><published>2026-06-18T00:00:00+00:00</published><updated>2026-06-18T00:00:00+00:00</updated><id>https://blog.veladan.org/ai,/hardware/2026/06/18/max-blackwell-vllm</id><content type="html" xml:base="https://blog.veladan.org/ai,/hardware/2026/06/18/max-blackwell-vllm.html"><![CDATA[<h1 id="maximizing-the-nvidia-pro-6000-blackwell-for-multi-agent-workflows">Maximizing the NVIDIA PRO 6000 Blackwell for Multi-Agent Workflows</h1>

<p><img src="https://blog.veladan.org/assets/pro6000/rtx-pro-6000.jpeg" alt="NVIDIA PRO 6000 Blackwell GPU" /></p>

<p>Running powerful AI models locally requires a careful balance of VRAM management, quantization techniques, and inference engine optimization. With my <strong>NVIDIA PRO 6000 Blackwell AI Workstation Max-Q (96GB)</strong>, I’ve managed to find a “sweet spot” configuration that allows me to run two of my favorite high-performance models simultaneously for different purposes.</p>

<h2 id="the-setup">The Setup</h2>

<p>I currently run two distinct vLLM instances to power my primary AI workflows:</p>

<ol>
  <li><strong>For OpenCode (Programming):</strong> I use <code class="language-plaintext highlighter-rouge">Qwen3.6-27B-FP8</code>. This model is <strong>exceptional for coding tasks</strong>, and the FP8 quantization allows it to run efficiently while maintaining high precision for complex logic.</li>
  <li><strong>For Hermes Agent (General &amp; Reasoning):</strong> I use <code class="language-plaintext highlighter-rouge">gemma-4-12B-it-qat-int4</code>. This model is incredibly nimble and offers great reasoning capabilities for my agentic workflows.</li>
</ol>

<p>By balancing the <code class="language-plaintext highlighter-rouge">gpu-memory-utilization</code> between these two services, I can keep both models active and responsive in the same environment without OOM (Out of Memory) errors.</p>

<p><img src="https://blog.veladan.org/assets/pro6000/multi-ai-agent.jpg" alt="Multi-agent system architecture" /></p>

<h2 id="how-i-launch-the-services">How I Launch the Services</h2>

<p>I manage these deployments using Docker Compose. The core of the setup involves two separate vLLM containers with specific configurations tailored for each model’s requirements (such as specific KV-cache types and max sequence lengths).</p>

<p>You can find the full configuration in my <code class="language-plaintext highlighter-rouge">docker-compose.yml</code> file:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># vLLM for Qwen3.6-27B-FP8</span>
  <span class="na">vllm-qwen</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">vllm/vllm-openai:latest</span>
    <span class="na">runtime</span><span class="pi">:</span> <span class="s">nvidia</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">unless-stopped</span>
    <span class="na">shm_size</span><span class="pi">:</span> <span class="s2">"</span><span class="s">32G"</span>
    <span class="na">privileged</span><span class="pi">:</span> <span class="no">true</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">VLLM_LOGGING_LEVEL=info</span>
      <span class="pi">-</span> <span class="s">VLLM_HOST_IP=0.0.0.0</span>
      <span class="pi">-</span> <span class="s">HF_HOME=/root/.cache/huggingface</span>
      <span class="pi">-</span> <span class="s">HF_TOKEN=hf_....baA</span>
      <span class="pi">-</span> <span class="s">FLASHINFER_DISABLE_VERSION_CHECK=1</span>
      <span class="pi">-</span> <span class="s">FLASHINFER_CUDA_ARCH_LIST=12.0f</span>
      <span class="pi">-</span> <span class="s">VLLM_MOE_FORCE_MARLIN=1</span>
      <span class="pi">-</span> <span class="s">CUTE_DSL_ARCH=sm_120a</span>
      <span class="pi">-</span> <span class="s">PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True</span>
      <span class="pi">-</span> <span class="s">VLLM_ALLOW_LONG_MAX_MODEL_LEN=1</span>
      <span class="pi">-</span> <span class="s">TRANSFORMERS_VERBOSITY=warning</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./huggingface:/root/.cache/huggingface</span>
      <span class="pi">-</span> <span class="s">./vllm_cache:/root/.cache/vllm</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8005:8000"</span>
    <span class="na">command</span><span class="pi">:</span> <span class="pi">&gt;</span>
      <span class="s">Qwen/Qwen3.6-27B-FP8</span>
      <span class="s">--served-model-name Qwen3.6-27B-FP8</span>
      <span class="s">--trust-remote-code</span>
      <span class="s">--host 0.0.0.0</span>
      <span class="s">--port 8000</span>
      <span class="s">--tensor-parallel-size 1</span>
      <span class="s">--kv-cache-dtype fp8_e4m3</span>
      <span class="s">--gpu-memory-utilization 0.70</span>
      <span class="s">--max-model-len 262144</span>
      <span class="s">--max-num-seqs 16</span>
      <span class="s">--max-num-batched-tokens 32768</span>
      <span class="s">--enable-chunked-prefill</span>
      <span class="s">--async-scheduling</span>
      <span class="s">--reasoning-parser qwen3</span>
      <span class="s">--enable-auto-tool-choice</span>
      <span class="s">--tool-call-parser qwen3_coder</span>
      <span class="s">--mm-encoder-tp-mode data</span>
      <span class="s">--default-chat-template-kwargs '{"enable_thinking": true, "preserve_thinking": true}'</span>
      <span class="s">--speculative-config '{"method":"mtp","num_speculative_tokens":1}'</span>
      <span class="s">--override-generation-config '{"temperature":0.6,"top_p":0.95,"presence_penalty":0.05,"repetition_penalty":1.05}'</span>
      <span class="s">--language-model-only</span>
      <span class="s">-O3</span>
    <span class="na">deploy</span><span class="pi">:</span>
      <span class="na">resources</span><span class="pi">:</span>
        <span class="na">reservations</span><span class="pi">:</span>
          <span class="na">devices</span><span class="pi">:</span>
            <span class="pi">-</span> <span class="na">driver</span><span class="pi">:</span> <span class="s">nvidia</span>
              <span class="na">count</span><span class="pi">:</span> <span class="m">1</span>
              <span class="na">capabilities</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">gpu</span><span class="pi">]</span>
    <span class="na">healthcheck</span><span class="pi">:</span>
      <span class="na">test</span><span class="pi">:</span> <span class="pi">[</span><span class="s2">"</span><span class="s">CMD"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">curl"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">-f"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">http://localhost:8000/health"</span><span class="pi">]</span>
      <span class="na">interval</span><span class="pi">:</span> <span class="s">30s</span>
      <span class="na">timeout</span><span class="pi">:</span> <span class="s">10s</span>
      <span class="na">retries</span><span class="pi">:</span> <span class="m">5</span>
      <span class="na">start_period</span><span class="pi">:</span> <span class="s">120s</span>
    <span class="na">logging</span><span class="pi">:</span>
      <span class="na">driver</span><span class="pi">:</span> <span class="s2">"</span><span class="s">json-file"</span>
      <span class="na">options</span><span class="pi">:</span>
        <span class="na">max-size</span><span class="pi">:</span> <span class="s2">"</span><span class="s">20m"</span>
        <span class="na">max-file</span><span class="pi">:</span> <span class="s2">"</span><span class="s">5"</span>

<span class="c1"># vLLM for gemma-4-12B-it-qat-int4</span>
  <span class="na">vllm-gemma</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">vllm/vllm-openai:latest</span>
    <span class="na">runtime</span><span class="pi">:</span> <span class="s">nvidia</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">unless-stopped</span>
    <span class="na">shm_size</span><span class="pi">:</span> <span class="s">16g</span>
    <span class="na">privileged</span><span class="pi">:</span> <span class="no">true</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">VLLM_LOGGING_LEVEL=info</span>
      <span class="pi">-</span> <span class="s">VLLM_HOST_IP=0.0.0.0</span>
      <span class="pi">-</span> <span class="s">HF_HOME=/root/.cache/huggingface</span>
      <span class="pi">-</span> <span class="s">PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True</span>
      <span class="pi">-</span> <span class="s">HF_TOKEN=hf_....baA</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./huggingface:/root/.cache/huggingface</span>
      <span class="pi">-</span> <span class="s">./vllm_cache:/root/.cache/vllm</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8006:8000"</span>
    <span class="na">command</span><span class="pi">:</span> <span class="pi">&gt;</span>
      <span class="s">google/gemma-4-12B-it-qat-w4a16-ct</span>
      <span class="s">--served-model-name gemma-4-12B-it-qat-int4</span>
      <span class="s">--tensor-parallel-size 1</span>
      <span class="s">--max-num-batched-tokens 8192</span>
      <span class="s">--gpu-memory-utilization 0.25</span>
      <span class="s">--kv-cache-dtype fp8</span>
      <span class="s">--max-num-seqs 1</span>
      <span class="s">--max-model-len 131072</span>
      <span class="s">--enable-auto-tool-choice</span>
      <span class="s">--tool-call-parser gemma4</span>
      <span class="s">--chat-template examples/tool_chat_template_gemma4.jinja</span>
      <span class="s">--reasoning-parser gemma4</span>
      <span class="s">--async-scheduling</span>
      <span class="s">--language-model-only</span>
      <span class="s">--speculative-config '{"model":"google/gemma-4-12B-it-assistant","num_speculative_tokens":4}'</span>
      <span class="s">-O3</span>
    <span class="na">deploy</span><span class="pi">:</span>
      <span class="na">resources</span><span class="pi">:</span>
        <span class="na">reservations</span><span class="pi">:</span>
          <span class="na">devices</span><span class="pi">:</span>
            <span class="pi">-</span> <span class="na">driver</span><span class="pi">:</span> <span class="s">nvidia</span>
              <span class="na">count</span><span class="pi">:</span> <span class="m">1</span>
              <span class="na">capabilities</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">gpu</span><span class="pi">]</span>
    <span class="na">healthcheck</span><span class="pi">:</span>
      <span class="na">test</span><span class="pi">:</span> <span class="pi">[</span><span class="s2">"</span><span class="s">CMD"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">curl"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">-f"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">http://localhost:8000/health"</span><span class="pi">]</span>
      <span class="na">interval</span><span class="pi">:</span> <span class="s">30s</span>
      <span class="na">timeout</span><span class="pi">:</span> <span class="s">10s</span>
      <span class="na">retries</span><span class="pi">:</span> <span class="m">5</span>
      <span class="na">start_period</span><span class="pi">:</span> <span class="s">120s</span>
    <span class="na">logging</span><span class="pi">:</span>
      <span class="na">driver</span><span class="pi">:</span> <span class="s2">"</span><span class="s">json-file"</span>
      <span class="na">options</span><span class="pi">:</span>
        <span class="na">max-size</span><span class="pi">:</span> <span class="s2">"</span><span class="s">20m"</span>
        <span class="na">max-file</span><span class="pi">:</span> <span class="s2">"</span><span class="s">5"</span>
</code></pre></div></div>

<p>This configuration represents the best way I’ve found so far to maximize the potential of my Blackwell hardware, providing a robust backend for both coding-heavy automation and general-purpose AI agency.</p>]]></content><author><name></name></author><category term="AI," /><category term="Hardware" /><category term="LLM" /><category term="vLLM" /><category term="Multi-Agent" /><category term="Hardware" /><summary type="html"><![CDATA[Maximizing the NVIDIA PRO 6000 Blackwell for Multi-Agent Workflows]]></summary></entry><entry><title type="html">Benchmarking Qwen3.6 Variants for OpenCode on NVIDIA RTX PRO 6000 Blackwell</title><link href="https://blog.veladan.org/2026/06/12/qwen3-6-benchmarks-vllm-recipe.html" rel="alternate" type="text/html" title="Benchmarking Qwen3.6 Variants for OpenCode on NVIDIA RTX PRO 6000 Blackwell" /><published>2026-06-12T00:00:00+00:00</published><updated>2026-06-12T00:00:00+00:00</updated><id>https://blog.veladan.org/2026/06/12/qwen3-6-benchmarks-vllm-recipe</id><content type="html" xml:base="https://blog.veladan.org/2026/06/12/qwen3-6-benchmarks-vllm-recipe.html"><![CDATA[<p>Yesterday, I conducted a series of local benchmarks using <a href="https://github.com/stevibe/BenchLocal"><strong>BenchLocal.app</strong></a> and a custom voicebot script. The goal was to evaluate different <strong>Qwen3.6</strong> variants to determine the best candidate for the OpenCode project.</p>

<p>The tests were performed on an <strong>NVIDIA RTX PRO 6000 Blackwell Max-Q</strong> GPU. Below are the results for the four models evaluated.</p>

<h2 id="benchmark-results">Benchmark Results</h2>

<h3 id="1-qwenqwen36-35b-a3b-fp8">1. Qwen/Qwen3.6-35B-A3B-FP8</h3>

<table>
  <thead>
    <tr>
      <th style="text-align: left"><strong>BenchLocal.app Results</strong></th>
      <th style="text-align: left"><strong>Performance &amp; Voicebot Metrics</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><strong>Score:</strong> 86.6</td>
      <td style="text-align: left"><strong>PP:</strong> 958 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>ToolCall:</strong> 100</td>
      <td style="text-align: left"><strong>TTFT (warm):</strong> 64ms</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>InstrucFollow:</strong> 90</td>
      <td style="text-align: left"><strong>TG:</strong> 194.1 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>DataExtract:</strong> 86</td>
      <td style="text-align: left"><strong>Voicebot:</strong> 80% (279ms)</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>BugFind:</strong> 84</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>HermesAgent:</strong> 73</td>
      <td style="text-align: left"><strong>Metrics:</strong> 5/6, 7/7, 5/9, 3/4, 4/4, 4/4, 1/3, 4/4</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-35B-A3B-FP8/benchlocal-bugfind-15-qwen3-6-35b-a3b-fp8.png" alt="BugFind" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-35B-A3B-FP8/benchlocal-dataextract-15-qwen3-6-35b-a3b-fp8.png" alt="DataExtract" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-35B-A3B-FP8/benchlocal-hermesagent-20-qwen3-6-35b-a3b-fp8.png" alt="HermesAgent" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-35B-A3B-FP8/benchlocal-instructfollow-15-qwen3-6-35b-a3b-fp8.png" alt="InstrucFollow" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-35B-A3B-FP8/benchlocal-toolcall-15-qwen3-6-35b-a3b-fp8.png" alt="ToolCall" /></td>
      <td> </td>
    </tr>
  </tbody>
</table>

<hr />

<h3 id="2-nvidiaqwen36-35b-a3b-nvfp4">2. nvidia/Qwen3.6-35B-A3B-NVFP4</h3>

<table>
  <thead>
    <tr>
      <th style="text-align: left">BenchLocal.app Results</th>
      <th style="text-align: left">Performance &amp; Voicebot Metrics</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><strong>Score:</strong> 84.4</td>
      <td style="text-align: left"><strong>PP:</strong> 1354 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>ToolCall:</strong> 97</td>
      <td style="text-align: left"><strong>TTFT (warm):</strong> 67ms</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>InstrucFollow:</strong> 98</td>
      <td style="text-align: left"><strong>TG:</strong> 230.6 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>DataExtract:</strong> 85</td>
      <td style="text-align: left"><strong>Voicebot:</strong> 82% (211ms)</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>BugFind:</strong> 84</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>HermesAgent:</strong> 58</td>
      <td style="text-align: left"><strong>Metrics:</strong> 5/6, 7/7, 6/9, 2/4, 4/4, 4/4, 2/3, 4/4</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/nvidia-Qwen3.6-35B-A3B-NVFP4/benchlocal-bugfind-15-qwen3-6-35b-a3b-nvfp4.png" alt="BugFind" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/nvidia-Qwen3.6-35B-A3B-NVFP4/benchlocal-dataextract-15-qwen3-6-35b-a3b-nvfp4.png" alt="DataExtract" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/nvidia-Qwen3.6-35B-A3B-NVFP4/benchlocal-hermesagent-20-qwen3-6-35b-a3b-nvfp4.png" alt="HermesAgent" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/nvidia-Qwen3.6-35B-A3B-NVFP4/benchlocal-instructfollow-15-qwen3-6-35b-a3b-nvfp4.png" alt="InstrucFollow" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/nvidia-Qwen3.6-35B-A3B-NVFP4/benchlocal-toolcall-15-qwen3-6-35b-a3b-nvfp4.png" alt="ToolCall" /></td>
      <td> </td>
    </tr>
  </tbody>
</table>

<hr />

<h3 id="3-qwenqwen36-27b-fp8">3. Qwen/Qwen3.6-27B-FP8</h3>

<table>
  <thead>
    <tr>
      <th style="text-align: left">BenchLocal.app Results</th>
      <th style="text-align: left">Performance &amp; Voicebot Metrics</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><strong>Score:</strong> 86.2</td>
      <td style="text-align: left"><strong>PP:</strong> 3847 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>ToolCall:</strong> 97</td>
      <td style="text-align: left"><strong>TTFT (warm):</strong> 222ms</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>InstrucFollow:</strong> 97</td>
      <td style="text-align: left"><strong>TG:</strong> 82.0 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>DataExtract:</strong> 85</td>
      <td style="text-align: left"><strong>Voicebot:</strong> 85% (729ms)</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>BugFind:</strong> 90</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>HermesAgent:</strong> 62</td>
      <td style="text-align: left"><strong>Metrics:</strong> 6/6, 7/7, 8/9, 3/4, 4/4, 2/4, 2/3, 3/4</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-27B-FP8/benchlocal-bugfind-15-qwen-qwen3-6-27b-fp8.png" alt="BugFind" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-27B-FP8/benchlocal-dataextract-15-qwen-qwen3-6-27b-fp8.png" alt="DataExtract" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-27B-FP8/benchlocal-hermesagent-20-qwen-qwen3-6-27b-fp8.png" alt="HermesAgent" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-27B-FP8/benchlocal-instructfollow-15-qwen-qwen3-6-27b-fp8.png" alt="InstrucFollow" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/qwen-qwen3.6-27B-FP8/benchlocal-toolcall-15-qwen-qwen3-6-27b-fp8.png" alt="ToolCall" /></td>
      <td> </td>
    </tr>
  </tbody>
</table>

<hr />

<h3 id="4-sakamakismilehuihui-qwen36-27b-abliterated-nvfp4-mtp">4. sakamakismile/Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP</h3>

<table>
  <thead>
    <tr>
      <th style="text-align: left">BenchLocal.app Results</th>
      <th style="text-align: left">Performance &amp; Voicebot Metrics</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><strong>Score:</strong> 83.4</td>
      <td style="text-align: left"><strong>PP:</strong> 5465 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>ToolCall:</strong> 90</td>
      <td style="text-align: left"><strong>TTFT (warm):</strong> 153ms</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>InstrucFollow:</strong> 97</td>
      <td style="text-align: left"><strong>TG:</strong> 105 t/s</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>DataExtract:</strong> 82</td>
      <td style="text-align: left"><strong>Voicebot:</strong> 78% (679ms)</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>BugFind:</strong> 95</td>
      <td style="text-align: left"> </td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>HermesAgent:</strong> 53</td>
      <td style="text-align: left"><strong>Metrics:</strong> 5/6, 7/7, 7/9, 3/4, 3/4, 2/4, 1/3, 4/4</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/sakamakismile-Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP/benchlocal-bugfind-15-sakamakismile-huihui-qwen3-6-27b-abliterated-nvfp4-mtp.png" alt="BugFind" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/sakamakismile-Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP/benchlocal-dataextract-15-sakamakismile-huihui-qwen3-6-27b-abliterated-nvfp4-mtp.png" alt="DataExtract" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/sakamakismile-Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP/benchlocal-hermesagent-20-sakamakismile-huihui-qwen3-6-27b-abliterated-nvfp4-mtp.png" alt="HermesAgent" /></td>
      <td><img src="https://blog.veladan.org/assets/benchmarks/sakamakismile-Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP/benchlocal-instructfollow-15-sakamakismile-huihui-qwen3-6-27b-abliterated-nvfp4-.png" alt="InstrucFollow" /></td>
    </tr>
    <tr>
      <td><img src="https://blog.veladan.org/assets/benchmarks/sakamakismile-Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP/benchlocal-toolcall-15-sakamakismile-huihui-qwen3-6-27b-abliterated-nvfp4-mtp.png" alt="ToolCall" /></td>
      <td> </td>
    </tr>
  </tbody>
</table>

<h2 id="vllm-deployment-recipe">vLLM Deployment Recipe</h2>

<p>To launch the <code class="language-plaintext highlighter-rouge">Qwen/Qwen3.6-35B-A3B-FP8</code> variant on Blackwell hardware, use the following Docker Compose configuration. Note the <code class="language-plaintext highlighter-rouge">flashinfer</code> attention backend required for FP8 KV cache support.</p>

<p>Other models require different recipies.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">services</span><span class="pi">:</span>
  <span class="na">vllm</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s2">"</span><span class="s">vllm/vllm-openai:nightly"</span>
    <span class="na">runtime</span><span class="pi">:</span> <span class="s">nvidia</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">unless-stopped</span>
    <span class="na">ipc</span><span class="pi">:</span> <span class="s">host</span>
    <span class="na">shm_size</span><span class="pi">:</span> <span class="s2">"</span><span class="s">32G"</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">VLLM_LOGGING_LEVEL=info</span>
      <span class="pi">-</span> <span class="s">VLLM_HOST_IP=0.0.0.0</span>
      <span class="pi">-</span> <span class="s">HF_HOME=/root/.cache/huggingface</span>
      <span class="pi">-</span> <span class="s">HF_TOKEN=hf_Il....KbaA</span>
      <span class="pi">-</span> <span class="s">FLASHINFER_DISABLE_VERSION_CHECK=1</span>
      <span class="pi">-</span> <span class="s">FLASHINFER_CUDA_ARCH_LIST=12.0f</span>
      <span class="pi">-</span> <span class="s">VLLM_MOE_FORCE_MARLIN=1</span>
      <span class="pi">-</span> <span class="s">CUTE_DSL_ARCH=sm_120a</span>
      <span class="pi">-</span> <span class="s">PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True</span>
      <span class="pi">-</span> <span class="s">VLLM_ALLOW_LONG_MAX_MODEL_LEN=1</span>
      <span class="pi">-</span> <span class="s">TRANSFORMERS_VERBOSITY=warning</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./llama-server/huggingface:/root/.cache/huggingface</span>
      <span class="pi">-</span> <span class="s">./llama-server/vllm_cache:/root/.cache/vllm</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">8000:8000"</span>
    <span class="na">command</span><span class="pi">:</span> <span class="pi">&gt;</span>
      <span class="s">Qwen/Qwen3.6-35B-A3B-FP8</span>
      <span class="s">--served-model-name Qwen3.6-35B-A3B-FP8</span>
      <span class="s">--trust-remote-code</span>
      <span class="s">--host 0.0.0.0</span>
      <span class="s">--port 8000</span>
      <span class="s">--tensor-parallel-size 1</span>
      <span class="s">--dtype auto</span>
      <span class="s">--kv-cache-dtype fp8_e4m3</span>
      <span class="s">--attention-backend flashinfer</span>
      <span class="s">--moe-backend marlin</span>
      <span class="s">--gpu-memory-utilization 0.96</span>
      <span class="s">--max-model-len 262144</span>
      <span class="s">--max-num-seqs 32</span>
      <span class="s">--max-num-batched-tokens 65536</span>
      <span class="s">--enable-chunked-prefill</span>
      <span class="s">--enable-prefix-caching</span>
      <span class="s">--async-scheduling</span>
      <span class="s">--reasoning-parser qwen3</span>
      <span class="s">--enable-auto-tool-choice</span>
      <span class="s">--tool-call-parser qwen3_coder</span>
      <span class="s">--structured-outputs-config.backend xgrammar</span>
      <span class="s">--default-chat-template-kwargs '{"enable_thinking": true, "preserve_thinking": true}'</span>
      <span class="s">--speculative-config '{"method":"mtp","num_speculative_tokens":2,"moe_backend":"triton"}'</span>
      <span class="s">--override-generation-config '{"temperature":0.6,"top_p":0.95,"presence_penalty":0.05,"repetition_penalty":1.05}'</span>
      <span class="s">--language-model-only</span>
      <span class="s">-O3</span>
    <span class="na">deploy</span><span class="pi">:</span>
      <span class="na">resources</span><span class="pi">:</span>
        <span class="na">reservations</span><span class="pi">:</span>
          <span class="na">devices</span><span class="pi">:</span>
            <span class="pi">-</span> <span class="na">driver</span><span class="pi">:</span> <span class="s">nvidia</span>
              <span class="na">count</span><span class="pi">:</span> <span class="m">1</span>
              <span class="na">capabilities</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">gpu</span><span class="pi">]</span>
    <span class="na">healthcheck</span><span class="pi">:</span>
      <span class="na">test</span><span class="pi">:</span> <span class="pi">[</span><span class="s2">"</span><span class="s">CMD"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">curl"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">-f"</span><span class="pi">,</span> <span class="s2">"</span><span class="s">http://localhost:8000/health"</span><span class="pi">]</span>
      <span class="na">interval</span><span class="pi">:</span> <span class="s">30s</span>
      <span class="na">timeout</span><span class="pi">:</span> <span class="s">10s</span>
      <span class="na">retries</span><span class="pi">:</span> <span class="m">5</span>
      <span class="na">start_period</span><span class="pi">:</span> <span class="s">120s</span>
    <span class="na">logging</span><span class="pi">:</span>
      <span class="na">driver</span><span class="pi">:</span> <span class="s2">"</span><span class="s">json-file"</span>
      <span class="na">options</span><span class="pi">:</span>
        <span class="na">max-size</span><span class="pi">:</span> <span class="s2">"</span><span class="s">20m"</span>
        <span class="na">max-file</span><span class="pi">:</span> <span class="s2">"</span><span class="s">5"</span>
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[Yesterday, I conducted a series of local benchmarks using BenchLocal.app and a custom voicebot script. The goal was to evaluate different Qwen3.6 variants to determine the best candidate for the OpenCode project.]]></summary></entry><entry><title type="html">The 6 Phases of a Programmer’s Adaptation to AI</title><link href="https://blog.veladan.org/2026/06/07/the-6-phases-of-programmers-adaptation-to-ai.html" rel="alternate" type="text/html" title="The 6 Phases of a Programmer’s Adaptation to AI" /><published>2026-06-07T00:00:00+00:00</published><updated>2026-06-07T00:00:00+00:00</updated><id>https://blog.veladan.org/2026/06/07/the-6-phases-of-programmers-adaptation-to-ai</id><content type="html" xml:base="https://blog.veladan.org/2026/06/07/the-6-phases-of-programmers-adaptation-to-ai.html"><![CDATA[<h2 id="the-6-phases-of-a-programmers-adaptation-to-ai">The 6 Phases of a Programmer’s Adaptation to AI</h2>

<h2 id="phase-1-curiosity-and-manual-copy-pasting">Phase 1: Curiosity and Manual Copy-Pasting</h2>

<p>It all starts with curiosity. You download a local LLM, open a chat, and start asking it things. You copy answers by hand. Sometimes they work, sometimes they don’t. But curiosity is enough to keep you interested.</p>

<p>The flow is simple: you think, the model responds, you copy. There’s no automation, no integration. It’s like having a pair programming partner who talks slowly and hallucinates sometimes. But it’s enough to experiment.</p>

<h2 id="phase-2-frustration">Phase 2: Frustration</h2>

<p>Then comes the reality check. Small local models promise a lot but deliver very little. They generate code that looks fine but has subtle bugs. They break imports. They forget contexts. Productivity drops below what you’d have without AI.</p>

<p>This is the “AI slop” phase: generated code nobody understands, nobody trusts, and nobody wants to maintain. You start doubting. Is this worth it? Or are we just playing with expensive toys?</p>

<h2 id="phase-3-the-qualitative-leap">Phase 3: The Qualitative Leap</h2>

<p>Then comes the moment when something changes. A new model, a leap in reasoning quality, and suddenly things start working. Not everything, but enough for the friction to disappear.</p>

<p>It’s like when you went from writing code by memorizing syntax to understanding what you wanted to express. The tool disappears and what remains is the work.</p>

<h2 id="phase-4-the-virtual-team-illusion">Phase 4: The Virtual Team Illusion</h2>

<p>Once you trust agents, the natural instinct is to replicate what you already know: teams with roles. You create a “PM” agent that plans, a “dev” agent that codes, a “QA” agent that tests. It seems natural. It makes sense.</p>

<p>But soon you discover it doesn’t work. Agents aren’t people. They don’t need functional role divisions — they need <em>cognitive depth</em> divisions. It’s not that one “plans” and another “codes”. It’s that some tasks require deep reasoning while others require mechanical execution.</p>

<p>The most common mistake is treating agents as mini-people. They aren’t. They’re tools with different levels of power. And mixing them for organizational convenience rather than cognitive necessity is the perfect recipe for chaos.</p>

<h2 id="phase-5-the-man-in-the-middle-trap">Phase 5: The “Man-in-the-Middle” Trap</h2>

<p>When the virtual team illusion collapses, many programmers fall into the opposite trap: reviewing everything. Every diff, every line, every decision. At first it seems responsible. You’re being careful.</p>

<p>But soon you discover the paradox: while the agent works, you do nothing. When you work (reviewing), the agent is idle. You’re creating a human bottleneck where there shouldn’t be one.</p>

<p>Productivity doesn’t scale because the human becomes the limiting factor of the system. And the more you trust the agent, the more frustrating it becomes to have to review its work. It’s like having a Ferrari and driving at 30 km/h.</p>

<h2 id="phase-6-automated-validation-strategic-oversight">Phase 6: Automated Validation, Strategic Oversight</h2>

<p>The final phase (for now) arrives when you understand that trust isn’t built by reviewing the agent’s work, but by building systems that validate the work automatically.</p>

<p>For code: tests that are generated and executed with every change. No passing tests, no integration. Validation is binary and automatic.</p>

<p>For thinking: reviewer agents. For research and planning, there are no tests to pass, but you can use a second agent with a critic role to review the first one’s work. It’s like automated code review applied to documents, plans, and architectural decisions.</p>

<p>You’re no longer the filter. You’re the architect of the validation system.</p>

<h2 id="and-phase-7">And Phase 7…</h2>

<p>I don’t know that one yet. You’ll probably discover it when you stop looking for it.</p>

<p>What I do know is that evolution isn’t linear. You’ll return to earlier phases with new perspective. Phase 6 isn’t a destination, it’s a starting point. And every qualitative leap in models will redefine what you thought you knew about programming with AI.</p>

<p>If you’re in Phase 5, don’t worry. Phase 6 exists. And Phase 7… that’s built along the way.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[How the relationship between a developer and AI agents evolves — from manual copy-pasting to automated validation.]]></summary></entry><entry><title type="html">My OpenCode Setup: Multi-Agent Coding with Local Models and Gitea</title><link href="https://blog.veladan.org/2026/06/01/opencode-setup.html" rel="alternate" type="text/html" title="My OpenCode Setup: Multi-Agent Coding with Local Models and Gitea" /><published>2026-06-01T06:00:00+00:00</published><updated>2026-06-01T06:00:00+00:00</updated><id>https://blog.veladan.org/2026/06/01/opencode-setup</id><content type="html" xml:base="https://blog.veladan.org/2026/06/01/opencode-setup.html"><![CDATA[<blockquote>
  <p>I replaced my AI coding workflow with OpenCode running a 10-agent orchestration system, backed by a mix of free-tier models and a local 27B model on my homelab workstation. Total monthly cost: cheap.</p>
</blockquote>

<h1 id="why-opencode">Why OpenCode?</h1>

<p>I have been thinking about local AI coding agents for a while. The constraints were clear: no Anthropic, no OpenAI, and definitely no Chinese providers for personal work. I want full control, reasonable cost, and the ability to iterate without hitting API rate limits or watching token bills spiral.</p>

<p><strong>OpenCode is a provider-agnostic, open-source coding agent</strong> that runs entirely in the terminal. It has a TUI for interactive sessions and a CLI for one-shot tasks. Critically, it supports arbitrary model providers through its plugin system, which means I can route <strong>different tasks to different models</strong> — free tier for quick queries, a local 27B model for medium work, and reserve paid models only where they earn it.</p>

<h1 id="installing-opencode">Installing OpenCode</h1>

<p>OpenCode has three installation methods. The install script is the simplest:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-fsSL</span> https://opencode.ai/install | bash
</code></pre></div></div>

<p>After installation, authenticate your model providers. OpenCode has a free tier called <strong>OpenCode Zen</strong> that gives you access to several models at no cost:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode auth login
</code></pre></div></div>

<p>Check your configured providers with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode auth list
</code></pre></div></div>

<p>I use both OpenCode Zen (free tier) and a local vLLM provider running on my homelab.</p>

<h2 id="updating-opencode">Updating OpenCode</h2>

<p>To update it, just execute command upgrade:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode upgrade
</code></pre></div></div>

<h1 id="oh-my-openagent-the-multi-agent-harness">Oh-My-OpenAgent: The Multi-Agent Harness</h1>

<p>This is where OpenCode gets interesting. <strong>Oh-My-OpenAgent</strong> is a plugin that transforms OpenCode from a single-model agent into a multi-agent orchestration system. It defines 10 specialized agents, each responsible for a different role in the coding workflow:</p>

<table>
  <thead>
    <tr>
      <th>Agent</th>
      <th>Role</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Sisyphus</strong></td>
      <td>Primary orchestrator — coordinates complex tasks</td>
    </tr>
    <tr>
      <td><strong>Hephaestus</strong></td>
      <td>Deep autonomous worker for heavy coding</td>
    </tr>
    <tr>
      <td><strong>Oracle</strong></td>
      <td>Architecture consultant</td>
    </tr>
    <tr>
      <td><strong>Prometheus</strong></td>
      <td>Strategic planner</td>
    </tr>
    <tr>
      <td><strong>Metis</strong></td>
      <td>Gap analyzer</td>
    </tr>
    <tr>
      <td><strong>Momus</strong></td>
      <td>Code reviewer</td>
    </tr>
    <tr>
      <td><strong>Atlas</strong></td>
      <td>General support</td>
    </tr>
    <tr>
      <td><strong>Explore</strong></td>
      <td>Fast codebase grep and search</td>
    </tr>
    <tr>
      <td><strong>Multimodal Looker</strong></td>
      <td>Screenshots and vision</td>
    </tr>
    <tr>
      <td><strong>Sisyphus Junior</strong></td>
      <td>Category executor</td>
    </tr>
  </tbody>
</table>

<h2 id="installing-oh-my-openagent">Installing Oh-My-OpenAgent</h2>

<p>The plugin installs through npm or bun. But don’t do that: just follow the instructions in their <a href="https://github.com/code-yeongyu/oh-my-openagent">Github</a></p>

<blockquote>
  <p>Paste this prompt into Claude Code, AmpCode, Cursor, or any agent:</p>

  <div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Install and configure oh-my-openagent by following the instructions here:
https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/refs/heads/dev/docs/guide/installation.md
</code></pre></div>  </div>
</blockquote>

<p><strong><em>Epic!</em></strong></p>

<p>The plugin generates a configuration file at <code class="language-plaintext highlighter-rouge">~/.config/opencode/oh-my-openagent.json</code>. This is where the magic happens — you assign models to agents and categories.</p>

<h2 id="running-oh-my-openagent">Running Oh-My-OpenAgent</h2>

<p>Once installed and configured, <strong>Oh-My-OpenAgent</strong> activates automatically when you run OpenCode. The plugin intercepts tasks and routes them to the appropriate agent based on the task category.</p>

<p>You can validate the installation with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npx oh-my-openagent doctor
<span class="c"># or</span>
bunx oh-my-openagent doctor
</code></pre></div></div>

<p><img src="https://blog.veladan.org/assets/opencode-tui-session.png" alt="OpenCode TUI showing an active session with Oh-My-OpenAgent routing a task to the Sisyphus agent. The terminal interface displays the model name, task category, and progress bar as the agent works through the codebase." /></p>

<h1 id="model-selection-strategy">Model Selection Strategy</h1>

<p>This is the most important configuration decision. Oh-My-OpenAgent lets you assign different models to different agents and task categories. My strategy is <strong>100% free and local</strong> — no paid API calls.</p>

<h2 id="free-models-from-opencode-zen">Free Models from OpenCode Zen</h2>

<p>OpenCode Zen offers several models free of charge. The current lineup (as first of June 2026) includes:</p>

<table>
  <thead>
    <tr>
      <th>Model ID</th>
      <th>Family</th>
      <th>Use Case</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">opencode/minimax-m3-free</code></td>
      <td>Frontier (multimodal, 1M context)</td>
      <td>Primary model for complex tasks</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">opencode/big-pickle</code></td>
      <td>Claude-like (GLM 4.6)</td>
      <td>Strong reasoning, reliable fallback</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">opencode/qwen3.6-plus-free</code></td>
      <td>Claude-like</td>
      <td>General purpose</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">opencode/deepseek-v4-flash-free</code></td>
      <td>GPT-like</td>
      <td>Deep thinking, autonomous coding</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">opencode/nemotron-3-super-free</code></td>
      <td>Gemini-like</td>
      <td>Reasoning, vision</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">opencode/mimo-v2.5-free</code></td>
      <td>Utility</td>
      <td>Fast fallback for simple tasks</td>
    </tr>
  </tbody>
</table>

<p>Check the current list at any time with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-s</span> https://opencode.ai/zen/v1/models | python3 <span class="nt">-m</span> json.tool
</code></pre></div></div>

<p>Models with <code class="language-plaintext highlighter-rouge">-free</code> in their ID are the free tier offerings. This list changes frequently, so always verify.</p>

<p><img src="https://blog.veladan.org/assets/opencode-zen-models.png" alt="OpenCode Zen model selection showing the free-tier models available through OpenCode's Zen API. The list includes MiniMax M3 Free, Big Pickle, Qwen3.6 Plus Free, DeepSeek V4 Flash Free, Nemotron 3 Super Free, and MiMo V2.5 Free, each with their model families and use cases highlighted." /></p>

<h2 id="local-model">Local Model</h2>

<p>My homelab workstation (which I call Tesla) runs a local model via vLLM. This is my anchor for tasks that need to be fast and private:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"provider"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"vllm-pro6000"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"npm"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@ai-sdk/openai-compatible"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Tesla VLLM"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"options"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"baseURL"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://192.168.1.47:8005/v1"</span><span class="w">
      </span><span class="p">},</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"Qwen3.6-27B"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Qwen3.6-27B"</span><span class="p">,</span><span class="w">
          </span><span class="nl">"limit"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"context"</span><span class="p">:</span><span class="w"> </span><span class="mi">262144</span><span class="p">,</span><span class="w">
            </span><span class="nl">"output"</span><span class="p">:</span><span class="w"> </span><span class="mi">65536</span><span class="w">
          </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>This gives me a Qwen3.6-27B model running on an RTX PRO 6000 (96 GB VRAM). It is my fallback for every agent — fast, private, and free.</p>

<h2 id="agent-model-assignments">Agent Model Assignments</h2>

<p>Here is my free-tier strategy, mapping models to agents:</p>

<table>
  <thead>
    <tr>
      <th>Agent</th>
      <th>Primary</th>
      <th>Fallback Chain</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sisyphus</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/minimax-m3-free</code></td>
      <td>big-pickle, qwen3.6-plus-free, deepseek-v4-flash-free, local</td>
    </tr>
    <tr>
      <td>Hephaestus</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/minimax-m3-free</code></td>
      <td>deepseek-v4-flash-free, nemotron-3-super-free, big-pickle, local</td>
    </tr>
    <tr>
      <td>Oracle</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/nemotron-3-super-free</code></td>
      <td>minimax-m3-free, deepseek-v4-flash-free, big-pickle, local</td>
    </tr>
    <tr>
      <td>Prometheus</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/minimax-m3-free</code></td>
      <td>qwen3.6-plus-free, big-pickle, deepseek-v4-flash-free, local</td>
    </tr>
    <tr>
      <td>Metis</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/minimax-m3-free</code></td>
      <td>big-pickle, deepseek-v4-flash-free, local</td>
    </tr>
    <tr>
      <td>Momus</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/deepseek-v4-flash-free</code></td>
      <td>minimax-m3-free, nemotron-3-super-free, big-pickle, local</td>
    </tr>
    <tr>
      <td>Atlas</td>
      <td><strong>local</strong></td>
      <td>minimax-m3-free, mimo-v2.5-free</td>
    </tr>
    <tr>
      <td>Explore</td>
      <td><strong>local</strong></td>
      <td>minimax-m3-free, mimo-v2.5-free</td>
    </tr>
    <tr>
      <td>Multimodal Looker</td>
      <td><strong>local</strong></td>
      <td>nemotron-3-super-free</td>
    </tr>
    <tr>
      <td>Sisyphus Junior</td>
      <td><strong>local</strong></td>
      <td>minimax-m3-free, deepseek-v4-flash-free</td>
    </tr>
  </tbody>
</table>

<p>The key insight: <strong>heavy agents get free frontier models, lightweight agents use the local model</strong>. MiniMax M3 is the workhorse — it is a genuine frontier model with 1M context window, multimodal support, and sparse attention that competes with paid options on coding benchmarks.</p>

<p>The local model anchors Explore and Atlas because those are fast, low-complexity tasks. Sending a grep query to a remote API wastes time and tokens. A 27B local model handles search and general support in milliseconds.</p>

<h2 id="category-model-assignments">Category Model Assignments</h2>

<p>Oh-My-OpenAgent also supports <strong>task categories</strong> — different model assignments based on what type of work is being done:</p>

<table>
  <thead>
    <tr>
      <th>Category</th>
      <th>Primary</th>
      <th>Fallback Chain</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>ultrabrain</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/nemotron-3-super-free</code></td>
      <td>minimax-m3-free, deepseek-v4-flash-free, big-pickle, local</td>
    </tr>
    <tr>
      <td>deep</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/deepseek-v4-flash-free</code></td>
      <td>minimax-m3-free, nemotron-3-super-free, big-pickle, local</td>
    </tr>
    <tr>
      <td>unspecified-high</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/minimax-m3-free</code></td>
      <td>big-pickle, qwen3.6-plus-free, deepseek-v4-flash-free, local</td>
    </tr>
    <tr>
      <td>visual-engineering</td>
      <td><strong>local</strong></td>
      <td>minimax-m3-free, nemotron-3-super-free, deepseek-v4-flash-free</td>
    </tr>
    <tr>
      <td>writing</td>
      <td><code class="language-plaintext highlighter-rouge">opencode/big-pickle</code></td>
      <td>minimax-m3-free, qwen3.6-plus-free, local</td>
    </tr>
    <tr>
      <td>quick</td>
      <td><strong>local</strong></td>
      <td>mimo-v2.5-free</td>
    </tr>
    <tr>
      <td>artistry</td>
      <td><strong>local</strong></td>
      <td>nemotron-3-super-free, deepseek-v4-flash-free</td>
    </tr>
    <tr>
      <td>unspecified-low</td>
      <td><strong>local</strong></td>
      <td>deepseek-v4-flash-free, big-pickle</td>
    </tr>
  </tbody>
</table>

<p>The golden rule: <strong>always include the local model as either primary or final fallback</strong>. This ensures the system never dead-ends.</p>

<h2 id="picking-the-right-models">Picking the Right Models</h2>

<p>When selecting models for Oh-My-OpenAgent, I follow these principles:</p>

<ol>
  <li>
    <p><strong>Check OpenCode Zen first</strong> — the free model lineup changes. Always verify with the API before committing to a configuration.</p>
  </li>
  <li><strong>Classify by behavior, not just benchmarks</strong>:
    <ul>
      <li><em>Claude-like</em> models follow instructions well and handle complex prompts (big-pickle, qwen3.6-plus-free).</li>
      <li><em>GPT-like</em> models are principle-driven and autonomous (deepseek-v4-flash-free).</li>
      <li><em>Gemini-like</em> models have different reasoning patterns, good for vision (nemotron-3-super-free).</li>
      <li><em>Utility</em> models are fast and cheap for simple tasks (mimo-v2.5-free).</li>
    </ul>
  </li>
  <li>
    <p><strong>Hephaestus needs deep reasoning</strong> — this agent does autonomous, multi-step coding. It cannot run on lightweight models. MiniMax M3 or DeepSeek V4 Flash are the minimum viable free options.</p>
  </li>
  <li>
    <p><strong>Cross-reference benchmarks</strong> — I check <a href="https://artificialanalysis.ai">ArtificialAnalysis.ai</a> for coding leaderboard rankings and cost-efficiency scores. The free tier lineup shifts, but the relative ordering between free models tends to be stable.</p>
  </li>
  <li><strong>Local model as anchor</strong> — it is always present. Fast, private, zero-cost. Use it for Explore, Atlas, and any category where latency matters more than capability.</li>
</ol>

<h1 id="gitea-integration-via-mcp">Gitea Integration via MCP</h1>

<p>One of the most powerful parts of my setup is connecting OpenCode to my self-hosted Gitea instance. This lets me say things like “resolve issue #34” and have OpenCode actually look up the issue on Gitea, read its description, implement the fix, and commit it.</p>

<h2 id="installing-the-gitea-mcp-server">Installing the Gitea MCP Server</h2>

<p>Gitea provides an official MCP (Model Context Protocol) server:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go <span class="nb">install </span>gitea.com/gitea/gitea-mcp@latest
</code></pre></div></div>

<p>This gives you a <code class="language-plaintext highlighter-rouge">gitea-mcp</code> binary that speaks the MCP protocol over stdio.</p>

<h2 id="configuring-gitea-mcp-in-opencode">Configuring Gitea MCP in OpenCode</h2>

<p>Add the Gitea MCP server to your <code class="language-plaintext highlighter-rouge">opencode.json</code>:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"mcp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"gitea"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"local"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"gitea-mcp"</span><span class="p">,</span><span class="w"> </span><span class="s2">"-t"</span><span class="p">,</span><span class="w"> </span><span class="s2">"stdio"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"environment"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"GITEA_HOST"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://192.168.1.47:3000"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"GITEA_ACCESS_TOKEN"</span><span class="p">:</span><span class="w"> </span><span class="s2">"your-access-token-here"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"GITEA_INSECURE"</span><span class="p">:</span><span class="w"> </span><span class="s2">"true"</span><span class="w">
      </span><span class="p">},</span><span class="w">
      </span><span class="nl">"enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">GITEA_HOST</code> with your Gitea instance URL and <code class="language-plaintext highlighter-rouge">GITEA_ACCESS_TOKEN</code> with a personal access token that has repository read/write permissions. The <code class="language-plaintext highlighter-rouge">GITEA_INSECURE</code> flag is only needed if your Gitea uses self-signed HTTPS or HTTP.</p>

<p>The Gitea MCP server exposes tools for issue management, repository browsing, pull requests, and more. Once connected, OpenCode agents can call these tools directly.</p>

<p><img src="https://blog.veladan.org/assets/gitea-issue-list.png" alt="Gitea instance showing an issue list. The screenshot demonstrates how OpenCode can read issue details directly from your self-hosted Gitea through the MCP server, then implement fixes and commit them back." /></p>

<h2 id="using-issue-references">Using Issue References</h2>

<p>With Gitea MCP configured, you can reference issues naturally:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode run <span class="s2">"Research issue #34 — explain what it's about and what needs to be done"</span>
</code></pre></div></div>

<p>Or for full resolution:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode run <span class="s2">"Resolve issue #5 — fix the bug described in the issue and commit the changes"</span>
</code></pre></div></div>

<p>OpenCode will:</p>
<ol>
  <li>Call the Gitea MCP <code class="language-plaintext highlighter-rouge">issue_get</code> tool to fetch the issue details</li>
  <li>Read the description, comments, and labels</li>
  <li>Understand what needs to be done</li>
  <li>Make the code changes</li>
  <li>Commit and (optionally) submit a pull request</li>
</ol>

<p>You can also ask OpenCode to list open issues, triage them, or summarize the state of a repository. The Gitea MCP server supports issue listing, commenting, label management, and more.</p>

<h2 id="configuring-your-working-directory">Configuring Your Working Directory</h2>

<p>For OpenCode to resolve <code class="language-plaintext highlighter-rouge">#issue</code> references correctly, make sure you run it inside the cloned repository that matches your Gitea instance:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> ~/projects/my-repo
opencode run <span class="s2">"Fix issue #42"</span>
</code></pre></div></div>

<p>OpenCode will match the local <code class="language-plaintext highlighter-rouge">.git</code> remote to your Gitea MCP configuration. If the remote is on your self-hosted Gitea, the agent will use the MCP tools. If it is on GitHub, it will use the GitHub integration instead.</p>

<h1 id="configuring-language-server-protocols-lsp">Configuring Language Server Protocols (LSP)</h1>

<p>OpenCode supports LSP servers for language-specific intelligence. This is essential for getting accurate code suggestions, type checking, and refactoring support.</p>

<p>Here is my LSP configuration for Rust:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"lsp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"rust-analyzer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"/Users/danielvela/.cargo/bin/rust-analyzer"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"extensions"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">".rs"</span><span class="p">,</span><span class="w"> </span><span class="s2">".toml"</span><span class="p">]</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>For other languages, the pattern is the same — specify the command path and the file extensions the server should handle. Common LSP servers include:</p>

<table>
  <thead>
    <tr>
      <th>Language</th>
      <th>LSP Server</th>
      <th>Install</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Rust</td>
      <td><code class="language-plaintext highlighter-rouge">rust-analyzer</code></td>
      <td><code class="language-plaintext highlighter-rouge">cargo install rust-analyzer</code></td>
    </tr>
    <tr>
      <td>Python</td>
      <td><code class="language-plaintext highlighter-rouge">pyright</code></td>
      <td><code class="language-plaintext highlighter-rouge">npm i -g pyright</code></td>
    </tr>
    <tr>
      <td>TypeScript</td>
      <td><code class="language-plaintext highlighter-rouge">typescript-language-server</code></td>
      <td><code class="language-plaintext highlighter-rouge">npm i -g typescript-language-server</code></td>
    </tr>
    <tr>
      <td>Go</td>
      <td><code class="language-plaintext highlighter-rouge">gopls</code></td>
      <td><code class="language-plaintext highlighter-rouge">go install golang.org/x/tools/gopls@latest</code></td>
    </tr>
    <tr>
      <td>Java</td>
      <td><code class="language-plaintext highlighter-rouge">eclipse.jdt.ls</code></td>
      <td>Download from Eclipse</td>
    </tr>
  </tbody>
</table>

<p>LSP integration gives OpenCode type awareness, import resolution, and accurate code completion. Without it, the agent is working blind on language-specific details.</p>

<p><img src="https://blog.veladan.org/assets/opencode-config-complete.png" alt="Complete OpenCode configuration showing opencode.json with plugins, MCP servers, LSP configuration, and provider settings. The file demonstrates how all the pieces connect: Oh-My-OpenAgent for multi-agent orchestration, Gitea MCP for issue tracking, local vLLM for the anchor model, and LSP for language-specific intelligence." /></p>

<h1 id="using-opencode-daily-workflow">Using OpenCode: Daily Workflow</h1>

<h2 id="one-shot-tasks">One-Shot Tasks</h2>

<p>For bounded tasks that do not need iteration, use <code class="language-plaintext highlighter-rouge">opencode run</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode run <span class="s2">"Add retry logic to the API client and update the tests"</span>
</code></pre></div></div>

<p>You can attach files for context:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode run <span class="s2">"Review this config for security issues"</span> <span class="nt">-f</span> config.yaml <span class="nt">-f</span> .env.example
</code></pre></div></div>

<p>Force a specific model:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode run <span class="s2">"Debug why the tests fail in CI"</span> <span class="nt">--model</span> opencode/minimax-m3-free <span class="nt">--thinking</span>
</code></pre></div></div>

<h2 id="interactive-sessions">Interactive Sessions</h2>

<p>For iterative work, launch the TUI:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode
</code></pre></div></div>

<p>This opens the terminal interface. Use <code class="language-plaintext highlighter-rouge">Ctrl+X M</code> to switch models, <code class="language-plaintext highlighter-rouge">Ctrl+X N</code> for a new session, <code class="language-plaintext highlighter-rouge">Ctrl+X L</code> to switch sessions, and <code class="language-plaintext highlighter-rouge">Ctrl+C</code> to exit.</p>

<h2 id="monitoring-progress">Monitoring Progress</h2>

<p>One important thing: the TUI is not easily monitorable from outside. If you need to automate or supervise sessions, prefer <code class="language-plaintext highlighter-rouge">opencode run</code> over the interactive TUI. The one-shot mode gives you complete output when finished, while the TUI redraws with ANSI escape codes that make external monitoring unreliable.</p>

<p>For long-running tasks, use the <code class="language-plaintext highlighter-rouge">--model</code> flag explicitly. Without it, OpenCode may try to resolve the default model from <code class="language-plaintext highlighter-rouge">opencode.json</code>, which can cause <code class="language-plaintext highlighter-rouge">ProviderModelNotFoundError</code> if the provider prefix is missing:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Correct — includes provider prefix</span>
opencode run <span class="s2">"Refactor auth module"</span> <span class="nt">--model</span> vllm-pro6000/Qwen3.6-27B

<span class="c"># Wrong — will fail with ProviderModelNotFoundError</span>
opencode run <span class="s2">"Refactor auth module"</span> <span class="nt">--model</span> Qwen3.6-27B
</code></pre></div></div>

<h2 id="session-management">Session Management</h2>

<p>Check your token usage:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode stats
</code></pre></div></div>

<p>List past sessions:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode session list
</code></pre></div></div>

<p>Resume your last session:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opencode <span class="nt">-c</span>
</code></pre></div></div>

<h1 id="lessons-learned">Lessons Learned</h1>

<p><strong>The local model is more valuable than I expected.</strong> A 27B model on a dedicated GPU handles code exploration, quick fixes, and simple tasks faster than any remote API. The latency advantage is enormous — sub-second responses versus the 10-30 second round-trip to a cloud provider. Reserve free tier and paid models for tasks that genuinely need more capability.</p>

<p><strong>MiniMax M3 is the free-tier workhorse.</strong> At SWE-Bench Pro scores around 59%, it competes with models that cost real money. The 1M context window means you can feed it entire codebases, and it actually uses that context effectively. The sparse attention mechanism gives it 15.6x speed advantage on long contexts compared to dense attention.</p>

<p><strong>Oh-My-OpenAgent changes the workflow.</strong> Instead of manually picking which model to use for each task, you delegate to the orchestrator. Sisyphus figures out whether a task needs deep reasoning, quick search, or creative exploration, and routes it accordingly. The agent model assignments are the configuration surface — once set up well, the system runs itself.</p>

<p><strong>Gitea MCP is the missing piece.</strong> Issue-driven development — “fix issue #34” — is how I actually work. Connecting OpenCode to my self-hosted Gitea via MCP makes this seamless. The agent reads the issue, understands the scope, implements the fix, and commits it. The <code class="language-plaintext highlighter-rouge">tea</code> CLI and <code class="language-plaintext highlighter-rouge">gitea-mcp</code> together form a complete local development loop.</p>

<h1 id="putting-it-all-together">Putting It All Together</h1>

<p>My complete <code class="language-plaintext highlighter-rouge">opencode.json</code> looks like this:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"$schema"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://opencode.ai/config.json"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"plugin"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"oh-my-openagent@latest"</span><span class="p">,</span><span class="w"> </span><span class="s2">"opencode-agent-skills"</span><span class="p">],</span><span class="w">
  </span><span class="nl">"mcp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"gitea"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"local"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"gitea-mcp"</span><span class="p">,</span><span class="w"> </span><span class="s2">"-t"</span><span class="p">,</span><span class="w"> </span><span class="s2">"stdio"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"environment"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"GITEA_HOST"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://192.168.1.47:3000"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"GITEA_ACCESS_TOKEN"</span><span class="p">:</span><span class="w"> </span><span class="s2">"your-token-here"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"GITEA_INSECURE"</span><span class="p">:</span><span class="w"> </span><span class="s2">"true"</span><span class="w">
      </span><span class="p">},</span><span class="w">
      </span><span class="nl">"enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"lsp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"rust-analyzer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"/Users/danielvela/.cargo/bin/rust-analyzer"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"extensions"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">".rs"</span><span class="p">,</span><span class="w"> </span><span class="s2">".toml"</span><span class="p">]</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"provider"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"vllm-pro6000"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"npm"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@ai-sdk/openai-compatible"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Tesla VLLM"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"options"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"baseURL"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://192.168.1.47:8005/v1"</span><span class="w">
      </span><span class="p">},</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"Qwen3.6-27B"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Qwen3.6-27B"</span><span class="p">,</span><span class="w">
          </span><span class="nl">"limit"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"context"</span><span class="p">:</span><span class="w"> </span><span class="mi">262144</span><span class="p">,</span><span class="w">
            </span><span class="nl">"output"</span><span class="p">:</span><span class="w"> </span><span class="mi">65536</span><span class="w">
          </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>And <code class="language-plaintext highlighter-rouge">oh-my-openagent.json</code> defines the agent and category model assignments shown above.</p>

<h1 id="next-steps">Next Steps</h1>

<p>The obvious upgrade path is a second GPU. I am considering an additional RTX PRO 6000 to serve larger models — 70B and beyond — that do not fit in 96 GB of VRAM. Two GPUs would let me run separate vLLM instances for different model sizes, routing them through the same provider configuration.</p>

<p>Beyond hardware, the next iteration is better issue automation. I want OpenCode to not just resolve individual issues but to triage entire repositories — scan open issues, prioritize by impact, and batch-fix related bugs in a single session. Oh-My-OpenAgent is already set up for this; it just needs the right prompt.</p>]]></content><author><name>Daniel Vela</name></author><summary type="html"><![CDATA[I replaced my AI coding workflow with OpenCode running a 10-agent orchestration system, backed by a mix of free-tier models and a local 27B model on my homelab workstation. Total monthly cost: cheap.]]></summary></entry><entry><title type="html">Building a Home GPU Lab: Tesla with RTX PRO 6000 for Local LLM Inference</title><link href="https://blog.veladan.org/2026/05/30/home-gpu-lab.html" rel="alternate" type="text/html" title="Building a Home GPU Lab: Tesla with RTX PRO 6000 for Local LLM Inference" /><published>2026-05-30T06:00:00+00:00</published><updated>2026-05-30T06:00:00+00:00</updated><id>https://blog.veladan.org/2026/05/30/home-gpu-lab</id><content type="html" xml:base="https://blog.veladan.org/2026/05/30/home-gpu-lab.html"><![CDATA[<blockquote>
  <p>I’m an iOS developer who got curious about local LLMs and ended up building a homelab with two NVIDIA GPUs, three machines, and way too many Docker containers. This is how it came together.</p>
</blockquote>

<h1 id="why-a-dedicated-ai-workstation">Why a Dedicated AI Workstation?</h1>

<p>It started as curiosity. I wanted to experiment with local models — run them privately, iterate quickly, not depend on cloud APIs. But consumer GPUs felt inadequate for the sizes I cared about. You hit VRAM walls fast when you want to serve a 27-billion-parameter model without collapsing into swap.</p>

<p>So I committed to a proper build: a workstation designed from day one to host inference, image generation, and all the plumbing around it. I named it <strong>Tesla</strong>.</p>

<h1 id="the-hardware">The Hardware</h1>

<p>Tesla is built around the <strong>AMD Ryzen 9 9950X</strong>, 96 GB DDR5, and an <strong>ASUS ROG Crosshair X870E Hero</strong> motherboard with dual PCIe x16 slots. Nothing exotic beyond that — the interesting part is the GPU selection.</p>

<table>
  <thead>
    <tr>
      <th>Component</th>
      <th>Spec</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CPU</td>
      <td>AMD Ryzen 9 9950X 4.3/5.7 GHz</td>
    </tr>
    <tr>
      <td>Motherboard</td>
      <td>ASUS ROG Crosshair X870E Hero</td>
    </tr>
    <tr>
      <td>RAM</td>
      <td>96 GB DDR5 6400 MHz (2×48 GB)</td>
    </tr>
    <tr>
      <td>GPU 1</td>
      <td>NVIDIA RTX PRO 6000 Blackwell — 96 GB VRAM</td>
    </tr>
    <tr>
      <td>GPU 2</td>
      <td>NVIDIA RTX 3060 — 12 GB VRAM</td>
    </tr>
    <tr>
      <td>PSU</td>
      <td>Corsair HX1500i 1500W 80+ Platinum</td>
    </tr>
    <tr>
      <td>Case</td>
      <td>Antec P101 Silent (Full Tower)</td>
    </tr>
    <tr>
      <td>Cooler</td>
      <td>Noctua NH-D15 G2</td>
    </tr>
    <tr>
      <td>Storage</td>
      <td>Samsung 990 Pro 2 TB NVMe + 980 1 TB NVMe + FireCuda 530 1 TB + 2× BX500 2 TB SATA</td>
    </tr>
    <tr>
      <td>OS</td>
      <td>Debian 13</td>
    </tr>
  </tbody>
</table>

<h2 id="why-the-rtx-pro-6000">Why the RTX PRO 6000?</h2>

<p>The RTX PRO 6000 Blackwell gives you <strong>96 GB of VRAM</strong> in a workstation card. That is the number that matters for local LLMs. At FP8, a 27B model fits comfortably with room for context. At FP16, you can still load larger models. There simply isn’t a consumer card in this range — the GeForce RTX 5090 tops out at 32 GB.</p>

<p>Yes, it costs more than a consumer flagship. But once you factor in that you avoid monthly cloud bills for heavy usage, the ROI starts to look reasonable. And for development work where you iterate dozens of times a day, not waiting on an API call changes everything.</p>

<p>The secondary RTX 3060 (12 GB) arrived from my gaming rig, <strong>Bolt</strong>. I moved the 7900 XTX to Bolt for gaming and brought the 3060 here — a cheap CUDA-capable card that handles secondary image generation tasks without eating the PRO 6000’s memory.</p>

<h2 id="it-is-not-just-capacity--bandwidth-matters-more">It Is Not Just Capacity — Bandwidth Matters More</h2>

<p>Capacity tells you whether a model fits. Bandwidth tells you whether it runs at a usable speed. This distinction is critical when comparing dedicated GPUs to unified-memory systems like Apple Silicon.</p>

<p>Chips like the <strong>M4 Pro</strong> or <strong>M5 Max</strong> advertise large amounts of unified memory — 48 GB, 64 GB, even 128 GB on Max variants. On paper, that looks like plenty. In practice, the memory bandwidth available to the neural engine is a fraction of what a dedicated GPU offers. An RTX PRO 6000 moves data at <strong>~2 TB/s</strong> over its 680-bit bus. An M4 Pro shares its bandwidth pool across CPU, GPU, and Neural Engine, effectively delivering far less to the inference workload.</p>

<p>The consequence is stark: on Apple Silicon, <strong>only Mixture-of-Experts (MoE) models are practically usable</strong> at scale. MoE models activate only a subset of their parameters per token, so they demand less throughput despite their total size. Dense models — which use all parameters for every token — starve for bandwidth and crawl.</p>

<p>On a dedicated NVIDIA GPU, dense models fly. A 27B dense model at FP8 on the PRO 6000 generates tokens at speeds that feel responsive. The same model on an M4 Pro can be orders of magnitude slower, making it impractical for interactive work.</p>

<p>And it is not just about speed. Dense models tend to carry more knowledge and capability per parameter than their MoE counterparts. They were trained on broader corpora, with richer instruction tuning. Losing access to dense models because of bandwidth constraints means losing access to a significant portion of what modern LLMs can do.</p>

<p>That is why, for serious local inference, a dedicated GPU is not a luxury — it is a requirement.</p>

<h1 id="the-rest-of-the-homelab">The Rest of the Homelab</h1>

<p>Tesla doesn’t work alone. Here’s the full picture:</p>

<p><strong>Bolt</strong> — Ryzen 5 5600X, 32 GB, RX 7900 XTX. Pure gaming machine running Nobara Linux. Where the AMD GPU belongs.</p>

<p><strong>Microx</strong> — Ryzen 7 5700G, 64 GB, 2×8 TB HDD mirror. Runs TrueNAS Scale as my NAS with AdGuard Home, Plex, and Transmission.</p>

<p><strong>Mac Mini M4 Pro</strong> — 14-core, 64 GB. The daily driver for Xcode and iOS development.</p>

<p><strong>MacBook Air M5</strong> — Portable work and travel.</p>

<h1 id="what-runs-on-tesla">What Runs on Tesla</h1>

<p>Tesla hosts roughly twenty services, all orchestrated through Docker Compose and exposed behind an nginx reverse proxy with Cloudflare tunnels for external access:</p>

<table>
  <thead>
    <tr>
      <th>Service</th>
      <th>GPU</th>
      <th>Purpose</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>vLLM</td>
      <td>PRO 6000</td>
      <td>Qwen3.6-27B-FP8, OpenAI-compatible API</td>
    </tr>
    <tr>
      <td>ComfyUI</td>
      <td>PRO 6000 / 3060</td>
      <td>Image generation (Flux, SDXL)</td>
    </tr>
    <tr>
      <td>Open WebUI</td>
      <td>CPU</td>
      <td>Chat frontend with RAG, connects to vLLM</td>
    </tr>
    <tr>
      <td>Gitea + Postgres</td>
      <td>CPU</td>
      <td>Self-hosted Git hosting</td>
    </tr>
    <tr>
      <td>SearXNG</td>
      <td>CPU</td>
      <td>Private metasearch</td>
    </tr>
    <tr>
      <td>Browserless</td>
      <td>CPU</td>
      <td>Headless Chrome</td>
    </tr>
    <tr>
      <td>Docker Registry</td>
      <td>CPU</td>
      <td>Local container images</td>
    </tr>
    <tr>
      <td>Firecrawl + deps</td>
      <td>CPU</td>
      <td>Web scraping (Postgres, Redis, RabbitMQ, Playwright)</td>
    </tr>
  </tbody>
</table>

<p>The PRO 6000 handles both vLLM and ComfyUI — they rarely peak at the same time, so 96 GB is enough for both workloads sequentially. The 3060 catches overflow image generation jobs.</p>

<h1 id="lessons-learned">Lessons Learned</h1>

<p><strong>VRAM capacity and bandwidth are both bottlenecks.</strong> Capacity determines what fits, but bandwidth determines what runs at a usable speed. Unified-memory systems like Apple Silicon look impressive on paper — 64 GB, 128 GB — but their shared bandwidth makes dense models painfully slow. Only MoE models remain practical there. A dedicated GPU with a fat memory bus is what you need for serious inference.</p>

<p><strong>Dual GPUs help more than you think.</strong> Even a modest secondary GPU like the 3060 frees you from fighting over the primary card. Image generation and inference can overlap without killing each other.</p>

<p><strong>Docker Compose is the glue.</strong> Twenty services on one machine sounds chaotic until you realize they’re all declared in a single compose file. Start, stop, update — one command.</p>

<p><strong>Self-hosting teaches you about dependencies.</strong> You don’t just run an LLM server. You need a registry, a reverse proxy, a search backend, headless browsers, queues… The ecosystem grows organically. Having it all local is satisfying precisely because it’s messy.</p>

<h1 id="next-steps">Next Steps</h1>

<p>The motherboard has two PCIe x16 slots. The second one is empty. When the workload demands it, a second RTX PRO 6000 goes in — doubling to 192 GB of VRAM for even larger models or concurrent workloads. Until then, one card is plenty.</p>

<p>The dream is simple: local models that rival cloud quality, running on hardware I control, in my own office. We’re getting close.</p>]]></content><author><name>Daniel Vela</name></author><summary type="html"><![CDATA[I’m an iOS developer who got curious about local LLMs and ended up building a homelab with two NVIDIA GPUs, three machines, and way too many Docker containers. This is how it came together.]]></summary></entry><entry><title type="html">Exploring the Vast Potential</title><link href="https://blog.veladan.org/2025/07/19/nostr-network-uses.html" rel="alternate" type="text/html" title="Exploring the Vast Potential" /><published>2025-07-19T03:00:00+00:00</published><updated>2025-07-19T03:00:00+00:00</updated><id>https://blog.veladan.org/2025/07/19/nostr-network-uses</id><content type="html" xml:base="https://blog.veladan.org/2025/07/19/nostr-network-uses.html"><![CDATA[<p>Hey there, fellow tech enthusiasts! If you’ve been following my ramblings here on the blog, you know I’m always diving into decentralized tech that pushes back against the walled gardens of big platforms. Today, let’s talk about Nostr – that simple, open protocol that’s quietly revolutionizing how we think about online interactions. Nostr, short for “Notes and Other Stuff Transmitted by Relays,” isn’t just another social media fad; it’s a foundational layer for all sorts of apps, leveraging its event-based protocols and distributed relays to create censorship-resistant, user-owned experiences.</p>

<p>For the uninitiated, Nostr works like this: Users create cryptographically signed “notes” (events) in client apps, which are then published to relays – essentially decentralized servers that store and distribute these events. Relays don’t control the content (they can’t alter it without breaking signatures), but they act as hubs for discovery and propagation. Clients pull data from multiple relays, giving users full control over what they see and share. It’s chaotic in the best way, reminiscent of the early internet, and it opens the door to a ton of innovative applications. Let’s break down some of the coolest ones that are already out there or could be built, grouped by category for clarity.</p>

<h2 id="social-media-and-communication-apps">Social Media and Communication Apps</h2>

<p>Nostr’s core strength lies in decentralized social networking, making it a natural fit for Twitter-like platforms but with way more freedom.</p>

<ul>
  <li><strong>Microblogging Clients</strong>: Apps like Damus (the OG iOS client) and Amethyst (Android powerhouse) let you post short updates, follow users, and engage in threads without a central authority banning you. Nostter offers a web-based Twitter vibe, while Nostur brings it to iPhone and macOS.</li>
  <li><strong>Chat and Instant Messaging</strong>: Beyond public posts, Nostr supports end-to-end encrypted DMs and group chats. Think Slack or MS Teams alternatives – DinoDaddy_arrived on Reddit suggested building E2EE chat apps that integrate seamlessly with Lightning Network for micropayments.</li>
  <li><strong>Video Conferencing</strong>: Hivetalk combines Nostr with Lightning for video calls, perfect for decentralized meetings.</li>
  <li><strong>Forums and Closed Groups</strong>: Using sub-protocols like NIP-29, you can create censorship-resistant forums or private communities, ideal for niche discussions without Big Tech oversight.</li>
</ul>

<h2 id="content-creation-and-sharing">Content Creation and Sharing</h2>

<p>Nostr isn’t limited to text; it’s a playground for all kinds of media and long-form content.</p>

<ul>
  <li><strong>Blogging and Long-Form Writing</strong>: Habla lets you read, write, curate, and even monetize articles over Nostr. Imagine a decentralized Substack where relays handle distribution.</li>
  <li><strong>Bookmarking and Web Annotations</strong>: Tools for saving and annotating web content, turning Nostr into a personal knowledge base.</li>
  <li><strong>Media Sharing</strong>: Share pictures, voice notes, or videos directly. Spring Browser (Android) focuses on Nostr media, while potential apps could mimic Pinterest for visual boards.</li>
  <li><strong>Decentralized Wikipedia</strong>: A collaborative encyclopedia where edits are signed events stored on relays, resistant to censorship.</li>
</ul>

<h2 id="collaboration-and-productivity-tools">Collaboration and Productivity Tools</h2>

<p>Why stop at social? Nostr’s protocol can power team tools and dev workflows.</p>

<ul>
  <li><strong>Code Collaboration</strong>: Jack Dorsey once bountied a GitHub alternative on Nostr – think decentralized repos with git integration for issue tracking and pull requests.</li>
  <li><strong>Productivity Suites</strong>: Alternatives to Salesforce for CRM or OpenTable/Yelp for reservations and reviews, all user-owned.</li>
  <li><strong>File Hosting and Sharing</strong>: Use relays for torrent sharing or file distribution, creating a decentralized Dropbox.</li>
  <li><strong>Task Management</strong>: Slack-like apps for teams, with events for tasks, reminders, and integrations.</li>
</ul>

<h2 id="media-and-entertainment-applications">Media and Entertainment Applications</h2>

<p>Get ready for fun – Nostr can disrupt streaming and gaming in big ways.</p>

<ul>
  <li><strong>Music and Podcasting</strong>: A Spotify alternative where artists publish tracks as events, monetized via zaps (Lightning tips).</li>
  <li><strong>Video Streaming and Livestreaming</strong>: Build YouTube clones with video notes, or apps for live broadcasts distributed across relays.</li>
  <li><strong>Gaming</strong>: As mentioned in a Medium series on Nostr, gaming apps could use the protocol for multiplayer coordination, leaderboards, or in-game chats.</li>
  <li><strong>Reddit Alternatives</strong>: Nvote is already out there as a decentralized voting and discussion platform.</li>
</ul>

<h2 id="commerce-and-marketplaces">Commerce and Marketplaces</h2>

<p>Nostr’s integration with Bitcoin and Lightning makes it prime for economic apps.</p>

<ul>
  <li><strong>Decentralized Marketplaces</strong>: Peer-to-peer buying/selling like a censorship-resistant eBay, with events for listings and transactions.</li>
  <li><strong>Couchsurfing Clones</strong>: Travel apps for hosting and staying, using signed events for reviews and bookings.</li>
  <li><strong>Wallets and Zaps</strong>: Tools like lnpass manage keys for Lightning and Nostr, while Zapstore is a web-of-trust app store.</li>
  <li><strong>Liquidity Marketplaces</strong>: Liquiditystr enables P2P Lightning swaps over Nostr.</li>
</ul>

<h2 id="other-innovative-and-niche-uses">Other Innovative and Niche Uses</h2>

<p>The beauty of Nostr is its extensibility – here’s where things get wild.</p>

<ul>
  <li><strong>Emergency Alerts</strong>: Nostr can be used for real-time alerts in crises, leveraging relays for instant distribution.</li>
  <li><strong>Analytics and Dashboards</strong>: Nashboard provides network stats, while NosTracker monitors NIP support.</li>
  <li><strong>Bots and Automation</strong>: LikZap auto-zaps liked notes, or bots for bridging to other networks.</li>
  <li><strong>Search and Discovery</strong>: Specialized search clients or ndxstr for advanced querying.</li>
  <li><strong>Identity and Login</strong>: “Login with Nostr” as a DID/VC system for data ownership across apps.</li>
</ul>

<p>Of course, this is just scratching the surface. With libraries in languages like Rust, Python, and JavaScript (e.g., nostr-tools, nostr-py), developers can whip up custom relays like Chorus or tools like nostcat for debugging. The ecosystem is exploding – check out awesome-nostr on GitHub for an exhaustive list.</p>

<p>In wrapping up, Nostr’s protocols and relays aren’t about replacing one app; they’re about enabling a thousand flowers to bloom in a truly open digital commons. If you’re a builder, dive in – the potential for censorship-resistant, user-sovereign apps is endless. What do you think we should build next? Drop a comment or hit me up on Nostr if you’re there. Until next time, keep decentralizing!</p>]]></content><author><name>Daniel Vela</name></author><summary type="html"><![CDATA[Hey there, fellow tech enthusiasts! If you’ve been following my ramblings here on the blog, you know I’m always diving into decentralized tech that pushes back against the walled gardens of big platforms. Today, let’s talk about Nostr – that simple, open protocol that’s quietly revolutionizing how we think about online interactions. Nostr, short for “Notes and Other Stuff Transmitted by Relays,” isn’t just another social media fad; it’s a foundational layer for all sorts of apps, leveraging its event-based protocols and distributed relays to create censorship-resistant, user-owned experiences.]]></summary></entry><entry><title type="html">Building Value First</title><link href="https://blog.veladan.org/2025/06/28/business-for-add-value.html" rel="alternate" type="text/html" title="Building Value First" /><published>2025-06-28T03:00:00+00:00</published><updated>2025-06-28T03:00:00+00:00</updated><id>https://blog.veladan.org/2025/06/28/business-for-add-value</id><content type="html" xml:base="https://blog.veladan.org/2025/06/28/business-for-add-value.html"><![CDATA[<p>When we think about successful businesses, it’s easy to focus on profits, market share, or stock prices. But at the heart of every enduring company lies a fundamental truth: businesses exist to create value for society. Profits are not the starting point—they are the result of delivering meaningful value and optimizing the processes behind it. This philosophy is beautifully illustrated by the story of <a href="https://en.wikipedia.org/wiki/Isaac_Carasso">Isaac Carasso</a>, the founder of Danone, whose mission to improve children’s nutrition laid the foundation for a global brand.</p>

<h3 id="the-core-principle-value-creation-comes-first">The Core Principle: Value Creation Comes First</h3>

<p>The most impactful businesses begin with a purpose beyond profit. They identify a societal need—a gap in health, education, connection, or convenience—and build solutions to address it. Only after delivering that value can a company capture a portion of it as profit, provided it has optimized its operations to balance quality and efficiency.</p>

<p>This approach flips the traditional mindset. Instead of chasing revenue, visionary entrepreneurs ask: <em>What problem can I solve?</em> When the solution resonates, customers respond, and financial success follows as a byproduct. But it all hinges on two critical steps: first, creating genuine value, and second, refining the processes to deliver that value sustainably.</p>

<h3 id="isaac-carasso-and-the-danone-legacy">Isaac Carasso and the Danone Legacy</h3>

<p>A shining example of this philosophy is Isaac Carasso, the founder of Danone. In the early 20th century, Carasso, a Sephardic Jewish immigrant from Thessaloniki, settled in Barcelona. At the time, many children in Europe suffered from digestive issues and malnutrition, exacerbated by a lack of accessible, nutritious food. Inspired by the emerging science of gut health and the work of Nobel laureate Élie Metchnikoff, Carasso saw an opportunity to make a difference.</p>

<p>He began producing yogurt, a food rich in probiotics that could improve digestion and overall health. In 1919, he founded Danone, naming it after his son Daniel’s nickname, “Danon.” Carasso’s mission was clear: to provide a nutritious, affordable product that would help children grow stronger and healthier. His focus wasn’t on immediate profits but on addressing a pressing societal need.</p>

<p>Carasso’s approach was rooted in value creation. He sourced high-quality bacterial cultures, ensured rigorous production standards, and made yogurt accessible through pharmacies, positioning it as a health product rather than a luxury. By prioritizing quality and purpose, he built trust with consumers. Only later, as Danone grew, did he refine production processes to scale efficiently, capturing value through profitability without compromising his mission.</p>

<h3 id="lessons-for-todays-entrepreneurs">Lessons for Today’s Entrepreneurs</h3>

<p>Isaac Carasso’s story offers timeless lessons for modern businesses:</p>

<ol>
  <li>
    <p><strong>Start with a Purpose</strong>: Identify a real problem and build a solution that matters. For Carasso, it was children’s health; for your business, it could be sustainability, education, or community empowerment.</p>
  </li>
  <li>
    <p><strong>Prioritize Quality Over Quick Wins</strong>: Delivering value means ensuring your product or service genuinely improves lives. Cutting corners may boost short-term profits but erodes long-term trust.</p>
  </li>
  <li>
    <p><strong>Optimize for Sustainability</strong>: Once you’ve created value, focus on efficiency. Streamline operations, reduce costs, and scale responsibly to capture value without diluting your mission.</p>
  </li>
  <li>
    <p><strong>Build Trust Through Impact</strong>: Carasso’s commitment to health earned him loyalty that transcended borders. Today, Danone remains a global leader because its foundation was built on purpose, not profit.</p>
  </li>
</ol>

<h3 id="conclusion-value-as-the-foundation-of-success">Conclusion: Value as the Foundation of Success</h3>

<p>Isaac Carasso’s journey with Danone reminds us that businesses thrive when they prioritize societal value over immediate financial gain. Profits are the reward for solving problems effectively and efficiently, not the starting point. Whether you’re launching a startup or leading an established company, the lesson is clear: create value first, optimize relentlessly, and the rewards will follow.</p>

<p>As entrepreneurs and innovators, let’s take inspiration from Carasso’s vision. What value can you bring to the world? Start there, and the rest will fall into place.</p>]]></content><author><name>Daniel Vela</name></author><summary type="html"><![CDATA[When we think about successful businesses, it’s easy to focus on profits, market share, or stock prices. But at the heart of every enduring company lies a fundamental truth: businesses exist to create value for society. Profits are not the starting point—they are the result of delivering meaningful value and optimizing the processes behind it. This philosophy is beautifully illustrated by the story of Isaac Carasso, the founder of Danone, whose mission to improve children’s nutrition laid the foundation for a global brand.]]></summary></entry></feed>