<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yong Yu</title>
    <description>The latest articles on DEV Community by Yong Yu (@yong_yu_f98e15562e9b120a0).</description>
    <link>https://dev.to/yong_yu_f98e15562e9b120a0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4111445%2F9d2f3d6e-4942-4b84-90f1-c3f0ff3b5479.jpg</url>
      <title>DEV Community: Yong Yu</title>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yong_yu_f98e15562e9b120a0"/>
    <language>en</language>
    <item>
      <title>Muse Spark Open Is Out: Reasoning You Can't Turn Off, KV-Cache Math at 128K vs 1M, and Hosted vs Mac vs GPU</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Fri, 16 Oct 2026 21:08:26 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/muse-spark-open-is-out-reasoning-you-cant-turn-off-kv-cache-math-at-128k-vs-1m-and-hosted-vs-181c</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/muse-spark-open-is-out-reasoning-you-cant-turn-off-kv-cache-math-at-128k-vs-1m-and-hosted-vs-181c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + two small offline scripts&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (all 2026-10-15):&lt;/strong&gt; Meta AI Research, &lt;a href="https://research.meta.ai/blog/muse-spark-open" rel="noopener noreferrer"&gt;Introducing Muse Spark Open&lt;/a&gt;; Hugging Face, &lt;a href="https://huggingface.co/blog/meta-muse-spark-open" rel="noopener noreferrer"&gt;Welcome Muse Spark Open&lt;/a&gt; by &lt;strong&gt;Pedro Cuenca&lt;/strong&gt;; Baseten, &lt;a href="https://www.baseten.co/blog/muse-spark-open-launch/" rel="noopener noreferrer"&gt;Muse Spark Open, an open-weight model for coding agents&lt;/a&gt; by &lt;strong&gt;Marylise Tauzia&lt;/strong&gt;; Meta developer docs: &lt;a href="https://dev.meta.ai/docs/muse-spark-open/get-the-model" rel="noopener noreferrer"&gt;Get the model&lt;/a&gt;, &lt;a href="https://dev.meta.ai/docs/muse-spark-open/deploy" rel="noopener noreferrer"&gt;Run inference&lt;/a&gt;, &lt;a href="https://dev.meta.ai/docs/muse-spark-open/prompting" rel="noopener noreferrer"&gt;Prompting guide&lt;/a&gt;, &lt;a href="https://dev.meta.ai/docs/muse-spark-open/settings" rel="noopener noreferrer"&gt;Recommended settings&lt;/a&gt;; &lt;a href="https://openrouter.ai/meta/muse-spark-open" rel="noopener noreferrer"&gt;OpenRouter: meta/muse-spark-open&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
I have &lt;strong&gt;not&lt;/strong&gt; downloaded or served the weights (the HF repo is gated, and this box has no GPU). The scripts below are arithmetic on published architecture values and list prices.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Meta released the weights for &lt;strong&gt;Muse Spark Open&lt;/strong&gt;: an &lt;strong&gt;816B-total / ~42B-active&lt;/strong&gt; mixture-of-experts model with a &lt;strong&gt;1M-token&lt;/strong&gt; context. It takes text, image, audio and video as input and returns text. Meta calls it "the most capable US open-weight model to date" and aims it at coding and agentic work. Hosted APIs went live on day 0 (Baseten, Fireworks AI, Groq, Modal, Nebius, OpenRouter, Together AI), and weights are on Hugging Face in &lt;strong&gt;BF16&lt;/strong&gt; and &lt;strong&gt;NVFP4&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Benchmarks will get argued about all week. This post covers three things that will actually bite you on the first day: reasoning can't be switched off, the KV cache is much smaller than the parameter count suggests, and choosing between hosted, Mac and GPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture numbers that matter
&lt;/h2&gt;

&lt;p&gt;From the HF blog and Meta's docs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Parameters&lt;/td&gt;
&lt;td&gt;~816B total, ~42B active per token (Baseten: 42.7B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Experts&lt;/td&gt;
&lt;td&gt;256 per MoE layer, 8 routed per token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decoder&lt;/td&gt;
&lt;td&gt;62 layers, hidden 8192, 128 query heads, &lt;strong&gt;16 KV heads&lt;/strong&gt;, head dim &lt;strong&gt;64&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attention schedule&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;46 sliding-window layers (2,048 tokens) + 16 full-attention layers&lt;/strong&gt; (Meta settings doc; Baseten adds that the global layers use NoPE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;max_position_embeddings&lt;/code&gt; = 1,048,576&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checkpoints&lt;/td&gt;
&lt;td&gt;BF16 ~1.65 TB (Meta) / NVFP4 ~537 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Baseten's post also describes a &lt;strong&gt;compressed MoE block&lt;/strong&gt;. A shared pooler shrinks the vector before it reaches the experts, and a shared unpooler expands it afterwards. This halves each expert, which Baseten says removes roughly 800B parameters compared with an uncompressed design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha 1: reasoning is always on, and it eats &lt;code&gt;max_tokens&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;From Meta's Run inference doc: the reasoning goes into &lt;code&gt;reasoning_content&lt;/code&gt; and the answer goes into &lt;code&gt;content&lt;/code&gt;, and &lt;strong&gt;"both are drawn from the same &lt;code&gt;max_tokens&lt;/code&gt; budget."&lt;/strong&gt; If the budget is too small, it all goes to reasoning and you get an &lt;strong&gt;empty &lt;code&gt;content&lt;/code&gt; with &lt;code&gt;finish_reason: "length"&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Three more details from the docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The default is &lt;code&gt;xhigh&lt;/code&gt;.&lt;/strong&gt; The chat template maps &lt;code&gt;low / medium / high / xhigh&lt;/code&gt; to strengths &lt;strong&gt;8 / 32 / 256 / 512&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There is no off switch.&lt;/strong&gt; &lt;code&gt;"none"&lt;/code&gt; and &lt;code&gt;"max"&lt;/code&gt; are rejected. If you want cheap calls, use &lt;code&gt;low&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A system-prompt line wins.&lt;/strong&gt; &lt;code&gt;Reasoning strength: 256.&lt;/code&gt; in the system prompt overrides &lt;code&gt;reasoning_effort&lt;/code&gt;. Streaming is recommended for high/xhigh so you don't hit timeouts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A request that won't silently return nothing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"meta-models/Muse-Spark-Open-816B-A42B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Find the race condition in this worker-pool design."&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16384&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;runs/20-muse-spark-open/budget.py&lt;/code&gt; simulates the shared budget. The reasoning lengths in it are &lt;strong&gt;hypothetical&lt;/strong&gt;, chosen only to show the failure modes, not measured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;max_tokens=  1024 reasoning=3000 answer=400: EMPTY content, finish_reason=length
max_tokens=  4096 reasoning=3000 answer=400: ok
max_tokens=  4096 reasoning=3800 answer=400: TRUNCATED answer
max_tokens= 16384 reasoning=3000 answer=400: ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice: set &lt;code&gt;reasoning_effort&lt;/code&gt; explicitly on every call. Treat an empty &lt;code&gt;content&lt;/code&gt; with &lt;code&gt;length&lt;/code&gt; as a budget bug, not a model failure, and log &lt;code&gt;completion_tokens_details.reasoning_tokens&lt;/code&gt; (Meta's reasoning doc says reasoning tokens are billed at the output rate).&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha 2 (a good one): the KV cache is small for an 816B model
&lt;/h2&gt;

&lt;p&gt;Each token stores K and V for 16 heads × 64 dims per layer: 4,096 bytes per layer in BF16. The HF blog multiplies that across all 62 layers and gets ~250 KB/token, or ~266 GB for a 1M context. That is the upper bound. Meta's settings doc says only the 16 full-attention layers keep the whole context. The 46 sliding-window layers are capped at 2,048 tokens.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;runs/20-muse-spark-open/kv_cache.py&lt;/code&gt; computes both, per sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;LAYERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOCAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GLOBAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WINDOW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;
&lt;span class="n"&gt;KV_HEADS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kv_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bpe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hybrid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;KV_HEADS&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;bpe&lt;/span&gt;          &lt;span class="c1"&gt;# K+V per layer per token
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;hybrid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;LAYERS&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;GLOBAL&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;LOCAL&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WINDOW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actual output (Python 3.13.5, run 2026-10-16):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   context dtype  all-global GiB  hybrid GiB  ratio
    32,768  BF16            7.75        2.36   3.28x
   131,072  BF16           31.00        8.36   3.71x
   131,072   FP8           15.50        4.18   3.71x
   262,144  BF16           62.00       16.36   3.79x
 1,048,576  BF16          248.00       64.36   3.85x
 1,048,576   FP8          124.00       32.18   3.85x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 128K row matches Baseten's published &lt;strong&gt;31 GiB → 8.4 GiB (~3.7×)&lt;/strong&gt; exactly. A full 1M context costs about &lt;strong&gt;64 GiB in BF16&lt;/strong&gt; (about 32 GiB if your runtime stores KV in FP8), not 248 GiB. With 100 GiB free after weights, that's about &lt;strong&gt;11&lt;/strong&gt; sessions at 128K and &lt;strong&gt;one&lt;/strong&gt; at 1M, before paging overhead. This is why Meta recommends setting &lt;code&gt;--max-model-len&lt;/code&gt; / &lt;code&gt;--context-length&lt;/code&gt; to what your workload needs instead of the full window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosted vs Mac vs GPU
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hosted (start here).&lt;/strong&gt; OpenRouter lists &lt;strong&gt;$1.25 / $4.25 per 1M&lt;/strong&gt; input/output tokens, $0.15/M cache reads, five providers, a 1,048,576-token context and up to 262,144 completion tokens. Baseten lists the same prices and serves NVFP4 with the full 1M context. My &lt;code&gt;budget.py&lt;/code&gt; arithmetic at list price: a 60K-in / 4K-out agent turn costs &lt;strong&gt;$0.092&lt;/strong&gt;. With 50K of that served from cache it's &lt;strong&gt;$0.037&lt;/strong&gt;, so 1,000 such turns come to about &lt;strong&gt;$37&lt;/strong&gt;. Remember that the 4K output includes reasoning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://openrouter.ai/api/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta/muse-spark-open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Review: def div(a, b): return a / b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;reasoning_effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;finish_reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Not run here. I don't have an OpenRouter key on the box.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mac (for tinkering, not serving).&lt;/strong&gt; HF tested it on an &lt;strong&gt;M3 Ultra with 512 GB&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;llama.cpp Q2_K: ~304 GB, ~18 tok/s&lt;/li&gt;
&lt;li&gt;oMLX oQ3e: ~344 GB, ~225 tok/s prefill and ~21 tok/s generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even the 3-bit quant needs more than 256 GB of RAM. The model card also says it's optimized for two Mac Studios with M5 Ultra using MLX. Fine for private experiments. Too slow for agent loops at &lt;code&gt;xhigh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPU (when you need control or volume).&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NVFP4: Meta's recipe uses TP4/EP4 on 4× B300. SGLang's reference runs it on 4× GB300.&lt;/li&gt;
&lt;li&gt;BF16: TP8/EP8 on 8× B300.&lt;/li&gt;
&lt;li&gt;HF Inference Endpoints has a preset recipe on 8× RTX Pro 6000 (128K context) or 8× H200 (1M).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NVFP4 needs Blackwell. Size the context to the KV table above, not to the marketing number.&lt;/p&gt;

&lt;p&gt;My rule: start hosted, at &lt;code&gt;low&lt;/code&gt; or &lt;code&gt;medium&lt;/code&gt; with a large &lt;code&gt;max_tokens&lt;/code&gt;. Move to dedicated GPUs only when you need data residency, fine-tuning (HF shows LoRA via TRL on 64× H100) or steady volume that beats the per-token price. Use the Mac when you want to poke at it offline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;The useful lesson here goes beyond this one model. A hybrid local/global attention schedule makes long context about 3.7–3.9× cheaper in memory, and an always-on reasoning budget turns &lt;code&gt;max_tokens&lt;/code&gt; into a correctness setting. Both are worth checking in your own harness before you look at any leaderboard.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Grok Voice 3.0 Just Landed: First Realtime Session, Full Duplex, and Why $0.08/min Beats Guessing Latency</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Thu, 15 Oct 2026 13:19:32 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/grok-voice-30-just-landed-first-realtime-session-full-duplex-and-why-008min-beats-guessing-mm0</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/grok-voice-30-just-landed-first-realtime-session-full-duplex-and-why-008min-beats-guessing-mm0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small offline smoke test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (xAI / SpaceXSI, ~2026-10-14/15):&lt;/strong&gt; &lt;a href="https://x.ai/news/grok-voice-3" rel="noopener noreferrer"&gt;Introducing Grok Voice 3.0&lt;/a&gt; (announcement), &lt;a href="https://docs.x.ai/developers/model-capabilities/audio/speech-to-speech" rel="noopener noreferrer"&gt;Speech to Speech&lt;/a&gt; docs, &lt;a href="https://docs.x.ai/developers/models/grok-voice-3.0" rel="noopener noreferrer"&gt;Grok Voice 3.0 model page&lt;/a&gt;, and &lt;a href="https://docs.x.ai/developers/release-notes" rel="noopener noreferrer"&gt;Release notes&lt;/a&gt; (October: Voice 3.0 available; Voice 2.0 deprecated)&lt;br&gt;&lt;br&gt;
Benchmark rows below are &lt;strong&gt;Artificial Analysis&lt;/strong&gt; (Speech-to-Speech Index, dated October 13, 2026 on the announcement), &lt;strong&gt;xAI&lt;/strong&gt; product claims, and &lt;strong&gt;ServiceNow&lt;/strong&gt; EVA-Bench (Nitin Aggarwal quote on the announcement). No &lt;code&gt;XAI_API_KEY&lt;/code&gt; on this box — &lt;strong&gt;I did not open a live WebSocket&lt;/strong&gt;. The run below is an offline model-id / &lt;code&gt;session.update&lt;/code&gt; / mock-event linter only.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;xAI shipped &lt;strong&gt;Grok Voice 3.0&lt;/strong&gt; into the Voice Agent API at the same list price as Voice 2.0: &lt;strong&gt;$0.08 / min ($4.80 / hr)&lt;/strong&gt;. If your agents already use the &lt;code&gt;grok-voice-latest&lt;/code&gt; alias, the announcement says they were switched to 3.0 automatically — same endpoint, same session fields, same events.&lt;/p&gt;

&lt;p&gt;The product pitch is speech-to-speech for support-style agents: under-one-second class latency (xAI), Full Duplex Bench at &lt;strong&gt;97%&lt;/strong&gt; (Artificial Analysis), and Tesla / Starlink production numbers on the announcement. This post is the practical first session: WebSocket URL, a clean &lt;code&gt;session.update&lt;/code&gt;, duplex/&lt;code&gt;server_vad&lt;/code&gt;, tools, cost arithmetic at list, and what the alias auto-upgrade means for pinned clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the announcement actually claims
&lt;/h2&gt;

&lt;p&gt;Artificial Analysis numbers as printed on the Grok Voice 3.0 post (source line: Artificial Analysis, October 13, 2026):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;Grok Voice 3.0&lt;/th&gt;
&lt;th&gt;Grok Voice 2.0&lt;/th&gt;
&lt;th&gt;GPT-Live-1 (Astra, Medium)&lt;/th&gt;
&lt;th&gt;Gemini 3.8 Live (Ext. Thinking, High)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Overall AA Speech-to-Speech Index&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;86.9&lt;/strong&gt; (#1)&lt;/td&gt;
&lt;td&gt;81.3&lt;/td&gt;
&lt;td&gt;83.2&lt;/td&gt;
&lt;td&gt;82.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speech Reasoning Big Bench Audio&lt;/td&gt;
&lt;td&gt;98.5%&lt;/td&gt;
&lt;td&gt;97.2%&lt;/td&gt;
&lt;td&gt;90.1%&lt;/td&gt;
&lt;td&gt;97.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human Preference Speech Agent Arena Elo&lt;/td&gt;
&lt;td&gt;1070&lt;/td&gt;
&lt;td&gt;1011&lt;/td&gt;
&lt;td&gt;1048&lt;/td&gt;
&lt;td&gt;990&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task Success Rate&lt;/td&gt;
&lt;td&gt;94.8%&lt;/td&gt;
&lt;td&gt;94.6%&lt;/td&gt;
&lt;td&gt;87.4%&lt;/td&gt;
&lt;td&gt;89.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full Duplex Bench&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97.0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;95.1%&lt;/td&gt;
&lt;td&gt;94.9%&lt;/td&gt;
&lt;td&gt;91.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;τ-Voice (support calls with accents, noise, interruptions): &lt;strong&gt;71.6%&lt;/strong&gt;, described as comparable to GPT-Live-1 (Astra) at roughly &lt;strong&gt;40% lower latency&lt;/strong&gt;. On ServiceNow's &lt;strong&gt;EVA-Bench&lt;/strong&gt;, the announcement cites &lt;strong&gt;74%&lt;/strong&gt; accuracy and a Pareto frontier vs accuracy + customer experience; Nitin Aggarwal (ServiceNow) is quoted there saying 3.0 pairs top accuracy with a natural, responsive conversation.&lt;/p&gt;

&lt;p&gt;Production color from the same post (vendor numbers, not mine): millions of conversations a day across Tesla and SpaceX; Starlink ~&lt;strong&gt;20,000&lt;/strong&gt; calls/day, roughly &lt;strong&gt;70%&lt;/strong&gt; no human, &lt;strong&gt;1 in 4&lt;/strong&gt; sales calls ending in a purchase. Tesla framing splits &lt;strong&gt;Connectors&lt;/strong&gt; (calendar / email hands-free) from &lt;strong&gt;Grok Bot&lt;/strong&gt; (bigger tasks). Anecdotes, not a public SLA. I did not reproduce any benches.&lt;/p&gt;

&lt;h2&gt;
  
  
  First realtime session (WebSocket)
&lt;/h2&gt;

&lt;p&gt;Docs endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wss://api.x.ai/v1/realtime?model=grok-voice-3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auth: Bearer &lt;code&gt;XAI_API_KEY&lt;/code&gt; on the server, or an ephemeral token (&lt;code&gt;xai-client-secret.…&lt;/code&gt;) for browsers. Model query params that matter:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model id&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grok-voice-latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alias → currently &lt;strong&gt;3.0&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grok-voice-3.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pin this release&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grok-voice-2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Deprecated&lt;/strong&gt; (same price; upgrade to 3.0 / latest)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A minimal &lt;code&gt;session.update&lt;/code&gt; after connect (shape from the Speech to Speech docs):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"session.update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"session"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"instructions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a concise support agent. Ask before issuing credits."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"turn_detection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server_vad"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web_search"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"function"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"issue_credit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Issue a billing credit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"amount_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"amount_usd"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reasoning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Acme Mobile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Acme Mobull"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;turn_detection.type = server_vad&lt;/code&gt;, stream mic audio via &lt;code&gt;input_audio_buffer.append&lt;/code&gt; (or binary if &lt;code&gt;audio.input.transport&lt;/code&gt; is &lt;code&gt;binary&lt;/code&gt;) and let the server handle turn boundaries — the duplex / barge-in path. Without VAD you commit/clear yourself.&lt;/p&gt;

&lt;p&gt;Untested live sketch (&lt;code&gt;websockets&lt;/code&gt; + a real key; &lt;strong&gt;not run against the API&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;websockets&lt;/span&gt;  &lt;span class="c1"&gt;# untested live against api.x.ai
&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;voice_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wss://api.x.ai/v1/realtime?model=grok-voice-3.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;XAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;websockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;additional_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session.update&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;voice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;turn_detection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;server_vad&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="c1"&gt;# ... append audio / conversation.item.create / response.create ...
&lt;/span&gt;        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# asyncio.run(voice_agent())  # do not run without a key and audio path
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same-session tools: &lt;code&gt;web_search&lt;/code&gt;, &lt;code&gt;x_search&lt;/code&gt;, &lt;code&gt;file_search&lt;/code&gt;, &lt;code&gt;mcp&lt;/code&gt;, and client &lt;code&gt;function&lt;/code&gt; tools. Server-side tools run on SpaceXSI; only custom functions need your &lt;code&gt;conversation.item.create&lt;/code&gt; + &lt;code&gt;response.create&lt;/code&gt; loop. Pronunciation &lt;code&gt;replace&lt;/code&gt; fixes spoken audio without changing the visible transcript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost arithmetic (list price, not a bill)
&lt;/h2&gt;

&lt;p&gt;Announcement list: &lt;strong&gt;$0.08 / min = $4.80 / hr&lt;/strong&gt;, unchanged from Voice 2.0.&lt;/p&gt;

&lt;p&gt;Illustrative only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1,000 support calls × 3 minutes = 3,000 minutes → &lt;strong&gt;$240&lt;/strong&gt; at list.&lt;/li&gt;
&lt;li&gt;Starlink-scale illustration using the announcement's ~20k calls/day: at 2 / 4 / 6 minute averages → &lt;strong&gt;$3,200 / $6,400 / $9,600 per day&lt;/strong&gt; at list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Arithmetic on published list rates and call volume — not an invoice. If duplex cuts average handle time by a minute, list saving is $0.08 per call before quality metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually ran (offline)
&lt;/h2&gt;

&lt;p&gt;No xAI key on the box, so &lt;code&gt;runs/19-grok-voice-3/preflight.py&lt;/code&gt; only checks shapes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;grok-voice-3.0&lt;/code&gt; / &lt;code&gt;grok-voice-latest&lt;/code&gt; → OK; &lt;code&gt;grok-voice-2.0&lt;/code&gt; → deprecated warning; prompt-shaped and fake ids → rejected.&lt;/li&gt;
&lt;li&gt;Clean &lt;code&gt;session.update&lt;/code&gt; (voice &lt;code&gt;eve&lt;/code&gt;, &lt;code&gt;server_vad&lt;/code&gt;, web/x/function tools, &lt;code&gt;replace&lt;/code&gt;, reasoning effort, json transport) → OK.&lt;/li&gt;
&lt;li&gt;Missing voice / bad &lt;code&gt;turn_detection&lt;/code&gt; / unknown tool type → flagged.&lt;/li&gt;
&lt;li&gt;List-price math prints the $240 and Starlink-scale day figures above.&lt;/li&gt;
&lt;li&gt;Hand-built mock stream (&lt;code&gt;session.updated&lt;/code&gt; → &lt;code&gt;response.output_audio.delta&lt;/code&gt; → &lt;code&gt;response.done&lt;/code&gt;) parses; missing &lt;code&gt;delta&lt;/code&gt; and unknown event types raise &lt;code&gt;ValueError&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Smoke test of &lt;strong&gt;your client contract&lt;/strong&gt;, not of Grok Voice 3.0. Full stdout: &lt;code&gt;run_output.txt&lt;/code&gt; (2026-10-15, Python 3.13, exit 0).&lt;/p&gt;

&lt;h2&gt;
  
  
  Alias auto-upgrade vs pinning
&lt;/h2&gt;

&lt;p&gt;Release notes and the Speech to Speech upgrade section agree: &lt;strong&gt;&lt;code&gt;grok-voice-latest&lt;/code&gt; already points at 3.0&lt;/strong&gt;, Voice 2.0 is deprecated, API surface unchanged, price unchanged. Two practical implications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;If you used the alias&lt;/strong&gt;, you are already on 3.0 — verify behavior (reasoning default is &lt;code&gt;"high"&lt;/code&gt; on 3.0 per the migration notes) rather than assuming a silent quality-only bump.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you pinned &lt;code&gt;grok-voice-2.0&lt;/code&gt;&lt;/strong&gt;, change the query param to &lt;code&gt;grok-voice-3.0&lt;/code&gt; (or latest). Deprecation is not the same as free forever; pin deliberately for prod, track release notes for the next alias flip.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Tesla product split is a useful design hint: &lt;strong&gt;Connectors-style&lt;/strong&gt; tools for short reversible actions (calendar, email) vs &lt;strong&gt;Grok Bot-style&lt;/strong&gt; loops for multi-step work with approvals. Same voice model, different authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I'd try it this week
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pin &lt;code&gt;grok-voice-3.0&lt;/code&gt; in a staging WebSocket&lt;/strong&gt; and send one &lt;code&gt;session.update&lt;/code&gt; with &lt;code&gt;server_vad&lt;/code&gt; + a single &lt;code&gt;function&lt;/code&gt; tool you already trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure barge-in and tool overlap audiowise&lt;/strong&gt; — docs warn that sending &lt;code&gt;response.create&lt;/code&gt; before prior audio finishes causes overlap; wait for playback (or nearly) after function outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget at $0.08/min&lt;/strong&gt; with a hard max session length before you chase Elo screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep irreversible tools behind confirmation&lt;/strong&gt; — credits, shipments, and outbound messages are still your harness's job.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Speech-to-speech rankings move weekly. What is copyable here is boring and useful: a stable realtime URL, unchanged session schema, an AA Full Duplex number, flat per-minute list price, and an alias that already moved. Build the duplex + tool harness once; swap pins when the next index drops.&lt;/p&gt;

&lt;p&gt;I have not called the Voice Agent API. Start with a keyed ping and one scripted support turn with approvals on.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>voice</category>
    </item>
    <item>
      <title>Coinbase's 9B Fraud Model Beat Opus 4.5: Copy the Pattern With a Verifiable Reward, Tier-Only Output, and Block-Only Harness</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Wed, 14 Oct 2026 13:27:20 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/coinbases-9b-fraud-model-beat-opus-45-copy-the-pattern-with-a-verifiable-reward-tier-only-4m05</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/coinbases-9b-fraud-model-beat-opus-45-copy-the-pattern-with-a-verifiable-reward-tier-only-4m05</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small offline run on synthetic data&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (Coinbase Engineering, "Owning Intelligence" series):&lt;/strong&gt; &lt;a href="https://www.coinbase.com/blog/part-one-how-coinbase-built-evaluated-and-post-trained-a-fraud-agent" rel="noopener noreferrer"&gt;Part 1/3 — Build&lt;/a&gt; by &lt;strong&gt;Yao Ma, Bo Lei, Xuwei Tan&lt;/strong&gt; (2026-10-06), &lt;a href="https://www.coinbase.com/blog/part-two-owning-intelligence-series" rel="noopener noreferrer"&gt;Part 2/3 — Evaluate&lt;/a&gt; by &lt;strong&gt;Yao Ma, Xuwei Tan&lt;/strong&gt; (2026-10-07), and &lt;a href="https://www.coinbase.com/blog/part-three-owning-intelligence-series" rel="noopener noreferrer"&gt;Part 3/3 — Own&lt;/a&gt; by &lt;strong&gt;Yao Ma, Xuwei Tan, Akshit Trehan, Aman Choudhary&lt;/strong&gt; with the Anyscale team (&lt;strong&gt;Eric Tang, Sumanth Hegde, Seiji Eicher, Jess Kong&lt;/strong&gt;) (2026-10-08)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Also:&lt;/strong&gt; &lt;a href="https://x.com/brian_armstrong/status/2109412046244913643" rel="noopener noreferrer"&gt;Brian Armstrong on X&lt;/a&gt; (2026-10-11); secondary coverage by &lt;a href="https://dealroom.co/news/161689-coinbase-post-trains-an-open-weight-9b-model-that-beats-opus-4-5-at-frau/" rel="noopener noreferrer"&gt;Dealroom&lt;/a&gt;, &lt;a href="https://cryptobriefing.com/coinbase-qwen-model-fraud-prevention/" rel="noopener noreferrer"&gt;Crypto Briefing&lt;/a&gt; (Diego Almada Lopez), &lt;a href="https://coincentral.com/coinbase-ai-agent-outperforms-opus-in-fraud-tests" rel="noopener noreferrer"&gt;CoinCentral&lt;/a&gt;, and &lt;a href="https://hdatf.com/ax-cases/ax137" rel="noopener noreferrer"&gt;HDATF AX case 137&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Every benchmark, latency and cost number about Coinbase's system is &lt;strong&gt;Coinbase's&lt;/strong&gt;, measured on their private data. I did not train anything. The run below is a tiny eval harness on a &lt;strong&gt;synthetic, seeded&lt;/strong&gt; transaction set.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The headline that went around X this week: Coinbase post-trained open-weight &lt;strong&gt;Qwen3.5-9B&lt;/strong&gt; on its own Onramp fraud data, and it beat Claude Opus 4.5 on Coinbase's fraud benchmark. Brian Armstrong's take was that specialist models will "out perform on more narrow tasks."&lt;/p&gt;

&lt;p&gt;The model swap is the least copyable part. The useful part is the system around it. That's what this post covers, plus a harness you can run on a laptop in under a second (the optional small-model reviewer takes a few minutes on CPU).&lt;/p&gt;

&lt;h2&gt;
  
  
  What Coinbase actually built
&lt;/h2&gt;

&lt;p&gt;From Part 1, in my own words:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Layered, not replaced.&lt;/strong&gt; Onramp sends a transaction to a Risk Service. The existing ML model and rules engine screen it first. The LLM agent sits &lt;em&gt;downstream&lt;/em&gt; and reviews only &lt;strong&gt;selected&lt;/strong&gt; transactions, using recent transaction history plus written review guidance and calibration examples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier-only output.&lt;/strong&gt; The model returns a risk level (their example is &lt;code&gt;RISK_LEVEL: 5&lt;/code&gt;) with no explanation. With a ~7,000-token prompt, Opus had a P50 of about 1.5 s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The harness decides.&lt;/strong&gt; Application code builds the context, parses the tier, and applies the decision policy. The model never executes a payment action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block-only authority.&lt;/strong&gt; The agent can block something upstream allowed. It cannot override an upstream block.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In a 50% traffic A/B test, the agent-enabled arm had &lt;strong&gt;30% fewer fraudulent transactions and 22% less fraud value&lt;/strong&gt;. Coinbase estimates fraud savings at roughly &lt;strong&gt;3×&lt;/strong&gt; the inference cost.&lt;/p&gt;

&lt;p&gt;Part 2 built a fixed benchmark: &lt;strong&gt;16,140 transactions from 7,293 users, 813 confirmed fraud&lt;/strong&gt;, taken from nine weeks &lt;em&gt;before&lt;/em&gt; the agent rolled out, so the agent's own blocks couldn't bias which outcomes got observed. Newer Opus, Sonnet and GPT versions each scored &lt;strong&gt;lower&lt;/strong&gt; on recall, F1 and dollar-weighted recall than the version before. GPT-5.6 (sol) gained 11.5 points of precision but lost 20.7 points of recall and 21.8 of dollar-weighted recall.&lt;/p&gt;

&lt;p&gt;Part 3 is the post-train: RLVR with GRPO and LoRA on SkyRL (on Anyscale), run on &lt;strong&gt;one RTX PRO 6000 96GB for under $100&lt;/strong&gt;. Against Opus 4.5 as a single-pass decision agent: &lt;strong&gt;+7.5 precision, +12.0 recall, +9.6 F1, +35.4 dollar-weighted recall&lt;/strong&gt;. The figure caption says these are percentage-point differences. Serving uses Ray Serve LLM + vLLM on L40S GPUs (2–8 replicas). P50 was &lt;strong&gt;0.683 s vs 1.515 s&lt;/strong&gt;, P99 &lt;strong&gt;1.036 s vs 3.312 s&lt;/strong&gt;. Coinbase notes that latency and detection were measured in separate evaluations. They also say the unadapted Qwen base "performed poorly."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the reward is "verifiable" here
&lt;/h2&gt;

&lt;p&gt;Most RL-for-LLM setups need a judge model to say whether an answer is good. Fraud doesn't. Historical transactions eventually get an outcome: chargeback or confirmed fraud, or not. So the reward is just a &lt;strong&gt;deterministic function of (model output, known label)&lt;/strong&gt;. Nothing gets graded on how persuasive it sounds.&lt;/p&gt;

&lt;p&gt;Part 3 adds two details worth copying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Format checks.&lt;/strong&gt; Unparseable output gets penalised.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Class balance.&lt;/strong&gt; If fraud is rare, "always say low risk" looks accurate. Their reward weights fraud and legit examples so a constant answer can't farm reward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GRPO then samples a group of answers to the same prompt and pushes the model toward the ones that scored above the group mean. You don't need a value network or a judge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why dollar-weighted recall, not just F1
&lt;/h2&gt;

&lt;p&gt;F1 counts incidents. One missed $5,000 cash-out counts the same as one missed $12 card test. Dollar-weighted recall asks what share of the fraud &lt;strong&gt;value&lt;/strong&gt; you caught. Part 2's point is that a model can miss relatively few transactions and still miss a large share of the money.&lt;/p&gt;

&lt;h2&gt;
  
  
  The run: a laptop-sized version of the pattern
&lt;/h2&gt;

&lt;p&gt;I wrote &lt;code&gt;fraud_tier_eval.py&lt;/code&gt;, about 200 lines of plain Python, plus an optional small-model reviewer. It runs on a &lt;strong&gt;synthetic&lt;/strong&gt; set (seed 18): 600 transactions, 47 labelled fraud worth $68,484.50 in total. I wrote the generator with three fraud shapes: card testing (many small buys), cash-out (one large buy, fresh card, new wallet), and quiet (mid-size, geo mismatch only). &lt;strong&gt;I designed the shapes, so the results show how the metrics behave. They don't show which reviewer is good.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The flow mirrors the pattern. Upstream rules block first. Routing picks 579/600 for review. Each reviewer returns only a string like &lt;code&gt;RISK_LEVEL: 4&lt;/code&gt;. The harness parses it with a strict regex and blocks at tier ≥ 4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upstream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reviewer_text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;upstream&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BLOCK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BLOCK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;upstream_block_kept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;# reviewer can never release
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reviewer_text&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALLOW&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_routed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviewer_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# ^RISK_LEVEL: ([1-5])$
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;upstream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parse_error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;          &lt;span class="c1"&gt;# log it, keep upstream decision
&lt;/span&gt;    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BLOCK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewer_block&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="nf"&gt;else &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALLOW&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewer_allow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reward function is the part a GRPO environment would call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;w_f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w_l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n_fraud&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n_legit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_fraud&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;
    &lt;span class="n"&gt;correct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;is_fraud&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;correct&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w_f&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_fraud&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;w_l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Printed results (2026-10-14, 8-vCPU Xeon, Python 3.13, CPU only):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Reviewer&lt;/th&gt;
&lt;th&gt;P&lt;/th&gt;
&lt;th&gt;R&lt;/th&gt;
&lt;th&gt;F1&lt;/th&gt;
&lt;th&gt;$-recall&lt;/th&gt;
&lt;th&gt;Legit $ blocked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;upstream rules only&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;td&gt;0.319&lt;/td&gt;
&lt;td&gt;0.484&lt;/td&gt;
&lt;td&gt;0.598&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;velocity (counts recent buys)&lt;/td&gt;
&lt;td&gt;0.714&lt;/td&gt;
&lt;td&gt;0.638&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.674&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.603&lt;/td&gt;
&lt;td&gt;846.55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;context (new wallet/card, amount vs history)&lt;/td&gt;
&lt;td&gt;0.379&lt;/td&gt;
&lt;td&gt;0.702&lt;/td&gt;
&lt;td&gt;0.493&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.979&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;49,411.22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d1-omni-600M, &lt;strong&gt;unadapted&lt;/strong&gt;, CPU&lt;/td&gt;
&lt;td&gt;0.455&lt;/td&gt;
&lt;td&gt;0.319&lt;/td&gt;
&lt;td&gt;0.375&lt;/td&gt;
&lt;td&gt;0.598&lt;/td&gt;
&lt;td&gt;12,521.50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What the run showed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;F1 and dollar-weighted recall picked different winners.&lt;/strong&gt; The velocity reviewer caught 24/29 card tests and none of the cash-outs that upstream let through: $-recall 0.603 vs 0.598 for upstream alone. The context reviewer caught 12/12 cash-outs ($-recall 0.979) but blocked $49,411.22 of legit purchases. Neither metric alone is enough. Track precision and legit-dollars-blocked next to them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A generic small model added nothing here.&lt;/strong&gt; LiquidAI's d1-omni-600M, prompted with a plain-English description of each transaction, added 18 blocks and every one was a false positive. Its recall stayed at the upstream 0.319. Median review time was 193.6 ms. That's one model on toy data, but it fits Coinbase's note that the unadapted base was weak and adaptation did the work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The class-balanced reward caught the lazy policy.&lt;/strong&gt; "Always &lt;code&gt;RISK_LEVEL: 1&lt;/code&gt;" had 0.922 plain accuracy and a mean reward of −0.000. The d1 reviewer scored −0.033.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The guard held, but it limits direction, not damage.&lt;/strong&gt; A deliberately buggy reviewer emitted &lt;code&gt;RELEASE&lt;/code&gt;, &lt;code&gt;RISK_LEVEL: 9&lt;/code&gt; and prose. That caused 344 parse errors, and every upstream block stayed blocked (asserted). It still added 111 random blocks, 104 of them legit. Block-only authority stops wrongful releases. It doesn't stop a broken model from blocking good customers, so alert on block rate too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GRPO-style group demo:&lt;/strong&gt; for one $4,733.38 cash-out, &lt;code&gt;RISK_LEVEL: 5&lt;/code&gt; and &lt;code&gt;RISK_LEVEL: 4&lt;/code&gt; scored +6.383 (advantage +0.935) and &lt;code&gt;RISK_LEVEL: 2&lt;/code&gt; scored −6.383. A correct tier with an explanation appended scored −1.0, so the format contract is part of the reward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not done:&lt;/strong&gt; no fine-tuning, no GRPO training run, no Qwen3.5-9B, no Coinbase data, no latency comparison with any frontier model. The set is tiny and synthetic. Files are in &lt;code&gt;runs/18-coinbase-specialist/&lt;/code&gt; (&lt;code&gt;fraud_tier_eval.py&lt;/code&gt;, &lt;code&gt;run_output.txt&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  When not to copy this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No trustworthy labels.&lt;/strong&gt; RLVR is only as good as the outcome label. If fraud confirmation is slow, noisy or missing, the reward becomes guesswork. Coinbase notes labels arrive late even for them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low volume.&lt;/strong&gt; Coinbase's benchmark alone had 813 confirmed fraud cases. If you have dozens, a prompted frontier model with a fixed eval set is cheaper to run and to reason about. That's my rule of thumb, not a Coinbase threshold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy that shifts weekly.&lt;/strong&gt; Part 1 points out that you can change natural-language guidance without retraining. Baked-in weights can't do that. If the rules move faster than you can retrain and re-evaluate, keep the policy in the prompt and the harness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No owner for the lifecycle.&lt;/strong&gt; Part 3's own checklist is to evaluate on domain outcomes, version weights, prompts and policy together, and keep a tested rollback. If no one owns those, don't self-host a model that sits in a payment flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I'd start this week
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Freeze a labelled eval set from a period &lt;em&gt;before&lt;/em&gt; any model touched decisions.&lt;/li&gt;
&lt;li&gt;Make the model return one parseable token. Put the policy in code.&lt;/li&gt;
&lt;li&gt;Score every candidate on precision, recall, F1, dollar-weighted recall and legit-dollars-blocked.&lt;/li&gt;
&lt;li&gt;Only then consider RL. The reward function you need is already in your eval harness.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Muse Wonder Just Landed: First muse-wonder-1.0 Call, Active Memory vs Active Focus, and Why max Isn't Wonder Full</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Tue, 13 Oct 2026 13:30:14 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/muse-wonder-just-landed-first-muse-wonder-10-call-active-memory-vs-active-focus-and-why-max-2n0c</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/muse-wonder-just-landed-first-muse-wonder-10-call-active-memory-vs-active-focus-and-why-max-2n0c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small offline smoke test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (Meta, 2026-10-12):&lt;/strong&gt; &lt;a href="https://research.meta.ai/blog/muse-wonder" rel="noopener noreferrer"&gt;Muse Wonder: A Frontier Model For Personal &amp;amp; Professional AI Agents&lt;/a&gt; (AI at Meta research blog), &lt;a href="https://dev.meta.ai/resources/blog/build-with-muse-wonder" rel="noopener noreferrer"&gt;Put your ideas to work with Muse Wonder and Muse Wonder Full&lt;/a&gt; by &lt;strong&gt;Josh Walters&lt;/strong&gt; (Meta), &lt;a href="https://research.meta.ai/static/muse-wonder-model-card" rel="noopener noreferrer"&gt;Muse Wonder Model Card&lt;/a&gt;, and the Meta Model API docs (&lt;a href="https://dev.meta.ai/docs/overview" rel="noopener noreferrer"&gt;overview&lt;/a&gt;, &lt;a href="https://dev.meta.ai/docs/models" rel="noopener noreferrer"&gt;models&lt;/a&gt;, &lt;a href="https://dev.meta.ai/docs/cookbook/quickstart-chat-completions" rel="noopener noreferrer"&gt;chat completions quickstart&lt;/a&gt;)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary:&lt;/strong&gt; &lt;a href="https://indianexpress.com/article/technology/artificial-intelligence/meta-muse-wonder-ai-frontier-model-explained-10919637/" rel="noopener noreferrer"&gt;Indian Express explainers&lt;/a&gt; (2026-10-13)&lt;br&gt;&lt;br&gt;
Benchmark and safety numbers are &lt;strong&gt;Meta's&lt;/strong&gt; (or third-party numbers they cite). No &lt;code&gt;MODEL_API_KEY&lt;/code&gt; on this box — &lt;strong&gt;I did not call Muse Wonder&lt;/strong&gt;. The run below is an offline request/response linter on hand-built mocks only.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Meta shipped &lt;strong&gt;Muse Wonder&lt;/strong&gt; and &lt;strong&gt;Muse Wonder Full&lt;/strong&gt; on 2026-10-12, into a feed already full of coding-agent head-to-heads. The pitch is not "another chat model." It is a frontier stack for &lt;strong&gt;personal and professional agents&lt;/strong&gt;: keep context across weeks (&lt;strong&gt;Active Memory&lt;/strong&gt;), keep working through blockers (&lt;strong&gt;Active Focus&lt;/strong&gt;), and survive long coding / computer-use jobs past turn three.&lt;/p&gt;

&lt;p&gt;Access is split on purpose. &lt;strong&gt;Muse Wonder&lt;/strong&gt; is on the Meta Model API and Muse Code at &lt;strong&gt;$4 / $20 per million tokens&lt;/strong&gt;. &lt;strong&gt;Muse Wonder Full&lt;/strong&gt; is Muse Code subscription only (Power and new Maximum Usage). That split is the catch when people paste &lt;code&gt;"reasoning_effort": "max"&lt;/code&gt; and expect Full.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Meta actually shipped
&lt;/h2&gt;

&lt;p&gt;From the research post and model card:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Muse Wonder&lt;/th&gt;
&lt;th&gt;Muse Wonder Full&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Where&lt;/td&gt;
&lt;td&gt;Model API + Muse Code&lt;/td&gt;
&lt;td&gt;Muse Code subscription only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model API id&lt;/td&gt;
&lt;td&gt;&lt;code&gt;muse-wonder-1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(not on Model API)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context&lt;/td&gt;
&lt;td&gt;1,048,576 tokens&lt;/td&gt;
&lt;td&gt;1M (same family)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modalities in&lt;/td&gt;
&lt;td&gt;text, image, video, audio&lt;/td&gt;
&lt;td&gt;same family&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modalities out&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;List price (API)&lt;/td&gt;
&lt;td&gt;$4 in / $0.20 cached in / $20 out per 1M&lt;/td&gt;
&lt;td&gt;included in Power / Maximum Usage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Docs say Wonder and Spark take the &lt;strong&gt;same request shapes&lt;/strong&gt;. Any Spark example becomes a Wonder call by changing the model string to &lt;code&gt;muse-wonder-1.0&lt;/code&gt;. Wonder is for longer, harder agent loops; Spark stays the cheaper default (and Contributor mode on Model API).&lt;/p&gt;

&lt;p&gt;Meta's product language for the two agent knobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active Memory&lt;/strong&gt; — carry what matters about you across conversations, and retrieve the bits that are relevant to the current task (not "dump the whole history into the prompt and hope").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active Focus&lt;/strong&gt; — keep pushing on a hard goal: try alternatives, work through blockers, ask when stuck, check in before consequential actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coding is where they claim those two meet: multi-file edits, long test/fix cycles, sub-agents, computer use. Treat DeepSWE / SWE-Marathon / PSI / Harvey LAB-AA rows as &lt;strong&gt;vendor or cited third-party scores&lt;/strong&gt;. I did not reproduce them.&lt;/p&gt;

&lt;h2&gt;
  
  
  First call (Chat Completions)
&lt;/h2&gt;

&lt;p&gt;Base URL is &lt;code&gt;https://api.meta.ai/v1&lt;/code&gt;. Auth is a Bearer &lt;code&gt;MODEL_API_KEY&lt;/code&gt;. OpenAI SDK drop-in:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.meta.ai/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MODEL_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;muse-wonder-1.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;developer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Be concise. Ask before irreversible actions.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I am wiring a personal agent that must remember lease clauses &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;across chats. In five bullets, what should go in durable memory &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vs what should stay in the current turn only?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.meta.ai/v1/chat/completions"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$MODEL_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "muse-wonder-1.0",
    "messages": [
      {"role": "user", "content": "Reply with the single word: ready"}
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things the docs make easy to miss:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prefer &lt;code&gt;developer&lt;/code&gt; over &lt;code&gt;system&lt;/code&gt;&lt;/strong&gt; for steering. &lt;code&gt;system&lt;/code&gt; still shows up in old OpenAI snippets; Meta's quickstart steers with &lt;code&gt;developer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do not send &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;logit_bias&lt;/code&gt;, or &lt;code&gt;reasoning_effort: "none"&lt;/code&gt;.&lt;/strong&gt; Reasoning Muse models return HTTP 400 on those.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;max&lt;/code&gt; on Wonder ≠ Wonder Full.&lt;/strong&gt; Model card and models page say Full is subscription-only in Muse Code; cranking reasoning effort on &lt;code&gt;muse-wonder-1.0&lt;/code&gt; does not promote you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For serious agent loops (tools, search grounding, file IDs, server-managed state), Meta points you at the &lt;strong&gt;Responses API&lt;/strong&gt; rather than raw Chat Completions. Chat Completions is still the right first ping and the path for simple multi-turn arrays you already have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost arithmetic (list price, not a bill)
&lt;/h2&gt;

&lt;p&gt;Josh Walters' post lists Wonder at &lt;strong&gt;$4 input / $20 output&lt;/strong&gt; per million tokens, with &lt;strong&gt;$0.20&lt;/strong&gt; cached input on the pricing card.&lt;/p&gt;

&lt;p&gt;Illustrative only: 50,000 calls × 4,000 prompt tokens × 800 completion tokens ≈ &lt;strong&gt;$800 input + $800 output = $1,600&lt;/strong&gt; at list (ignores retries, tools, browsing, Muse Code plan floors). Same call with 3,500 of those 4,000 prompt tokens cached drops one-call list cost from about &lt;strong&gt;$0.032&lt;/strong&gt; to about &lt;strong&gt;$0.019&lt;/strong&gt;. That is why prompt caching matters once your agent system prompt and tool schemas stop changing every request.&lt;/p&gt;

&lt;p&gt;Wonder Full's economics are different: Muse Code Power / Maximum Usage quotas, not a public per-token meter. Launch-day quota bugs got a Meta reset — check your usage bar before a weekend marathon.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually ran (offline)
&lt;/h2&gt;

&lt;p&gt;No Meta key on the box, so I wrote a small preflight that only checks shapes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean &lt;code&gt;muse-wonder-1.0&lt;/code&gt; Chat Completions body → OK; Spark model id → OK (swap-compatible).&lt;/li&gt;
&lt;li&gt;Fake &lt;code&gt;muse-wonder-full-1.0&lt;/code&gt; + &lt;code&gt;reasoning_effort: "max"&lt;/code&gt; → flagged as &lt;strong&gt;not on Model API&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Legacy &lt;code&gt;prompt&lt;/code&gt; (no &lt;code&gt;messages&lt;/code&gt;) → rejected; &lt;code&gt;system&lt;/code&gt; + &lt;code&gt;stop&lt;/code&gt; + &lt;code&gt;reasoning_effort: "none"&lt;/code&gt; → doc warnings / 400s.&lt;/li&gt;
&lt;li&gt;Hand-built mock &lt;code&gt;choices[0].message.content&lt;/code&gt; parses; completions-v1-shaped mock raises &lt;code&gt;ValueError&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The $1,600 / $0.032 / $0.019 figures above are the same list-price arithmetic the linter prints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Smoke test of &lt;strong&gt;your client&lt;/strong&gt;, not of Muse Wonder. Scripts: &lt;code&gt;runs/17-muse-wonder/&lt;/code&gt; (&lt;code&gt;preflight.py&lt;/code&gt;, &lt;code&gt;run_output.txt&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Full / API catch (and the memory catch)
&lt;/h2&gt;

&lt;p&gt;Two product traps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Full is not an API model id.&lt;/strong&gt; If your eval harness hard-codes "use max reasoning to get the best Muse," you are still on Wonder for API traffic. For Full you need Muse Code on Power or Maximum Usage. Compare apples to apples when you paste Twitter win rates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Active Memory is not free durability.&lt;/strong&gt; The research framing is "carry important context across conversations and retrieve what matters." In &lt;em&gt;your&lt;/em&gt; agent, that still needs a store, a write policy, and a retrieve policy. Wonder does not magically make a stateless Chat Completions call remember last month's lease PDF. Put durable facts in a store you control; use the model to decide what to write and what to fetch. Meta's own card recommends human-in-the-loop confirmation for irreversible agent actions — that is the right default even with Active Focus.&lt;/p&gt;

&lt;p&gt;Also noted on the card: visual / 3D spatial work is a known weakness; harness and quantization change results; not intended for under-18 use. Read Meta's safety section before giving an agent real credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I'd try it this week
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ping Model API&lt;/strong&gt; with the curl above — confirm key, model id, and &lt;code&gt;usage&lt;/code&gt; before rebuilding a harness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port one Spark agent loop&lt;/strong&gt; by changing only the model string; keep tools identical for a fair A/B.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate memory writes from the chat transcript.&lt;/strong&gt; Log what the agent decided to remember.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate irreversible tools.&lt;/strong&gt; Active Focus keeps trying — good for long SWE tasks, bad for &lt;code&gt;rm&lt;/code&gt;, payments, and outbound email.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;This month's frontier noise is loud. Muse Wonder is Meta's clearest "personal agent" bet: same family behind a consumer Muse app and a developer API. For builders the useful part is boring — OpenAI-compatible base URL, stable model id, documented Full/API split, and two named behaviors (memory + focus) you can design around after you measure them yourself.&lt;/p&gt;

&lt;p&gt;I have not run Wonder live. Start with the ping, then one real repo task with approvals on.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>meta</category>
    </item>
    <item>
      <title>Microsoft-Decision-1 Just Landed: First systemone Call, Free Output Tokens, and the Qwen-to-MAI Rebase Catch</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Mon, 12 Oct 2026 13:43:30 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/microsoft-decision-1-just-landed-first-systemone-call-free-output-tokens-and-the-qwen-to-mai-1819</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/microsoft-decision-1-just-landed-first-systemone-call-free-output-tokens-and-the-qwen-to-mai-1819</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small offline smoke test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (Microsoft, 2026-10-09):&lt;/strong&gt; &lt;a href="https://commandline.microsoft.com/microsoft-decision-1-model-foundry/" rel="noopener noreferrer"&gt;Microsoft-Decision-1: Our model for fast decision-making&lt;/a&gt; by &lt;strong&gt;Achint Srivastava&lt;/strong&gt; (Command Line / Microsoft), &lt;a href="https://learn.microsoft.com/en-us/azure/foundry/foundry-models/how-to/use-foundry-models-microsoft-decision" rel="noopener noreferrer"&gt;Deploy and use Microsoft-Decision-1 in Microsoft Foundry&lt;/a&gt; (Microsoft Learn), and the OpenRouter model page for &lt;a href="https://openrouter.ai/microsoft/microsoft-decision-1" rel="noopener noreferrer"&gt;microsoft/microsoft-decision-1&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary:&lt;/strong&gt; &lt;a href="https://thenextweb.com/news/microsoft-decision-1-qwen-decision-model" rel="noopener noreferrer"&gt;Microsoft launches a decision model built on Alibaba’s Qwen&lt;/a&gt; by The Next Web (2026-10-12)&lt;br&gt;&lt;br&gt;
Accuracy, latency multiples, flip rates, and internal Xbox/Copilot anecdotes are &lt;strong&gt;Microsoft's&lt;/strong&gt;. I have no Foundry or OpenRouter key on this box, so &lt;strong&gt;I did not call Microsoft-Decision-1&lt;/strong&gt;. What I ran is an offline request/response linter against hand-built mocks, described below as exactly that.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Microsoft shipped &lt;strong&gt;Microsoft-Decision-1&lt;/strong&gt; into Foundry and OpenRouter on 2026-10-09, three days after Liquid open-weighted d1. Satya Nadella's launch post on X cleared a million impressions within hours. Same category shift: stop asking a chat model for JSON and ask a &lt;strong&gt;decision model&lt;/strong&gt; for typed probabilities.&lt;/p&gt;

&lt;p&gt;The access difference matters. Liquid gave you weights. Microsoft gave you a hosted &lt;code&gt;systemone&lt;/code&gt; endpoint, &lt;strong&gt;$0.042 per million input tokens with output free&lt;/strong&gt;, and a &lt;strong&gt;Qwen3.5-9B&lt;/strong&gt; base with an explicit plan to rebase onto MAI and OpenAI later. Same API shape either way. That rebase note is the catch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually returns
&lt;/h2&gt;

&lt;p&gt;From Microsoft Learn and the OpenRouter page, a request is not a chat completion. You send a &lt;code&gt;state&lt;/code&gt; (string or JSON) plus named &lt;code&gt;questions&lt;/code&gt;. Each question is one of three types:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;type&lt;/th&gt;
&lt;th&gt;you give&lt;/th&gt;
&lt;th&gt;you get back&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noul&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a yes/no condition&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;P(yes)&lt;/code&gt; in &lt;code&gt;[0, 1]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;choice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;named options with descriptions&lt;/td&gt;
&lt;td&gt;selected option + per-option probabilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;score&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;an ordered rubric (2+ levels)&lt;/td&gt;
&lt;td&gt;probability-weighted level index&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is no free-form text and no written rationale. That is the point. Your code thresholds the probability, routes the ticket, or blocks the tool call. Learn's endpoint path on Foundry is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;your-foundry-resource-endpoint&amp;gt;/providers/microsoft/v1/systemone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request's &lt;code&gt;model&lt;/code&gt; field is &lt;strong&gt;your deployment name&lt;/strong&gt;, not the string &lt;code&gt;Microsoft-Decision-1&lt;/code&gt;. On OpenRouter the model id is &lt;code&gt;microsoft/microsoft-decision-1&lt;/code&gt;, and OpenRouter documents that chat-completions SDKs will not work — you need the Decisions / System One surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Microsoft is claiming
&lt;/h2&gt;

&lt;p&gt;From Srivastava's post, labeled as vendor numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highest accuracy in Microsoft's &lt;strong&gt;36-benchmark&lt;/strong&gt; comparison (~150k questions kept blind from training).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~35×&lt;/strong&gt; faster (P50) than GPT-6 Sol in their latency test; &lt;strong&gt;2.5×&lt;/strong&gt; faster than H2O-Lightning-4B v1.1.&lt;/li&gt;
&lt;li&gt;Under eight input perturbations, decisions flipped &lt;strong&gt;1.3%&lt;/strong&gt; of the time on average; zero flips when option descriptions were paraphrased or options were reversed/shuffled.&lt;/li&gt;
&lt;li&gt;Xbox Research: competitive with GPT-6 Sol on labeling 10k+ feedback items, &lt;strong&gt;&amp;gt;14×&lt;/strong&gt; faster and &lt;strong&gt;~200×&lt;/strong&gt; cheaper (Microsoft's framing).&lt;/li&gt;
&lt;li&gt;Copilot quality scoring: competitive with GPT-5.6 Luna and &lt;strong&gt;~100×&lt;/strong&gt; faster (Microsoft's framing).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did not reproduce any of that. Treat it as a launch claim sheet, then measure on your own labeled tickets.&lt;/p&gt;

&lt;h2&gt;
  
  
  First request shape (Foundry-style)
&lt;/h2&gt;

&lt;p&gt;A single call can ask three questions over the same state. Pattern from Learn + OpenRouter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DEPLOYMENT_NAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;# your Foundry deployment name
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Help! My payouts have been failing for 3 days.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;questions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_urgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Does this message convey urgency?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criteria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explicitly time-sensitive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No urgency expressed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;team&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Which team should handle this?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criteria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Payments, invoicing, refunds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bugs, outages, integrations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sales&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pricing, upgrades, new accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cannot_tell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not enough information, or not a support request&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frustration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;How frustrated is the customer?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criteria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Calm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Frustrated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Very angry&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AZURE_ENDPOINT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;rstrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/providers/microsoft/v1/systemone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AZURE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# with urllib.request.urlopen(req) as resp: print(resp.read().decode())
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things before production:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;cannot_tell&lt;/code&gt; is deliberate.&lt;/strong&gt; A &lt;code&gt;choice&lt;/code&gt; always picks one option. Without an abstention label, gibberish still gets a team. Learn says to include abstention when the model should not be forced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option descriptions are the policy.&lt;/strong&gt; "Payments, invoicing, refunds" does not cover "is this phishing email from you?". Write phishing into the criteria if it belongs in fraud/security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth is Entra ID or &lt;code&gt;api-key&lt;/code&gt;.&lt;/strong&gt; Learn prefers &lt;code&gt;DefaultAzureCredential&lt;/code&gt;; the snippet uses an API key because it is shorter to read.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cost arithmetic (list price, not a bill)
&lt;/h2&gt;

&lt;p&gt;Microsoft and OpenRouter both list &lt;strong&gt;$0.042 / 1M input&lt;/strong&gt; and &lt;strong&gt;$0 / 1M output&lt;/strong&gt;. Output is free because there are no completion tokens in the chat sense — you get structured answers.&lt;/p&gt;

&lt;p&gt;Illustrative only: 100,000 requests × 2,000 billable input tokens ≈ &lt;strong&gt;$8.40&lt;/strong&gt; of model input (ignores retries, retrieval, review, platform fees). That is why decision models look attractive for the boring 80% of routing.&lt;/p&gt;

&lt;p&gt;OpenRouter lists a &lt;strong&gt;32,768&lt;/strong&gt;-token context, text in, structured decision out. No images or audio here (unlike Liquid's multimodal d1-omni).&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually ran (offline)
&lt;/h2&gt;

&lt;p&gt;No Azure and no OpenRouter key on the box, so I wrote a small preflight that only checks shapes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A legacy chat request (&lt;code&gt;messages&lt;/code&gt; + &lt;code&gt;temperature=0&lt;/code&gt;) is flagged as the wrong API.&lt;/li&gt;
&lt;li&gt;A multi-question Foundry body with &lt;code&gt;noul&lt;/code&gt; / &lt;code&gt;choice&lt;/code&gt; / &lt;code&gt;score&lt;/code&gt; lints clean.&lt;/li&gt;
&lt;li&gt;A two-option &lt;code&gt;choice&lt;/code&gt; without an abstention key gets a warning.&lt;/li&gt;
&lt;li&gt;A hand-built mock &lt;code&gt;answers&lt;/code&gt; object parses; a chat-completions-shaped mock raises &lt;code&gt;ValueError: missing answers object&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The $8.40 figure above is the same list-price arithmetic the linter prints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a smoke test of &lt;strong&gt;your client&lt;/strong&gt;, not of Microsoft-Decision-1. Scripts live under &lt;code&gt;runs/16-microsoft-decision-1/&lt;/code&gt; (&lt;code&gt;preflight.py&lt;/code&gt;, &lt;code&gt;run_output.txt&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Qwen-to-MAI rebase catch
&lt;/h2&gt;

&lt;p&gt;Microsoft says Decision-1 was post-trained from &lt;strong&gt;Qwen3.5-9B&lt;/strong&gt;, and that it will &lt;strong&gt;soon rebase&lt;/strong&gt; onto other bases including &lt;strong&gt;MAI and OpenAI&lt;/strong&gt;. The API shape is supposed to stay put while the weights under it change.&lt;/p&gt;

&lt;p&gt;Practical consequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do &lt;strong&gt;not&lt;/strong&gt; bake "this is a Qwen model" into monitoring, eval harnesses, or compliance docs as a permanent fact. Pin the &lt;strong&gt;deployment / model version&lt;/strong&gt; you evaluated.&lt;/li&gt;
&lt;li&gt;Re-run your labeled set after any silent base swap. Calibration and flip rate are product claims; they are not a contract that survives a rebase without measurement.&lt;/li&gt;
&lt;li&gt;If you needed open weights or air-gapped inference, this product is the wrong shelf. Liquid d1 (or another open decision model) is the local path; Decision-1 is the hosted path inside Foundry/OpenRouter.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I'd wire it for an agent
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gate tool calls with &lt;code&gt;noul&lt;/code&gt;.&lt;/strong&gt; "Does this tool argument touch production data?" — auto-allow only above a high threshold; otherwise ask a human or a stronger model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route with &lt;code&gt;choice&lt;/code&gt; + abstention.&lt;/strong&gt; Escalate when &lt;code&gt;cannot_tell&lt;/code&gt; wins or when top probability is below your threshold (start around 0.7 and tune).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grade agent steps with &lt;code&gt;score&lt;/code&gt;.&lt;/strong&gt; Rubric the proposed next action before you execute it. Microsoft's Discovery anecdote is exactly this pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Decision-1 off consequential people decisions.&lt;/strong&gt; Microsoft's own card and Learn page say not to use it as the sole basis for employment, credit, healthcare, and similar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log state, criteria, answers, and the action you took.&lt;/strong&gt; When something routes wrong, you need to know whether the bug was missing evidence, a bad option description, or your threshold.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Agent stacks are full of "call an LLM, beg for JSON, parse it." A hosted decision endpoint that returns calibrated probabilities, charges nothing for output, and already sits next to Foundry deployments is a concrete alternative for routing, gating, and grading. It does not replace a generative model for writing. It stops you from using one for a multiple-choice question.&lt;/p&gt;

&lt;p&gt;Keep Liquid's open d1 for edge and offline. Use Microsoft-Decision-1 when you already live in Azure or OpenRouter. Measure both on the same labeled set before you trust either.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>llm</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Liquid AI's d1 Decision Models Went Open: Triage Support Tickets on a CPU With the 600M One (and Where It Fools You)</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Fri, 09 Oct 2026 13:45:49 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/liquid-ais-d1-decision-models-went-open-triage-support-tickets-on-a-cpu-with-the-600m-one-and-44b0</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/liquid-ais-d1-decision-models-went-open-triage-support-tickets-on-a-cpu-with-the-600m-one-and-44b0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small real CPU run&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (Liquid AI, 2026-10-07):&lt;/strong&gt; &lt;a href="https://www.liquid.ai/blog/d1-open" rel="noopener noreferrer"&gt;Open d1: Edge decision models for text, vision, and audio&lt;/a&gt; (Liquid AI blog), &lt;a href="https://huggingface.co/blog/LiquidAI/open-d1" rel="noopener noreferrer"&gt;Multimodal open d1 decision models for the edge&lt;/a&gt; (Hugging Face blog), and the model cards for &lt;a href="https://huggingface.co/LiquidAI/d1-3B" rel="noopener noreferrer"&gt;d1-3B&lt;/a&gt; and &lt;a href="https://huggingface.co/LiquidAI/d1-omni-600M" rel="noopener noreferrer"&gt;d1-omni-600M&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Background:&lt;/strong&gt; &lt;a href="https://www.liquid.ai/blog/d1-decision-model" rel="noopener noreferrer"&gt;Introducing d1: The most capable decision model, now with vision&lt;/a&gt; (Liquid AI, 2026-10-05)&lt;br&gt;&lt;br&gt;
All benchmark and latency figures for d1-3B are Liquid AI's. The numbers I report for d1-omni-600M come from one run on a shared 8-vCPU Linux box with 12 tickets I wrote myself. That is a smoke test, not an evaluation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;This week Liquid AI put two of its &lt;strong&gt;d1 "decision models"&lt;/strong&gt; on Hugging Face as open weights: &lt;strong&gt;d1-3B&lt;/strong&gt; (text + images) and an experimental &lt;strong&gt;d1-omni-600M&lt;/strong&gt; (text + images, or text + audio). It landed the same week OpenAI put its Decisions API into public beta, and the conversation on X quickly turned to running these decisions locally instead of paying per call.&lt;/p&gt;

&lt;p&gt;The idea is simple and, for backend people, more interesting than another chat model. A decision model does not write text. You hand it a &lt;strong&gt;state&lt;/strong&gt; (a string, JSON, an image) and a set of &lt;strong&gt;named questions&lt;/strong&gt;, and it returns typed, calibrated answers in &lt;strong&gt;one forward pass, with zero output tokens&lt;/strong&gt;. Three question types cover most pipeline glue:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;type&lt;/th&gt;
&lt;th&gt;you give&lt;/th&gt;
&lt;th&gt;you get back&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noul&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a yes/no question&lt;/td&gt;
&lt;td&gt;&lt;code&gt;P(yes)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;choice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;named options with descriptions&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;choice&lt;/code&gt;, &lt;code&gt;confidence&lt;/code&gt;, &lt;code&gt;probabilities&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;score&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2 to 10 ordered levels&lt;/td&gt;
&lt;td&gt;expected level, &lt;code&gt;confidence&lt;/code&gt;, &lt;code&gt;probabilities&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is exactly the shape of the ticket routers, intent classifiers, and moderation checks that a lot of us currently build with an LLM call, a prompt that says "answer only with JSON", and a parser that hopes for the best.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Liquid AI is claiming
&lt;/h2&gt;

&lt;p&gt;From the blog and model cards, in short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;d1-3B&lt;/strong&gt; (3.12B params, built on LFM2.5-VL-3B) scores 48.57 on Decision Index v0.2.1, which Liquid says is the best under 10B and on par with a 35B-A3B decision model. Liquid reports 8 ms per decision on an RTX 4090, 30 ms on an Apple M5 Pro, and 50 ms on a Jetson Orin Nano.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;d1-omni-600M&lt;/strong&gt; is built on a 350M bidirectional encoder plus vision and audio encoders. Liquid calls it an early research release, scores it 15.95 on the same index, and deliberately publishes no speed numbers for it.&lt;/li&gt;
&lt;li&gt;Both have day-one &lt;code&gt;transformers&lt;/code&gt; support via &lt;code&gt;trust_remote_code&lt;/code&gt;, and Liquid mentions llama.cpp support for the family.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 3B model is the one Liquid is pushing. I ran the 600M one, for a boring reason: d1-3B wants about 12 GB in float32 on CPU, and the box I used had about 6 GB free. If you have a GPU or an M-series Mac, start with the 3B.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it yourself (CPU, about 10 minutes)
&lt;/h2&gt;

&lt;p&gt;The 600M model card asks for &lt;code&gt;transformers&amp;gt;=5.15&lt;/code&gt; (the 3B card says &lt;code&gt;&amp;gt;=5.14&lt;/code&gt;). so pin it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/cpu torch torchvision
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"transformers&amp;gt;=5.15"&lt;/span&gt; pillow soundfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then one call answers three questions over the same ticket:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LiquidAI/d1-omni-600M&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trust_remote_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;questions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refund&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Is the customer asking for a refund?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;team&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Which team should handle this?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criteria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Charges, refunds, invoices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;App or site faults&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fraud&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Suspected unauthorised use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;urgency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instructions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;How urgent is this?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criteria&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Can wait&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Today&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Blocking the customer now&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I was charged twice for my October plan. Please refund the duplicate.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;questions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On my run, that ticket came back as &lt;code&gt;billing&lt;/code&gt; with confidence 0.994, &lt;code&gt;P(refund)&lt;/code&gt; = 0.999, and an urgency score of 1.69 on the 0 to 2 scale, using 157 input tokens and 0 output tokens. Two notes from the card: use float32 on CPU (the model was trained in it), and avoid bfloat16 on GPU, which Liquid says flipped the top answer on a small share of rows. &lt;code&gt;trust_remote_code&lt;/code&gt; also downloads Python files from the repo, so pin a &lt;code&gt;revision&lt;/code&gt; before you ship this anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened on 12 tickets
&lt;/h2&gt;

&lt;p&gt;I wrote 12 short support tickets and their expected team and refund labels before running anything: four billing, four technical, four fraud-ish, including a phishing email question and a hijacked account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Team:&lt;/strong&gt; 12 of 12 matched my labels. &lt;strong&gt;Refund (P &amp;gt;= 0.5):&lt;/strong&gt; 12 of 12.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency, three questions in one pass, warm:&lt;/strong&gt; median 208 ms, range 160 to 471 ms. One question alone: median 114 ms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch:&lt;/strong&gt; 48 single-question requests through &lt;code&gt;system_one_batch&lt;/code&gt; took 3.63 s, about 13 tickets per second.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are CPU numbers on a shared Xeon box, so treat them as "fast enough for a background queue", not as a latency benchmark. Twelve easy tickets also say nothing about your data; the point is that the API shape works and the probabilities are usable.&lt;/p&gt;

&lt;p&gt;The more useful part was where confidence dropped. The phishing question ("I got an email asking me to confirm my card number on a weird link. Is that you?") still went to &lt;code&gt;fraud&lt;/code&gt;, but at &lt;strong&gt;0.477&lt;/strong&gt;. The hijacked-account ticket went to &lt;code&gt;fraud&lt;/code&gt; at &lt;strong&gt;0.633&lt;/strong&gt;. Those are exactly the tickets I'd want a human to see, and the confidence field flags them without any prompt engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it fools you: forced choices
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;choice&lt;/code&gt; question always picks one of your options. I sent two inputs that are not tickets at all:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What's your office address in Toronto?" went to &lt;code&gt;billing&lt;/code&gt; at 0.496. The low confidence gives it away.&lt;/li&gt;
&lt;li&gt;"asdf asdf test test" went to &lt;code&gt;technical&lt;/code&gt; at &lt;strong&gt;0.907&lt;/strong&gt;. High confidence, and wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a confidence threshold alone does not catch junk. The obvious fix is a catch-all option, so I added &lt;code&gt;"other": "None of the above, or not a real support request"&lt;/code&gt; and a separate &lt;code&gt;noul&lt;/code&gt; gate, "Is this a genuine customer support request?". That fixed the junk: the gibberish moved to &lt;code&gt;other&lt;/code&gt; (0.663) with &lt;code&gt;P(request)&lt;/code&gt; = 0.004, and the address question moved to &lt;code&gt;other&lt;/code&gt; (0.896).&lt;/p&gt;

&lt;p&gt;It also moved two real tickets. With &lt;code&gt;other&lt;/code&gt; available, the phishing question went to &lt;code&gt;other&lt;/code&gt; (0.603) and "Do you have a nonprofit discount?" went to &lt;code&gt;other&lt;/code&gt; (0.699) instead of &lt;code&gt;billing&lt;/code&gt;. The clear tickets (double charge, crashing app) stayed put at 0.90 or higher. Adding a catch-all moves the decision boundary for every borderline input, not just the junk.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I'd actually wire it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gate first.&lt;/strong&gt; Ask a &lt;code&gt;noul&lt;/code&gt; "is this a real request?" question and drop or queue anything with very low &lt;code&gt;P(yes)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route with explicit options, no catch-all,&lt;/strong&gt; and send anything under a confidence threshold (I'd start around 0.7 and tune it on real tickets) to a human or a bigger LLM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write option descriptions like policy.&lt;/strong&gt; "Suspected unauthorised use" did not obviously cover "someone asking if a phishing email is real". If phishing reports should go to fraud, say so in the description.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Label 100 real tickets before trusting any of this.&lt;/strong&gt; My 12 are a smoke test. Measure agreement, and check which tickets land between 0.4 and 0.7.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin the revision&lt;/strong&gt; of a &lt;code&gt;trust_remote_code&lt;/code&gt; model, and try d1-3B if you have the memory. It's the one Liquid benchmarks.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;For years the pattern has been to call an LLM, beg for JSON, and parse it. A small model that returns probabilities in one pass, runs on a CPU, and costs nothing per call is a real option for the boring 80% of classification work. It doesn't replace judgment on the hard 20%, but it tells you which tickets those are.&lt;/p&gt;

&lt;p&gt;The scripts and raw output from this run (&lt;code&gt;triage.py&lt;/code&gt;, &lt;code&gt;other_option.py&lt;/code&gt;) need only the pip install above and no API key.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>python</category>
      <category>llm</category>
    </item>
    <item>
      <title>Claude Haiku 5.5 Just Landed: Migrating a Haiku 4.5 Classifier Without the 400s (temperature, Prefill, Thinking Blocks)</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Thu, 08 Oct 2026 13:20:08 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/claude-haiku-55-just-landed-migrating-a-haiku-45-classifier-without-the-400s-temperature-2lj2</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/claude-haiku-55-just-landed-migrating-a-haiku-45-classifier-without-the-400s-temperature-2lj2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small offline smoke test&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (Anthropic, 2026-10-07):&lt;/strong&gt; &lt;a href="https://www.anthropic.com/claude-haiku-5-5" rel="noopener noreferrer"&gt;Introducing Claude Haiku 5.5&lt;/a&gt; (Anthropic); the Claude Platform docs &lt;a href="https://platform.claude.com/docs/en/models/haiku-5-5/whats-new-haiku-5-5" rel="noopener noreferrer"&gt;What's new in Claude Haiku 5.5&lt;/a&gt;, &lt;a href="https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide" rel="noopener noreferrer"&gt;Migration guide&lt;/a&gt;, and &lt;a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5" rel="noopener noreferrer"&gt;Prompting Claude Haiku 5.5&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary:&lt;/strong&gt; &lt;a href="https://aws.amazon.com/blogs/machine-learning/introducing-claude-haiku-5-5-on-aws/" rel="noopener noreferrer"&gt;Introducing Claude Haiku 5.5 on AWS&lt;/a&gt; by &lt;strong&gt;Aamna Najmi, Dani Mitchell, Alfredo Castillo, and Sofian Hamiti&lt;/strong&gt; (AWS Machine Learning Blog, 2026-10-07)&lt;br&gt;&lt;br&gt;
Prices, benchmark claims, and the "~30% more tokens" figure are Anthropic's. I have no Claude API key on this box, so &lt;strong&gt;I did not call Haiku 5.5&lt;/strong&gt;. What I did run is an offline check of the current Python SDK and a small request linter against hand-built mock responses, described below as exactly that.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Anthropic shipped &lt;strong&gt;Claude Haiku 5.5&lt;/strong&gt; yesterday, and its launch post on X drew close to 5 million views within a day. The headline is price. Anthropic lists $0.10 per million input tokens and $0.50 per million output tokens for prompts up to 100K tokens ($0.50 / $2.50 above that), against $1 / $5 for Haiku 4.5, and says it costs "around 75% less to run" on average. It also gets a 1M-token context window, 128K max output, and, for the first time on a Haiku, an &lt;code&gt;effort&lt;/code&gt; setting.&lt;/p&gt;

&lt;p&gt;Most coverage is about benchmarks. My view as a backend engineer is narrower: Haiku is the model people put behind ticket routers, intent classifiers, and extraction jobs. Those are exactly the integrations written in the Haiku 3/4.5 style, with &lt;code&gt;temperature=0&lt;/code&gt;, a prefilled &lt;code&gt;{"label": "&lt;/code&gt;, and &lt;code&gt;max_tokens=20&lt;/code&gt;. Every one of those habits now breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changed for a classifier
&lt;/h2&gt;

&lt;p&gt;Anthropic's migration guide lists several breaking changes. Three hit a typical classifier directly, and three more change behavior without an error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hard errors (HTTP 400 per the docs):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sampling parameters.&lt;/strong&gt; &lt;code&gt;temperature&lt;/code&gt; must be omitted or exactly &lt;code&gt;1&lt;/code&gt;. &lt;code&gt;top_p&lt;/code&gt; must be omitted or exactly &lt;code&gt;0.99&lt;/code&gt; (even &lt;code&gt;1&lt;/code&gt; fails), &lt;code&gt;top_k&lt;/code&gt; is rejected at any value, and sending &lt;code&gt;temperature&lt;/code&gt; and &lt;code&gt;top_p&lt;/code&gt; together also fails. The "set temperature to 0 for deterministic labels" reflex is now an error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assistant prefill.&lt;/strong&gt; A final assistant turn for the model to continue is rejected, even with thinking off. The docs recommend structured outputs or &lt;strong&gt;a tool with an enum field&lt;/strong&gt; for classification instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual thinking budgets.&lt;/strong&gt; &lt;code&gt;thinking: {"type": "enabled", "budget_tokens": N}&lt;/code&gt; is gone. Use &lt;code&gt;{"type": "adaptive"}&lt;/code&gt; and steer it with &lt;code&gt;output_config.effort&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Silent changes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Thinking is on by default&lt;/strong&gt;, so a response can &lt;em&gt;start&lt;/em&gt; with a &lt;code&gt;thinking&lt;/code&gt; block even if you never asked for one. By default that block arrives with an empty &lt;code&gt;thinking&lt;/code&gt; field and only a &lt;code&gt;signature&lt;/code&gt;. Code that reads &lt;code&gt;content[0].text&lt;/code&gt; gets nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thinking tokens count toward &lt;code&gt;max_tokens&lt;/code&gt;.&lt;/strong&gt; A &lt;code&gt;max_tokens=20&lt;/code&gt; request can stop with &lt;code&gt;stop_reason: "max_tokens"&lt;/code&gt; after the thinking block and before any text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The tokenizer changed.&lt;/strong&gt; Anthropic says the same text counts as about 30% more tokens than on Haiku 4.5. Token-based budgets, truncation limits, and cost dashboards all shift.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is also a new failure path: Haiku 5.5 runs safety classifiers that can return &lt;code&gt;stop_reason: "refusal"&lt;/code&gt; with a &lt;code&gt;stop_details.category&lt;/code&gt;, and the docs say retrying usually refuses again. If you run Priority Tier on Haiku 4.5, the guide also notes Priority Tier isn't supported on 5.5.&lt;/p&gt;

&lt;h2&gt;
  
  
  The smoke test: what I could check without an API key
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SDK check.&lt;/strong&gt; I created a fresh virtualenv on a Linux box (Python 3.13) and ran &lt;code&gt;pip install anthropic&lt;/code&gt;, which resolved to &lt;strong&gt;anthropic 1.12.1&lt;/strong&gt; today. Inspecting &lt;code&gt;client.messages.create&lt;/code&gt; showed &lt;code&gt;thinking&lt;/code&gt;, &lt;code&gt;output_config&lt;/code&gt;, and &lt;code&gt;tool_choice&lt;/code&gt; parameters, and &lt;strong&gt;no &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;top_p&lt;/code&gt;, or &lt;code&gt;top_k&lt;/code&gt; parameters at all&lt;/strong&gt;. Calling it with &lt;code&gt;temperature=0&lt;/code&gt; raised:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeError: Messages.create() got an unexpected keyword argument 'temperature'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That happens client-side, before any network call. So depending on which SDK version your service pins, the same legacy code fails either as a Python &lt;code&gt;TypeError&lt;/code&gt; at call time or, per Anthropic's docs, as a server-side 400. Both look like "the classifier is down," and neither tells you which label you would have gotten. I didn't check older SDK versions or the &lt;code&gt;extra_body&lt;/code&gt; escape hatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request linter.&lt;/strong&gt; I wrote a ~150-line &lt;code&gt;preflight.py&lt;/code&gt; that encodes the migration-guide rules and points them at a classic Haiku 4.5 ticket classifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;legacy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-haiku-4-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Classify the support ticket. Reply with JSON only.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I was charged twice this month, please refund one.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;# prefill
&lt;/span&gt;    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The linter flagged the model ID, &lt;code&gt;temperature=0&lt;/code&gt;, the prefill, and the 20-token &lt;code&gt;max_tokens&lt;/code&gt; (as a warning, since thinking eats into it). The migrated version replaces the prefill with a forced enum tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fixed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-haiku-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Classify the support ticket. Reply with JSON only.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I was charged twice this month, please refund one.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Record the single best label for the ticket.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_schema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enum&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;account&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;other&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}},&lt;/span&gt;
                         &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
    &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_choice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why a &lt;em&gt;forced&lt;/em&gt; tool? Per the migration guide, with a forced &lt;code&gt;tool_choice&lt;/code&gt; the response starts with the tool call and carries no thinking block. For a single-label router, that's the behavior you want: no reasoning tokens to pay for, and an answer constrained to your enum. If the label needs judgment, use &lt;code&gt;tool_choice: {"type": "auto"}&lt;/code&gt; and let adaptive thinking work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response reader.&lt;/strong&gt; Finally, I built four mock responses by hand, shaped the way the docs describe: thinking-then-text, forced tool call, thinking-then-&lt;code&gt;max_tokens&lt;/code&gt;, and a refusal. They validated against the SDK's own &lt;code&gt;Message&lt;/code&gt; pydantic type. A type-aware reader handled all four:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stop_reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refusal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;refused&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stop_details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stop_reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;truncated_after_thinking&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Haiku 4.5-era &lt;code&gt;content[0].text&lt;/code&gt; returned &lt;code&gt;None&lt;/code&gt; on three mocks and raised &lt;code&gt;IndexError&lt;/code&gt; on the refusal mock, where I'd given it an empty content list. These are mocks, not model output. They show what your parsing code does with the documented shapes, not how often Haiku 5.5 actually produces each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  On the cost math
&lt;/h2&gt;

&lt;p&gt;The pricing is compelling, but recompute it with the new token counts instead of reusing Haiku 4.5 numbers. As an illustration using Anthropic's list prices and its ~30% estimate: a prompt measured at 400 input tokens on 4.5 becomes roughly 520 on 5.5. Per million such requests, input cost goes from about $400 to about $52. That's still a large cut, but it's smaller than the per-token price drop suggests. Effort matters too. Anthropic's prompting guide says moving from &lt;code&gt;low&lt;/code&gt; to &lt;code&gt;medium&lt;/code&gt; roughly halved early stopping in long agent prompts and more than doubled output tokens per attempt. Medium is the default on the API, so a high-volume classifier that never sets effort pays for thinking it may not need.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;count_tokens&lt;/code&gt; with &lt;code&gt;model="claude-haiku-5-5"&lt;/code&gt; on a sample of real prompts rather than trusting the 30% figure for your content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it fits, and where something else might
&lt;/h2&gt;

&lt;p&gt;Anthropic and AWS both pitch Haiku 5.5 as the fast layer: routing, classification, extraction, summaries, and subagents under Opus or Sonnet. Anthropic says Sonnet and Opus remain the better choice for complex agentic coding. For pure bounded-choice decisions, it's worth knowing that OpenAI put a &lt;a href="https://community.openai.com/t/decisions-api-is-now-available-in-public-beta/1403877" rel="noopener noreferrer"&gt;Decisions API&lt;/a&gt; into public beta the day before, which returns typed predicates, choices, and scores from &lt;code&gt;gpt-6-luna&lt;/code&gt;. I haven't tested either. If your workload is "pick one of N labels," evaluate both on your own labeled set before committing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Swap the model ID (&lt;code&gt;claude-haiku-5-5&lt;/code&gt;; Bedrock uses &lt;code&gt;anthropic.claude-haiku-5-5&lt;/code&gt; or a regional inference profile).&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;top_p&lt;/code&gt;, and &lt;code&gt;top_k&lt;/code&gt;, and check whether your pinned SDK still accepts them.&lt;/li&gt;
&lt;li&gt;Replace prefills with an enum tool or structured outputs.&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;budget_tokens&lt;/code&gt; with adaptive thinking plus an explicit &lt;code&gt;effort&lt;/code&gt;. Start a classifier at &lt;code&gt;low&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Raise small &lt;code&gt;max_tokens&lt;/code&gt; values, or force the tool call so there's no thinking block.&lt;/li&gt;
&lt;li&gt;Read content blocks by &lt;code&gt;type&lt;/code&gt;, never by position.&lt;/li&gt;
&lt;li&gt;Handle &lt;code&gt;stop_reason: "refusal"&lt;/code&gt; without blind retries.&lt;/li&gt;
&lt;li&gt;Recount tokens and redo cost estimates on real prompts.&lt;/li&gt;
&lt;li&gt;Before switching traffic, compare labels from 4.5 and 5.5 on a few hundred real inputs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anthropic's guide also mentions a &lt;code&gt;/claude-api migrate&lt;/code&gt; skill inside Claude Code that applies these edits across a repo. I didn't try it, but the checklist above tells you what to check in its diff.&lt;/p&gt;

&lt;p&gt;The SDK check and the response reader can be reproduced from the snippets above with &lt;code&gt;pip install anthropic&lt;/code&gt; and no API key. Again, no live model calls were made.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;YongBo Yu is an AI engineer in Toronto building LLM workflows and agent systems. More at &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;yongbo-yu.vercel.app&lt;/a&gt; and &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>claude</category>
    </item>
    <item>
      <title>EmbeddingGemma 2 Just Dropped: Local Code Search on a CPU, the Install Gotcha, and Two Ways It Fails Silently</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:15:16 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/embeddinggemma-2-just-dropped-local-code-search-on-a-cpu-the-install-gotcha-and-two-ways-it-3j32</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/embeddinggemma-2-just-dropped-local-code-search-on-a-cpu-the-install-gotcha-and-two-ways-it-3j32</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile + one small real run&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources (all Google, 2026-10-06):&lt;/strong&gt; &lt;a href="https://blog.google/innovation-and-ai/technology/developers-tools/embeddinggemma-2/" rel="noopener noreferrer"&gt;EmbeddingGemma 2 is a best-in-class open model for natively multimodal embeddings&lt;/a&gt; by &lt;strong&gt;Sahil Dua&lt;/strong&gt; and &lt;strong&gt;Henrique Schechter Vera&lt;/strong&gt; (Google DeepMind); &lt;a href="https://developers.googleblog.com/en/embeddinggemma-2-the-developer-guide/" rel="noopener noreferrer"&gt;EmbeddingGemma 2: The Developer Guide&lt;/a&gt; by &lt;strong&gt;Maarten Grootendorst&lt;/strong&gt; and &lt;strong&gt;Ian Ballantyne&lt;/strong&gt;; &lt;a href="https://developers.googleblog.com/en/google-ai-edge-with-embeddinggemma-2/" rel="noopener noreferrer"&gt;Bring multimodal semantic search to the edge with EmbeddingGemma 2&lt;/a&gt; (Google AI Edge and Android ML teams); the &lt;a href="https://huggingface.co/google/embeddinggemma-2" rel="noopener noreferrer"&gt;google/embeddinggemma-2 model card&lt;/a&gt; on Hugging Face&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary coverage:&lt;/strong&gt; &lt;a href="https://runtimewire.com/article/google-embeddinggemma-2-on-device-multimodal-search" rel="noopener noreferrer"&gt;Google releases a 740M-parameter embedding model for local multimodal search&lt;/a&gt; by &lt;strong&gt;Ryan Merket&lt;/strong&gt; (Runtime Wire, 2026-10-06)&lt;br&gt;&lt;br&gt;
Model specs, benchmark scores, and on-device RAM figures below are Google's own numbers. The only thing I measured is the tiny text-only code-search test in this post, run once on a CPU-only Linux box. It is a smoke test, not a benchmark. I did not test images, video, or audio.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Google released &lt;strong&gt;EmbeddingGemma 2&lt;/strong&gt; yesterday: an Apache 2.0 embedding model, built on Gemma 4, that puts text, code, images, video, and audio into one 768-dimensional vector space. The first EmbeddingGemma was text-only and, per Google, passed 20 million downloads. This one is the "search my photos with a sentence, without uploading them" version.&lt;/p&gt;

&lt;p&gt;Most coverage focuses on the multimodal demos. As a backend engineer, I care about a narrower question: can I drop the text-and-code part into a RAG pipeline today, on a CPU, and what bites first? I ran it to find out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What shipped (vendor-reported)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular size.&lt;/strong&gt; 740M parameters in total, but you load only what you need. Text and code alone is 270M. Adding vision makes it 440M, adding audio instead makes it 570M, and everything together is 740M. Google's AI Edge team reports about 191 MB of active RAM for text-only and about 567 MB for the full model on a Pixel 11 Pro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One shared space.&lt;/strong&gt; A text query can be compared directly with an image, a video frame, or an audio clip. All inputs share an 8,192-token budget. Google prices an image at 280 tokens, a video frame at 140 tokens (sampled at 1 fps by default), and audio at 25 tokens per second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Matryoshka truncation.&lt;/strong&gt; You can keep only the first 512, 256, or 128 dimensions of each vector to save storage. Google's table shows the cost: the code benchmark drops from 78.68 at 768d to 71.41 at 128d, and the overall multimodal score drops from 59.01 to 45.65. Google recommends 128d mainly for text-only workloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code is the headline text gain.&lt;/strong&gt; On MTEB Code, Google lists 78.68 versus 68.76 for the first EmbeddingGemma. Multilingual MTEB barely moved (61.36 versus 61.15). So if you only embed prose, the upgrade is mostly about multimodality, not text quality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task prefixes matter.&lt;/strong&gt; The model was trained with short instructions such as &lt;code&gt;task: code retrieval | query: ...&lt;/code&gt; for queries and &lt;code&gt;title: "... | text: ...&lt;/code&gt; for documents. Sentence Transformers exposes these as named prompts."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The run: natural-language code search on a CPU
&lt;/h2&gt;

&lt;p&gt;My setup: a CPU-only Linux box with 8 vCPUs, Python 3.13, &lt;code&gt;torch 2.14.1+cpu&lt;/code&gt;, &lt;code&gt;sentence-transformers 6.1.0&lt;/code&gt;, and &lt;code&gt;transformers 5.19.0&lt;/code&gt;. The weights are not gated on Hugging Face, so there is no license click-through or token.&lt;/p&gt;

&lt;p&gt;I wrote eight small Python snippets (retry with backoff, slugify, JWT signature check, text chunker, token-bucket rate limiter, CSV dedupe, a FastAPI health check, cosine similarity). Then I asked six plain-English questions that deliberately avoid the function names, like "back off and try again when a call fails."&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;google/embeddinggemma-2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;config_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vision_config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio_config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;# text + code only
&lt;/span&gt;    &lt;span class="n"&gt;model_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;torch_dtype&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;                   &lt;span class="c1"&gt;# never float16
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;\&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; for name, code in snippets.items()]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truncate_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normalize_embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CodeRetrieval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;truncate_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normalize_embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;   &lt;span class="c1"&gt;# cosine similarity, since both sides are unit length
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happened on this run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The text-only model loaded in 6.4 seconds and reported &lt;strong&gt;271M parameters&lt;/strong&gt;, which matches Google's 270M text configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All six queries put the right snippet first&lt;/strong&gt;, at both 768d and 128d. For example, "check that a signed auth token wasn't tampered with" returned &lt;code&gt;jwt_check.py&lt;/code&gt;, and "remove duplicate customers from a spreadsheet export" returned &lt;code&gt;csv_dedupe.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Encoding the eight snippets plus six queries took about half a second on the CPU.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eight documents is far too few to say anything about quality at scale. What it does show is that the text path runs comfortably on an ordinary CPU, and that the &lt;code&gt;CodeRetrieval&lt;/code&gt; prompt works as documented.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha 1: "text-only" still needs the image stack to load
&lt;/h2&gt;

&lt;p&gt;My first two attempts crashed before any embedding happened. Even with &lt;code&gt;vision_config=None&lt;/code&gt; and &lt;code&gt;audio_config=None&lt;/code&gt;, loading failed first with &lt;code&gt;EmbeddingGemma2Processor requires the PIL library&lt;/code&gt;, and after installing Pillow, with &lt;code&gt;No module named 'torchvision'&lt;/code&gt;. In this version combination the processor imports Gemma 4's image-processing code no matter which encoders you enable.&lt;/p&gt;

&lt;p&gt;The fix that worked for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; sentence-transformers transformers pillow
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/cpu torch torchvision
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are building a slim Docker image for a text-only RAG service, budget for both packages, or pin versions and check again when a later release decouples them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha 2: slicing vectors without re-normalizing
&lt;/h2&gt;

&lt;p&gt;Matryoshka truncation tempts you to store 768d vectors and slice them later. The model card warns that sliced vectors are no longer unit length, and that cosine scores then degrade "silently." I checked what that looks like in practice.&lt;/p&gt;

&lt;p&gt;After slicing my normalized 768d document vectors to their first 128 values, their lengths were about &lt;strong&gt;0.58 to 0.60&lt;/strong&gt; instead of 1.0. The score for the retry query against &lt;code&gt;retry.py&lt;/code&gt; fell from &lt;strong&gt;0.849&lt;/strong&gt; (properly re-normalized 128d) to &lt;strong&gt;0.295&lt;/strong&gt; (raw slice). Nothing errors. If your retriever has a similarity cutoff such as "drop anything under 0.5," the raw slice silently returns nothing.&lt;/p&gt;

&lt;p&gt;The safe version is to let the library do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truncate_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normalize_embeddings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also keep query and document dimensions identical. A 768d query can't be scored against a 128d index.&lt;/p&gt;

&lt;p&gt;A related surprise from the same run: the correct 128d scores were all &lt;em&gt;higher&lt;/em&gt; than the 768d ones (0.82 to 0.87 versus 0.75 to 0.79). The rankings matched, but the absolute numbers moved. &lt;strong&gt;Any threshold you tuned at one dimension needs re-tuning at another.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha 3: float16 (per Google, not tested)
&lt;/h2&gt;

&lt;p&gt;Google's guide says the model's activations overflow &lt;code&gt;float16&lt;/code&gt;, which produces NaN or degraded vectors without raising an error. Use &lt;code&gt;bfloat16&lt;/code&gt; on GPUs that support it and &lt;code&gt;float32&lt;/code&gt; on CPUs. I only ran &lt;code&gt;float32&lt;/code&gt;, so I'm passing this along rather than confirming it. It matters because "cast to fp16 to save memory" is a common reflex.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small prompt-name note
&lt;/h2&gt;

&lt;p&gt;Google's current docs use names like &lt;code&gt;SearchQuery&lt;/code&gt;, &lt;code&gt;Document&lt;/code&gt;, and &lt;code&gt;CodeRetrieval&lt;/code&gt;. The checkpoint I loaded also still exposes the older names (&lt;code&gt;Retrieval-query&lt;/code&gt;, &lt;code&gt;Retrieval-document&lt;/code&gt;, &lt;code&gt;STS&lt;/code&gt;) from EmbeddingGemma 1. Pick one convention and use it for both indexing and querying. Mixing a query prefix from one family with documents embedded under another is the kind of mismatch that never throws an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to reach for it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Private, local search&lt;/strong&gt; over notes, code, screenshots, or recordings that shouldn't leave the machine. This is the case Google is designing for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code search inside a dev tool&lt;/strong&gt;, where the 270M text configuration is small enough to ship with the tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-shot intent routing.&lt;/strong&gt; Google's edge post pitches matching user input directly against label descriptions, with no training data, as a cheap router in front of a bigger model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you already pay for a hosted embedding API and your data can leave the device, Google's own cloud counterpart, Gemini Embedding 2, is the comparison to run on your own corpus before switching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;pillow&lt;/code&gt; and &lt;code&gt;torchvision&lt;/code&gt; even for text-only use.&lt;/li&gt;
&lt;li&gt;Load only the encoders you need via &lt;code&gt;config_kwargs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;float32&lt;/code&gt; on CPU and &lt;code&gt;bfloat16&lt;/code&gt; on GPU. Avoid &lt;code&gt;float16&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the right task prefix: &lt;code&gt;CodeRetrieval&lt;/code&gt; or &lt;code&gt;SearchQuery&lt;/code&gt; for queries, and &lt;code&gt;title: "... | text: ...&lt;/code&gt; for documents."&lt;/li&gt;
&lt;li&gt;Truncate with &lt;code&gt;truncate_dim&lt;/code&gt; plus &lt;code&gt;normalize_embeddings=True&lt;/code&gt;, never by slicing.&lt;/li&gt;
&lt;li&gt;Re-tune similarity thresholds whenever you change dimensions.&lt;/li&gt;
&lt;li&gt;Validate on 50 to 100 of your own queries before trusting the 128d setting.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Byline:&lt;/em&gt; &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;YongBo Yu&lt;/a&gt; — Toronto AI engineer (agents, LLM workflows, RAG). GitHub: &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;YongBoYu1&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>machinelearning</category>
      <category>rag</category>
    </item>
    <item>
      <title>Gemini Skills Just Landed in Workspace: Your First SKILL.md, Moving a Gem, and Why a Migrated Gem Isn't a Working Skill</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Tue, 06 Oct 2026 13:23:42 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/gemini-skills-just-landed-in-workspace-your-first-skillmd-moving-a-gem-and-why-a-migrated-gem-1n5a</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/gemini-skills-just-landed-in-workspace-your-first-skillmd-moving-a-gem-and-why-a-migrated-gem-1n5a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile (not original research)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary sources:&lt;/strong&gt; &lt;a href="https://blog.google/products-and-platforms/products/gemini/automate-tasks-with-skills/" rel="noopener noreferrer"&gt;Let skills in Gemini tackle your most repetitive tasks&lt;/a&gt; by &lt;strong&gt;Deven Tokuno&lt;/strong&gt;, Senior Product Manager, Gemini App (Google, &lt;strong&gt;2026-09-30&lt;/strong&gt;); &lt;a href="https://workspaceupdates.googleblog.com/2026/09/skills-gemini-app-workspace.html" rel="noopener noreferrer"&gt;Introducing skills in the Gemini app and Workspace, plus what's next for Gems&lt;/a&gt; (Google Workspace Updates, &lt;strong&gt;2026-09-30&lt;/strong&gt;, with the Workspace rollout starting &lt;strong&gt;2026-10-05&lt;/strong&gt;); Google's help pages &lt;a href="https://support.google.com/gemini/answer/17094296?hl=en" rel="noopener noreferrer"&gt;Create &amp;amp; manage skills for Gemini Apps&lt;/a&gt; and &lt;a href="https://support.google.com/gemini/answer/17102773?hl=en" rel="noopener noreferrer"&gt;Write effective skills for Gemini Apps&lt;/a&gt;; the open &lt;a href="https://agentskills.io/specification" rel="noopener noreferrer"&gt;Agent Skills specification&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary coverage:&lt;/strong&gt; &lt;a href="https://affitronix.com/google-gemini-skills-rollout-replacing-gems/" rel="noopener noreferrer"&gt;Google Gemini Skills Start Rolling Out Today, Replacing Gems&lt;/a&gt; by &lt;strong&gt;Abhilasha Raut&lt;/strong&gt; (Affitronix, &lt;strong&gt;2026-10-05&lt;/strong&gt;); &lt;a href="https://onthewire.ai/article/google-is-retiring-gemini-gems-in-november-what-happens-to-yours-and-how-to-move" rel="noopener noreferrer"&gt;Google starts retiring Gemini Gems in November&lt;/a&gt; (On The Wire, &lt;strong&gt;2026-10-03&lt;/strong&gt;); &lt;a href="https://beckmann.ai/en/ai-in-practice/2026-10/google-gemini-skills-replace-gems" rel="noopener noreferrer"&gt;Google launches Skills in Gemini&lt;/a&gt; by &lt;strong&gt;Brian Beckmann&lt;/strong&gt; (&lt;strong&gt;2026-10-01&lt;/strong&gt;)&lt;br&gt;&lt;br&gt;
This post restates Google's announcements and help docs in my own words, with a practical first-skill checklist. &lt;strong&gt;I did not create, upload, or migrate a skill in Gemini or Workspace for this article.&lt;/strong&gt; Feature descriptions, dates, and limits are vendor-reported or attributed to the named source. The &lt;code&gt;SKILL.md&lt;/code&gt; and folder examples are adapted patterns based on the spec. The small Python checker was run locally against a sample folder only. It is not a Google tool and was not tested against Gemini's uploader.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Google is retiring Gems. Their replacement, &lt;strong&gt;skills&lt;/strong&gt;, started reaching Workspace Rapid Release domains on October 5. Personal accounts in the Gemini app have been getting them gradually since the September 30 announcement.&lt;/p&gt;

&lt;p&gt;The headline is convenience: save an instruction set once, then call it with &lt;code&gt;/&lt;/code&gt; in any chat. The more interesting part for engineers is the format. Google says skills are "built entirely on the open, Markdown-native SKILL.md standard." That is the same folder-plus-Markdown format used by the Agent Skills spec, which Beckmann notes is also read by Claude, GitHub Copilot, and Google's own Gemini CLI.&lt;/p&gt;

&lt;p&gt;So a skill you write for Gemini can be a plain file in a Git repo. It is no longer a setting trapped in one product.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed (and when)
&lt;/h2&gt;

&lt;p&gt;Here are the dates from Google's Workspace Updates post and blog:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;What happens (vendor-reported)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sep 30, 2026&lt;/td&gt;
&lt;td&gt;Skills announced; rolling out "directly into Gemini chat globally" for personal accounts, 18+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oct 5 – Oct 12&lt;/td&gt;
&lt;td&gt;Skills in Workspace apps, Rapid Release domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oct 13 – mid-Nov&lt;/td&gt;
&lt;td&gt;Skills in the Gemini app for Workspace domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oct 19 – mid-Nov&lt;/td&gt;
&lt;td&gt;Skills in Workspace apps, Scheduled Release domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nov 17, 2026&lt;/td&gt;
&lt;td&gt;Gems move into the Gemini app's Settings panel (still usable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;November 2026&lt;/td&gt;
&lt;td&gt;Gem support removal begins for personal accounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No sooner than Mar 1, 2027&lt;/td&gt;
&lt;td&gt;Business/enterprise: Gems stop working; leftovers auto-migrate to &lt;strong&gt;draft&lt;/strong&gt; skills&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No sooner than Jun 1, 2027&lt;/td&gt;
&lt;td&gt;Education: same, plus Classroom and LTI integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If your Gemini looks different from your coworker's, this staggered schedule is probably why. Personal account, Workspace domain, and release channel each land on a different date.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental model: skills are loaded lazily
&lt;/h2&gt;

&lt;p&gt;A Gem was a separate assistant with its own chat. A skill is closer to a plugin that the model pulls into the current conversation. Google's help page describes three stages, which line up with the "progressive disclosure" section of the Agent Skills spec:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Match.&lt;/strong&gt; Gemini reads only each skill's &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; to decide whether it is relevant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load.&lt;/strong&gt; If it matches, Gemini reads the full instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch.&lt;/strong&gt; Attached files (templates, style guides, data) are opened only when a step needs them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The practical consequence: &lt;strong&gt;your description is your router.&lt;/strong&gt; Gemini can apply skills automatically, and a vague description means the skill never fires. Google's writing guide says to start with a third-person capability statement, add "Use when…" triggers, and stay under 1,024 characters. The spec sets the same 1,024-character limit.&lt;/p&gt;

&lt;p&gt;You can also stack skills. Google's example pairs a writing-style skill with a brand-guidelines skill in one prompt. Because each skill should do one job, this pushes you toward small, composable files rather than one giant system prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your first SKILL.md (adapted pattern)
&lt;/h2&gt;

&lt;p&gt;Per the spec, a skill is a folder whose name matches the skill's &lt;code&gt;name&lt;/code&gt;, with &lt;code&gt;SKILL.md&lt;/code&gt; at the root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;draft-weekly-update/
├── SKILL.md
└── references/
    └── tone.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;draft-weekly-update&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Drafts a weekly status update from meeting notes and task lists. Use when the user asks for a weekly update, status report, or Friday summary.&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-name&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Weekly update&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; Read the notes the user provides (or the attached doc).
&lt;span class="p"&gt;2.&lt;/span&gt; Group items under: Shipped, In progress, Blocked, Next week.
&lt;span class="p"&gt;3.&lt;/span&gt; Use the tone rules in &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;references/tone.md&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;references/tone.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.

&lt;span class="gu"&gt;## Common mistakes&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Do not invent dates or owners. If one is missing, ask.
&lt;span class="p"&gt;-&lt;/span&gt; Keep it under 200 words unless the user asks for more.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "common mistakes" section and the "ask instead of guessing" rule both come straight from Google's best-practices page. They are the cheapest anti-hallucination measures you can add.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-upload check (adapted pattern)
&lt;/h2&gt;

&lt;p&gt;Google's upload rules: a &lt;code&gt;SKILL.md&lt;/code&gt; in the root folder, a lowercase-hyphenated name, plain-text files only (no &lt;code&gt;.docx&lt;/code&gt; or &lt;code&gt;.xlsx&lt;/code&gt;), 100 MB total, and a tip to strip hidden files like &lt;code&gt;.DS_Store&lt;/code&gt; and &lt;code&gt;.pyc&lt;/code&gt;. Scripts can't reach external websites. One surprise: &lt;code&gt;.env&lt;/code&gt; appears on the supported-file list, so nothing stops you from uploading a secret by accident. This checker flags all of that before you click Upload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# check_skill.py: pre-upload sanity check for a SKILL.md folder
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;NAME_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^[a-z0-9]+(-[a-z0-9]+)*$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# lowercase, single hyphens
&lt;/span&gt;&lt;span class="n"&gt;BLOCKED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.DS_Store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;                        &lt;span class="c1"&gt;# junk + secrets
&lt;/span&gt;&lt;span class="n"&gt;BINARY_EXT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.docx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.doc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.pyc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;         &lt;span class="c1"&gt;# not plain text
&lt;/span&gt;&lt;span class="n"&gt;MAX_BYTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;                          &lt;span class="c1"&gt;# Gemini's 100 MB total
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;errs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SKILL.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_file&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SKILL.md missing from folder root&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^---\n(.*?)\n---\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^(\w[\w-]*):\s*(.+)$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;NAME_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fullmatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bad name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;folder &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt; != name &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description must be 1-1024 chars&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rglob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_file&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;BLOCKED&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;suffix&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;BINARY_EXT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;errs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remove before upload: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_size&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_BYTES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;errs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total size over 100 MB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errs&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;python check_skill.py draft-weekly-update&lt;/code&gt;. On my sample folder it printed &lt;code&gt;OK&lt;/code&gt;. On a copy renamed to &lt;code&gt;Weekly_Update&lt;/code&gt; with a stray &lt;code&gt;.DS_Store&lt;/code&gt;, it flagged the folder/name mismatch and the hidden file. It is a lint, not a full YAML parser. For spec-level validation, the Agent Skills project points to &lt;code&gt;skills-ref validate ./my-skill&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap: a migrated Gem is a draft, not a working skill
&lt;/h2&gt;

&lt;p&gt;Google says remaining Gems will be auto-migrated, and the Workspace post calls the result &lt;strong&gt;draft&lt;/strong&gt; skills. Read the fine print before you count on that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Some Gem tools don't carry over yet.&lt;/strong&gt; As relayed by On The Wire, Google's help page says most default Gem tools don't work with skills for now, naming Create video, Create music, Canvas, Deep Research, and Guided Learning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills don't sync.&lt;/strong&gt; Google says skills in the Gemini app and skills in Workspace apps are separate. You have to create each one twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharing and Drive files are "coming weeks."&lt;/strong&gt; Both are promised but not shipped yet, per Google's blog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Labs Gems and Opal don't migrate.&lt;/strong&gt; Google's footnote says Gems by Google Labs will not become skills, and Opal shuts down in November.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editing files means re-uploading.&lt;/strong&gt; To change a skill's files, you upload the whole folder again (Skill actions → Replace skill).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Checklist for moving a Gem early
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open each Gem and download its Knowledge files into a folder named exactly like the future skill (lowercase, hyphens).&lt;/li&gt;
&lt;li&gt;Create the skill in Settings → Skills → &lt;strong&gt;Create manually&lt;/strong&gt;, then paste in the name, description, and instructions. Use the web app; Google lists manual creation on mobile as a known bug.&lt;/li&gt;
&lt;li&gt;Rewrite the description as a router: what it does, then "Use when…".&lt;/li&gt;
&lt;li&gt;Download the new skill's &lt;code&gt;.zip&lt;/code&gt;, move &lt;code&gt;SKILL.md&lt;/code&gt; into your folder, run the checker, then use &lt;strong&gt;Replace skill&lt;/strong&gt; to upload the folder.&lt;/li&gt;
&lt;li&gt;Commit the folder to a repo. That copy is your source of truth for Workspace, for Gemini CLI, and for anything else that reads &lt;code&gt;SKILL.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Test any Gem that relied on Deep Research or Canvas &lt;em&gt;before&lt;/em&gt; November, not after.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Gems were product configuration. Skills are files. Once Google, Anthropic, and GitHub all read the same &lt;code&gt;SKILL.md&lt;/code&gt; layout, your prompt engineering stops belonging to one vendor's settings page and becomes something you can version, review, and lint. The work that pays off is the description, because it decides when a skill fires, and the "ask instead of guessing" rules, because they decide whether the output can be trusted.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Byline:&lt;/em&gt; &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;YongBo Yu&lt;/a&gt; — Toronto AI engineer (agents, LLM workflows). GitHub: &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;YongBoYu1&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>gemini</category>
      <category>ai</category>
      <category>promptengineering</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Codex CLI's Big Refresh Just Landed: First Session, Parallel Agents, and Why /fork Isn't a Worktree</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Mon, 05 Oct 2026 19:01:35 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/codex-clis-big-refresh-just-landed-first-session-parallel-agents-and-why-fork-isnt-a-worktree-1i1i</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/codex-clis-big-refresh-just-landed-first-session-parallel-agents-and-why-fork-isnt-a-worktree-1i1i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile (not original research)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary source:&lt;/strong&gt; &lt;a href="https://developers.openai.com/codex/changelog" rel="noopener noreferrer"&gt;ChatGPT &amp;amp; Codex changelog&lt;/a&gt; by &lt;strong&gt;OpenAI&lt;/strong&gt;, Codex CLI releases &lt;strong&gt;0.156.0 (2026-09-22)&lt;/strong&gt; through &lt;strong&gt;0.160.0 (2026-10-01)&lt;/strong&gt;, plus OpenAI's &lt;a href="https://developers.openai.com/codex/cli/slash-commands" rel="noopener noreferrer"&gt;Codex CLI command reference&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Announcement context:&lt;/strong&gt; OpenAI Developers announced the "major refresh" on &lt;strong&gt;2026-09-29&lt;/strong&gt;; the text was reposted in &lt;a href="https://community.openai.com/t/major-codex-cli-refresh-with-a-new-look-and-powerful-new-capabilities/1402400" rel="noopener noreferrer"&gt;Major Codex CLI refresh, with a new look and powerful new capabilities&lt;/a&gt; (OpenAI Developer Community, &lt;strong&gt;2026-09-30&lt;/strong&gt;)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary coverage:&lt;/strong&gt; &lt;a href="https://www.thenextgentechinsider.com/pulse/openai-refreshes-codex-cli-with-full-screen-ui-and-parallel-task-management" rel="noopener noreferrer"&gt;OpenAI Refreshes Codex CLI with Full-Screen UI and Parallel Task Management&lt;/a&gt; by &lt;strong&gt;Hiren Dave&lt;/strong&gt; (TheNextGenTechInsider, &lt;strong&gt;2026-10-04&lt;/strong&gt;); &lt;a href="https://www.codexworkshop.com/research/codex-cli-update-voice-agents-worktrees" rel="noopener noreferrer"&gt;Codex CLI Update: Voice, the /agents View, Resume and Worktrees&lt;/a&gt; by &lt;strong&gt;Rogier Muller&lt;/strong&gt; (Codex Workshop, &lt;strong&gt;2026-09-29&lt;/strong&gt;)&lt;br&gt;&lt;br&gt;
This post restates OpenAI's release notes and docs in my own words, with a first-session checklist. &lt;strong&gt;I did not run the new Codex CLI build for this article.&lt;/strong&gt; Feature descriptions are vendor-reported or attributed to the named secondary source. Shell snippets are adapted patterns using documented commands, not output from a real session.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;OpenAI is calling it a "major refresh" of Codex CLI. The announcement pitches three things: a full-screen terminal interface, better readability, and "ways to manage parallel work" without leaving the terminal. Under the hood it is not one release. It is a run of builds, 0.156.0 through 0.160.0, shipped between September 22 and October 1.&lt;/p&gt;

&lt;p&gt;That matters for a practical reason. Which version you have decides what you actually see. And one headline phrase, "/fork into a worktree," is easy to misread in a way that can cost you a messy checkout.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changed (by release)
&lt;/h2&gt;

&lt;p&gt;Here is the changelog, grouped by what you will notice:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Release&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;What changed (vendor-reported)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.156.0&lt;/td&gt;
&lt;td&gt;Sep 22&lt;/td&gt;
&lt;td&gt;Optional full-screen UI via &lt;code&gt;/tui&lt;/code&gt; (transcript search, mouse selection, right-click copy); voice on by default (F8); &lt;code&gt;/usage&lt;/code&gt; analytics dashboard; worktree sessions from the agent command center, with &lt;strong&gt;worktree support on by default&lt;/strong&gt;; Mermaid diagrams and equations rendered in the terminal; &lt;code&gt;--no-daemon&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.157.0&lt;/td&gt;
&lt;td&gt;Sep 25&lt;/td&gt;
&lt;td&gt;Full-screen transcript &lt;strong&gt;on by default&lt;/strong&gt;; automatic background-server startup for eligible sessions; GPT-6 Sol and Luna in the catalog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.159.0&lt;/td&gt;
&lt;td&gt;Sep 29&lt;/td&gt;
&lt;td&gt;Opt-in &lt;code&gt;instant_interrupt&lt;/code&gt; so new input can steer mid-response; compact welcome screen; &lt;code&gt;.aws&lt;/code&gt; directories protected by default under writable roots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.159.1&lt;/td&gt;
&lt;td&gt;Sep 29&lt;/td&gt;
&lt;td&gt;GPT-6.1 Sol becomes the default in the bundled catalog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.160.0&lt;/td&gt;
&lt;td&gt;Oct 1&lt;/td&gt;
&lt;td&gt;"Show more" history in the agent command center; projectless sessions (when policy permits); unsent queued messages resume after a reconnect without being sent twice&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The community repost of the announcement points to two quality-of-life fixes. Older history now loads as you scroll, past your terminal's own scrollback limit. And the composer stays pinned at the bottom, so you no longer scroll back down to type during a long session. One commenter in the thread called the old behaviour a bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental model: the TUI is now a control plane
&lt;/h2&gt;

&lt;p&gt;Before this refresh, Codex CLI was basically a chat loop in your terminal. Now it is closer to a supervisor for several agent threads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The agent command center&lt;/strong&gt; (OpenAI's announcement calls it the &lt;code&gt;/agents&lt;/code&gt; view) lists your sessions. You can filter them by status and start worktree sessions from there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent threads&lt;/strong&gt; are things you switch into with &lt;code&gt;/agent&lt;/code&gt; or &lt;code&gt;/subagents&lt;/code&gt;, per the current command reference. Codex Workshop notes that the announcement and the docs use different names here, so type &lt;code&gt;/&lt;/code&gt; and check what your build actually offers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering vs queueing.&lt;/strong&gt; Press Enter while Codex is working to inject instructions into the current turn. Press Tab to queue a follow-up for the next turn. Press Escape twice with an empty composer to edit your last message and fork the chat from that point.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The trap: /fork is a chat fork, not automatically a checkout
&lt;/h2&gt;

&lt;p&gt;As relayed in press coverage, the announcement says you can "/fork a conversation into a worktree with the same context and a separate checkout." That sounds like &lt;code&gt;/fork&lt;/code&gt; always gives you filesystem isolation.&lt;/p&gt;

&lt;p&gt;OpenAI's own command reference describes &lt;code&gt;/fork&lt;/code&gt; more narrowly. It clones the current chat into a new chat with a fresh ID and leaves the original transcript alone. The thing that creates a separate checkout is a &lt;strong&gt;worktree session&lt;/strong&gt;. Per the 0.156.0 notes, you start one from the agent command center, and worktree support is on by default.&lt;/p&gt;

&lt;p&gt;If you fork a chat and both threads keep writing to the same directory, you have two agents editing one working tree. The isolation you assumed isn't there. So check before you let a second agent write anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Adapted pattern: confirm isolation before parallel edits&lt;/span&gt;
git worktree list            &lt;span class="c"&gt;# the second session should have its own path&lt;/span&gt;
&lt;span class="c"&gt;# inside each Codex session:&lt;/span&gt;
&lt;span class="c"&gt;#   /status  -&amp;gt; check writable roots point at the path you expect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Codex Workshop, citing OpenAI's worktree guide, adds two caveats. Managed worktrees sit under &lt;code&gt;$CODEX_HOME/worktrees&lt;/code&gt; on a detached HEAD. And ignored files such as &lt;code&gt;.env&lt;/code&gt; are &lt;strong&gt;not&lt;/strong&gt; copied into them automatically. Git's usual rule also still applies: a branch can be checked out in only one worktree at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  First session checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upgrade.&lt;/strong&gt; Run &lt;code&gt;npm install -g @openai/codex@latest&lt;/code&gt;, or pin &lt;code&gt;@openai/codex@0.160.0&lt;/code&gt; if you want the October 1 build exactly. &lt;code&gt;codex update&lt;/code&gt; works when your installed release supports self-update.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health check.&lt;/strong&gt; Run &lt;code&gt;codex doctor --summary&lt;/code&gt; to check install, config, auth, Git, and terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with sane permissions.&lt;/strong&gt; The docs suggest &lt;code&gt;codex --sandbox workspace-write --ask-for-approval on-request&lt;/code&gt; for low-friction local work. Avoid &lt;code&gt;--yolo&lt;/code&gt; outside an isolated VM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirm the session.&lt;/strong&gt; Run &lt;code&gt;/status&lt;/code&gt; to see the active model, approval policy, writable roots, and context usage. If GPT-6.1 Sol isn't what you expected, switch with &lt;code&gt;/model&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallelize deliberately.&lt;/strong&gt; Start the second task as a worktree session, then verify with &lt;code&gt;git worktree list&lt;/code&gt;. Codex Workshop also warns that approval prompts can come from a thread you aren't looking at, so read which thread is asking before you approve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cap concurrency.&lt;/strong&gt; Codex Workshop documents a per-project limit you can set:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;   &lt;span class="c"&gt;# .codex/config.toml (pattern from Codex Workshop's restatement of the docs)&lt;/span&gt;
   &lt;span class="nn"&gt;[agents]&lt;/span&gt;
   &lt;span class="py"&gt;max_concurrent_threads_per_session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Watch the bill.&lt;/strong&gt; Subagents each do their own model and tool work, so parallel sessions use more tokens. Use &lt;code&gt;/usage&lt;/code&gt; (added in 0.156.0) to see token activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End each thread with a review.&lt;/strong&gt; Run &lt;code&gt;/diff&lt;/code&gt;, then &lt;code&gt;/review&lt;/code&gt;, before you merge anything a parallel thread produced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escape hatch.&lt;/strong&gt; If the full-screen UI fights your tmux or SSH setup, &lt;code&gt;/tui&lt;/code&gt; picks the UI mode for your next launch, and &lt;code&gt;--no-alt-screen&lt;/code&gt; turns off alternate-screen mode for a single run.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Terminal coding agents are turning into orchestrators. The full-screen UI is the visible part. The real change is that one terminal now supervises several threads, each with its own context, permissions, and maybe its own checkout. That makes "which directory is this agent writing to?" a question you have to answer on purpose. Before you run two agents at once, check &lt;code&gt;git worktree list&lt;/code&gt; and look at the writable roots in &lt;code&gt;/status&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Byline:&lt;/em&gt; &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;YongBo Yu&lt;/a&gt; â€” Toronto AI engineer (agents, LLM workflows). GitHub: &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;YongBoYu1&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>openai</category>
      <category>codex</category>
      <category>ai</category>
      <category>cli</category>
    </item>
    <item>
      <title>Claude Code Mods Just Landed: First Hook, Blast Radius Guard, and Why They're Not Sandboxed</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Fri, 02 Oct 2026 13:20:24 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/claude-code-mods-just-landed-first-hook-blast-radius-guard-and-why-theyre-not-sandboxed-3225</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/claude-code-mods-just-landed-first-hook-blast-radius-guard-and-why-theyre-not-sandboxed-3225</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile (not original research)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary source:&lt;/strong&gt; &lt;a href="https://claude.dev/blog/getting-started-with-claude-code-mods/" rel="noopener noreferrer"&gt;Getting started with Claude Code mods&lt;/a&gt; by &lt;strong&gt;Addy Osmani&lt;/strong&gt; (claude.dev), published &lt;strong&gt;2026-10-01&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary roundup:&lt;/strong&gt; &lt;a href="https://aiweekly.co/alerts/anthropic-launches-claude-code-mods-typescript-functions-that-rewrite-prompts" rel="noopener noreferrer"&gt;Anthropic Launches Claude Code Mods, TypeScript Agent Hooks&lt;/a&gt; (AI Weekly), published &lt;strong&gt;2026-10-02&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This post restates Anthropic’s Claude Code Mods launch packaging in my own words, with a builder checklist for first hooks and install hygiene. &lt;strong&gt;I did not run Claude Code Mods for this article.&lt;/strong&gt; Hook shapes, example mods, version floors, and trust claims below are vendor-reported (or clearly attributed to the named secondary source). Code snippets adapt the public API patterns from Osmani’s guide — not a dump of the full sample modules.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Anthropic shipped &lt;strong&gt;Claude Code Mods&lt;/strong&gt; on October 1, 2026. Per Osmani’s guide, a mod is a small JavaScript or TypeScript module that lives inside a plugin, registers hooks into Claude Code’s event loop, and can rewrite prompts, hold or deny tool calls, approve or refuse permissions, redact secrets, and draw or replace UI. Claude Code &lt;strong&gt;2.1.287+&lt;/strong&gt; is the floor; mods are &lt;strong&gt;on by default&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That last detail is the product decision. You are not opting into a toy extension API. You are sitting on a middleware layer that already powers first-party features — and that runs with the same machine reach as Claude Code itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a mod actually is (middleware, not a settings shell)
&lt;/h2&gt;

&lt;p&gt;Osmani frames mods as hooks that ship inside plugins. The folder is a normal plugin (&lt;code&gt;.claude-plugin/plugin.json&lt;/code&gt;). &lt;code&gt;hooks/hooks.json&lt;/code&gt; points at one module under &lt;code&gt;modules&lt;/code&gt;. That module exports &lt;code&gt;register(on, options)&lt;/code&gt;, and inside it you attach handlers with &lt;code&gt;on(event, matcher?, hook)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every hook shares one shape (API pattern from Osmani’s post):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool.call&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// $ = mods API (ui, session, state, fs, process, …)&lt;/span&gt;
  &lt;span class="c1"&gt;// e = this event's plain data&lt;/span&gt;
  &lt;span class="c1"&gt;// next = pass e down the chain to other mods / Claude Code&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hooks chain like Express middleware. The first-loaded mod sees the event first and the result last — AI Weekly restates the same load-order rule from Anthropic’s packaging. Inside a hook you pick one of three moves:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Move&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Typical use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Observe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;const r = await next(e); /* inspect */; return r&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Log edits, meter context, build a replay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rewrite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;return next({ ...e, command: safer })&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Change what the rest of the chain sees&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Answer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;return { deny: "…" }&lt;/code&gt; &lt;em&gt;without&lt;/em&gt; calling &lt;code&gt;next&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Refuse a tool call; serve a command yourself&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Events cover tool calls, prompt submit, turn start/finish, session lifecycle, slash commands, and &lt;code&gt;ui.render&lt;/code&gt;. Osmani notes the module itself has no DOM and no Node — everything outside goes through &lt;code&gt;$&lt;/code&gt;. That is &lt;em&gt;not&lt;/em&gt; the same as “sandboxed from your laptop.” &lt;code&gt;$&lt;/code&gt; exposes &lt;code&gt;fs&lt;/code&gt;, &lt;code&gt;process&lt;/code&gt;, &lt;code&gt;http&lt;/code&gt;, and friends. Treat install like npm: trusted source or skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  First-party features are already mods
&lt;/h2&gt;

&lt;p&gt;Claude Code dogfoods the system. Osmani says &lt;strong&gt;AGENTS.md&lt;/strong&gt; support and the &lt;strong&gt;&lt;code&gt;/diff&lt;/code&gt;&lt;/strong&gt; pane beside the conversation ship as mods; their sources live under &lt;code&gt;mods/&lt;/code&gt; in the public &lt;code&gt;anthropics/claude-code&lt;/code&gt; repo. AI Weekly adds that Team/Enterprise plans load a built-in &lt;strong&gt;&lt;code&gt;sec-default&lt;/code&gt;&lt;/strong&gt; mod first, aimed at blocking risky overrides of permission denials.&lt;/p&gt;

&lt;p&gt;Practical takeaway: if Anthropic’s own UX is a mod, your team’s conventions, cost meters, and Bash guards belong in the same layer — not as one-off shell hooks that restart on every event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three example mods (vendor demos, not my harness)
&lt;/h2&gt;

&lt;p&gt;Osmani walks three public demos. I am summarizing behavior only; numbers and line counts are from the guide.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token Weather (~80 lines)&lt;/strong&gt; — After each main-loop turn, reads &lt;code&gt;$.session.usage()&lt;/code&gt;, keeps history in &lt;code&gt;$.state&lt;/code&gt;, and draws a one-line forecast in the &lt;code&gt;AbovePrompt&lt;/code&gt; band (Clear → Cloudy → Showers → Storm → Compact soon). Teaching point: hot reload wipes module variables; put session history in &lt;code&gt;$.state&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blast Radius&lt;/strong&gt; — On risky &lt;code&gt;Bash&lt;/code&gt; (&lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;git reset --hard&lt;/code&gt;, force push, migrations, …), classifies the command, dry-runs impact via &lt;code&gt;$.process.run&lt;/code&gt;, opens a Proceed/Cancel pane, and either &lt;code&gt;next(e)&lt;/code&gt; or returns &lt;code&gt;{ deny: "…" }&lt;/code&gt;. Teaching point: the &lt;strong&gt;Answer&lt;/strong&gt; move is how you hold a call without rewriting Claude Code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replay Theater&lt;/strong&gt; — Observes Edit/Write calls, registers &lt;code&gt;/replay&lt;/code&gt;, and steps diffs in a pane. Teaching point: observe-only mods never call &lt;code&gt;deny&lt;/code&gt;; they pair &lt;code&gt;turn.start&lt;/code&gt; / &lt;code&gt;turn.complete&lt;/code&gt; and filter out subagents via &lt;code&gt;e.agentId&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you only build one thing this week, build a Blast Radius–style guard tuned to &lt;em&gt;your&lt;/em&gt; stack (production kubectl contexts, &lt;code&gt;terraform apply&lt;/code&gt;, drop-table SQL). Permission rules are still the hard block; Blast Radius is a safety net that reads command text and can miss &lt;code&gt;$(…)&lt;/code&gt;, aliases, and nested scripts — Osmani says that explicitly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal Blast Radius core (adapted pattern)
&lt;/h2&gt;

&lt;p&gt;The heart of holding Bash is the Answer move. Adapted from Osmani’s Blast Radius sketch (not the full module):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool.call&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;risk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;risk&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// safe path: pass through&lt;/span&gt;

  &lt;span class="c1"&gt;// measure($, …) dry-runs via git status / git clean -n / du, etc.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;askUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pane or AbovePrompt band&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proceed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Held by Blast Radius: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validate with &lt;code&gt;claude plugin validate ./your-mod&lt;/code&gt; before you share it. Osmani’s guide shows the validator listing hooks, &lt;code&gt;$&lt;/code&gt; calls, and declared &lt;code&gt;PluginState&lt;/code&gt; keys — fail closed on undeclared state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install path and the trust model
&lt;/h2&gt;

&lt;p&gt;Shipping is the existing plugin channel. From Osmani:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add your-org/my-mods
/plugin install token-weather@your-mods
/reload-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude directory submissions go through &lt;code&gt;claude.ai/directory/manage&lt;/code&gt;. Hot reload watches the folder in a session started with &lt;code&gt;--plugin-dir&lt;/code&gt;; Claude may ask once to enable it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trust is the feature, not a footnote.&lt;/strong&gt; AI Weekly quotes Anthropic bluntly: mods run with the same access to your machine as Claude Code; they are not sandboxed; install only sources you trust. Osmani’s share section says the same in packaging language — publisher code, not Anthropic-signed isolation. &lt;code&gt;sec-default&lt;/code&gt; helps Team/Enterprise at the front of the chain; it does not make a random marketplace plugin safe.&lt;/p&gt;

&lt;p&gt;Shortcut Osmani highlights: describe the mod to Claude Code and let it scaffold the plugin. You still own the review of what it wrote before &lt;code&gt;/plugin install&lt;/code&gt; hits a shared machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Builder checklist (this week)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upgrade&lt;/strong&gt; to Claude Code &lt;strong&gt;2.1.287+&lt;/strong&gt; and confirm &lt;code&gt;claude --version&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do not&lt;/strong&gt; mass-install marketplace mods until you have a trusted-source list (internal org marketplace first).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaffold one observe mod&lt;/strong&gt; (Token Weather–style) so you learn &lt;code&gt;$.state&lt;/code&gt; + &lt;code&gt;ui.render&lt;/code&gt; / &lt;code&gt;AbovePrompt&lt;/code&gt; without touching Bash.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaffold one Answer mod&lt;/strong&gt; (Blast Radius–style) for the three commands your team fears most; keep permission rules as the hard deny.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run&lt;/strong&gt; &lt;code&gt;claude plugin validate&lt;/code&gt; and at least one &lt;code&gt;claude plugin test&lt;/code&gt; before sharing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer&lt;/strong&gt; &lt;code&gt;$.state&lt;/code&gt; over module &lt;code&gt;let&lt;/code&gt; — hot reload re-runs &lt;code&gt;register&lt;/code&gt; and &lt;code&gt;session.start&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On Team/Enterprise&lt;/strong&gt;, confirm &lt;code&gt;sec-default&lt;/code&gt; is loaded first; document whether local users can dilute it (AI Weekly flags this as an open admin question).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review&lt;/strong&gt; any mod Claude writes for you the same way you review a PR that gets &lt;code&gt;fs&lt;/code&gt; + &lt;code&gt;process&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this post exists
&lt;/h2&gt;

&lt;p&gt;Coding agents are becoming extension hosts. Mods make Claude Code’s loop a public middleware surface: rewrite, hold, redraw. The durable skill is not memorizing &lt;code&gt;AbovePrompt&lt;/code&gt; — it is treating install hygiene as part of agent security, and shipping one guard that matches &lt;em&gt;your&lt;/em&gt; blast radius before the directory fills with convenience plugins.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Byline:&lt;/em&gt; &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;YongBo Yu&lt;/a&gt; — Toronto AI engineer (agents, LLM workflows). GitHub: &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;YongBoYu1&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>anthropic</category>
      <category>ai</category>
      <category>codingagents</category>
    </item>
    <item>
      <title>Gemini 4 Argon Just Dropped — But You Can't Call It Yet: Pricing, 1M Output Tokens, and What to Do Until the API Lands</title>
      <dc:creator>Yong Yu</dc:creator>
      <pubDate>Thu, 01 Oct 2026 13:46:06 +0000</pubDate>
      <link>https://dev.to/yong_yu_f98e15562e9b120a0/gemini-4-argon-just-dropped-but-you-cant-call-it-yet-pricing-1m-output-tokens-and-what-to-do-4bel</link>
      <guid>https://dev.to/yong_yu_f98e15562e9b120a0/gemini-4-argon-just-dropped-but-you-cant-call-it-yet-pricing-1m-output-tokens-and-what-to-do-4bel</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attributed compile (not original research)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Primary source:&lt;/strong&gt; &lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-4-argon/" rel="noopener noreferrer"&gt;Gemini 4 Argon: our next era of frontier intelligence&lt;/a&gt; by &lt;strong&gt;Koray Kavukcuoglu&lt;/strong&gt; (Google DeepMind / Google blog), published &lt;strong&gt;2026-09-30&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Secondary roundup:&lt;/strong&gt; &lt;a href="https://9to5google.com/2026/09/30/gemini-4-argon-announcement/" rel="noopener noreferrer"&gt;Google announces Gemini 4 Argon as its new frontier model&lt;/a&gt; (9to5Google), published &lt;strong&gt;2026-09-30&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Optional context:&lt;/strong&gt; &lt;a href="https://www.engadget.com/2274263/google-gemini-4-model-argon/" rel="noopener noreferrer"&gt;Google's first Gemini 4 model is 'Argon'&lt;/a&gt; (Engadget), published &lt;strong&gt;2026-10-01&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Contrast only (not the headline):&lt;/strong&gt; &lt;a href="https://openai.com/index/introducing-gpt-6-1-sol" rel="noopener noreferrer"&gt;Introducing GPT-6.1 Sol&lt;/a&gt; (OpenAI) and &lt;a href="https://github.blog/changelog/2026-09-29-gpt-6-1-sol-in-github-copilot/" rel="noopener noreferrer"&gt;GPT-6.1 Sol in GitHub Copilot&lt;/a&gt; (GitHub Changelog), both &lt;strong&gt;2026-09-29&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This post restates Googles launch packaging in my own words, with a builder checklist for what to do &lt;em&gt;before&lt;/em&gt; a public model ID exists. &lt;strong&gt;I did not run Gemini 4 Argon&lt;/strong&gt;  it is not publicly available yet. Every price, benchmark, and access claim below is vendor-reported (or clearly attributed to a named secondary source).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Google announced &lt;strong&gt;Gemini 4 Argon&lt;/strong&gt; on September 30, 2026, as its next frontier model after the Gemini 3.x line. The capability story is long-horizon software engineering, enterprise knowledge work, and defensive cybersecurity. The access story matters more for builders this week: Argon is live only inside Google’s &lt;strong&gt;Fairwind Program&lt;/strong&gt; for trusted cyber defenders. Broader rollout is “soon,” starting with paid API customers and Google AI Ultra subscribers. There is &lt;strong&gt;no public model ID&lt;/strong&gt; and &lt;strong&gt;no first-call snippet&lt;/strong&gt; for general developers yet.&lt;/p&gt;

&lt;p&gt;That phased release is the difference between bookmark the blog” and “ship a production default tomorrow.”&lt;/p&gt;

&lt;h2&gt;
  
  
  What Google announced (and why Fairwind-first matters)
&lt;/h2&gt;

&lt;p&gt;Per Kavukcuoglu’s post, Argon is built for deep reasoning across complex, multi-step workflows. Google says it is already using Argon internally (thousands of Googlers, vendor claim) for specialized coding, research, and writing. External access starts with Fairwind — and for trusted defenders plus Google’s own teams, Google will ship a version &lt;strong&gt;without cyber guardrails&lt;/strong&gt; so they can use full defensive capability.&lt;/p&gt;

&lt;p&gt;For everyone else, Google is still iterating on safeguards (misuse including CBRN/cyber, prompt injection, misalignment monitoring of chain-of-thought and actions, and hardened sandboxes) while engaging the U.S. government’s voluntary pre-release process. Treat Fairwind-only as a hard product constraint: &lt;strong&gt;do not plan a customer-facing pipeline on Argon until you have a documented API model ID and a paid access path.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing trap: intro $2/$10 vs post-intro $4/$20
&lt;/h2&gt;

&lt;p&gt;Googles stated launch pricing (vendor):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Per 1M tokens (Google)&lt;/th&gt;
&lt;th&gt;Introductory&lt;/th&gt;
&lt;th&gt;After intro period&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$4&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$20&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cached input&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;95% off&lt;/strong&gt; input price&lt;/td&gt;
&lt;td&gt;same discount structure stated at launch&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Intro sticker matches the familiar &lt;strong&gt;$2 / $10&lt;/strong&gt; band many teams already budget for mid-frontier coding models. After the introductory period, Google says rates move to &lt;strong&gt;$4 / $20&lt;/strong&gt; — Opus-class list territory. Cached input at &lt;strong&gt;95% off&lt;/strong&gt; input price is the quiet lever: long agent loops that re-send the same system prompt, repo summary, or tool schema will live or die on cache hit rate once Argon is in the API.&lt;/p&gt;

&lt;p&gt;Build cost models for &lt;strong&gt;both&lt;/strong&gt; columns now. An eval that looks cheap at intro rates can double on input/output when the promo ends. Do not bake “Argon is $2/$10 forever” into a board deck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 1M &lt;em&gt;output&lt;/em&gt; tokens changes agent design
&lt;/h2&gt;

&lt;p&gt;Google expands Argon’s &lt;strong&gt;output&lt;/strong&gt; token limit to &lt;strong&gt;1M&lt;/strong&gt;, up from &lt;strong&gt;64K&lt;/strong&gt; — framed as industry-leading generation headroom for long trajectories. Context-window talk is saturated. Output headroom is different: one trajectory can think, tool-call, revise, and emit a large artifact (migration plan, multi-file patch set, research memo) without mid-flight truncation.&lt;/p&gt;

&lt;p&gt;Loops designed for 64K128K completions assume early summarization or multi-turn “continue. A 1M ceiling (once callable) means fewer artificial breakpoints — and more runaway-spend risk. Add budgets, stop conditions, and per-step logs &lt;em&gt;before&lt;/em&gt; you get an API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vendor benchmarks (labeled as such)
&lt;/h2&gt;

&lt;p&gt;These figures come from Google’s announcement and secondary reporting. They are &lt;strong&gt;not&lt;/strong&gt; my harness results.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark (vendor-reported)&lt;/th&gt;
&lt;th&gt;Gemini 4 Argon&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DeepSWE v1.1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;77.9%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Long-horizon SWE; 9to5Google cites Claude Opus 5.5 at &lt;strong&gt;74.2%&lt;/strong&gt; and GPT-6 Astra at &lt;strong&gt;74.1%&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AutomationBench (Zapier)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;51.3%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google claims &lt;strong&gt;#1&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LVBench (long video)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;91.7%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google claims &lt;strong&gt;SOTA&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CWE-bench v1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;68%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google claims &lt;strong&gt;tied for first&lt;/strong&gt; (vuln remediation)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Google also points to leading placement on the Vals Index and strong domain results on Vals Finance Agent v2 and Harvey’s Legal Agent Benchmark. Orientation only: different benches measure different jobs. Your golden set still wins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Google anecdotes (vendor examples, not your SLA)
&lt;/h3&gt;

&lt;p&gt;Capability &lt;em&gt;hints&lt;/em&gt;, not SLAs: quantum subroutine optimization (&lt;strong&gt;40%&lt;/strong&gt; better than a published baseline in one example); fleet memory work freeing &lt;strong&gt;300+ TiB&lt;/strong&gt;; CRust migrations from &lt;strong&gt;re2&lt;/strong&gt; / &lt;strong&gt;libgav1&lt;/strong&gt; up to &lt;strong&gt;800K+&lt;/strong&gt; lines for Fuchsia Zircon (under heavy audit); and a &lt;strong&gt;libgav1&lt;/strong&gt; Rust SIMD rewrite claimed &lt;strong&gt;2.7×&lt;/strong&gt; faster than the prior Rust port with identical video output.&lt;/p&gt;

&lt;p&gt;Cyber angle: Argon is trained for defense; Wiz’s Scan for Good is cited for a critical healthcare exposure previous frontier models missed. Vendor narrative — not an independent pen-test for compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What builders should do &lt;em&gt;this week&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;OpenAI shipped &lt;strong&gt;GPT-6.1 Sol&lt;/strong&gt; on September 29 at the same sticker band (&lt;strong&gt;$2 / $10&lt;/strong&gt;) and it is &lt;strong&gt;already&lt;/strong&gt; in the API and GitHub Copilot per OpenAI and GitHub’s changelog. That contrast is actionable: do not stall shipping while Fairwind widens.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Keep shipping&lt;/strong&gt; on models you can call today: GPT-6.1 Sol, Claude Opus / Sonnet 5.5, Grok where it fits.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare long-horizon SWE evals&lt;/strong&gt; now — multi-file edits, flaky tests, migration-style tasks. When Argon’s model ID lands, you want a 2050 trajectory harness ready.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch for the public model ID&lt;/strong&gt; and paid API / Ultra notes. No ID → no production default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do not&lt;/strong&gt; block a release on Fairwind-only access unless you are in that program.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price for the post-intro column&lt;/strong&gt; ($4/$20) in any Argon ROI slide; assume cache misses until you measure them.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security posture:&lt;/strong&gt; if you ever get a no-guardrail cyber build, isolate it. Fairwind is defense capability plus staged safeguards  not “same sandbox as the public chatbot.”&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When Argon might become your default (once the API lands)
&lt;/h2&gt;

&lt;p&gt;Only after a callable model ID and billing access:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Workloads are &lt;strong&gt;long-horizon&lt;/strong&gt; and you are hitting today’s completion caps.
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;golden eval&lt;/strong&gt; shows Argon beating your current default on &lt;em&gt;your&lt;/em&gt; failures — not DeepSWE screenshots alone.
&lt;/li&gt;
&lt;li&gt;Cost model survives &lt;strong&gt;post-intro&lt;/strong&gt; $4/$20 &lt;em&gt;and&lt;/em&gt; realistic cache hit rates.
&lt;/li&gt;
&lt;li&gt;Prompt-injection / tool-exfiltration tests pass under your threat model (Google claims Gray Swan IPI leadership — verify on your agents).
&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;rollback&lt;/strong&gt; to Sol / Opus / Sonnet without rewriting orchestration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Until then, Argon is a roadmap signal. Treat the blog as planning input; treat GPT-6.1 Sol and the Claude 5.5 pair as this week’s shipping surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this post exists
&lt;/h2&gt;

&lt;p&gt;Frontier launches now split into two products: the &lt;strong&gt;capability blog&lt;/strong&gt; and the &lt;strong&gt;availability calendar&lt;/strong&gt;. Argon is a serious capability claim with a Fairwind-first calendar. The durable skill is refusing to confuse them — and having harnesses, budgets, and rollbacks ready for the day a public model ID appears.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Byline:&lt;/em&gt; &lt;a href="https://yongbo-yu.vercel.app" rel="noopener noreferrer"&gt;YongBo Yu&lt;/a&gt; — Toronto AI engineer (agents, LLM workflows). GitHub: &lt;a href="https://github.com/YongBoYu1" rel="noopener noreferrer"&gt;YongBoYu1&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codingagents</category>
      <category>gemini</category>
      <category>google</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
