<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Asharaf Ali · Field notes</title>
  <link>https://www.asharafali.com/notes/</link>
  <atom:link href="https://www.asharafali.com/feed.xml" rel="self" type="application/rss+xml" />
  <description>Field notes on enterprise AI architecture, sovereign deployment, and the trade-offs of building Generative AI inside regulated walls.</description>
  <language>en-us</language>
  <lastBuildDate>Tue, 25 Aug 2026 06:04:43 GMT</lastBuildDate>
  <item>
    <title>Your model weights should outlive the process</title>
    <link>https://www.asharafali.com/notes/sglang-weight-cache-daemon/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/sglang-weight-cache-daemon/</guid>
    <pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate>
    <description>Your model weights should outlive the process that serves them. SGLang shipped that idea on August 21.</description>
    <content:encoded><![CDATA[<p>Your model weights should outlive the process that serves them. SGLang shipped that idea on August 21.</p>
<p>Anyone running big models on-prem knows the restart: for several minutes every in-flight request fails or queues, and no autoscaler hides it.</p>
<p>The numbers, from Ant Group, Alibaba and the SGLang team. Ling-2.6-1T in FP8 on 8x H20: weight loading took about 495s of a 527s boot, 94% of the restart. With the weight cache daemon it drops under a second, and total boot goes from 8.8 minutes to about 32 seconds. Qwen3-235B FP8 goes from about five minutes to under one.</p>
<p>A per-GPU daemon loads and quantizes the weights once and keeps them resident. A new engine initialises the model on the meta device, then swaps each parameter pointer to the daemon&#39;s tensor over CUDA IPC. There is one copy in GPU memory and nothing gets copied. If the engine dies, the daemon still holds the weights. If the daemon dies, running engines keep their mapped tensors.</p>
<p>Active-standby then works without parking a full idle GPU replica, and a batch job can share a GPU with an online service, get evicted, and come back in under a second.</p>
<p>The trap: it only supports unquantized and block-wise FP8 today. AWQ, GPTQ and Marlin repack weights, so the daemon raises a hard error rather than serve wrong numerics. Most on-prem 70B boxes I have seen run exactly those formats.</p>
<p>Put engine restart time in your latency SLO and measure it the way you measure p99.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Where do the pixels actually go?</title>
    <link>https://www.asharafali.com/notes/multimodal-as-tool-boundary/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/multimodal-as-tool-boundary/</guid>
    <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
    <description>&quot;Multimodal-native&quot; has quietly come to mean a tool call rather than a model property. Qwen&#39;s new plugin repo is honest about that; a lot of the commentary around it is not.</description>
    <content:encoded><![CDATA[<p>&quot;Multimodal-native&quot; has quietly come to mean a tool call rather than a model property. Qwen&#39;s new plugin repo is honest about that; a lot of the commentary around it is not.</p>
<p>Qwen-MM-Plugins makes an existing agent harness handle images, video, OCR, ASR and segmentation. The README&#39;s own definition of a capability: a skill, so the model knows the toolset exists, plus an optional MCP server, the tools themselves. Apache-2.0, no tagged releases yet, about 1.6k GitHub stars in under two weeks.</p>
<p>None of it touches the weights. There is no adapter and no retraining, which for a harness is the right call: you add OCR to a coding agent without owning a vision stack, and the providers stay swappable.</p>
<p>Read the data path anyway. The local plugin reads frames and crops images on your machine. The understanding calls out to a hosted API, DashScope by default. If you are under data residency rules or genuinely air-gapped, that one line is the whole procurement conversation, and repointing it is your work, not theirs.</p>
<p><strong>The trap:</strong> telling a model a tool exists is not the same as the model using it well. The failure mode moves from &quot;cannot see the image&quot; to &quot;picked the wrong tool and summarised it confidently.&quot; That needs an eval per modality, and the repo ships no benchmarks.</p>
<p>Ask where the pixels go.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Prefill and decode are two different workloads</title>
    <link>https://www.asharafali.com/notes/disaggregated-prefill-decode/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/disaggregated-prefill-decode/</guid>
    <pubDate>Wed, 29 Jul 2026 00:00:00 GMT</pubDate>
    <description>Prefill and decode are two different workloads. On July 23 the hardware stopped pretending otherwise.</description>
    <content:encoded><![CDATA[<p>Prefill and decode are two different workloads. On July 23 the hardware stopped pretending otherwise.</p>
<p>AMD launched Helios and, the same day, announced a Cerebras pairing that splits inference across two machines: Helios processes the prompts and large context windows, the Wafer-Scale Engine handles token generation. AMD&#39;s own term for it is disaggregated inference.</p>
<p>If you have sized an on-prem cluster you already knew the split. Prefill is compute bound and batches well. Decode is memory bandwidth bound and does not, which is why a single pool sized for both means you overpay on prefill and still miss your latency SLO on decode.</p>
<p>Two numbers came out that day. Keep them apart.</p>
<p>30% more tokens per dollar: Helios against NVIDIA Vera Rubin NVL72. AMD Performance Labs estimate, Kimi K2 Thinking, 32K in and 8K out.</p>
<p>5x tokens per second per watt: AMD plus Cerebras against a Cerebras WSE-only configuration. Different model, Kimi 2.6 1T. Vendor modelling, not measured silicon.</p>
<p><strong>The trap:</strong> that 5x is not a win over NVIDIA. It is Cerebras with Helios against Cerebras without it, and the headline says per watt while the footnote says per kilowatt.</p>
<p>The topology is right. The benchmark is still someone else&#39;s marketing.</p>
]]></content:encoded>
  </item>
  <item>
    <title>MCP just deleted its session handshake</title>
    <link>https://www.asharafali.com/notes/mcp-stateless-spec/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/mcp-stateless-spec/</guid>
    <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
    <description>MCP just deleted its session handshake. That one change does more for enterprise agent deployment than any model release this month.</description>
    <content:encoded><![CDATA[<p>MCP just deleted its session handshake. That one change does more for enterprise agent deployment than any model release this month.</p>
<p>The 2026-07-28 spec drops the initialize/initialized handshake and the Mcp-Session-Id header. Protocol version and capabilities now ride in _meta on every request, and a new server/discover method covers the rest.</p>
<p>What that buys you is a tool server you can put behind a plain round-robin load balancer. No session affinity to maintain, so you can drop the shared session store your horizontal deployment needed. Proxies route on the Mcp-Method header instead of inspecting bodies. Your MCP fleet becomes an ordinary stateless HTTP service, which is the only shape most platform teams will agree to run.</p>
<p>Roots, Sampling and Logging are deprecated in the same release. Annotation-only, still functional through 2027. Logging moves to stderr and OpenTelemetry.</p>
<p>The trap: read the Sampling deprecation carefully. If your tool server calls back through the client for model access, the replacement is a direct provider API from inside the server. In an air-gapped or egress-controlled estate that is a network and procurement change, not a code change.</p>
<p>Your tool servers just became ordinary web services. Deploy them like it.</p>
]]></content:encoded>
  </item>
  <item>
    <title>The attacker went agentic before you did</title>
    <link>https://www.asharafali.com/notes/jadepuffer-agentic-ransomware/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/jadepuffer-agentic-ransomware/</guid>
    <pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate>
    <description>The first fully agentic ransomware just ran. It used the same primitives you build defensive agents on.</description>
    <content:encoded><![CDATA[<p>The first fully agentic ransomware just ran. It used the same primitives you build defensive agents on.</p>
<p>Sysdig documented JadePuffer this month: an LLM agent that ran the whole chain by itself. RCE into an exposed Langflow box, swept the host for provider keys and cloud creds, moved laterally into a Nacos/MySQL config server, installed a beacon, then encrypted 1,342 config items and wrote its own ransom note.</p>
<p>The entry point was not novel. CVE-2025-3248, patched April 2025. What was new is tempo. When a Nacos admin login failed, the agent diagnosed it and self-corrected in 31 seconds, switching from a subprocess call to a direct bcrypt import. No human triages that fast.</p>
<p>Sysdig caught it on 600+ distinct payloads, each one narrating its own targeting rationale in plain language. That self-narration is the fingerprint.</p>
<p>The trap: the agent&#39;s blast radius was exactly the creds and tools its host could reach. Same rule as your defensive agents. Leave provider keys sitting in your orchestration server env and you have scoped the attacker&#39;s reach for them.</p>
<p>Attackers went agentic before most defenders did. Your perimeter is now whatever your agent&#39;s tools can touch.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Route by task, not by loyalty</title>
    <link>https://www.asharafali.com/notes/capability-routing-sonnet5/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/capability-routing-sonnet5/</guid>
    <pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate>
    <description>The biggest cost lever in an agent stack right now is a router that knows when not to call the frontier model.</description>
    <content:encoded><![CDATA[<p>The biggest cost lever in an agent stack right now is a router that knows when not to call the frontier model.</p>
<p>Anthropic shipped Sonnet 5 last week at $2 in / $10 out per million tokens intro pricing ($3/$15 from September). Vendor numbers put it just under Opus 4.8 on agentic coding and ahead on some knowledge work. Terminal-Bench went from 67.0 on Sonnet 4.6 to 80.4.</p>
<p>Mid-tier models now clear the bar for most production agent loops. That changes the architecture more than the bill. What I would do with it:</p>
<ol>
<li><p><strong>Route by task, not by loyalty.</strong> Tool-call planning, extraction, classification go mid-tier. Deep multi-file reasoning escalates. Two tiers beat a monolith on cost per task.</p>
</li>
<li><p><strong>Meter cost per task, not per token.</strong> Token price tells you little once models think for variable lengths. Tag every run with its task class and its dollars. Alert on outliers.</p>
</li>
<li><p><strong>Re-run your evals before flipping traffic.</strong> The gap to frontier is benchmark-thin, and your workload is not a benchmark. Golden set first, then migrate.</p>
</li>
</ol>
<p>We run the same tiering on-prem with open weights. Same math, different price tags.</p>
<p><strong>The trap:</strong> the effort dial is a budget, not a quality knob. Uncapped, the cheap model on a hard task can spend past Opus and hand you the same answer.</p>
<p>Cost per task is the only price that matters in an agent stack.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Everyone quantizes the weights and forgets the KV cache</title>
    <link>https://www.asharafali.com/notes/kv-cache-quantization/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/kv-cache-quantization/</guid>
    <pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate>
    <description>Everyone quantizes the weights and forgets the KV cache. On long context, that cache is what blows your VRAM budget.</description>
    <content:encoded><![CDATA[<p>Everyone quantizes the weights and forgets the KV cache. On long context, that cache is what blows your VRAM budget.</p>
<p>You AWQ the model to 4-bit, fit it on the GPU, ship it. Then a user pastes a 200-page contract, and per-token KV at 128K quietly eats more memory than the weights you just shrank.</p>
<p>Low-bit KV cache used to be a trap: push it to 2-bit and needle-in-haystack recall falls apart. New work (Block-GTQ, RoPE-aware bit allocation, Jun 2026) says stop quantizing it uniformly. Under RoPE, key energy concentrates in a few frequency blocks. Spend bits where the signal is, starve the rest.</p>
<p>Paper-stated on Llama-3.1-8B, benchmark your own:</p>
<ul>
<li>3.24x KV-cache compression at fp16-comparable quality</li>
<li>needle recall 70.6 to 97.4 vs naive low-bit</li>
<li>1.34x faster than fp16 attention at 128K on one H800</li>
</ul>
<p>The trap: uniform 2-bit KV looks clean on short prompts and silently wrecks recall past 32K. You won&#39;t catch it in eval until a customer&#39;s long document returns the wrong clause.</p>
<p>Quantize the weights for the GPU bill. Quantize the KV cache for the context window. That second one is the on-prem win nobody is pricing in yet.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Open weights just hit the frontier. Read the token bill.</title>
    <link>https://www.asharafali.com/notes/glm-5-2-open-weight-frontier/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/glm-5-2-open-weight-frontier/</guid>
    <pubDate>Tue, 16 Jun 2026 00:00:00 GMT</pubDate>
    <description>An open-weight model just matched the frontier on long-horizon agentic coding and MCP tool use. If you run air-gapped, the build-vs-buy math quietly flipped this week.</description>
    <content:encoded><![CDATA[<p>An open-weight model just matched the frontier on long-horizon agentic coding and MCP tool use. If you run air-gapped, the build-vs-buy math quietly flipped this week.</p>
<p>GLM-5.2 shipped MIT-licensed, full weights, 1M context. The numbers (vendor and third-party, so benchmark your own):</p>
<ul>
<li>SWE-bench Pro 62.1, up from 58.4 on 5.1.</li>
<li>FrontierSWE 74.4, within a point of Opus 4.8 at 75.4.</li>
<li>Terminal-Bench 2.1 climbed from 63.5 to 81.</li>
<li>MCP-Atlas tool-use sits near Opus.</li>
</ul>
<p>For on-prem that flips the calculus. Frontier-class long-horizon coding now runs inside the air gap: no egress, no per-call metering, weights you own outright. The model-ownership red line got cheaper to hold.</p>
<p>The trap: on-prem you don&#39;t pay per token, you pay in decode tok/s and KV cache. GLM-5.2 is token-hungry, by early reviews one of the least efficient in its class. A model that wins the leaderboard while burning 2-3x the tokens can still lose your GPU budget.</p>
<p>Own the weights. Then benchmark the tok/s, because the leaderboard doesn&#39;t pay your GPU bill.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Prompt injection is permanent. Design around it.</title>
    <link>https://www.asharafali.com/notes/prompt-injection-permanent/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/prompt-injection-permanent/</guid>
    <pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate>
    <description>Prompt injection isn&#39;t a bug you&#39;ll patch. It&#39;s a property of how the model reads, and OWASP&#39;s new report stops pretending otherwise.</description>
    <content:encoded><![CDATA[<p>Prompt injection isn&#39;t a bug you&#39;ll patch. It&#39;s a property of how the model reads, and OWASP&#39;s new report stops pretending otherwise.</p>
<p>The model sees the system prompt, the user request, and a retrieved document as one token stream. No boundary between <em>instruction</em> and <em>data</em>. That isn&#39;t a missing feature. It&#39;s the architecture. OWASP&#39;s &quot;State of Agentic AI Security&quot; v2.01 (June 11) maps injection to 6 of the 10 agentic Top-10 categories. You don&#39;t patch the foundation.</p>
<p>So stop filtering inputs and start budgeting capability. Two rules worth stealing:</p>
<ul>
<li><strong>Lethal trifecta</strong> (Willison): private data + untrusted content + external comms. One agent holding all three is an exfiltration tool waiting for one poisoned input.</li>
<li><strong>Rule of Two</strong> (Meta): an unsupervised agent gets at most two of those three legs. Want all three? A human signs off. Full stop.</li>
</ul>
<p><strong>The trap:</strong> the trifecta is a property of the <em>session</em>, not the agent. A safe RAG read, a safe DB lookup, and a safe send-email tool each pass review, then co-occur in one context window and arm the bomb. Audit the composition, not the tools.</p>
<p>Guardrail classifiers lower the incidence. They don&#39;t close the class. You&#39;re always one encoding away.</p>
<p>Design the blast radius. Don&#39;t litigate the prompt.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Your agent&#39;s tools are your new perimeter</title>
    <link>https://www.asharafali.com/notes/mcp-server-security/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/mcp-server-security/</guid>
    <pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate>
    <description>Every MCP tool you wire into an agent is a new unauthenticated door into your network — and the data says most teams forgot the lock.</description>
    <content:encoded><![CDATA[<p>Every MCP tool you wire into an agent is a new unauthenticated door into your network — and the data says most teams forgot the lock.</p>
<p>A year into Model Context Protocol, the numbers are ugly. A taint-analysis sweep of ~39,800 open-source MCP servers confirmed 106 zero-days with working exploits and 67 CVE IDs assigned (VIPER-MCP, arXiv). Censys counted ~12,500 internet-exposed MCP services — most with no auth at all. This month the NSA published MCP security design guidance.</p>
<p><strong>The tool list IS the attack surface.</strong> MCP&#39;s whole job is letting a model call your tools — and that same path is taint-style injection: prompt → vulnerable sink → SQL injection, metadata exfiltration, command execution. The model is now an untrusted input source pointed straight at your systems.</p>
<p><strong>Auth got treated as optional, so teams skipped it.</strong> Unauthenticated metadata exfil and CVSS-9.8 command-injection keep surfacing in DB-connected servers.</p>
<p>So treat every MCP server like the RPC boundary it is: auth in front of all of them, allowlist tools instead of &quot;expose everything&quot;, scope credentials per tool, and audit-log every call with the reasoning that triggered it.</p>
<p><strong>The trap:</strong> the dangerous servers aren&#39;t the public ones — they&#39;re the internal ones someone stood up with auth off because &quot;it&#39;s behind the firewall.&quot;</p>
<p>An agent&#39;s tools aren&#39;t features. They&#39;re your new perimeter.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Gemma 4 12B deleted the encoders</title>
    <link>https://www.asharafali.com/notes/gemma4-encoder-free/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/gemma4-encoder-free/</guid>
    <pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate>
    <description>Gemma 4 12B just deleted the vision and audio encoders. Most multimodal models still bolt on three separate networks. Google ships one weight space.</description>
    <content:encoded><![CDATA[<p>Gemma 4 12B just deleted the vision and audio encoders. Most multimodal models still bolt on three separate networks. Google ships one weight space.</p>
<p>How it actually works:</p>
<p><strong>Vision.</strong> Raw images → 48×48 patches → a single matrix multiply into the LLM&#39;s embedding space. No standalone ViT, no cross-attention adapter.</p>
<p><strong>Audio.</strong> Raw 16kHz frames → linear projection into that same text embedding space. RoPE already handles the timing, so the 12 conformer layers older Gemma needed are simply gone.</p>
<p><strong>Result.</strong> Three encoder stacks collapse to one. Apache 2.0, Q4, runs on a 16GB laptop. Text, image, audio and video in native.</p>
<p>Google published no benchmarks at launch. The &quot;near-26B at half the memory&quot; line going around is community-reported — treat it as a hypothesis, then benchmark your own task.</p>
<p><strong>The trap:</strong> one weight space means your single Q4 build <em>is</em> the whole multimodal stack, and LoRA now updates vision, audio and text in one pass. Great — until you quantize. There&#39;s no separate encoder to keep at higher precision, so a sloppy quant degrades every modality at once.</p>
<p>When the encoders disappear, your quantization config becomes your entire multimodal strategy.</p>
]]></content:encoded>
  </item>
  <item>
    <title>The model got the headline. The pattern is the product.</title>
    <link>https://www.asharafali.com/notes/multi-agent-fan-out-orchestration/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/multi-agent-fan-out-orchestration/</guid>
    <pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate>
    <description>The headline last week was a new model. The lesson was an architecture.</description>
    <content:encoded><![CDATA[<p>The headline last week was a new model. The lesson was an architecture.</p>
<p>Anthropic shipped Opus 4.8 on May 28. Buried under the benchmarks was the part that matters for anyone building agents: &quot;dynamic workflows&quot; — the model writes its own orchestration script, fans out tens to hundreds of parallel subagents, points adversarial agents at their findings to refute them, and iterates until the answers converge.</p>
<p>That&#39;s not a model feature. That&#39;s an architecture going mainstream. And you can build it on open weights, air-gapped, today.</p>
<p>Three things I&#39;d tell anyone wiring up fan-out agent systems:</p>
<p><strong>1. Fan-out is cheap. Convergence is the product.</strong>
Spawning 100 subagents is one loop. Knowing when they&#39;ve actually agreed — and aren&#39;t just echoing the same wrong context — is the hard part. Your orchestrator needs an explicit convergence criterion (K consecutive rounds with no new finding), not a fixed iteration count.</p>
<p><strong>2. Adversarial verifiers beat more generators.</strong>
Ten agents generating answers gives you ten plausible answers. One agent whose only job is to refute a finding kills the plausible-but-wrong ones. Spend your token budget on skeptics, not on a bigger crowd.</p>
<p><strong>3. The orchestrator is code, not a prompt.</strong>
Fan-out, barriers, retries, loop-until-dry — that&#39;s deterministic control flow wrapped around stochastic agents. If your &quot;orchestration&quot; is one giant prompt asking the model to coordinate itself, you don&#39;t have an orchestrator. You have a wish.</p>
<p><strong>The trap:</strong> fan-out without a convergence test burns tokens forever — or worse, returns false consensus when every subagent inherited the same poisoned context. Diversity of angle is what makes the votes mean anything.</p>
<p>You don&#39;t need a frontier API to run this shape. LangGraph + a self-hosted 70B + a disciplined orchestration script gives you fan-out, adversarial verification, and convergence — inside your VPC, with a token bill that doesn&#39;t explode the moment the agent count does.</p>
<p>The model got the headline. The pattern is the product.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Subquadratic sparse attention finally shipped</title>
    <link>https://www.asharafali.com/notes/subquadratic-sparse-attention/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/subquadratic-sparse-attention/</guid>
    <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
    <description>Your next long-context model probably won&#39;t run quadratic attention.</description>
    <content:encoded><![CDATA[<p>Your next long-context model probably won&#39;t run quadratic attention.</p>
<p>For five years, subquadratic attention was a research artifact. In 2025 it shipped.</p>
<p><strong>Three architectures to know:</strong></p>
<p><strong>NSA — Native Sparse Attention</strong> (DeepSeek, ACL 2025 best paper)
Three parallel paths per query: compressed coarse-grained tokens, selectively retained fine-grained tokens, and a sliding window. Hardware-aligned. Trainable end-to-end — not bolted on after pretraining.</p>
<p><strong>DSA — DeepSeek Sparse Attention</strong> (DeepSeek-V3.2-Exp, 2025-09-29)
Lightning indexer + fine-grained token selection. The first frontier model where sparse attention is the production path, not an ablation. MMLU-Pro 85.0 (par with V3.1-Terminus dense). AIME 2025: 89.3 vs 88.4. API price cut &gt;50%.</p>
<p><strong>SSA — Subquadratic Selective Attention</strong> (Subquadratic, launched 2026-05-05)
Content-dependent selection. 1M tokens production, 12M tokens research. Claims 52× speedup at 1M tokens vs FlashAttention-2 on B200s. Independent benchmarks pending — discount accordingly.</p>
<p><strong>What it means for your stack today:</strong></p>
<ul>
<li>SGLang v0.5.9 ships TRT-LLM DSA kernels. Flag: <code>--nsa-prefill-backend trtllm</code>. 3–5× speedup on Blackwell.</li>
<li>A 1M-token system prompt is now a budget question, not a research project.</li>
<li>Long-context evals get harder, not easier. Sparse models pass needle-in-haystack and still miss multi-hop reasoning at depth — your eval harness needs a long-context reasoning section, not just retrieval.</li>
</ul>
<p><strong>The trap:</strong> <em>subquadratic</em> is a complexity class, not a quality guarantee. Mamba and RWKV were both subquadratic. Both ended up hybrid. Bet on architectures that ship par-quality benchmarks, not ones that ship throughput plots.</p>
]]></content:encoded>
  </item>
  <item>
    <title>The LLM eval harness rubric</title>
    <link>https://www.asharafali.com/notes/eval-harness-rubric/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/eval-harness-rubric/</guid>
    <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
    <description>Most production LLM eval harnesses ship with one column: accuracy. That&#39;s a vibes check, not an eval.</description>
    <content:encoded><![CDATA[<p>Most production LLM eval harnesses ship with one column: accuracy. That&#39;s a vibes check, not an eval.</p>
<p>A real harness has five sections:</p>
<p><strong>1. Golden set</strong> — frozen labeled examples. Pass rate per task. The set has an owner and a last-updated date. Without this, a model swap silently regresses.</p>
<p><strong>2. Schema set</strong> — does output parse? Match the contract? Pydantic validation passes? Grammar-gated decoding trends this to 100%, but eval anyway — schema drift catches you when frameworks upgrade.</p>
<p><strong>3. Calibration set</strong> — when the model says <em>&quot;0.95 confidence&quot;</em>, is it actually right 95% of the time? Brier score or reliability diagram. Most teams skip this. Then they wonder why their auto-route threshold is wrong.</p>
<p><strong>4. Latency budget</strong> — P50, P95, P99 per stage (router, retrieval, decode, tool-call). Hard cap per stage. A feature that violates the budget is a regression by definition.</p>
<p><strong>5. Adversarial set</strong> — jailbreaks, prompt injection, OOD inputs, ambiguous queries. Pass rate baseline. Run on every model swap. The day you skip this is the day a customer finds your prompt-break on Twitter.</p>
<p>Each section needs three things: a <strong>metric</strong>, an <strong>owner</strong>, and a <strong>frequency</strong>.</p>
<p>The metric without the owner is theatre. The owner without the frequency is a someday-list.</p>
<p>A harness with fewer than five sections can&#39;t tell you whether the next deploy is an upgrade or a regression. The model gets better. The harness tells you.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Your agent doesn&#39;t have a JSON problem. It has a decoding problem.</title>
    <link>https://www.asharafali.com/notes/grammar-gated-routing/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/grammar-gated-routing/</guid>
    <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
    <description>Your agent doesn&#39;t have a JSON problem. It has a decoding problem.</description>
    <content:encoded><![CDATA[<p>Your agent doesn&#39;t have a JSON problem. It has a decoding problem.</p>
<p>Most production agents I&#39;ve reviewed ship some version of this pattern:</p>
<p>→ Call the LLM.
→ Try to json.loads the output.
→ On JSONDecodeError, re-prompt with &quot;Respond ONLY in valid JSON&quot; and call the LLM again.</p>
<p>It mostly works. ~5–10% of calls retry. Each retry is a second full inference - a tax on throughput, latency, and GPU cost for a problem unrelated to the model&#39;s reasoning.</p>
<p>The fix isn&#39;t a better prompt. It&#39;s grammar-constrained decoding (xgrammar in SGLang, Outlines in vLLM). The decoder masks every token that would produce invalid output. Result is always parseable, by construction.</p>
<p>The biggest payoff isn&#39;t on tool-call args. It&#39;s on the router. Define a Pydantic schema -</p>
<p>  agent: Literal[&quot;billing&quot;, &quot;support&quot;, &quot;sales&quot;, &quot;escalate&quot;]
  confidence: float
  reason: str</p>
<ul>
<li>hand it to the decoder, and the router cannot pick an agent that doesn&#39;t exist. Cannot malform confidence. Cannot omit reason. Structural correctness is guaranteed before the first token decodes.</li>
</ul>
<p>PRODUCTION NUMBERS (Llama-3.3-70B router, H100, SGLang + xgrammar):
• Parse-error rate: ~7% → 0%
• Per-decode masking overhead: ~5–15ms
• Net per-user tok/s: higher - no retry tokens</p>
<p>THE TRAP: over-constrained schemas make the model lie. Always include an &quot;escalate&quot; or null option in your enum, or nonsense queries get routed somewhere wrong with high confidence.</p>
<p>If your agent still wraps every model call in try/except JSONDecodeError on the hot path, you&#39;re paying for a problem that&#39;s been solved for two years.</p>
]]></content:encoded>
  </item>
  <item>
    <title>TGI went into maintenance mode. Here&#39;s the on-prem 70B picture now.</title>
    <link>https://www.asharafali.com/notes/on-prem-70b-numbers/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/on-prem-70b-numbers/</guid>
    <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
    <description>HuggingFace quietly put Text Generation Inference into maintenance mode in December 2025.</description>
    <content:encoded><![CDATA[<p>HuggingFace quietly put Text Generation Inference into maintenance mode in December 2025.</p>
<p>If you&#39;re running TGI in production, that&#39;s the memo. Here&#39;s the picture for anyone serving a ~70B model on their own GPUs right now:</p>
<p>Three things to take from that table:</p>
<p><strong>1. TGI still works - but it stops improving.</strong></p>
<p>The single-user decode is still competitive. But HuggingFace itself is now pointing new deployments at vLLM or SGLang. If TGI is your runtime today, the migration conversation happens in the next two quarters, not later.</p>
<p><strong>2. Ollama is not a production runtime.</strong></p>
<p>A single user on an H100 gets ~24 tok/s. Great for dev boxes and for building your eval harness. But ~1–3 concurrent req/sec means your product dies the minute the second customer shows up. We use Ollama daily - never in production.</p>
<p><strong>3. Per-user decode tok/s is the number nobody benchmarks.</strong></p>
<p>Every framework publishes aggregate throughput because aggregate looks big. What your user feels is per-user streaming speed at batch=1. Below ~30 tok/s the UX feels slow. Above 60 and you&#39;ve won the perception battle. vLLM on a single H100 with int4 weights sits comfortably above that line.</p>
<p>Our stack for sovereign-AI clients: vLLM for serving, AWQ / GPTQ for quantisation, Ollama for dev boxes, H100 / H200 for production, Prometheus + Grafana for the whole path. All on-prem. All air-gappable. No OpenAI bill.</p>
<p>The &quot;which model&quot; question is the last one I ask a client. The first is: what&#39;s your SLO, and what GPUs do you already own?</p>
<p>Numbers in the table are verified as of April 2026 (sources in the comments). Per-user tok/s moves ±30% with context length - benchmark your own.</p>
]]></content:encoded>
  </item>
  <item>
    <title>The tools are the product</title>
    <link>https://www.asharafali.com/notes/pentest-agent/</link>
    <guid isPermaLink="true">https://www.asharafali.com/notes/pentest-agent/</guid>
    <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
    <description>Autonomous agents touching production is a terrible idea.</description>
    <content:encoded><![CDATA[<p>Autonomous agents touching production is a terrible idea.</p>
<p>Autonomous agents touching production, behind a 5-second human gate, is a product.</p>
<p>We shipped a LangGraph multi-agent system this quarter that mutates state in an enterprise customer&#39;s production environment. Three things I&#39;d tell anyone building agents that touch real systems:</p>
<p><strong>1. Your toolbelt is the product.</strong></p>
<p>The LLM picks. Your tools decide what&#39;s possible. If <code>run_command</code> exists, someone will run <code>rm -rf /</code>. We locked the toolbelt before we tuned a single prompt. Every tool has a named blast radius, a rate limit, and a scope the planner cannot widen.</p>
<p><strong>2. Human-in-the-loop is a UX problem, not a safety feature.</strong></p>
<p>If the review gate takes 40 seconds, your operator auto-approves by week two. We built a 5-second review: diff, blast radius, one-click undo. Approval rate dropped from 100% to 62%. That 38% is the product working.</p>
<p><strong>3. The audit log is not a side-effect. It is the product.</strong></p>
<p>Procurement reads it. Insurance reads it. The customer-facing report is generated from it — by a narrator node that cites every claim with an evidence hash. We designed the log schema before we designed the agent graph.</p>
<p>Stack: LangGraph + self-hosted open-weights models + a disciplined tool surface. No OpenAI key in the build. Runs inside the client&#39;s VPC. The team sleeps.</p>
<p>If you&#39;re building agents that touch anything destructive — infra, code, money, or customers — the same three rules apply. The model is not the hard part.</p>
]]></content:encoded>
  </item>
</channel>
</rss>
