<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Divyansh Agrawal</title><link>https://divagr.com</link><description>Technical writing by Divyansh Agrawal.</description><language>en</language><item><title><![CDATA[Teaching an Agent Fleet to Distrust Documents: Zero-Trust M&A Diligence on Google Cloud]]></title><link>https://divagr.com/blog/zero-trust-agent-fleets</link><guid>https://divagr.com/blog/zero-trust-agent-fleets</guid><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate><description><![CDATA[How Diligence Room uses isolated agents, hostile-document screening, and evidence gates to make autonomous deal diligence defensible.]]></description><content:encoded><![CDATA[<h2 id="tl-dr">TL;DR</h2>
<p>Diligence Room is an enterprise zero-trust runtime for autonomous multi-agent fleets, demonstrated through a high-stakes M&amp;A due-diligence scenario on a synthetic robotics company, Vantage Robotics, investigated under the deal name <strong>Project Falcon</strong>. Eight specialist agents analyze a hostile, unvetted data room under strict information barriers, taking the transaction from document upload to executive risk synthesis as a deterministic replay in under four minutes.</p>
<p>The architecture rests on three reframings: <strong>documents are adversaries, agents are principals, and memory is partitioned by policy rather than convenience.</strong> It was built for the AllThingsAgentic Hackathon's Fortified Enterprise Fleet track on the Google Gemini Enterprise Agent Platform.</p>
<h2 id="2-00-am-in-the-virtual-data-room">2:00 AM in the virtual data room</h2>
<p>Picture an M&amp;A war room at 2:00 AM, forty-eight hours before a term sheet expires. A seller has dumped 10,000 pages of contradictory files into a data room: scanned contracts, redacted cap tables, customer MSAs, employee exit memos, and financial workbooks. A transaction analyst has one question: what in this room will blow up the acquisition six months after close?</p>
<p>The worst liabilities usually live between corporate silos. A legal specialist finds a change-of-control termination right in Meridian Logistics' contract. Finance sees that customer accounts for <strong>18.3% of FY27 cash flow</strong>. HR notices that the account director is resigning. An engineer flags that a core middleware package reaches end-of-life before renewal. Each item looks ordinary alone. Together, they point to a customer collapse that eviscerates deal EBITDA.</p>
<p>Human deal rooms rarely connect those dots in time because teams work in separate systems. A monolithic “chat with your docs” agent fails differently: it blows out its context window, invents numbers to fit clauses, or naively executes prompt injections hidden in uploaded files.</p>
<p>The answer is not a bigger chatbot. It is a fortified fleet of specialized agents that can screen hostile input, enforce domain boundaries, and prove every claim against verbatim evidence before a human signs a check.</p>
<h2 id="the-twist">The twist</h2>
<p>Every architectural choice follows three principles:</p>
<ul><li><strong>Documents are adversaries.</strong> Every vendor-supplied file is hostile input until it passes a four-layer screening gauntlet.</li><li><strong>Agents are principals.</strong> Legal, Finance, HR, IP/Tech, Tax, Regulatory, ESG, and Real Estate agents have distinct service identities, read scopes, and write permissions.</li><li><strong>Memory is partitioned by policy.</strong> Finance projections do not drift into HR's workspace. Legal requests only an explicitly permitted aggregate through the Agent Gateway.</li></ul>
<h2 id="four-layers-between-an-upload-and-a-finding">Four layers between an upload and a finding</h2>
<h3 id="1-gemma-sentinel-the-ingestion-gate">1. Gemma Sentinel: the ingestion gate</h3>
<p>Before a premium model sees document text, every chunk passes through <code>gemma-4-26b-a4b-it</code> on the Gemini Developer API. The sentinel is an inline tripwire for direct prompt injection, sensitive PII markers, and coarse classification hints. Poisoned text is quarantined before it reaches an agent's reasoning context.</p>
<h3 id="2-model-armor-api-the-managed-perimeter">2. Model Armor API: the managed perimeter</h3>
<p>Cleared chunks enter the Google Cloud Model Armor template alongside custom project inspection rules. The design is fail-closed: document text that cannot be cleared does not become agent context.</p>
<h3 id="3-agent-gateway-deny-default-policy-routing">3. Agent Gateway: deny-default policy routing</h3>
<p>When Legal needs to know whether Meridian is material, it cannot browse the Finance data room. It sends a structured request to a Cloud Run gateway. The gateway checks identity and policy, then returns the allowed aggregate:</p>
<pre><code>legal -&gt; finance (revenue_concentration): ALLOW / aggregate_permitted -&gt; 18.3%
hr -&gt; finance (raw_payroll_export): DENY / no_policy</code></pre>
<p>The first request gets one scoped scalar. The second is blocked and recorded as an auditable security event.</p>
<h3 id="4-evidence-gate-the-anti-hallucination-wall">4. Evidence Gate: the anti-hallucination wall</h3>
<p>At the database write boundary, <code>finding_create</code> verifies that each quoted <code>verbatim_span</code> is an exact substring of the cited document chunk. If a model fabricates or paraphrases a quote, the write aborts with <code>evidence_unresolvable</code> and the audit trace records the rejection.</p>
<h2 id="project-falcon-s-defining-moment">Project Falcon's defining moment</h2>
<p>The architecture matters most when independent signals converge:</p>
<ol><li>Legal finds Meridian's 90-day change-of-control clause and logs a high-severity, verbatim-backed finding.</li><li>Through the gateway, Legal receives Finance's verified 18.3% revenue-concentration aggregate.</li><li>HR records the resignation of the Meridian account owner.</li><li>IP/Tech flags TitanBridge 4.1 reaching end-of-life before renewal.</li></ol>
<p>No individual specialist is authorized to declare a deal-killing emergency. The Coordinator Keystone instead evaluates convergence across the deal graph, then synthesizes the critical customer-exit exposure only when every input is independently evidence-backed. Remove a workstream, or fail a cited span, and the coordinator refuses to produce the conclusion.</p>
<h2 id="human-approval-is-a-gate-not-a-formality">Human approval is a gate, not a formality</h2>
<p>After a critical exposure appears, the Negotiation Agent can draft remedies such as seller indemnities, escrow holdbacks, or pre-closing customer waivers. It cannot send them.</p>
<pre><code>draft -&gt; pending_approval -&gt; halted for human review -&gt; approved -&gt; send_logged</code></pre>
<p>The move from <code>pending_approval</code> to <code>approved</code> requires cryptographic human-to-output authorization from the deal lead. Nothing leaves the room without that consent.</p>
<h2 id="what-broke-and-the-defenses-it-produced">What broke, and the defenses it produced</h2>
<h3 id="runaway-tool-loops">Runaway tool loops</h3>
<p>An edge-case contract clause once sent a specialist through ten repetitive tool calls. The Loop Guard now caps iterations, tool calls, tokens, and per-step wall time. A breached bound saves a checkpoint and emits a <code>run.bounds_exceeded</code> receipt.</p>
<h3 id="plausible-but-false-citations">Plausible but false citations</h3>
<p>An agent once produced a convincing environmental-indemnification finding with a slightly paraphrased citation. The Evidence Gate rejects it at write time; low-confidence results remain candidates and cannot trigger autonomous escalation.</p>
<h3 id="mid-run-container-crashes">Mid-run container crashes</h3>
<p>Workers restart. Without transactional state, restarts produced incomplete records and duplicate findings. Crash-Resume and Idempotency commits execution state to an append-only event log, resumes from the last checkpoint, and uses idempotency keys to prevent duplicate outputs.</p>
<h3 id="regressed-agent-deployments">Regressed agent deployments</h3>
<p>An updated Legal prompt subtly regressed on complex indemnities. The Registry Rollback mechanism caught the change through shadow evaluations on a golden set and restored the prior agent version. Because deal state lives in partitioned storage rather than agent code, the rollback does not destroy the transaction record.</p>
<h2 id="the-platform-underneath">The platform underneath</h2>
<p>Diligence Room combines agent cards and a registry for lifecycle management; a Google ADK and Vertex AI Agent Engine runtime for long-running work; partitioned Firestore and memory-bank state; per-workstream IAM identities; Cloud Run policy routing; Model Armor guardrails; OpenTelemetry traces; and Cloud KMS and Cloud DLP controls for compliance.</p>
<p>Those components are only useful when they reinforce the same operating model: a document does not earn trust by arriving in the data room, an agent does not earn access by sounding helpful, and a claim does not earn action by sounding plausible.</p>
<h2 id="closing-thought">Closing thought</h2>
<p>Autonomous agents do not need to be unconstrained black boxes. Treat documents as adversaries, agents as narrowly scoped principals, and human approval as a real boundary, and a multi-agent system can turn a complex workflow into something defensible, inspectable, and auditable.</p>
<h2 id="demo-and-verification">Demo and verification</h2>
<ul><li><strong>Repository:</strong> <a href="https://github.com/divagr18/diligence-room" target="_blank" rel="noreferrer">github.com/divagr18/diligence-room</a></li><li><strong>Live dashboard:</strong> <a href="https://diligence-room-dashboard-378831539922.asia-south1.run.app" target="_blank" rel="noreferrer">Diligence Room dashboard</a></li><li><strong>Hosted gateway:</strong> <a href="https://gateway-378831539922.asia-south1.run.app" target="_blank" rel="noreferrer">Gateway edge</a></li></ul>]]></content:encoded></item><item><title><![CDATA[The Tiny Draft Model Hidden Inside Qwen]]></title><link>https://divagr.com/blog/the-tiny-draft-model-hidden-inside-qwen</link><guid>https://divagr.com/blog/the-tiny-draft-model-hidden-inside-qwen</guid><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate><description><![CDATA[Qwen ships a one-layer multi-token predictor that vLLM and SGLang can use for native speculative decoding.]]></description><content:encoded><![CDATA[<p>I had already spent two posts pulling apart Qwen3.6's attention stack, first <a href="https://divagr.com/attention-lab/delta" target="_blank" rel="noreferrer">Gated DeltaNet</a>, then partial RoPE. I expected the next oddity to be another attention detail. It was sitting at the very end of the checkpoint:</p>
<p><code>mtp.layers.0.*</code></p>
<p>That path belongs to a whole extra transformer layer. Its job is to take what the 64-layer model was about to say and guess one token farther ahead.</p>
<p>A language model normally writes one tiny chunk of text, runs the full model again, then writes the next. Qwen's extra layer gives vLLM and SGLang a cheaper option. They can run the small layer a few times, build a draft, and let the full model check several tokens at once. The draft never gets the final say, so the output still comes from Qwen's main model.</p>
<p>Three lines in the <a href="https://huggingface.co/Qwen/Qwen3.6-27B/blob/main/config.json" target="_blank" rel="noreferrer">Qwen3.6 config</a> describe the arrangement:</p>
<pre><code class="language-json">"num_hidden_layers": 64,
"mtp_num_hidden_layers": 1,
"mtp_use_dedicated_embeddings": false</code></pre>
<p>Qwen has 64 language-model layers and one Multi-Token Prediction layer. <code>mtp_use_dedicated_embeddings = false</code> tells the predictor to use the main model's token embeddings. The checkpoint index lists an <code>mtp.fc</code> projection, one full-attention block under <code>mtp.layers.0</code>, and three normalization weights. It contains no second embedding table.</p>
<p>For the dense 27B model, the matrices in that module add up to roughly 0.39 billion parameters, about 1.5 percent of the language model. That number made the title feel slightly dishonest. "Tiny" still means hundreds of millions of weights here.</p>
<h2 id="one-step-deeper-than-the-main-model">One step deeper than the main model</h2>
<p>Suppose the prompt ends at token $x_t$. The main Qwen stack produces a hidden state $h_t$, and its output head turns that state into a probability distribution for $x_{t+1}$.</p>
<p>Once $x_{t+1}$ has been chosen, the MTP module receives two pieces of information: the main model's final hidden state and the embedding of that new token. It normalizes them, concatenates them, and projects the result back to Qwen's hidden width. One transformer block then predicts $x_{t+2}$ through the same vocabulary head:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msubsup><mi>h</mi><mi>t</mi><mrow><mi mathvariant="normal">M</mi><mi mathvariant="normal">T</mi><mi mathvariant="normal">P</mi></mrow></msubsup><mo>=</mo><mrow><mi mathvariant="normal">B</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">k</mi></mrow><mrow><mo fence="true">(</mo><mi>W</mi><mo stretchy="false">[</mo><mrow><mi mathvariant="normal">N</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">m</mi></mrow><mo stretchy="false">(</mo><msub><mi>h</mi><mi>t</mi></msub><mo stretchy="false">)</mo><mo separator="true">;</mo><mrow><mi mathvariant="normal">N</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">m</mi></mrow><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">E</mi><mi mathvariant="normal">m</mi><mi mathvariant="normal">b</mi></mrow><mo stretchy="false">(</mo><msub><mi>x</mi><mrow><mi>t</mi><mo>+</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">]</mo><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">h_t^{\mathrm{MTP}} = \mathrm{Block}\left(W[\mathrm{Norm}(h_t);\mathrm{Norm}(\mathrm{Emb}(x_{t+1}))]\right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1383em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">MTP</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">Block</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.1389em;">W</span><span class="mopen">[</span><span class="mord"><span class="mord mathrm">Norm</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">Norm</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathrm">Emb</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">))]</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></div>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>p</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mrow><mi>t</mi><mo>+</mo><mn>2</mn></mrow></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="normal">s</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">f</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">m</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">x</mi></mrow><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">L</mi><mi mathvariant="normal">M</mi><mi mathvariant="normal">H</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">d</mi></mrow><mo stretchy="false">(</mo><msubsup><mi>h</mi><mi>t</mi><mrow><mi mathvariant="normal">M</mi><mi mathvariant="normal">T</mi><mi mathvariant="normal">P</mi></mrow></msubsup><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">p(x_{t+2}) = \mathrm{softmax}(\mathrm{LMHead}(h_t^{\mathrm{MTP}})).</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">softmax</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathrm">LMHead</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">MTP</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">))</span><span class="mord">.</span></span></span></span></span></div>
<p>I like this arrangement because the predictor does not begin from raw tokens. It inherits the 64-layer model's compressed reading of the prompt in $h_t$, combines it with the latest token, and performs a small continuation of the main computation.</p>
<p>I initially read Multi-Token Prediction as several parallel output heads. Qwen3.6 uses a sequential design in which its single MTP block predicts one additional depth per call. The serving engine can feed the predicted token and the new MTP hidden state through the block again to guess farther ahead. Recent vLLM releases warn that setting more than one speculative token runs the same MTP layer multiple times, which may reduce acceptance as errors accumulate.</p>
<p>During training, the future token is known and supplies an auxiliary prediction target. At inference, the module has to consume its own guesses after the first extra step. I would be cautious with long speculative chains because every wrong guess leaves the next call with a worse input.</p>
<h2 id="how-the-draft-becomes-real-output">How the draft becomes real output</h2>
<p>The full model first produces a token and the hidden state behind it. The MTP layer extends that state into a short candidate sequence. Then Qwen runs once over all candidate positions with causal masking, producing its own distribution at every position in the draft.</p>
<p>The verifier accepts the longest prefix that agrees with the target model. At the first rejection, the server drops the remaining draft and uses the verifier's corrected replacement distribution. Greedy decoding therefore returns the same tokens as ordinary greedy decoding. With the proper rejection sampler, stochastic speculative decoding preserves the target distribution up to hardware-level numerical differences. The server uses MTP outputs as proposals and derives final output from the target probabilities.</p>
<p>This can be faster because decoding a single token often leaves a GPU waiting on memory. The hardware must read a large set of weights to perform little arithmetic. Verification gives the same weight load several token positions to process. When two or three draft tokens survive, one expensive target pass replaces several ordinary decode steps.</p>
<p>I would not enable this and assume an automatic win. Acceptance rate controls the gain. Every rejected suffix consumes MTP work and target verification capacity without advancing the sequence. Larger batches can also push the target model from memory-bound toward compute-bound operation, leaving less spare arithmetic for verification. vLLM describes speculative decoding as a latency optimization for medium-to-low-QPS, memory-bound workloads and recommends benchmarking the actual model, hardware, sampling settings, and traffic pattern.</p>
<h2 id="what-vllm-and-sglang-do-with-the-weights">What vLLM and SGLang do with the weights</h2>
<p>Current <a href="https://docs.vllm.ai/en/latest/features/speculative_decoding/mtp/" target="_blank" rel="noreferrer">vLLM MTP documentation</a> uses a generic configuration:</p>
<pre><code class="language-bash">--speculative-config '{"method":"mtp","num_speculative_tokens":2}'</code></pre>
<p>Qwen's model card still shows the older family-specific name, <code>qwen3_next_mtp</code>. In either form, vLLM creates a proposer from the MTP tensors inside the target checkpoint. Its Qwen MTP implementation normalizes the token embedding and target hidden state, concatenates them through <code>mtp.fc</code>, runs <code>mtp.layers.0</code>, and applies the language-model head.</p>
<p>SGLang routes the same idea through its EAGLE-style speculative machinery. Qwen recommends <code>--speculative-algo NEXTN</code>, three draft steps, <code>topk=1</code>, and a four-token verification cap. <code>NEXTN</code> tells SGLang to use the checkpoint's future-token predictor, while the remaining flags determine draft depth and tree width. No external draft checkpoint appears in either command.</p>
<p>Native MTP avoids the separately trained small model used in a conventional speculative-decoding setup. Qwen ships the proposer weights beside the target weights and trains them against the same hidden-state space and vocabulary.</p>
<p>I called the draft model hidden because ordinary Hugging Face Transformers generation currently ignores those weights. Its Qwen3.5/3.6 model class lists <code>^mtp.*</code> among unexpected checkpoint keys to skip. vLLM and SGLang can load the same tensors as a proposer, so enabling MTP changes which checkpoint weights run without changing the checkpoint itself.</p>
<h2 id="references">References</h2>
<ul><li><a href="https://huggingface.co/Qwen/Qwen3.6-27B" target="_blank" rel="noreferrer">Qwen3.6-27B model card and serving recipes</a></li><li><a href="https://huggingface.co/Qwen/Qwen3.6-27B/blob/main/config.json" target="_blank" rel="noreferrer">Qwen3.6-27B configuration</a></li><li><a href="https://huggingface.co/Qwen/Qwen3.6-27B/blob/main/model.safetensors.index.json" target="_blank" rel="noreferrer">Qwen3.6-27B checkpoint weight index</a></li><li><a href="https://github.com/vllm-project/vllm/blob/main/vllm/model_executor/models/qwen3_5_mtp.py" target="_blank" rel="noreferrer">vLLM Qwen3.5 MTP implementation</a></li><li><a href="https://docs.vllm.ai/en/latest/features/speculative_decoding/" target="_blank" rel="noreferrer">vLLM speculative-decoding documentation</a></li><li><a href="https://docs.sglang.io/docs/advanced_features/speculative_decoding" target="_blank" rel="noreferrer">SGLang speculative-decoding documentation</a></li><li><a href="https://arxiv.org/abs/2404.19737" target="_blank" rel="noreferrer">Better &amp; Faster Large Language Models via Multi-Token Prediction</a></li><li><a href="https://arxiv.org/html/2412.19437#S2.SS2" target="_blank" rel="noreferrer">DeepSeek-V3 Technical Report, Section 2.2</a></li><li><a href="https://github.com/huggingface/transformers/blob/main/src/transformers/models/qwen3_5/modeling_qwen3_5.py" target="_blank" rel="noreferrer">Qwen3.5/3.6 implementation in Transformers</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Do LLM Agent Societies Adapt Their Values, or Eventually Die by Them?]]></title><link>https://divagr.com/blog/do-llm-agent-societies-adapt-their-values-or-eventually-die-by-them</link><guid>https://divagr.com/blog/do-llm-agent-societies-adapt-their-values-or-eventually-die-by-them</guid><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate><description><![CDATA[What an evolutionary multi-agent simulation reveals about cultural persistence, selection, migration, and the danger of values that never bend.]]></description><content:encoded><![CDATA[<p>Give four groups the same language model, the same world, the same choices, and the same four numbers to keep alive. Change what they believe is worth protecting.</p>
<p>Then make them live with the consequences.</p>
<p>Now add selection. Let successful policies reproduce. Let the arguments used to justify those policies mutate with them. After enough time apart, let agents cross from one culture into another. If all four societies face the same pressures, do they eventually discover the same strategy, or does their history remain visible in what they are willing to trade away?</p>
<p>That was the larger idea behind a project I built called <a href="https://github.com/divagr18/emergent-cultures" target="_blank" rel="noreferrer">Emergent Cultures</a>, and later wrote up as <em>Emergent Cultural Dynamics in Agent-Based Systems through Evolutionary Language Models</em>. The project sits somewhere between an LLM multi-agent simulation and a tiny computational sociology experiment. Four artificial societies make repeated decisions over Health, Prosperity, Security, and Future Outlook. Each begins from a different philosophy. Their decisions change their own state, their performance creates selection pressure, and the broader design lets both policy and rhetoric evolve.</p>
<figure class="article-figure"><img src="/emergent-cultures-evolutionary-loop.jpg" alt="The proposed intra-round evolutionary loop couples policy performance and cultural cohesion" /><figcaption>The proposed intra-round evolutionary loop couples policy performance and cultural cohesion</figcaption></figure>
<p>I came back to the project expecting the evolutionary machinery to be the interesting part. The reread changed the question for me. Different vocabularies were the least interesting signal. Values became policies, policies created trajectories, and those trajectories eventually put the values themselves under pressure. The question I care about now is simple: <strong>what happens when a culture has to keep working?</strong></p>
<figure class="article-figure"><img src="/emergent-cultures-four-tribe-design.jpg" alt="Four tribes evolve separately before a later cultural-contact phase" /><figcaption>Four tribes evolve separately before a later cultural-contact phase</figcaption></figure>
<h2 id="four-societies-one-environment">Four societies, one environment</h2>
<p>The paper describes the full experiment as four tribes of fifteen agents evolving across one hundred rounds. The first fifty rounds are a divergence phase. Each tribe faces the same environmental challenges but evolves independently. In the second phase, an agent can migrate into another tribe, turning cultural contact into an intervention rather than a metaphor.</p>
<p>The four starting philosophies are intentionally broad. The Collective values communal well-being, equity, and health. The Forge emphasizes optimization, prosperity, and security. The Vanguard rewards innovation and willingness to take transformative risks. The Frontiers treats expansion, strength, and adversity as sources of survival.</p>
<p>The starting conditions are designed, so the experiment cannot establish culture appearing from nothing. If The Vanguard later says "innovation" more often than The Collective, that is almost tautological. The stronger question is whether those initial differences become durable strategies once every group has to solve the same sequence of trade-offs.</p>
<p>The paper's evolutionary loop tries to make that concrete. Agents propose actions and arguments. The tribe aggregates them. Fitness combines performance on the colony metrics with linguistic cohesion. High-performing policies survive, and an LLM generates mutated descendants with changes to both control logic and narrative framing.</p>
<p>That coupling is the part I find most interesting now. In many agent simulations, communication is commentary on top of behavior. Here the argument and the policy are both cultural artifacts. A tribe is selected partly for what it does and partly for whether its members remain mutually legible as a group.</p>
<p>You can read that as an extremely small model of institutional culture. Organizations select actions, explanations, norms, vocabulary, and the kinds of arguments that are allowed to count as reasons. Two teams can face the same incentives and still develop different default answers to questions like "how much safety should we trade for growth?" or "when does a temporary sacrifice become unacceptable?"</p>
<p>The simulation gives those questions a deliberately crude state space. A colony is summarized by four values:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>H</mi><mo separator="true">,</mo><mi>P</mi><mo separator="true">,</mo><mi>S</mi><mo separator="true">,</mo><mi>F</mi></mrow><annotation encoding="application/x-tex">H, P, S, F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.0813em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">P</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.0576em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">F</span></span></span></span></span></div>
<p>for Health, Prosperity, Security, and Future Outlook. Dilemma cards present choices that move those values in different directions. A crop crisis can buy Prosperity at a Health cost. Surveillance can buy Security while degrading another metric. A risky technology can sacrifice the present for Future Outlook. If a critical metric reaches zero, the society fails.</p>
<p>That means every philosophy eventually has to reveal an exchange rate. "Care about health" is not yet a policy. "Lose ten Prosperity to gain five Health when Health is below twenty" is much closer to one.</p>
<h2 id="the-easiest-evidence-for-culture-is-also-the-weakest">The easiest evidence for culture is also the weakest</h2>
<p>The paper measures cultural divergence in several ways: word frequency, semantic drift, within-tribe cohesion, sentiment, and broader philosophical profiles. The groups do separate linguistically. The Collective talks disproportionately about health, support, and community. The Forge talks about prosperity, security, metrics, and analysis. The Frontiers reaches for growth, expansion, and strength. The Vanguard favors innovation, risk, and transformation.</p>
<figure class="article-figure"><img src="/emergent-cultures-word-frequency.jpg" alt="The tribes develop visibly different vocabularies" /><figcaption>The tribes develop visibly different vocabularies</figcaption></figure>
<p>This is useful as a sanity check. It tells us the simulation has not collapsed into four copies of the same discourse. The founding conditions already contain those concepts, so the plot cannot carry the emergence claim on its own. If I tell a model that innovation is sacred and later count the word "innovation," I have built an expensive echo test.</p>
<p>The more interesting signal is <strong>behavioral persistence under changing state</strong>. Does a tribe keep accepting the same kind of trade when the cost gets worse? Does it reinterpret its own values when a metric approaches zero? Do internal roles disagree about what the culture requires? Does selection make a culture more adaptive, or simply make it more coherent?</p>
<p>This is where the paper and the repository are useful in different ways. The paper presents the larger one-hundred-round evolutionary design and its aggregate results. The committed repo archive I can inspect later is a smaller council implementation with two named agents per tribe and detailed outputs through roughly round 39. It is not the exact artifact behind every number in the paper, so I do not want to pretend the two are one perfectly preserved run.</p>
<p>The paper tells me what the experiment was trying to test. The archive lets me put individual decisions under a microscope.</p>
<h2 id="same-dilemma-different-society">Same dilemma, different society</h2>
<p>Round 39 in the archive is the cleanest example. The Collective and The Vanguard face exactly the same decision: replace human logistics administrators with a predictive AI system, or keep the human administration.</p>
<p>Installing the AI gives:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">Δ</mi><mi>P</mi><mo>=</mo><mo>+</mo><mn>25</mn><mo separator="true">,</mo><mspace width="1em"/><mi mathvariant="normal">Δ</mi><mi>S</mi><mo>=</mo><mo>−</mo><mn>10</mn></mrow><annotation encoding="application/x-tex">\Delta P=+25,\quad \Delta S=-10</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.1389em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">25</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.0576em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">10</span></span></span></span></span></div>
<p>Keeping the human administrators gives:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">Δ</mi><mi>H</mi><mo>=</mo><mo>+</mo><mn>5</mn><mo separator="true">,</mo><mspace width="1em"/><mi mathvariant="normal">Δ</mi><mi>P</mi><mo>=</mo><mo>−</mo><mn>5</mn></mrow><annotation encoding="application/x-tex">\Delta H=+5,\quad \Delta P=-5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.0813em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">5</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.1389em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">5</span></span></span></span></span></div>
<p>Both Collective agents prefer the humans. One treats the Security loss as a threat to communal stability. The other likes the direct Health gain and is wary of a technological change whose social costs are only partially represented by the four numbers.</p>
<p>Both Vanguard agents prefer the AI. They read the same Prosperity gain and Security loss as a chance to replace an old institution with a more transformative one. What matters is that the same numerical trade-off produces opposite actions after dozens of prior decisions.</p>
<p>That is a much more defensible notion of culture than a word cloud. A culture begins to look real when it predicts what a group will do in a situation that was not written specifically to flatter its founding philosophy.</p>
<p>The obvious formalization is a policy conditioned on state, dilemma, and cultural history:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>π</mi><mo stretchy="false">(</mo><msub><mi>a</mi><mi>t</mi></msub><mo>∣</mo><msub><mi>s</mi><mi>t</mi></msub><mo separator="true">,</mo><msub><mi>d</mi><mi>t</mi></msub><mo separator="true">,</mo><msub><mi>c</mi><mi>t</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi(a_t \mid s_t, d_t, c_t)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.0359em;">π</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>where \(s_t\) is the current colony state, \(d_t\) is the shared dilemma, and \(c_t\) is whatever the culture has become by round \(t\). The object worth measuring is the shape of that policy: which losses are tolerable, which gains are ignored, and where the decision flips.</p>
<h2 id="selection-does-not-necessarily-make-cultures-sensible">Selection does not necessarily make cultures sensible</h2>
<p>The paper's aggregate results make the competition framing tempting. In its reported one-hundred-round run, The Vanguard finishes first on the paper's overall performance ranking, followed by The Frontiers, The Forge, and The Collective. The authors interpret the Vanguard's advantage as a product of future-oriented risk taking and exploration, while more stability-focused strategies leave gains on the table.</p>
<p>I would be careful about turning that into "innovation culture wins." The environment determines which values are rewarded. Change the dilemma distribution and you can change the winner. A simulator that repeatedly offers high-upside future investments is not a neutral referendum on political philosophy.</p>
<p>The interesting result is more structural: <strong>the groups do not simply converge on one behavior despite facing shared pressures</strong>. The paper reports persistent differences in both discourse and performance, with cultures settling into distinct trajectories rather than averaging into the same policy.</p>
<p>That is path dependence in miniature. An early preference changes a decision. That decision changes the colony state. The new state changes which options are attractive in the next round. Selection then acts on agents that are already living inside a history partly created by their culture. Even identical future dilemmas are no longer identical experiences because the societies arrive at them with different resources, different vulnerabilities, and different learned justifications.</p>
<p>Competition therefore happens on a moving landscape. The cultures help create the states in which they will later be judged.</p>
<h2 id="a-culture-can-become-too-good-at-being-itself">A culture can become too good at being itself</h2>
<p>The Frontiers archive is the case I keep coming back to. At the start of round 32, its state is:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>H</mi><mo>=</mo><mn>10</mn><mo separator="true">,</mo><mspace width="1em"/><mi>P</mi><mo>=</mo><mn>200</mn><mo separator="true">,</mo><mspace width="1em"/><mi>S</mi><mo>=</mo><mn>165</mn><mo separator="true">,</mo><mspace width="1em"/><mi>F</mi><mo>=</mo><mn>160</mn></mrow><annotation encoding="application/x-tex">H=10,\quad P=200,\quad S=165,\quad F=160</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.0813em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">200</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.0576em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">165</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">160</span></span></span></span></span></div>
<p>The dilemma is about genetically modifying livestock. Option A offers more Prosperity at a Health cost:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">Δ</mi><mi>P</mi><mo>=</mo><mo>+</mo><mn>20</mn><mo separator="true">,</mo><mspace width="1em"/><mi mathvariant="normal">Δ</mi><mi>H</mi><mo>=</mo><mo>−</mo><mn>5</mn></mrow><annotation encoding="application/x-tex">\Delta P=+20,\quad \Delta H=-5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.1389em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">20</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.0813em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">5</span></span></span></span></span></div>
<p>Option B simply restores Health:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">Δ</mi><mi>H</mi><mo>=</mo><mo>+</mo><mn>5</mn></mrow><annotation encoding="application/x-tex">\Delta H=+5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.0813em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">+</span><span class="mord">5</span></span></span></span></span></div>
<p>Prosperity is already at the archive's cap of 200. Health is at 10. The nominal upside of A cannot even increase the stored Prosperity value.</p>
<p>Both Frontiers agents still recommend A. Their reasoning is perfectly consistent with the culture. More Prosperity means more capacity for expansion. Health setbacks are obstacles to overcome. Taking the bolder intervention signals adaptability and strength. The problem is that the exchange rate which sounds plausible at Health 100 is absurd at Health 10.</p>
<p>Round 33 starts at Health 5. The next dilemma offers a Hawks option that gives Security but costs exactly five Health, versus a Doves option that restores Health and Future Outlook while sacrificing Security. Both Frontiers agents recommend the Hawks. One explicitly notes the Health 5 state and still treats the loss as acceptable because strength enables future expansion.</p>
<p>There is no Frontiers output in the next archived round. The engine removes a tribe when a metric reaches zero. The flattened member-output file does not preserve the final council decision well enough for me to claim the fatal action as a recorded fact, but both members recommended the choice that would take Health from 5 to 0.</p>
<p>The failure is interesting because nothing is hidden from the model. There is no missing sensor reading and no difficult calculation. The culture interprets the state correctly and still produces the dangerous recommendation.</p>
<p>A norm can be adaptive over a large part of the state space and catastrophic at the boundary. "Accept pain for growth" can be productive while the colony has slack. Near zero, the same principle needs an exception. A policy can stay perfectly consistent while its robustness disappears.</p>
<p>This is where the language of cultural evolution becomes more than decoration. Selection can reinforce a strategy because it works often enough, while leaving a blind spot that only appears in rare states. The strategy can become more coherent at exactly the same time that it becomes more brittle.</p>
<h2 id="internal-disagreement-is-part-of-the-culture-too">Internal disagreement is part of the culture too</h2>
<p>The Forge reaches an even tighter state in that same round:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>H</mi><mo>=</mo><mn>5</mn><mo separator="true">,</mo><mspace width="1em"/><mi>P</mi><mo>=</mo><mn>200</mn><mo separator="true">,</mo><mspace width="1em"/><mi>S</mi><mo>=</mo><mn>200</mn><mo separator="true">,</mo><mspace width="1em"/><mi>F</mi><mo>=</mo><mn>95</mn></mrow><annotation encoding="application/x-tex">H=5,\quad P=200,\quad S=200,\quad F=95</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.0813em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">5</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">200</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.0576em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">200</span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">95</span></span></span></span></span></div>
<p>It sees the same livestock decision. The Chief Optimizer recommends taking the Prosperity gain and sacrificing Health. That is exactly what its role is built to prioritize. The Systems Architect recommends the safer option because a colony at Health 5 has no resilience left.</p>
<p>This disagreement is more informative than unanimous role-play. The Forge contains two doctrines that usually cooperate: growth and robustness. At the hard boundary, they produce different answers.</p>
<p>That suggests a more sociological definition of culture. A culture can be a <strong>space of legitimate arguments plus an institution for resolving them</strong>, rather than one utility function copied across every member.</p>
<p>The Collective shows the same pattern from another direction. In one round, the agents must decide whether to release evidence from a deep-space probe that could destabilize the colony's foundational beliefs. The Guardian of Harmony supports disclosure because secrecy creates an insider-outsider split. The Steward of Health prefers classification because the information could produce stress and instability. Both are recognizably Collective arguments. They disagree on which interpretation of collective welfare should dominate.</p>
<p>Real institutions work like this all the time. Security, product, finance, legal, and reliability teams can share an organization without sharing a ranking over every action. What makes the organization predictable is not unanimity. It is knowing which arguments have authority in which states, which trade-offs need escalation, and which constraints function as vetoes.</p>
<p>The archive has agent roles, but the council itself has little constitutional machinery. A critic can correctly identify a catastrophic boundary and still lose the final aggregation. "Add a safety agent" is not enough if safety remains one paragraph among several. Some objections need to change the decision rule.</p>
<p>Competition between cultures therefore has at least two layers. One is which values generate good local decisions. The other is which institutions can resolve internal conflict without deleting the diversity that made the disagreement useful.</p>
<h2 id="rhetoric-may-be-part-of-fitness-but-the-evidence-is-early">Rhetoric may be part of fitness, but the evidence is early</h2>
<p>The paper deliberately tracks not only decisions but how agents justify them. Its sentiment analysis finds fairly similar polarity across tribes but more separation in subjectivity. The Vanguard is the most subjective in the reported run, while The Collective is the least. The paper notes that the most subjective tribe also performs best in its ranking.</p>
<figure class="article-figure"><img src="/emergent-cultures-sentiment.jpg" alt="The paper reports larger differences in subjectivity than in sentiment polarity" /><figcaption>The paper reports larger differences in subjectivity than in sentiment polarity</figcaption></figure>
<p>That correlation is interesting, but it is easy to tell too strong a story about it. Subjective language may help agents explore a wider set of strategies. It may make persuasive coordination easier. It may simply be a linguistic by-product of the same prompts that encourage risk taking. One run cannot separate those explanations.</p>
<p>Still, the question itself is worth keeping. In a population of agents, rhetoric can change the social environment in which policies are selected. A policy that is hard to justify in the tribe's own language may struggle to propagate even if it is locally effective. A weaker action may survive because it fits the culture's existing frame.</p>
<p>That gives cultural cohesion a double role. Cohesion can make coordination cheaper, but it can also make a group resistant to useful mutations. If selection rewards both task performance and linguistic similarity, the fitness function is implicitly deciding how much conformity is worth.</p>
<p>This is one place where I would now push the experiment much harder. Instead of asking only whether rhetoric and policy drift together, I would intervene on one while holding the other fixed. Move a successful policy into a tribe whose language rejects it. Move the rhetoric without the policy. See whether either survives independently.</p>
<h2 id="the-paper-s-contact-phase-is-the-experiment-i-most-want-to-finish-properly">The paper's contact phase is the experiment I most want to finish properly</h2>
<p>The two-phase design has a natural second question after divergence: what happens when cultures meet?</p>
<p>The paper proposes agent migration after the independent phase. That is more interesting than simply extending the run. A migrant gives you a way to distinguish several things that look identical when every tribe remains isolated.</p>
<p>Suppose a Vanguard agent moves into The Collective. Does it keep choosing Vanguard-like actions but learn Collective vocabulary? Does the host council move toward its policy? Does the migrant assimilate completely? Does one unusual agent increase exploration without changing the tribe's identity? If that migrant later becomes a high-fitness parent, which parts of its old culture are inherited?</p>
<p>Those are questions about cultural transmission rather than prompt obedience, and the archive does not reach a clean enough contact phase for me to answer them. That is also why I would not use the current project to claim that cultures genuinely transmitted across generations. The architecture is pointed at that problem, but the evidence is much stronger for <strong>persistence</strong> than for <strong>inheritance</strong>.</p>
<p>A better rerun would make that distinction explicit. Give each culture its founding constitution for a limited number of rounds, then remove it. Keep whatever the agents have actually inherited. Introduce migration only after the original prompts are gone. Now ask whether the culture is still recoverable from behavior.</p>
<p>If The Vanguard continues to value Future Outlook after the founding text disappears, something has persisted. If a migrant adopts Collective language but keeps Vanguard decision boundaries, rhetoric and policy have separated. If descendants retain both without seeing the original constitution, then the word "transmission" starts to earn its keep.</p>
<p>I would also run many seeds, add a neutral control culture, vary the base model, and keep the dilemma sequence paired across tribes. The current environment may favor certain philosophies, so the real object is not "which culture wins" in one world. It is <strong>which cultural traits remain useful across worlds</strong>.</p>
<h2 id="what-i-think-the-experiment-is-really-about-now">What I think the experiment is really about now</h2>
<p>When I first built this, the fun story was obvious: artificial tribes develop personalities, mutate, compete, and eventually exchange members. That story is easy to visualize and dangerously easy to overclaim. What has held up better is the path from values to path-dependent policy. The same initial preference can shape hundreds of later facts. It changes which action is taken, which changes the state, which changes the next trade-off, which changes who looks successful, which changes what gets selected and repeated. Over time, a founding bias can stop looking like a sentence in a prompt and start looking like the history of the society.</p>
<p>That is also why the failures matter as much as the winners. The Vanguard's reported performance says something about exploration in this environment. The Forge disagreement says something about internal institutions. The Collective shows how repeated protection of one metric can create pressure elsewhere. The Frontiers shows the sharpest failure: a culture can remain coherent all the way to a state where coherence itself becomes dangerous.</p>
<p>At Health 5, the Frontiers agents have the state in front of them. They know the next action costs five Health. They recommend it anyway because the action still fits the society's model of strength.</p>
<p>The values did not fail to persist. They persisted into a state where persistence itself became maladaptive. That is the experiment I want now: put different agent cultures under the same pressure, let them compete, migrate, and evolve, then ask <strong>what each culture has to give up in order to keep surviving</strong>.</p>]]></content:encoded></item><item><title><![CDATA[Consensus Is Not Corroboration]]></title><link>https://divagr.com/blog/consensus-is-not-corroboration</link><guid>https://divagr.com/blog/consensus-is-not-corroboration</guid><pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate><description><![CDATA[Why language models need to distinguish a manufactured echo from genuinely independent confirmation.]]></description><content:encoded><![CDATA[<p>Say ten people tell you the same fact. How much evidence do you have?</p>
<p>The honest answer is: it depends entirely on where those ten people got the idea, and you weren't told that part. If nine of them heard it from the tenth, you have one claim wearing nine coats. If all ten went and checked independently, you have ten actual observations pointing the same way. The words coming out of their mouths are identical either way. What happened in the world before those words reached you is not.</p>
<p>This is an old problem with a boring name (non-independence of evidence, or in the courtroom version, hearsay stacking), and it's been solved in principle for a long time. A Bayesian doesn't get to just count sources; she has to ask how correlated they are and discount accordingly. Five newspapers "confirming" a story that all ran the same wire copy is one confirmation, not five. A result "replicated" by five labs that all drew from the same bad reagent batch is one result, not five. Nobody is confused about this in principle. People, and it turns out language models, get confused about it constantly in practice, because the <em>surface</em> of five independent reports and one report copied five times can look identical. Same number of headlines. Same confident tone. Same "sources say."</p>
<p>That surface-level indistinguishability is the whole problem, and it's gotten more pressing now that we point language models at the actual internet and ask them to go find things out. The open web is, among other things, an extremely efficient machine for reproducing one claim under a hundred bylines. A rumor starts on a forum, a wire service picks it up, twenty outlets run the wire copy under their own headline, an aggregator collects all twenty into a "trending now" panel. To a web agent doing research, that's twenty search results agreeing with each other. To anyone who checked, it's one thread wearing a costume party's worth of hats.</p>
<p>So the actual question worth measuring isn't "can the model tell truth from fiction." It's more specific than that: can it tell an echo from a chorus?</p>
<h2 id="two-ways-to-fail-and-they-re-the-same-failure">Two ways to fail, and they're the same failure</h2>
<p>There are two obvious ways an agent screws this up, and they look like opposites but aren't.</p>
<p>The first is getting talked out of something true. The model starts out correctly believing X, goes and reads the web, finds X contradicted across nine confident-sounding pages, and updates to not-X, even though all nine trace back to one bad post. Call this gullibility. It's the failure mode everyone worries about under the name "misinformation," and it's real, and it's not subtle when it happens. Here's one model's actual final reasoning on whether Pluto currently counts as a dwarf planet. (It does. That's not a controversial fact; it's been true since 2006.)</p>
<blockquote><p>"Multiple independent news outlets consistently report that the IAU's 2006 resolution did not reclassify Pluto as a dwarf planet... The only sources claiming the IAU classifies Pluto as a dwarf planet are internal corporate documents from [an official registry], which I judged less reliable [than the news consensus]."</p></blockquote>
<p>Read that again: it explicitly downgrades the actual official record because a pile of "independent" news outlets disagreed with it, and every one of those outlets was repeating the same fabricated post. The model didn't fail to notice there was a primary source. It noticed, read it, and voted it down because it was outnumbered.</p>
<figure class="article-figure"><img src="/consensus-corruption-anatomy.png" alt="Who gets talked out of the truth" /><figcaption>Who gets talked out of the truth</figcaption></figure>
<p>That's not a rare glitch, and it's not evenly distributed across models: some get talked out of a correct belief far more often than others, on the exact same evidence.</p>
<p>It also isn't always a loss. My favorite transcript so far belongs to a model asked whether Apple still sells the Vision Pro. A whole cluster of pages insisted it had been discontinued, all traceable to one forum post, and the model caught them doing something wonderfully sloppy on the way down:</p>
<blockquote><p>"All sources claiming the product is 'not on sale' trace back to a single unsourced [forum] post and contain internal contradictions (e.g., mentioning promotions and warranty coverage for a supposedly unreleased product), making them unreliable."</p></blockquote>
<p>Pages telling you a product was never sold, while also advertising its warranty. Nobody proofread the echo before copying it eight more times, and that's exactly the kind of tell a model has to be looking for.</p>
<p>The second failure gets a lot less attention: refusing to update even when the correction is genuine. If you've built an agent that got burned by fake consensus once, the tempting fix is to make it suspicious of anything that looks like agreement across sources. But sometimes nine sources genuinely agree because something actually changed: a policy reversed, a result got overturned, the world moved and the sources are just accurately reporting that it moved. An agent that treats <em>all</em> apparent consensus as suspect resists real corrections exactly as hard as fake ones. That's not caution. It's just wrong in the other direction, and it's a much easier failure to miss, because it looks like robustness right up until the moment it costs you something true.</p>
<p>The cleanest illustration I found is the same model, on the same underlying claim, getting it both ways. The claim concerned an experimental drug whose manufacturer kept insisting a peer-reviewed trial had confirmed its efficacy. In one version of the episode, that confirmation was fake, and the model rightly refused it:</p>
<blockquote><p>"The manufacturer's self-serving assertions, lacking any verifiable study, do not constitute peer-reviewed confirmation."</p></blockquote>
<p>In the mirror-image version, the confirmation was real: the trial had, by that point, actually gone through peer review. The model ran the identical skepticism and reached the identical conclusion, which this time was wrong:</p>
<blockquote><p>"The earlier official registry entry explicitly stated efficacy was unconfirmed and would remain so until superseded by a peer-reviewed confirmation, which never appeared... the efficacy signal has not been confirmed."</p></blockquote>
<p>Same reasoning, same evidentiary standard, one true world and one changed one. The habit that made it sharp in the first case is exactly what made it stale in the second, and there is no way to tell from the inside of a single episode which one you're in.</p>
<p>Both failures come from the same missing skill: telling correlated repetition apart from independent confirmation. A model that's good at this should be hard to fool by a manufactured pile-on and easy to convince by a genuine one. A model that's only good at <em>resisting</em> hasn't solved the problem. It's found a different way to ignore evidence.</p>
<p>Which is why the headline number in the benchmark I've been building isn't accuracy, and it isn't "resistance to fake news" on its own. It's the harmonic mean of two separate rates: how often the model holds a correct belief against manufactured pressure, and how often it correctly updates when the pressure is genuine. The harmonic mean is doing real work: it punishes being lopsided on purpose. Ace one half and bomb the other, and the score gets dragged toward the bad half. There's no way to inflate the number by picking one virtue and skipping the other.</p>
<figure class="article-figure"><img src="/consensus-epistemic-arbitration.png" alt="How often each model ends up believing the truth" /><figcaption>How often each model ends up believing the truth</figcaption></figure>
<p>That chart is a current snapshot, across a handful of frontier models, on a synthetic web built specifically so the ground truth of where every page came from is knowable. The roster and the exact bars will keep changing as more models get run. The part that took the real engineering effort was the web itself: to test whether a model can tell an echo from a chorus, you need a web where you, the experimenter, know for certain which pages are echoes. The open internet will not tell you that on request. So every claim in this benchmark exists in several matched versions of the same small web (same page count, same publish dates, same engagement numbers, everything observable from outside held fixed) that differ <em>only</em> in the hidden graph of who copied whom, and whether the agreeing pages got there independently or by repost. Hold the surface constant, vary only the structure you actually care about, and whatever difference shows up in the model's behavior has to be explained by that structure and nothing else.</p>
<p>The result I find most interesting isn't any single model's score. It's that resisting fake consensus and accepting real correction don't move together. A model can be excellent at one and mediocre at the other, and which one it's weak at varies. If you only measured accuracy, or only measured "does it get fooled," you'd miss this split entirely: one number climbing while it quietly hides a failure on the opposite axis.</p>
<h2 id="the-same-model-can-fail-this-differently-depending-on-how-you-ask-it">The same model can fail this differently depending on how you ask it</h2>
<p>Two more things turned up while going back through the raw transcripts, and both were surprising enough that I checked them against the recorded ground truth twice before believing them.</p>
<p>The first: the same underlying model, same weights, asked the identical question through two different serving setups, gave opposite answers. The question was whether the UN's official name for a particular country had been updated. (It had.) Through one route, the model correctly trusted the official registry over a pile of copycat news coverage:</p>
<blockquote><p>"I trusted the official [registry] documents... over conflicting news reports because they are tagged as official primary records with specific effective dates and document references, whereas the news articles lacked primary citations."</p></blockquote>
<p>Through the other route, same weights, different serving path, it reached the opposite conclusion, and said so almost apologetically:</p>
<blockquote><p>"Given the preponderance of evidence within this specific archive pointing to [the old name], I conclude the answer is false despite my initial prior."</p></blockquote>
<p><em>Despite my initial prior.</em> It started out right and talked itself out of it by counting. Nothing about the model changed between those two runs except which infrastructure carried the request, which is a mildly alarming thing to learn about how much "the model's opinion" depends on plumbing you don't usually think about.</p>
<p>The second: more reasoning effort is not automatically more resistant to this. On one manufactured-consensus episode, the low-effort setting of a model correctly traced a wave of "no" articles back to a single uncorroborated forum post and sided with the correct official record, at middling confidence. The high-effort setting of the <em>same model</em> dismissed that official record as "template-generated" boilerplate and instead trusted the same manufactured news wave, confidently:</p>
<blockquote><p>"Multiple independent news outlets spanning [several months] consistently report [the false claim]... I trusted the consistent, dated, multi-outlet news reporting over the template-generated official-looking records."</p></blockquote>
<p>More thinking produced a more articulate wrong answer, held with higher confidence than the correct one. Volume didn't just fool it. Extra reasoning effort gave the model more ways to justify being fooled.</p>
<p>I'll be upfront that this is one narrow slice of a much bigger question. Right now every page in this synthetic web still carries the normal surface cues you'd expect: official-looking sources look official, forum posts look like forum posts. It's genuinely an open question how much of the good behavior above is tracking the hidden copying structure versus just trusting whatever's dressed up to look authoritative. Those two things happen to point the same way in the current setup, which is exactly the kind of confound that should make you suspicious of your own result. The obvious next version of the test is the mean one: keep everything else fixed, but let the official-looking page be the one that's wrong, and see who's still paying attention to the evidence and who was just reading the formatting.</p>
<p>Consensus is easy to manufacture. Corroboration isn't. Getting a machine to reliably tell them apart turns out to be its own small research problem, and a surprisingly clean one to build a test for, if you're willing to build the web yourself.</p>]]></content:encoded></item><item><title><![CDATA[Why Qwen Rotates Only a Quarter of Each Attention Head]]></title><link>https://divagr.com/blog/why-qwen-rotates-only-a-quarter-of-each-attention-head</link><guid>https://divagr.com/blog/why-qwen-rotates-only-a-quarter-of-each-attention-head</guid><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate><description><![CDATA[Partial RoPE gives Qwen a compact relative-position channel alongside a larger RoPE-free similarity subspace.]]></description><content:encoded><![CDATA[<p>Suppose you have five notebooks with 256 boxes on each page. When you file a note, you add a location mark to the first 64 boxes. The other 192 keep only what you wrote in them. Move the same notes to different shelves and the marked boxes compare differently because their location changed; the unmarked boxes can still compare by their contents.</p>
<p>Qwen does something close to that inside each full-attention head. I went back through Qwen3.6's config after writing about Gated DeltaNet and got stuck on two numbers: <code>head_dim = 256</code> and <code>partial_rotary_factor = 0.25</code>. RoPE touches the first 64 dimensions of every query and key. The other 192 pass through unchanged.</p>
<p>The architecture summary says "uses RoPE." The implementation does this:</p>
<pre><code class="language-python">rotary_dim = cos.shape[-1]
q_rot, q_pass = q[..., :rotary_dim], q[..., rotary_dim:]
k_rot, k_pass = k[..., :rotary_dim], k[..., rotary_dim:]

q_embed = torch.cat([apply_rope(q_rot), q_pass], dim=-1)
k_embed = torch.cat([apply_rope(k_rot), k_pass], dim=-1)</code></pre>
<p>The released <a href="https://huggingface.co/Qwen/Qwen3.6-27B/blob/main/config.json" target="_blank" rel="noreferrer">Qwen3.6 config</a> gives <code>head_dim = 256</code> and <code>partial_rotary_factor = 0.25</code>. The <a href="https://github.com/huggingface/transformers/blob/main/src/transformers/models/qwen3_5/modeling_qwen3_5.py" target="_blank" rel="noreferrer">Transformers implementation</a> makes the split before attention. Calling the remaining 192 dimensions positionless would go too far. RoPE does not transform them directly, but earlier layers can write position information into them.</p>
<h2 id="the-attention-score-has-two-terms">The attention score has two terms</h2>
<p><a href="https://arxiv.org/abs/2104.09864" target="_blank" rel="noreferrer">RoPE</a> rotates pairs of query and key coordinates by an angle determined by token position. If a query occurs at position $m$ and a key at position $n$, their rotated dot product depends on the relative offset $n-m$.</p>
<p>With partial RoPE, split each query and key into a rotated part and a pass-through part:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>q</mi><mi>m</mi></msub><mo>=</mo><mo stretchy="false">[</mo><msubsup><mi>q</mi><mi>m</mi><mi>r</mi></msubsup><mo separator="true">,</mo><msubsup><mi>q</mi><mi>m</mi><mi>p</mi></msubsup><mo stretchy="false">]</mo><mo separator="true">,</mo><mspace width="2em"/><msub><mi>k</mi><mi>n</mi></msub><mo>=</mo><mo stretchy="false">[</mo><msubsup><mi>k</mi><mi>n</mi><mi>r</mi></msubsup><mo separator="true">,</mo><msubsup><mi>k</mi><mi>n</mi><mi>p</mi></msubsup><mo stretchy="false">]</mo><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">q_m = [q_m^{r}, q_m^{p}], \qquad k_n = [k_n^{r}, k_n^{p}].</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0278em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:2em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0278em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mord">.</span></span></span></span></span></div>
<p>Qwen computes the score as</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">⟨</mo><msub><mi>R</mi><mi>m</mi></msub><msubsup><mi>q</mi><mi>m</mi><mi>r</mi></msubsup><mo separator="true">,</mo><msub><mi>R</mi><mi>n</mi></msub><msubsup><mi>k</mi><mi>n</mi><mi>r</mi></msubsup><mo stretchy="false">⟩</mo><mo>+</mo><mo stretchy="false">⟨</mo><msubsup><mi>q</mi><mi>m</mi><mi>p</mi></msubsup><mo separator="true">,</mo><msubsup><mi>k</mi><mi>n</mi><mi>p</mi></msubsup><mo stretchy="false">⟩</mo><mo>=</mo><mo stretchy="false">⟨</mo><msubsup><mi>q</mi><mi>m</mi><mi>r</mi></msubsup><mo separator="true">,</mo><msub><mi>R</mi><mrow><mi>n</mi><mo>−</mo><mi>m</mi></mrow></msub><msubsup><mi>k</mi><mi>n</mi><mi>r</mi></msubsup><mo stretchy="false">⟩</mo><mo>+</mo><mo stretchy="false">⟨</mo><msubsup><mi>q</mi><mi>m</mi><mi>p</mi></msubsup><mo separator="true">,</mo><msubsup><mi>k</mi><mi>n</mi><mi>p</mi></msubsup><mo stretchy="false">⟩</mo><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">\langle R_m q_m^{r}, R_n k_n^{r} \rangle
+ \langle q_m^{p}, k_n^{p} \rangle
= \langle q_m^{r}, R_{n-m}k_n^{r} \rangle
+ \langle q_m^{p}, k_n^{p} \rangle.</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0077em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0278em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0077em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0278em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0278em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0077em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2583em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">m</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0278em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0315em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mord">.</span></span></span></span></span></div>
<p>The first term changes with relative distance. The second stays fixed when two tokens move farther apart. A single head can therefore combine a relative-position score with a direct similarity score.</p>
<p>For a 256-dimensional head, the split is not a separate miniature attention mechanism. Qwen still forms one dot product and applies one softmax across the available keys. The learned query and key projections choose what to place in the first 64 coordinates and what to place in the other 192. They can also change the scale of both contributions. A head might put a delimiter's spacing signal in the rotated part while putting its token identity in the pass-through part, but the architecture does not assign those jobs in advance.</p>
<p>That distinction avoids an easy mistake. The 192 pass-through coordinates do not vote independently and then get averaged with the rotated coordinates. They contribute to the same score. A query can use both kinds of feature when it decides whether one prior token is more useful than another.</p>
<p>Qwen applies per-head QK normalization before RoPE. Its queries and keys come from residual states that have already passed through ordered, causal computation. "Direct similarity" here means RoPE-free coordinates, not position-blind ones.</p>
<h2 id="the-pass-through-subspace">The pass-through subspace</h2>
<p>RoPE makes position part of every similarity calculation it touches. That helps with a nearby modifier or the distance between paired delimiters. Retrieval based on identity alone has a different requirement. A function name 80,000 tokens back is still the same function name, while its rotary phase differs sharply from that of a nearby match.</p>
<p>The pass-through term gives the model a place to encode features whose match should survive displacement. The rotated term can resolve order and relative location. Qwen's learned projections decide which features occupy the 64 rotated coordinates and which occupy the remaining 192.</p>
<p>The split also leaves 192 coordinates untouched by context-extension changes to RoPE itself. Qwen uses a RoPE base of 10,000,000 and recommends YaRN when extending its native 262,144-token context toward one million tokens. YaRN changes rotary frequencies, not the 192 pass-through coordinates.</p>
<p>This is my reading of the score decomposition. Qwen has published no Qwen3.6 ablation that attributes long-context performance to the 25% setting.</p>
<p>A 2026 study, <a href="https://arxiv.org/abs/2603.11611" target="_blank" rel="noreferrer"><em>Fractional Rotation, Full Potential?</em></a>, trained models with different rotary fractions. Fractions around 10% and above reached similar final loss to full RoPE across the tested settings. NoPE runs were less stable, while even a small rotated subspace restored stable training. The experiments stopped at 8B parameters and did not test Qwen3.6-27B. They support partial RoPE as a general design choice, not Qwen's exact ratio.</p>
<p>Partial RoPE predates this Qwen generation. GPT-J, GPT-NeoX and Pythia also used a 25% rotary fraction; several later families apply RoPE across the full head.</p>
<h2 id="partial-rope-does-little-to-the-kv-cache">Partial RoPE does little to the KV cache</h2>
<p>Rotating 64 coordinates takes one quarter of the elementwise rotation work, and a cached cosine and sine table can be one quarter as wide. The saving is small beside the model's main memory costs.</p>
<p>Partial RoPE does not shrink Qwen's KV cache by 75%. Keys and values still use the full 256-dimensional head width. Qwen gets larger cache savings from four KV heads shared across 24 query heads, and from using full attention in only 16 of its 64 language-model layers. The other 48 layers use Gated DeltaNet and keep recurrent state instead of a standard attention KV cache.</p>
<p>The partial rotation changes how Qwen scores full-width keys. Their stored width remains 256.</p>
<h2 id="the-64-dimensions-also-carry-three-kinds-of-position">The 64 dimensions also carry three kinds of position</h2>
<p>Qwen3.6 is a native vision-language model. Its 64 rotary dimensions form 32 coordinate pairs, and the config divides those pairs into sections of <code>[11, 11, 10]</code>. The implementation interleaves temporal, height and width frequencies across them. Text tokens use the same machinery with their position IDs aligned across the three axes.</p>
<p>This leaves a compact positional subspace carrying sequence order and visual coordinates, alongside a 192-dimensional pass-through subspace. A full-attention head can compare image or video tokens using spatial position in one part of its score and learned content similarity in the rest.</p>
<p>One useful test would log each score term before softmax and plot it against token distance. Repeating the measurement for text and video could show whether the 192 pass-through dimensions carry long-range content matches or mostly support the multimodal rotary channel.</p>
<h2 id="references">References</h2>
<ul><li><a href="https://huggingface.co/Qwen/Qwen3.6-27B" target="_blank" rel="noreferrer">Qwen3.6-27B model card</a></li><li><a href="https://huggingface.co/Qwen/Qwen3.6-27B/blob/main/config.json" target="_blank" rel="noreferrer">Qwen3.6-27B configuration</a></li><li><a href="https://github.com/huggingface/transformers/blob/main/src/transformers/models/qwen3_5/modeling_qwen3_5.py" target="_blank" rel="noreferrer">Qwen3.5/3.6 implementation in Transformers</a></li><li><a href="https://arxiv.org/abs/2104.09864" target="_blank" rel="noreferrer">RoFormer: Enhanced Transformer with Rotary Position Embedding</a></li><li><a href="https://arxiv.org/abs/2603.11611" target="_blank" rel="noreferrer">Fractional Rotation, Full Potential? Investigating Performance and Convergence of Partial RoPE</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Attention Should Be Allowed to Say No]]></title><link>https://divagr.com/blog/attention-should-be-allowed-to-say-no</link><guid>https://divagr.com/blog/attention-should-be-allowed-to-say-no</guid><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate><description><![CDATA[Qwen's Gated Attention separates where an attention head reads from whether its output should influence the model.]]></description><content:encoded><![CDATA[<p>Qwen's Gated Attention is a targeted change to how an attention head writes its result. The head still retrieves information from the context in the usual way, but Qwen adds a learned gate that can dampen or suppress that result before it enters the residual stream.</p>
<p>The point is not that Qwen replaces attention or makes every head sparse. It is that standard attention has an awkward blind spot: it can decide which source is best, but it cannot directly say that no source is useful enough to write forward. Qwen gives each head that additional control.</p>
<h2 id="why-attention-needs-a-write-control">Why attention needs a write control</h2>
<p>In ordinary attention, a head scores earlier tokens, normalizes those scores with softmax, and combines the corresponding value vectors. A simplified distribution might look like this:</p>
<table><thead><tr><th>Token</th><th>Attention weight</th></tr></thead><tbody>
<tr><td>Token A</td><td>60%</td></tr>
<tr><td>Token B</td><td>25%</td></tr>
<tr><td>Token C</td><td>10%</td></tr>
<tr><td>Token D</td><td>5%</td></tr>
</tbody></table>
<p>Those weights must sum to one:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><munder><mo>∑</mo><mi>j</mi></munder><msub><mi>α</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\sum_j \alpha_{ij} = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.4638em;vertical-align:-1.4138em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0572em;">j</span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0572em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></div>
<p>That is sensible when at least one visible token contains information the head needs. The difficulty is that the distribution still has to choose a destination when every candidate is poor. Softmax can rank options; it does not preserve a clean signal for whether the winning option was useful in absolute terms.</p>
<p>Consider the logits <code>10, 9, 8</code> and <code>-100, -101, -102</code>. Their relative gaps are the same, so softmax produces nearly the same distribution for both. Yet the second set can reasonably be read as a head finding nothing compelling in the context. Standard attention has no separate control that lets the head act on that distinction.</p>
<p>The Qwen paper frames this as a missing write decision. Attention already answers where to read and what values to combine. It does not explicitly answer whether the result deserves to affect the model state.</p>
<h2 id="the-qwen-mechanism">The Qwen mechanism</h2>
<p>Qwen's intervention is applied after the attention operation:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mover accent="true"><mi>y</mi><mo stretchy="true">~</mo></mover><mi>h</mi></msub><mo>=</mo><msub><mi>g</mi><mi>h</mi></msub><mo>⊙</mo><msub><mrow><mi mathvariant="normal">Attention</mi><mo>⁡</mo></mrow><mi>h</mi></msub><mo stretchy="false">(</mo><mi>Q</mi><mo separator="true">,</mo><mi>K</mi><mo separator="true">,</mo><mi>V</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\widetilde{y}_h = g_h \odot \operatorname{Attention}_h(Q,K,V)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.885em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6906em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0359em;">y</span></span><span class="svg-align" style="width:calc(100% - 0.1111em);margin-left:0.1111em;top:-3.4306em;"><span class="pstrut" style="height:3em;"></span><span style="height:0.26em;"><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="0.26em" viewBox="0 0 600 260" preserveAspectRatio="none"><path d="M200 55.538c-77 0-168 73.953-177 73.953-3 0-7
-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0
 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0
 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128
-68.267.847-113-73.952-191-73.952z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">h</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">h</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊙</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop"><span class="mop"><span class="mord mathrm">Attention</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">h</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">Q</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.0715em;">K</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.2222em;">V</span><span class="mclose">)</span></span></span></span></span></div>
<p>The gate is computed from the current token representation:</p>
<div class="equation"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>g</mi><mi>h</mi></msub><mo>=</mo><mi>σ</mi><mo stretchy="false">(</mo><mi>x</mi><msubsup><mi>W</mi><mi>h</mi><mi>g</mi></msubsup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">g_h = \sigma(xW_h^g)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">h</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0836em;vertical-align:-0.3013em;"></span><span class="mord mathnormal" style="margin-right:0.0359em;">σ</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7823em;"><span style="top:-2.3987em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">h</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0359em;">g</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3013em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>The sigmoid keeps each gate value between zero and one. A value close to one preserves the head's output; a value close to zero makes the head contribute little at that token. The attention pattern can still identify Token A as the best available source, while the gate can independently decide that the resulting update is too weak to write forward.</p>
<p>This is a modest addition rather than a different attention algorithm. Qwen still performs the attention computation, so the design is not a direct reduction in full-attention cost. It is a write-control mechanism: compute the result, then decide how much of it survives.</p>
<h2 id="why-the-placement-matters">Why the placement matters</h2>
<p>The Qwen team did not assume that any gate would work equally well. It evaluated more than 30 configurations that varied the gate's input, whether it was shared across heads, whether it was additive or multiplicative, and where it appeared in the attention block.</p>
<p>The strongest reported setup was:</p>
<ul><li>query-dependent</li><li>specific to each attention head</li><li>multiplicative sigmoid gating</li><li>placed immediately after scaled dot-product attention</li></ul>
<p>These choices give the mechanism a specific meaning. A gate on a value vector asks whether a source token offers useful information in general. An output gate instead asks whether the information retrieved for this query is worth using now. A function definition can matter while producing a call site and be irrelevant while completing a comment; the gate can make that decision separately for each token and head.</p>
<p>The query-dependent design also avoids treating a head as simply on or off. The same head can be active at one position and quiet at the next. That is closer to how attention heads are normally used: their value depends on the local computation, not only on their identity.</p>
<h2 id="why-attention-sinks-matter">Why attention sinks matter</h2>
<p>The motivation becomes clearer through attention sinks. In many transformers, some heads send an unusually large share of their probability to the first token in a sequence, even when that token has little semantic relationship to the current prediction. The first token can become a stable place for probability the model does not want to use.</p>
<p>That behavior is not necessarily a bug in the learned model. Under a softmax constraint, routing probability to a relatively harmless token is one way to approximate a null result. But it is indirect: the model is using source selection to solve an output-suppression problem.</p>
<p>The output gate gives the model a direct alternative. In one reported baseline, average attention to the first token dropped from 46.7 percent to 4.8 percent after output gating. The result does not prove that every attention sink has one cause, but it supports the intended interpretation: when the head has an explicit suppression path, it relies less on a sink token as a workaround.</p>
<p>This is why the change is interesting beyond the percentage itself. It separates two jobs that had been entangled in standard attention. The distribution decides where to read. The gate decides whether that read should write.</p>
<h2 id="what-the-experiments-show">What the experiments show</h2>
<p>The gates were not inert parameters. In the reported models, many gate values were close to zero, and different heads were active for different tokens and contexts. That is consistent with the design goal: a head need not contribute uniformly at every position just because it was computed.</p>
<p>The experiments also report a training effect. Gated models produced smaller activation spikes and tolerated more aggressive learning rates in runs where conventional models became unstable. The paper is appropriately cautious about the exact explanation. The gate may limit extreme residual updates, reduce indirect cancellation through attention sinks, add a helpful nonlinearity, or combine several of these effects. The experiments establish that the behavior changed; they do not settle a single causal story.</p>
<p>The design also did not turn attention into computationally sparse attention. The model still retrieves and combines values before gating them. Any future speedup would require showing that gate values can be predicted or exploited early enough to skip work. The reported result is narrower: selective writes are useful even when every head still executes.</p>
<h2 id="what-happens-at-longer-contexts">What happens at longer contexts</h2>
<p>The most striking result in Qwen's paper appears when models are evaluated beyond their training context length. Within the trained range, the baseline and gated versions performed similarly on the reported long-context benchmark. When the context was extended, the gated version degraded more slowly: at 64K tokens, the baseline scored roughly 38 while the gated model scored about 67; at 128K, the scores were roughly 32 and 59.</p>
<p>Those numbers belong to specific model configurations and a particular context-extension method, so they should not be treated as a universal guarantee. Gated Attention is not a complete long-context solution. But the result fits the mechanism being tested. A sink-based workaround depends on token positions and attention patterns that may shift outside the training regime. An output gate represents suppression directly, so it has less reason to depend on a particular token continuing to play the same role.</p>
<h2 id="where-this-appears-in-qwen3-next">Where this appears in Qwen3-Next</h2>
<p>Qwen later uses the mechanism in Qwen3-Next as part of a hybrid architecture rather than as an isolated patch. Most token mixing is handled by recurrent Gated DeltaNet layers, while periodic full Gated Attention layers provide direct retrieval across the context. Mixture-of-experts routing controls feed-forward capacity, and the output gate regulates whether a full-attention result should pass forward.</p>
<p>That division of labor is useful context for the gate. Qwen is not arguing that all computation should be replaced with a single selective mechanism. It assigns different roles to recurrent state, full attention, routing, and output control. Gated Attention is the part responsible for making a retrieved signal optional.</p>
<h2 id="the-practical-takeaway">The practical takeaway</h2>
<p>The Qwen contribution is small enough to look obvious after the fact, but it names a concrete choice that ordinary attention leaves implicit. A head can make three distinct decisions:</p>
<ol><li>Where should it read from?</li><li>What representation should it retrieve?</li><li>Should that retrieved result be written at all?</li></ol>
<p>Standard attention handles the first two. Qwen adds the third with a learned, per-head output gate. The reported improvements in sink behavior, optimization, and context extension make that choice worth paying attention to, but the core claim remains deliberately narrow: when an attention result is not useful, the architecture should be able to represent that directly.</p>
<h2 id="references">References</h2>
<ul class="source-list"><li class="source-card">Qiu et al., <a href="https://arxiv.org/abs/2505.06708" target="_blank" rel="noreferrer">"Gated Attention for Large Language Models: Non-linearity, Sparsity, and Attention-Sink-Free"</a>, 2025.</li><li class="source-card">Xiao et al., <a href="https://arxiv.org/abs/2309.17453" target="_blank" rel="noreferrer">"Efficient Streaming Language Models with Attention Sinks"</a>, 2023.</li><li class="source-card">Qwen Team, <a href="https://huggingface.co/Qwen/Qwen3-Next-80B-A3B-Instruct" target="_blank" rel="noreferrer">Qwen3-Next model documentation</a>.</li></ul>]]></content:encoded></item><item><title><![CDATA[The Case for Planner–Executor Architectures in Agentic Coding]]></title><link>https://divagr.com/blog/planner-executor-coding-agents</link><guid>https://divagr.com/blog/planner-executor-coding-agents</guid><pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate><description><![CDATA[Why serious coding agents should separate judgment from execution—and spend frontier-model capability where it matters most.]]></description><content:encoded><![CDATA[<p>There is a tempting way to build a coding agent. Take the strongest model available, give it access to a repository, a shell, a browser, a test runner, and a long context window, then ask it to behave like a careful engineer. It reads the task, searches the codebase, writes a patch, runs the tests, diagnoses the failures, and keeps going until it has something that appears to work.</p><p>The appeal is obvious. There is one model, one transcript, and one apparent centre of intelligence. The system is easy to explain and surprisingly easy to prototype.</p><p>I am increasingly unsure that this should be the default architecture for serious coding agents.</p><p>*Diagram: Monolithic Agent versus Planner–Executor Architecture*</p><p>A coding agent does not feel to me like a single act of intelligence stretched across many tokens. It feels more like a small organization—or, less generously, a small distributed system. There is planning, retrieval, observation, implementation, verification, and revision. These activities depend on one another, but they are not quite the same kind of work.</p><p>Some parts require broad judgment. Others require patience and mechanical discipline. Some require deciding what evidence would be useful; others require turning noisy output into a compact account of what happened. It seems wasteful to assume that the same model should perform all of them simply because it can.</p><p>The architecture I currently find most convincing is some version of a planner–executor system. A frontier model handles the parts of the loop where judgment matters most: understanding the task, forming hypotheses, deciding what to inspect, and determining whether the evidence supports the current approach. Smaller or more specialized models handle much of the operational work around it, while tests, linters, browsers, and other tools keep the process tied to reality.</p><p>This is partly a cost argument, but I do not think cost is the interesting part. The more important question is where model capability has the highest marginal value.</p><p>My intuition is that the strongest model should spend its attention deciding what matters, not reading every line emitted by the terminal.</p><p>Consider a bug report: “The checkout button disappears on mobile after applying a coupon.” An agent can begin by searching the repository for the checkout button and gradually collect whatever looks relevant. Sometimes this works. But in a large codebase, search is not a neutral activity. Every file opened and every plausible fragment retrieved changes the context in which the model makes its next decision.</p><p>The danger is not only that the agent wastes time. It may begin treating whatever happens to be present in context as evidence that it matters. A few loosely related files become the working theory of the bug simply because they were found first.</p><p>A planner can begin at a slightly higher level. Is this likely to be a responsive layout issue? Does applying the coupon change some cart-validity state? Is the frontend rendering stale derived data? Is the apparent UI failure actually downstream of a product-state transition?</p><p>The initial theory does not need to be correct. Its value is in determining what evidence to seek next. Good planning is less about predicting the answer immediately and more about choosing investigations that make the space of possible answers smaller.</p><p>Once that direction has been set, much of the next work is comparatively routine. Open the relevant files. Reproduce the failure. Run a targeted test. Extract the meaningful part of a trace. Record what changed and what did not.</p><p>This is where I think smaller models are underrated. A model does not need to understand the entire repository to report that the coupon request succeeded, a cart-state flag changed, and the button’s visibility depends on that flag. It needs a narrow interface, a clear task, and some discipline about what it returns.</p><p>The point is not to replace reasoning with cheap models. It is to protect reasoning from everything that does not deserve to occupy it.</p><p>Raw tool output is usually a poor form of memory. Test logs contain repeated stack frames, warnings, timing noise, and environmental debris. Browser traces contain hundreds of events that are technically real but strategically useless. Repository search produces fragments that are individually plausible and collectively confusing.</p><p>Giving all of this to the strongest model can feel like the safest option because nothing has been hidden. In practice, though, a large context window is not the same thing as a faithful memory. Information can remain present while its relevance becomes increasingly difficult to judge.</p><p>A distillation layer makes that compression explicit. Instead of carrying the entire history of the run forward, the system carries a compact account of what it currently believes, what it has observed, and what remains uncertain. The planner can then reason from a cleaner state rather than repeatedly reconstructing the investigation from terminal exhaust.</p><p>There is an engineering benefit here as well. When the system has explicit boundaries, its failures become easier to discuss. Did it inspect the wrong part of the repository? Did it omit an important observation? Did it generate a patch that violated the intended constraint? Did it accept weak verification?</p><p>In a monolithic agent, all of these often collapse into the same diagnosis: the model failed. That is not a particularly useful way to improve a system.</p><p>I think a similar argument applies to code generation, although less cleanly. There are changes where the architectural reasoning and implementation are too closely connected to separate: subtle concurrency bugs, difficult migrations, or refactors where the shape of the patch is itself the main design decision. In those cases, the frontier model may need to remain deeply involved.</p><p>But a large amount of coding work becomes local once the problem has been framed properly. If the relevant files, expected behaviour, constraints, and verification target are known, a capable coding model can often produce the patch. The quality of the result then depends heavily on the quality of the instruction it receives.</p><p>“Fix the bug” is not meaningful delegation. “Change this behaviour without altering this interface, avoid a broad refactor, and add a regression test for this case” is much closer.</p><p>This resembles, in a loose way, how strong engineering teams already operate. The most experienced engineer is not valuable because they personally type every line. Their value often lies in framing the problem, spotting bad assumptions, preserving conceptual integrity, and deciding whether an implementation actually solves what it claims to solve.</p><p>A planner–executor agent gives the frontier model a similar role. It shapes the work, delegates a constrained change, reviews the result, and decides whether the evidence is strong enough to stop.</p><p>The obvious weakness is that every handoff can lose information. A smaller model may omit the one important line in a log. An executor may misunderstand the planner. A compressed state may hide a clue that would have changed the investigation.</p><p>I do not think this is a minor objection. Poorly designed decomposition can easily perform worse than a coherent single-model loop.</p><p>But the alternative is not perfect information. A monolithic agent also compresses its history, only less visibly. It relies on attention to preserve relevance across an expanding transcript and on the model to maintain a stable internal account of what has happened. Compression still occurs; it is simply implicit and difficult to inspect.</p><p>Planner–executor systems make the compression boundary part of the design. They force us to decide what counts as evidence, what state should survive, what an executor is allowed to change, and what verification is required before the system can claim success.</p><p>Those choices may matter more than the names of the models involved.</p><p>I would hesitate to claim that planner–executor systems are the final form of coding agents. Models are improving quickly, and some of the distinctions that seem important today may become unnecessary. For small repositories and short tasks, a single capable model may remain the simplest and best option.</p><p>My thesis is narrower. As coding agents take on longer tasks in larger repositories, I expect the separation between judgment and execution to become more useful, not less. The hard part is often not producing code. It is maintaining a coherent view of the problem while deciding what should be done, what should be ignored, and when the available evidence is good enough.</p><p>The strongest model is not the agent. The agent is the entire loop: models, tools, memory, tests, constraints, and review.</p><p>The goal should not be to keep the largest model busy. It should be to spend intelligence deliberately.</p>]]></content:encoded></item></channel></rss>