<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lynkr</title>
    <description>The latest articles on DEV Community by Lynkr (@lynkr).</description>
    <link>https://dev.to/lynkr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3645387%2F794ced23-25c9-41ed-863a-401839a48d59.png</url>
      <title>DEV Community: Lynkr</title>
      <link>https://dev.to/lynkr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lynkr"/>
    <language>en</language>
    <item>
      <title>Lynkr vs LiteLLM's New `complexity_router`</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Wed, 05 Aug 2026 22:17:24 +0000</pubDate>
      <link>https://dev.to/lynkr/lynkr-vs-litellms-new-complexityrouter-464p</link>
      <guid>https://dev.to/lynkr/lynkr-vs-litellms-new-complexityrouter-464p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure up front:&lt;/strong&gt; this benchmark was designed, written, and run by Lynkr's&lt;br&gt;
maintainer, using Lynkr's own regression harness. The scenario set was written to&lt;br&gt;
test routing behaviors Lynkr considers important — that is a real selection bias&lt;br&gt;
and it is not hand-waved away here (see Limitations). Mitigations:&lt;br&gt;
both proxies route over &lt;strong&gt;identical backends&lt;/strong&gt;, LiteLLM ran its &lt;strong&gt;out-of-the-box&lt;br&gt;
defaults&lt;/strong&gt; exactly as Lynkr did, every scenario ran twice, the full config and&lt;br&gt;
harness are in this repo, and the results include the scenarios where LiteLLM&lt;br&gt;
wins and where Lynkr shows drift. Reproduction steps are at the bottom.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;In early August 2026, LiteLLM shipped &lt;code&gt;complexity_router&lt;/code&gt; in core — a rule-based&lt;br&gt;
tier router that classifies each request as SIMPLE / MEDIUM / COMPLEX / REASONING&lt;br&gt;
(the same four-tier taxonomy Lynkr uses) via weighted keyword scoring across 7&lt;br&gt;
dimensions, with zero API calls and sub-millisecond decisions. It ships alongside&lt;br&gt;
&lt;code&gt;adaptive_router&lt;/code&gt; (Thompson-sampling bandits) and a savings baseline.&lt;/p&gt;

&lt;p&gt;This is the category leader validating tier-based cost routing as a core proxy&lt;br&gt;
feature. We benchmarked it the week it shipped, on the same backends Lynkr routes&lt;br&gt;
to in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Systems under test
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;version&lt;/th&gt;
&lt;th&gt;routing decision mechanism&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lynkr&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;git working tree, 2026-08-05&lt;/td&gt;
&lt;td&gt;embedding-anchor intent score (local, no LLM call) + risk analyzer + agentic detector + session pins + calibrated thresholds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LiteLLM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.95.0 (PyPI; latest release)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;complexity_router&lt;/code&gt;, heuristic classifier, default weights/boundaries, untouched&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note: LiteLLM git-main (1.97.0) could not be run — the git wheel is missing&lt;br&gt;
&lt;code&gt;proxy_server.py&lt;/code&gt; and current main is incompatible with fastapi ≥0.140&lt;br&gt;
(&lt;code&gt;get_flat_dependant&lt;/code&gt; removed). Both are being reported upstream. 1.95.0 is the&lt;br&gt;
latest installable release and includes &lt;code&gt;complexity_router&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Identical backends, only the decision differs
&lt;/h3&gt;

&lt;p&gt;Both proxies map their four tiers to the same deployments (mirroring Lynkr's live&lt;br&gt;
&lt;code&gt;.env&lt;/code&gt; at test time):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;tier&lt;/th&gt;
&lt;th&gt;backend&lt;/th&gt;
&lt;th&gt;cost class&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SIMPLE&lt;/td&gt;
&lt;td&gt;ollama &lt;code&gt;minimax-m3:cloud&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MEDIUM&lt;/td&gt;
&lt;td&gt;ollama &lt;code&gt;minimax-m3:cloud&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;COMPLEX&lt;/td&gt;
&lt;td&gt;azure &lt;code&gt;gpt-5.6-sol&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REASONING&lt;/td&gt;
&lt;td&gt;moonshot &lt;code&gt;kimi-k3&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;paid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;LiteLLM config: &lt;code&gt;litellm-autorouter-v2.yaml&lt;/code&gt; (in-repo), using the shipped&lt;br&gt;
&lt;code&gt;auto_router/complexity_router&lt;/code&gt; schema with &lt;code&gt;tiers&lt;/code&gt; mapping and &lt;code&gt;default_model&lt;/code&gt;,&lt;br&gt;
nothing else configured. Each tier deployment carries &lt;code&gt;model_info.id&lt;/code&gt; so the&lt;br&gt;
&lt;code&gt;x-litellm-model-id&lt;/code&gt; response header reveals which tier served each request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Harness
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;benchmark-tier-routing.js&lt;/code&gt; (in-repo), &lt;code&gt;MODE=routing RUNS=2&lt;/code&gt;. Each scenario&lt;br&gt;
declares an &lt;strong&gt;acceptable-tier set&lt;/strong&gt;; a proxy is routing-correct when the tier that&lt;br&gt;
served the request is in the set. &lt;code&gt;RUNS=2&lt;/code&gt; means a scenario passes only if &lt;strong&gt;both&lt;/strong&gt;&lt;br&gt;
runs pass — this catches non-deterministic classifiers. Stateful scenarios embed a&lt;br&gt;
per-run nonce so session pins and caches can't leak between runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scoreboard: 11 scenarios, acceptable-tier judging
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;scenario (gist)&lt;/th&gt;
&lt;th&gt;acceptable&lt;/th&gt;
&lt;th&gt;Lynkr&lt;/th&gt;
&lt;th&gt;LiteLLM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;S1&lt;/td&gt;
&lt;td&gt;"What does git stash do?"&lt;/td&gt;
&lt;td&gt;SIMPLE|MEDIUM&lt;/td&gt;
&lt;td&gt;✓ MEDIUM&lt;/td&gt;
&lt;td&gt;✓ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R1&lt;/td&gt;
&lt;td&gt;JWT security trade-offs for a banking app, step by step&lt;/td&gt;
&lt;td&gt;COMPLEX|REASONING&lt;/td&gt;
&lt;td&gt;✓ REASONING&lt;/td&gt;
&lt;td&gt;✗ MEDIUM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F1&lt;/td&gt;
&lt;td&gt;"Refactor the entire ingestion pipeline, give me the plan"&lt;/td&gt;
&lt;td&gt;COMPLEX|REASONING&lt;/td&gt;
&lt;td&gt;✓ COMPLEX&lt;/td&gt;
&lt;td&gt;✗ MEDIUM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F2&lt;/td&gt;
&lt;td&gt;"Fix the null check in &lt;code&gt;src/auth/middleware.ts&lt;/code&gt; + tests"&lt;/td&gt;
&lt;td&gt;COMPLEX|REASONING&lt;/td&gt;
&lt;td&gt;✓ REASONING&lt;/td&gt;
&lt;td&gt;✗ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RS1&lt;/td&gt;
&lt;td&gt;"17+25" wrapped in injected &lt;code&gt;&amp;lt;system-reminder&amp;gt;&lt;/code&gt; security noise&lt;/td&gt;
&lt;td&gt;SIMPLE|MEDIUM&lt;/td&gt;
&lt;td&gt;✓ MEDIUM&lt;/td&gt;
&lt;td&gt;✓ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SR1&lt;/td&gt;
&lt;td&gt;Suggestion-mode side request over a prior security conversation&lt;/td&gt;
&lt;td&gt;SIMPLE|MEDIUM&lt;/td&gt;
&lt;td&gt;✓ SIMPLE&lt;/td&gt;
&lt;td&gt;✓ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A1&lt;/td&gt;
&lt;td&gt;"Work autonomously: run tests, fix, iterate until green"&lt;/td&gt;
&lt;td&gt;COMPLEX|REASONING&lt;/td&gt;
&lt;td&gt;✓ REASONING&lt;/td&gt;
&lt;td&gt;✗ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P1&lt;/td&gt;
&lt;td&gt;"hi, you there?" (fresh session)&lt;/td&gt;
&lt;td&gt;SIMPLE|MEDIUM&lt;/td&gt;
&lt;td&gt;✓ MEDIUM&lt;/td&gt;
&lt;td&gt;✓ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P2&lt;/td&gt;
&lt;td&gt;same session, then "architecture review of the routing module"&lt;/td&gt;
&lt;td&gt;COMPLEX|REASONING&lt;/td&gt;
&lt;td&gt;✓ COMPLEX&lt;/td&gt;
&lt;td&gt;✗ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IV1&lt;/td&gt;
&lt;td&gt;"Review this retry helper for bugs" (bare)&lt;/td&gt;
&lt;td&gt;MEDIUM|COMPLEX&lt;/td&gt;
&lt;td&gt;✓ MEDIUM&lt;/td&gt;
&lt;td&gt;✗ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IV2&lt;/td&gt;
&lt;td&gt;identical ask + ~600 tokens of harness/IDE envelope noise&lt;/td&gt;
&lt;td&gt;MEDIUM|COMPLEX&lt;/td&gt;
&lt;td&gt;✓ MEDIUM&lt;/td&gt;
&lt;td&gt;✗ SIMPLE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Lynkr: 11/11 · LiteLLM: 4/11.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The sharper cut: the 11 scenarios split into 4 "stay cheap" tests and 7&lt;br&gt;
"escalate correctly" tests. &lt;strong&gt;LiteLLM went 4/4 on stay-cheap and 0/7 on&lt;br&gt;
escalation.&lt;/strong&gt; A router biased toward the cheap tier passes every stay-cheap test&lt;br&gt;
by construction — the escalation tests are where routing is actually hard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Failure analysis: three clusters, not seven random misses
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Semantics beyond keywords (R1, F1, A1).&lt;/strong&gt; "Security trade-offs for a
banking application" and "work autonomously until the tests are green" carry
complexity in &lt;em&gt;meaning&lt;/em&gt;. The 7-dimension keyword sum doesn't reach the 0.35
COMPLEX boundary, so reasoning-grade work lands on the free tier. This is the
published, predicted weakness of ex-ante lexical scoring on real traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No risk model (F2).&lt;/strong&gt; "Fix the null check in &lt;code&gt;src/auth/middleware.ts&lt;/code&gt;" is
lexically trivial — and it is exactly the request you never send to an
uncontrolled free model. LiteLLM has no concept of protected paths; Lynkr's
risk analyzer forces auth/middleware edits to the governance tier regardless
of complexity score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No session or envelope awareness (P2, IV1, IV2).&lt;/strong&gt; After a "hi" opener,
"now do an architecture review" stayed on SIMPLE — no pin-escape mechanism.
The invariance pair is subtler: LiteLLM was technically invariant (SIMPLE both
times) but invariantly &lt;em&gt;wrong&lt;/em&gt; — a code-review ask never accumulated enough
keyword weight in either form.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The cost table pathology (read before quoting)
&lt;/h3&gt;

&lt;p&gt;The harness's raw cost line shows LiteLLM at &lt;strong&gt;$0.00 — "100% cheaper."&lt;/strong&gt; That is&lt;br&gt;
the failure, not a win: it spent nothing because it routed nearly everything —&lt;br&gt;
including the 7 escalation-grade requests — to the free tier. A router that sends&lt;br&gt;
everything to the cheapest model is always the "cheapest" router and always the&lt;br&gt;
worst one. Cost numbers for a router are only meaningful &lt;strong&gt;conditional on routing&lt;br&gt;
correctness.&lt;/strong&gt; Any quotation of this benchmark that includes the cost table&lt;br&gt;
without this caveat is misleading, in either direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lynkr's own warts (strict-expectation view)
&lt;/h3&gt;

&lt;p&gt;The harness also checks stricter per-scenario expectations than the acceptable&lt;br&gt;
sets. Lynkr drifted on 3 of 11:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;R1, F2:&lt;/strong&gt; over-routed COMPLEX → REASONING — correct-but-expensive (kimi-k3
spent where gpt-5.6-sol would do). Likely threshold drift after recent tier
remapping; the nightly calibration should re-fit, being watched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;P1:&lt;/strong&gt; SIMPLE → MEDIUM pin drift on the trivial opener.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over-routing burns money silently; it is the mirror image of LiteLLM's failure&lt;br&gt;
mode and it deserves the same scrutiny.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where LiteLLM is better
&lt;/h2&gt;

&lt;p&gt;Symmetry matters, so plainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decision latency.&lt;/strong&gt; Sub-millisecond, allocation-free keyword scoring vs
Lynkr's embedding lookup (~10–50 ms warm, more on classifier cold start). For
latency-critical single-model workloads that difference is real.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero infrastructure for the decision.&lt;/strong&gt; No embedding model, no classifier
model, no state. Lynkr's anchor scorer wants a local embedding model available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Determinism and auditability.&lt;/strong&gt; A weighted keyword sum is trivially
explainable to a compliance reviewer; an embedding similarity is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity of config.&lt;/strong&gt; One YAML block. Lynkr's routing intelligence has
meaningfully more surface to understand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tunability from a known base.&lt;/strong&gt; Weights, boundaries, and keyword lists are
all exposed; a team willing to tune per-workload could close some of the gap
(out-of-the-box was tested here, on both sides).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem and adoption.&lt;/strong&gt; LiteLLM is the default proxy of the ecosystem, and
the same release train ships &lt;code&gt;adaptive_router&lt;/code&gt; (bandit-based) — the direction
of travel is serious.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Lynkr is better
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Escalation correctness: 7/7 vs 0/7&lt;/strong&gt; — the entire hard half of the problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk-aware routing&lt;/strong&gt; — protected-path and instruction-risk signals route
security-relevant work to governed tiers independent of complexity score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session pinning with escape&lt;/strong&gt; — sticky sessions that release when the work
outgrows the pin (P2), instead of trapping or ignoring session state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload invariance by construction&lt;/strong&gt; — the intent score is computed on
cleaned user text, so harness envelopes, system-reminders, and IDE noise don't
move the decision (IV1/IV2, RS1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A verification cascade behind the decision&lt;/strong&gt; (not exercised in this routing-
only benchmark): cheap-tier answers are structurally verified and escalated on
failure, so a mis-route down is a recoverable event rather than a silent
quality loss. LiteLLM's architecture is predict-then-commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third-party evaluation&lt;/strong&gt; — RouterArena (ICLR 2026): 67.65 arena / 68.41%
accuracy / $0.29 per 1K queries / 92.38 robustness, leaderboard #15.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Every one of these is a genuine limitation of this benchmark:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;N=11, author-selected.&lt;/strong&gt; The scenarios encode Lynkr's view of what routing
should do. A LiteLLM-authored scenario set would probably look different.
(Counterpoint: the escalation scenarios are not exotic — auth-file edits,
refactor plans, and agentic loops are everyday coding-agent traffic.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defaults vs defaults.&lt;/strong&gt; LiteLLM's router is configurable; a tuned
configuration was not tested. Neither was a tuned Lynkr.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One day, one version pair.&lt;/strong&gt; LiteLLM 1.95.0; main moves fast and the
&lt;code&gt;adaptive_router&lt;/code&gt; (which may compensate for complexity_router misses over
time via bandit feedback) was not enabled or tested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routing-only.&lt;/strong&gt; Response quality, verification, compression, and caching
were all out of scope; the cost figures are therefore not end-to-end claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RUNS=2&lt;/code&gt;&lt;/strong&gt; is enough to catch gross nondeterminism, not enough for
statistics. Both systems were deterministic across runs on every scenario.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# LiteLLM (Python ≥3.10 venv)&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"litellm[proxy]==1.95.0"&lt;/span&gt; &lt;span class="s2"&gt;"fastapi&amp;lt;0.140"&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^(MOONSHOT_API_KEY|AZURE_OPENAI_API_KEY)='&lt;/span&gt; .env | xargs&lt;span class="si"&gt;)&lt;/span&gt;
litellm &lt;span class="nt"&gt;--port&lt;/span&gt; 8082 &lt;span class="nt"&gt;--config&lt;/span&gt; litellm-autorouter-v2.yaml

&lt;span class="c"&gt;# Lynkr&lt;/span&gt;
node index.js   &lt;span class="c"&gt;# serves :8081 per .env&lt;/span&gt;

&lt;span class="c"&gt;# head-to-head, routing-only, 2 runs per scenario&lt;/span&gt;
&lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;routing &lt;span class="nv"&gt;RUNS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="nv"&gt;LITELLM_MASTER_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-1234 node benchmark-tier-routing.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scenario definitions: &lt;code&gt;benchmark-tier-routing.js&lt;/code&gt;. LiteLLM config:&lt;br&gt;
&lt;code&gt;litellm-autorouter-v2.yaml&lt;/code&gt;. Raw logs from this run: &lt;code&gt;/tmp/litellm-bench.log&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;/tmp/lynkr-bench.log&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow-ups queued
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Paraphrase-pair robustness scenarios (same intent, different surface — the
lexical scorer's structural weakness deserves its own measured number).&lt;/li&gt;
&lt;li&gt;Re-run with LiteLLM &lt;code&gt;adaptive_router&lt;/code&gt; enabled on top of &lt;code&gt;complexity_router&lt;/code&gt;,
with enough traffic for its bandit to update — the fairest version of this
comparison over time.&lt;/li&gt;
&lt;li&gt;File the two upstream LiteLLM bugs found while setting up (git wheel missing
&lt;code&gt;proxy_server.py&lt;/code&gt;; fastapi ≥0.140 incompatibility).&lt;/li&gt;
&lt;li&gt;Investigate Lynkr's R1/F2 over-routing drift after tier remapping.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>litellm</category>
    </item>
    <item>
      <title>Loop Engineering Is Mostly Papering Over a Model That Won't Converge</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Thu, 30 Jul 2026 07:25:49 +0000</pubDate>
      <link>https://dev.to/lynkr/loop-engineering-is-mostly-papering-over-a-model-that-wont-converge-4kh2</link>
      <guid>https://dev.to/lynkr/loop-engineering-is-mostly-papering-over-a-model-that-wont-converge-4kh2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FFast-Editor%2FLynkr%2Fmain%2F.hermes-temp%2Floop-engineering-infographic.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FFast-Editor%2FLynkr%2Fmain%2F.hermes-temp%2Floop-engineering-infographic.jpg" alt="Loop engineering infographic" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, an open-source LLM gateway with loop-guard middleware, so I have a stake in this argument. Read this as a thesis to challenge, not a neutral survey.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agent discourse has shifted from prompts to loops: the read-act-observe cycle that keeps running until the model decides it's done. My contrarian take is that most so-called &lt;em&gt;loop engineering&lt;/em&gt; is optimizing the wrong variable. &lt;strong&gt;A longer, richer loop is usually a convergence failure wearing a costume.&lt;/strong&gt; The well-engineered loop is the short one that knows when to stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The consensus I'm arguing against
&lt;/h2&gt;

&lt;p&gt;When an agent fails, the default move is to give the loop &lt;em&gt;more&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More turns before it gives up.&lt;/li&gt;
&lt;li&gt;More context stuffed into the window.&lt;/li&gt;
&lt;li&gt;More scaffolding: planners, critics, reflection steps, sub-agents spawning sub-agents.&lt;/li&gt;
&lt;li&gt;More retries with more feedback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implicit theory is simple: intelligence accumulates across iterations, so more turns should mean more convergence. Sometimes that works. Mostly, on real traffic, it doesn't — and the cost structure is brutal even when it does.&lt;/p&gt;

&lt;p&gt;A concrete example from coding agents: give an underpowered model a repo-wide refactor and it usually doesn't "reason longer" into success. It misreads one dependency, anchors on the wrong file, and spends the next dozen turns elaborating the mistake. The loop isn't rescuing the model. It's financing the failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why longer loops compound the wrong things
&lt;/h2&gt;

&lt;p&gt;Two things compound across a loop, and neither is intelligence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Loop cost grows fast.&lt;/strong&gt; Every turn re-sends accumulated context. A 20-turn session isn't just 20 single calls back-to-back; each later turn drags earlier tokens back through the model. In many agentic workloads, the loop becomes the most expensive object in the serving budget, and "add more turns" becomes the most expensive knob you can turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Reliability collapses across dependent steps.&lt;/strong&gt; Even with optimistic per-step reliability, multi-step chains degrade quickly. Long loops don't average out mistakes; they multiply the chance of staying on the correct trajectory. The agent that "just needs more turns" is often an agent walking deeper into the wrong branch with more conviction, because each turn conditions on its own earlier errors as if they were facts.&lt;/p&gt;

&lt;p&gt;We wrote earlier about how stuffing the context window can make agents worse, not smarter: attention dilutes, retrieval anchors on the wrong chunk, and signal gets buried. Loop length is the same failure on the time axis. More is not more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a long loop is actually signaling
&lt;/h2&gt;

&lt;p&gt;When an agent needs 30 turns to do something, that's usually not the harness being clever. It's a signal of one of two failures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The task was routed to a model that can't do it.&lt;/strong&gt; The loop is that model thrashing. Scaffolding rarely fixes an underpowered model decision; it usually just makes the failure more elaborate and more expensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The task genuinely has many steps.&lt;/strong&gt; In that case, the engineering problem is not "how do I allow more turns" but "how do I verify each step cheaply so the wrong branch gets caught at turn 3 instead of compounding to turn 30?"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both point the same direction: either allocate the step to a better model, or verify the step before proceeding. Neither says: add turns and hope.&lt;/p&gt;

&lt;h2&gt;
  
  
  What loop engineering should actually be
&lt;/h2&gt;

&lt;p&gt;If loops are where cost and error compound, then good loop engineering should minimize compounding, not maximize capability-per-turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cap the loop hard.&lt;/strong&gt; Every loop needs a turn ceiling and a tool-call ceiling that it cannot exceed, full stop. Not as an emergency fallback — as a first-class design constraint. A loop that &lt;em&gt;can&lt;/em&gt; run forever will, on some input, cost you a fortune to produce garbage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Verify each step cheaply.&lt;/strong&gt; The highest-leverage addition to a loop is usually not another reasoning stage. It's a fast, deterministic check on the step output that catches the failure modes you actually see: truncation, malformed tool calls, empty answers, degeneration loops, repeated echoes. Detection beats prediction because you already have the output in hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Escalate the failing step, not the whole session.&lt;/strong&gt; When a step fails verification, redo &lt;em&gt;that step&lt;/em&gt; on a better tier. Don't grant the entire loop more turns to flail. Escalation is targeted; more-turns is a blank check.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part where this bit us too
&lt;/h2&gt;

&lt;p&gt;We're not exempt. In Lynkr, we shipped a terse mode meant to save output tokens by pushing models toward shorter answers. Our verifier then misread some of those short answers as low-effort failures and escalated trivial requests up a tier into a longer, more expensive path.&lt;/p&gt;

&lt;p&gt;The fix was one predicate. The broader lesson wasn't. &lt;strong&gt;A check inside a loop is itself part of the loop's cost and failure surface.&lt;/strong&gt; "Add verification" is not free virtue; a bad verifier can extend loops as eagerly as a naive retry does. Verification has to be engineered with the same suspicion as any other turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thesis, plainly
&lt;/h2&gt;

&lt;p&gt;A lot of popular loop engineering optimizes capability-per-turn while treating turn count as free. That's backwards. On real traffic, turn count is often the dominant cost and a major source of compounded error.&lt;/p&gt;

&lt;p&gt;If a task needs more intelligence, buy more intelligence for that step. If a task needs more reliability, verify the step. If a loop keeps growing, treat that as a failure signal, not sophistication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make the loop shorter. Make it stop. That's the engineering.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Lynkr is Apache-2.0 and self-hosted. The loop-guard middleware and step-level escalation ideas behind this post are in the repo: &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;github.com/Fast-Editor/Lynkr&lt;/a&gt;. If you've seen a loop run too long and know why, I'd love to hear the war story.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Your LLM Bill Is a Misallocation Problem, Not a Model Problem</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Thu, 30 Jul 2026 06:50:28 +0000</pubDate>
      <link>https://dev.to/lynkr/your-llm-bill-is-a-misallocation-problem-not-a-model-problem-18dg</link>
      <guid>https://dev.to/lynkr/your-llm-bill-is-a-misallocation-problem-not-a-model-problem-18dg</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, an open-source LLM router, so this post argues a thesis my own product embodies. The mitigation: every claim below is either published research, a July 2026 release you can verify, or a measurement you can reproduce — including the part where the obvious approach (and an earlier version of ours) doesn't work.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The dominant inefficiency in LLM serving is no longer kernel speed or quantization. It's &lt;strong&gt;per-request compute misallocation&lt;/strong&gt; — and the research says you can't fix it with prediction. You fix it with verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup: the gap closed, the dispersion didn't
&lt;/h2&gt;

&lt;p&gt;Three things became true more or less simultaneously in mid-2026:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open-weight models sit within single-digit percentage points of frontier models on everyday work.&lt;/strong&gt; GLM-5.2 (744B MoE, 40B active, MIT license) leads several long-horizon coding benchmarks outright. Kimi K3 shipped in July at 2.8T parameters with ~1.8% expert activation and a 1M-token context — open weights, hosted access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The cost of that near-frontier capability is 4–10× lower.&lt;/strong&gt; Hosted GLM-class models run at a fraction of frontier per-token prices; aggressive hosts (Meituan's LongCat 2.0 launched at $0.30/$1.20 per million) keep pushing the floor down.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Price-per-capability dispersion across providers has never been wider.&lt;/strong&gt; The same request can cost $0.10 or $15 per million output tokens depending on where you send it, for a quality difference that on most traffic is inside the noise.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Put those together and the largest line item in a serving budget is no longer "the model is slow" or "the quant is fat." It's &lt;strong&gt;every request routed to a frontier model that a cheaper tier would have cleared.&lt;/strong&gt; That's pure deadweight loss, and at current dispersion it usually dominates everything a kernel engineer can save you.&lt;/p&gt;

&lt;p&gt;I say that as someone who ships kernel PRs: a +13–15% decode win on a CPU inference engine (measured, merged, byte-identical output) saves you 13% &lt;em&gt;on one backend&lt;/em&gt;. Routing 60% of traffic down two price tiers saves ~90% &lt;em&gt;across the fleet&lt;/em&gt;. Same engineering effort. The leverage moved up the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive fix fails: you can't predict difficulty from the prompt
&lt;/h2&gt;

&lt;p&gt;The obvious architecture is ex-ante routing: classify the prompt, pick the model, done. Every "smart routing" product demo shows this.&lt;/p&gt;

&lt;p&gt;It doesn't survive contact with real traffic. &lt;strong&gt;Ex-ante difficulty prediction consistently fails to beat trivial baselines on agentic coding traffic.&lt;/strong&gt; When we ran the deep-research pass for Lynkr's cascade design (July 2025 literature, SWE-Bench-style workloads), the pattern was blunt: prompt surface features don't carry enough signal about downstream difficulty. A one-line ask ("fix the flaky test") can require repo-wide reasoning. A 3,000-token prompt can be boilerplate a 9B model handles. The information you need to route correctly mostly doesn't exist until &lt;em&gt;after&lt;/em&gt; a model has attempted the task.&lt;/p&gt;

&lt;p&gt;If your router's accuracy story is a difficulty classifier — however fancy the embeddings — you've built a system that's confidently wrong in both directions: burning frontier tokens on easy requests and serving garbage on hard ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  What works: try cheap, verify, escalate
&lt;/h2&gt;

&lt;p&gt;The architecture that actually gains is the &lt;strong&gt;cascade&lt;/strong&gt;: route to the cheapest plausible tier, run &lt;em&gt;deterministic verification&lt;/em&gt; on the answer, escalate only on failure. Published cascade results show up to &lt;strong&gt;+14% over static assignment&lt;/strong&gt; — and the gain lives in the verifier, because the cascade converts routing from a prediction problem (hard, information-starved) into a &lt;strong&gt;detection problem&lt;/strong&gt; (tractable, information-rich: you have the actual answer in hand).&lt;/p&gt;

&lt;p&gt;The verifier doesn't need to be an LLM judge. Ours is two layers of pure functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structural checks&lt;/strong&gt; targeting the cheap-model failure modes we actually observed live: language drift (CJK tokens appearing mid-English answer), degeneration loops, truncation, malformed tool calls, empty/echo responses. High precision — flag only what is definitely broken.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A coarse effort score&lt;/strong&gt;: substantive ask answered with a stub, structure requested but not delivered, code requested but not delivered. Conservative threshold; only clear failures escalate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No LLM call in the loop. The verification cost is microseconds, which matters because a router that spends tokens deciding where to send tokens is eating the margin it exists to create.&lt;/p&gt;

&lt;h3&gt;
  
  
  A war story about verifiers
&lt;/h3&gt;

&lt;p&gt;One production bug worth sharing because it generalizes: we shipped a brevity mode that injects "answer tersely" into system prompts to cut output tokens. The verifier's effort-scorer then read the resulting short answers as &lt;em&gt;low-effort&lt;/em&gt; and started cascading trivial greetings up to the frontier tier — burning the exact money the brevity mode saved, and then some.&lt;/p&gt;

&lt;p&gt;The fix was one predicate (skip the effort check when the brevity instruction is present; keep the structural checks), but the lesson is bigger: &lt;strong&gt;a verifier must know what the model was asked to be.&lt;/strong&gt; Any answer-quality check that ignores the instructions that produced the answer will misfire exactly when your prompt engineering works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second-order effect: verification failures are free training data
&lt;/h2&gt;

&lt;p&gt;Here's where cascades stop being a cost trick and become a learning system.&lt;/p&gt;

&lt;p&gt;Every verification failure is a &lt;strong&gt;labeled hard negative&lt;/strong&gt;: "this request, routed to this tier, produced a detectably bad answer." Every escalation that then passes is a label: "requests like this outgrow the cheap tier." Feed those back into the routing decision — we treat it as a contextual bandit with verifier-generated rewards, logging propensities at decision time so the feedback isn't biased by the router's own choices — and the router learns the difficulty structure of &lt;em&gt;your&lt;/em&gt; traffic, from &lt;em&gt;your&lt;/em&gt; outcomes.&lt;/p&gt;

&lt;p&gt;No benchmark in the loop. That mattered more than usual this month: &lt;strong&gt;one of the field's most-cited coding benchmarks was retracted as broken.&lt;/strong&gt; Every router configured against it inherited the error silently, for months, with nothing in the loop that could detect it. Ground truth from your own traffic doesn't get retracted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Receipts
&lt;/h2&gt;

&lt;p&gt;This is the architecture behind Lynkr (Apache-2.0, self-hosted): deterministic embedding-anchor tier classification (zero LLM calls to route), structural verification on cheap-tier answers only (never second-guess the expensive tier — the loss is asymmetric), cascade escalation, reward pipeline with propensity logging.&lt;/p&gt;

&lt;p&gt;On &lt;a href="https://arxiv.org/abs/2510.00202" rel="noopener noreferrer"&gt;RouterArena&lt;/a&gt; (ICLR 2026, 8,400 queries, evaluation-only rules — no component tuned on their data), our submitted configuration measured &lt;strong&gt;67.65 arena score / 68.41% accuracy at $0.29 per 1K queries, robustness 92.38&lt;/strong&gt; — above GPT-5's built-in router and NotDiamond at a fraction of the per-decision cost. The &lt;a href="https://github.com/RouteWorks/RouterArena/pull/167" rel="noopener noreferrer"&gt;submission PR&lt;/a&gt; has the full config, prediction files, and the disclosures, including the metrics where we're mediocre (routing concentration is real; read the PR).&lt;/p&gt;

&lt;h2&gt;
  
  
  The thesis, restated
&lt;/h2&gt;

&lt;p&gt;For a decade the way to cut inference cost was to make the model cheaper: quantize, distill, fuse kernels. That work still matters — I still do it — but it's optimizing the &lt;em&gt;price of a decision that's already been made&lt;/em&gt;. In a world where capability is a commodity spectrum with 50× price dispersion and single-digit quality spread, the decision itself is where the money is.&lt;/p&gt;

&lt;p&gt;The gap between open and frontier closed. &lt;strong&gt;Allocation is the frontier now.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Lynkr is Apache-2.0 and self-hosted: &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;github.com/Fast-Editor/Lynkr&lt;/a&gt; · &lt;a href="https://www.npmjs.com/package/lynkr" rel="noopener noreferrer"&gt;npm&lt;/a&gt;. If you route production LLM traffic and have cascade/verification war stories, I want to hear them — the failure modes section of our verifier is built from exactly those.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>machinelearning</category>
      <category>devtools</category>
    </item>
    <item>
      <title>We Put Our Router on an Academic Benchmark. Here Are the Numbers We'd Rather Hide.</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Mon, 27 Jul 2026 07:36:49 +0000</pubDate>
      <link>https://dev.to/lynkr/we-put-our-router-on-an-academic-benchmark-here-are-the-numbers-wed-rather-hide-1c83</link>
      <guid>https://dev.to/lynkr/we-put-our-router-on-an-academic-benchmark-here-are-the-numbers-wed-rather-hide-1c83</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, the router being benchmarked, so read everything here with that in mind. The mitigation: every number in this post comes from &lt;a href="https://arxiv.org/abs/2510.00202" rel="noopener noreferrer"&gt;RouterArena&lt;/a&gt;'s automated evaluation pipeline, run by their CI on their infrastructure, not by me — including the numbers that make us look mediocre.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every LLM router's README — ours included — makes the same claim: it sends easy queries to cheap models and hard queries to good ones, and saves you money without hurting quality. Almost none of them attach evidence. The numbers that do exist are self-reported, measured on datasets the vendor picked, with baselines the vendor chose.&lt;/p&gt;

&lt;p&gt;So when RouterArena showed up — an open, standardized benchmark for LLM routers out of the RouteWorks group (&lt;a href="https://arxiv.org/abs/2510.00202" rel="noopener noreferrer"&gt;paper&lt;/a&gt;, &lt;a href="https://routeworks.github.io/" rel="noopener noreferrer"&gt;leaderboard&lt;/a&gt;) — we submitted Lynkr to it. This post is what we learned, including the metrics where we did badly, because a benchmark result you only quote selectively is just marketing with extra steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What RouterArena actually measures
&lt;/h2&gt;

&lt;p&gt;RouterArena evaluates a router over &lt;strong&gt;8,400 queries spanning 9 domains and 44 categories&lt;/strong&gt; at three difficulty levels, and scores it on five axes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arena Score&lt;/strong&gt; — the headline number, a combined accuracy-vs-cost tradeoff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accuracy&lt;/strong&gt; — did the model your router picked answer correctly?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt; — average $ per 1K queries, at real provider prices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimality&lt;/strong&gt; — three sub-metrics against the oracle: how often you picked the &lt;em&gt;cheapest correct&lt;/em&gt; model (Opt.Sel), how close your spend was to optimal (Opt.Cost), and how close your accuracy was to the best achievable with your pool (Opt.Acc).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robustness&lt;/strong&gt; — do trivial rephrasings of the same query flip your routing decision?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One rule matters more than the metrics: &lt;strong&gt;RouterArena is evaluation-only.&lt;/strong&gt; Any router component trained, fitted, or tuned on their data or labels gets rejected, and violations found later get withdrawn. Keep that rule in mind — it comes back at the end of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we submitted
&lt;/h2&gt;

&lt;p&gt;We submitted Lynkr's &lt;strong&gt;untuned production default&lt;/strong&gt; — the same complexity scorer and the same tier boundaries that ship in the repo. The adapter is &lt;a href="https://github.com/RouteWorks/RouterArena/pull/167" rel="noopener noreferrer"&gt;~70 lines of Python&lt;/a&gt; that sends each query to a live Lynkr instance's &lt;code&gt;/routing/analyze&lt;/code&gt; endpoint and maps the returned tier to a model. No benchmark-special code path: the endpoint runs the exact intent scorer the live proxy uses (local embeddings, no LLM call in the routing decision itself).&lt;/p&gt;

&lt;p&gt;The model pool, all via OpenRouter:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lynkr tier&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SIMPLE&lt;/td&gt;
&lt;td&gt;gpt-oss-120b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MEDIUM&lt;/td&gt;
&lt;td&gt;Qwen3-235B-A22B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;COMPLEX / REASONING&lt;/td&gt;
&lt;td&gt;GLM-4.7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Running all 8,400 queries cost &lt;strong&gt;$2.46 total&lt;/strong&gt;. That's the entire eval bill, which says something on its own about where inference prices are in mid-2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;From RouterArena's automated evaluation on our submission PR:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Lynkr&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arena Score&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;67.65&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accuracy&lt;/td&gt;
&lt;td&gt;68.41%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost per 1K queries&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.29&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Robustness&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;92.38&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opt.Acc (accuracy vs. optimal)&lt;/td&gt;
&lt;td&gt;84.48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opt.Cost (cost efficiency vs. optimal)&lt;/td&gt;
&lt;td&gt;16.08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opt.Sel (optimal model selection)&lt;/td&gt;
&lt;td&gt;10.97&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On the official leaderboard (our submission &lt;a href="https://github.com/RouteWorks/RouterArena/pull/167" rel="noopener noreferrer"&gt;merged 2026-07-23&lt;/a&gt;), that lands mid-table — &lt;strong&gt;15th of 27 routers&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts we'll be quoting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;We beat GPT-5 used as a router — at 34× lower cost.&lt;/strong&gt; The leaderboard includes GPT-5 itself as a routing baseline: Arena score 64.32 at &lt;strong&gt;$10.02 per 1K queries&lt;/strong&gt;. Lynkr scores 67.65 at &lt;strong&gt;$0.29 per 1K&lt;/strong&gt;. A local intent scorer making the decision without any LLM call outperforms asking a frontier model to route — which is the entire thesis Lynkr is built on, so we're relieved the benchmark agrees. Several well-known systems (NotDiamond at 57.29, RouteLLM at 48.07, both RouterBench baselines) also land below us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Robustness 92.38 is top-five territory.&lt;/strong&gt; Most leaderboard routers sit between 22 and 72 — meaning a rephrased query frequently flips their model choice. Lynkr's routing decision survives rephrasing 92% of the time. For an interactive tool where users iterate on prompts, decision stability is arguably worth more than a couple of accuracy points: a router that sends your reworded follow-up to a different model mid-conversation is a router you turn off.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts we'd rather hide (but won't)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Opt.Sel is 10.97.&lt;/strong&gt; When multiple models in our pool could answer a query correctly, we picked the &lt;em&gt;cheapest&lt;/em&gt; correct one about 11% of the time. Lynkr routes conservatively — when in doubt, it escalates a tier. That's a deliberate live-serving bias (a wrong cheap answer costs more user trust than an unnecessarily good one costs dollars), and $0.29/1K shows the absolute spend stays low. But the oracle comparison is unambiguous: there was money on the table we didn't pick up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The accuracy gap to the top is real.&lt;/strong&gt; Cross-Router leads at 78.14% accuracy; we're at 68.41%. Part of that is the pool (three self-hostable open-weight models — no frontier closed models to escalate to), but part is genuinely the router. Mid-table is where we are, not where we'd spin it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the benchmark taught us — and why we won't act on all of it
&lt;/h2&gt;

&lt;p&gt;Reading our failure cases was the most valuable part of the exercise. The clearest pattern: our SIMPLE→MEDIUM boundary is conservative — a chunk of queries scored just past the boundary and got a mid-tier model when the cheap tier would have answered correctly.&lt;/p&gt;

&lt;p&gt;So we prototyped a shifted boundary and ran it on a ~10% subsample locally: Arena score 69.93, accuracy 71.07%, Opt.Sel jumping from ~11 to ~66. A two-point arena gain from moving one threshold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That config will never appear on the leaderboard.&lt;/strong&gt; It was diagnosed from RouterArena's own failure cases, which makes it exactly what their evaluation-only rule exists to prevent — a router fitted to the eval. The leaderboard entry is the untuned default, and stays that way. The honest generalization claim is much narrower: the benchmark showed us &lt;em&gt;which knob&lt;/em&gt; matters, and we'll validate new defaults on our own traffic, not on theirs.&lt;/p&gt;

&lt;p&gt;If you maintain a router: this is the trap. The moment a public benchmark exists, the incentive is to tune against it, and every point you gain that way is a point of overfitting you ship to your actual users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats, so you can weigh this properly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RouterArena is single-turn Q&amp;amp;A-style evaluation. Lynkr's primary workload is multi-turn coding agents, which RouterArena doesn't measure — agentic routing (tool-call density, context accumulation) is a different problem than classifying one prompt.&lt;/li&gt;
&lt;li&gt;Our score depends on our chosen pool. A pool with a frontier model on top would score differently in both directions (higher ceiling, higher cost).&lt;/li&gt;
&lt;li&gt;Leaderboard positions move; check the &lt;a href="https://routeworks.github.io/" rel="noopener noreferrer"&gt;live leaderboard&lt;/a&gt; rather than trusting this snapshot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're evaluating routers — including ours — ask every vendor for their RouterArena number. It costs a few dollars and a PR to get one. "We haven't submitted" is also an answer.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://arxiv.org/abs/2510.00202" rel="noopener noreferrer"&gt;RouterArena paper (arXiv:2510.00202)&lt;/a&gt; · &lt;a href="https://routeworks.github.io/" rel="noopener noreferrer"&gt;leaderboard&lt;/a&gt; · &lt;a href="https://github.com/RouteWorks/RouterArena/pull/167" rel="noopener noreferrer"&gt;our submission PR&lt;/a&gt; · &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>benchmarking</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Stuffing the Context Window Is Making Your Agent Dumber: What the Research Says</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Fri, 17 Jul 2026 01:10:15 +0000</pubDate>
      <link>https://dev.to/lynkr/stuffing-the-context-window-is-making-your-agent-dumber-what-the-research-says-2063</link>
      <guid>https://dev.to/lynkr/stuffing-the-context-window-is-making-your-agent-dumber-what-the-research-says-2063</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, an open-source gateway that (among other things) compresses agent tool outputs — so I have a horse in this race. This piece, though, is about the research, and every number in it is cited to its primary source.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's an intuition almost every LLM user shares: more context = better answers. Million-token context windows are marketed as a capability. We paste in whole files "just in case." Our coding agents accumulate every grep result, every file read, every test log, on the theory that the model might need it.&lt;/p&gt;

&lt;p&gt;The research says this intuition is not just wrong — it's &lt;em&gt;backwards&lt;/em&gt;, and the size of the effect is embarrassing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result that should change how you build
&lt;/h2&gt;

&lt;p&gt;The cleanest demonstration comes from the Hindsight memory system (&lt;a href="https://arxiv.org/abs/2512.12818" rel="noopener noreferrer"&gt;arXiv:2512.12818&lt;/a&gt;, demo at ACL 2026). On LongMemEval — a benchmark of questions over long conversational histories — the same open-source 20B model scores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;39.0%&lt;/strong&gt; when handed the &lt;em&gt;full context&lt;/em&gt; — everything, the whole history&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;83.6%&lt;/strong&gt; when handed a &lt;em&gt;curated slice&lt;/em&gt; selected by a structured memory system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same model. Same available information. The difference is that one setup made the model read everything, and the other selected what mattered. &lt;strong&gt;+44.6 points from subtraction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It gets more uncomfortable: that 20B model with curated context also &lt;strong&gt;beats full-context GPT-4o&lt;/strong&gt;, which scores 60.2% on the same benchmark. A model a fraction of the size, winning because someone cleaned its desk. As the authors put it, the memory architecture — not model scale — drives the performance.&lt;/p&gt;

&lt;p&gt;One benchmark, one paper? No — this is a pile-on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Lost in the middle"&lt;/strong&gt; (Liu et al., 2023) established the shape of the problem early: models attend well to the start and end of long contexts and poorly to the middle — exactly where your agent's fifteenth tool result lives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context-rot studies&lt;/strong&gt; (notably Chroma's 2025 report) showed performance degrading as context grows &lt;em&gt;even when the added tokens are relevant&lt;/em&gt;, and degrading faster when they're distractors.&lt;/li&gt;
&lt;li&gt;A whole 2026 research wave now treats context as a resource to be &lt;strong&gt;managed, not maximized&lt;/strong&gt;: "Agentic Context Engineering" was accepted at ICLR 2026, active context compression systems prune their own working memory (&lt;a href="https://arxiv.org/abs/2601.07190" rel="noopener noreferrer"&gt;arXiv:2601.07190&lt;/a&gt;), and two consolidating surveys (&lt;a href="https://arxiv.org/abs/2512.13564" rel="noopener noreferrer"&gt;arXiv:2512.13564&lt;/a&gt;, &lt;a href="https://arxiv.org/abs/2603.07670" rel="noopener noreferrer"&gt;arXiv:2603.07670&lt;/a&gt;) formalize memory as a write–&lt;em&gt;manage&lt;/em&gt;–read loop — with "manage" doing the heavy lifting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The marketing said "bigger window." The research says "better librarian."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why more context makes things worse
&lt;/h2&gt;

&lt;p&gt;Three mechanisms, all well-documented:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Attention is a budget, not a spotlight.&lt;/strong&gt; Every token in context competes for attention mass. Pack in 50k tokens of tool output and the three lines that matter are now competing with 49,900 tokens of noise. Needle-in-a-haystack benchmarks — the ones vendors publish — test &lt;em&gt;retrieval&lt;/em&gt; of a planted string, which models are good at. Real tasks require &lt;em&gt;reasoning over&lt;/em&gt; the context, which degrades much faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Distractors don't just dilute — they actively mislead.&lt;/strong&gt; The context-rot findings show semantically-similar-but-irrelevant content is worse than random filler. Your agent's context is &lt;em&gt;full&lt;/em&gt; of this: old versions of the file it's editing, error messages from an already-fixed bug, grep hits from a deprecated module. Each is a plausible-looking wrong answer sitting one attention head away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Position effects compound over turns.&lt;/strong&gt; Agents append. Every turn pushes the important early material (the task! the constraints!) toward the middle of the context — the attention dead zone — while burying the recent signal under boilerplate tool output. A long agent session is a machine for constructing worst-case attention layouts.&lt;/p&gt;

&lt;p&gt;Coding agents are the pathological case of all three at once: they generate enormous, distractor-dense, structurally-repetitive context (JSON tool results, file dumps, test logs) at machine speed, across dozens of turns.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the research says works instead
&lt;/h2&gt;

&lt;p&gt;The successful systems in the literature share a shape — they spend compute &lt;em&gt;deciding what the model sees&lt;/em&gt; instead of showing it everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Selection over inclusion.&lt;/strong&gt; Hindsight's four memory networks (facts vs. experiences vs. summaries vs. beliefs) exist so retrieval pulls the &lt;em&gt;right kind&lt;/em&gt; of memory for each question. The general lesson: retrieval into a small context beats residence in a big one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression as a first-class operation.&lt;/strong&gt; Active-context-compression agents treat "shrink my working set" as an action the agent itself takes, on par with tool calls. Summarize the resolved, drop the superseded, keep the live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure beats soup.&lt;/strong&gt; Tabular, labeled, deduplicated context consistently outperforms raw dumps of the same information — the model spends attention on content, not parsing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What you can do about it today
&lt;/h2&gt;

&lt;p&gt;You don't need a research memory system to benefit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Treat context as a liability with interest, not an asset.&lt;/strong&gt; Every tool result you leave in the window is re-read (and re-billed) every subsequent turn, while making each turn slightly dumber.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compact aggressively and early.&lt;/strong&gt; Whatever your agent's compaction/clear mechanism is (&lt;code&gt;/compact&lt;/code&gt;, &lt;code&gt;/clear&lt;/code&gt;, fresh sessions per task), use it &lt;em&gt;before&lt;/em&gt; quality degrades — by the time you notice the agent going in circles, the context has been hurting you for many turns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope sessions to tasks.&lt;/strong&gt; One task, one session. The 40-turn omnibus session is the exact scenario the position-effect research warns about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolate research from execution.&lt;/strong&gt; Subagents (or separate sessions) that read a lot and report a little are context firewalls: the summary crosses over; the 30k tokens of grep output don't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compress tool outputs before they enter context.&lt;/strong&gt; Test logs, JSON blobs, and directory listings compress 40–90% with zero information the model actually needs lost. Whether you do it with a proxy layer (this is the part where I mention that's what &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt; does), a harness setting, or a wrapper script — do it somewhere.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The next time a model launch leads with context-window size, remember the 20B model with a good librarian beating GPT-4o with a hoard. Capacity isn't capability. Curation is.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Primary sources:&lt;/strong&gt; &lt;a href="https://arxiv.org/abs/2512.12818" rel="noopener noreferrer"&gt;Hindsight (arXiv:2512.12818)&lt;/a&gt; · &lt;a href="https://github.com/vectorize-io/hindsight-benchmarks" rel="noopener noreferrer"&gt;benchmark data&lt;/a&gt; · &lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Lost in the Middle (Liu et al.)&lt;/a&gt; · &lt;a href="https://arxiv.org/abs/2601.07190" rel="noopener noreferrer"&gt;Active Context Compression (arXiv:2601.07190)&lt;/a&gt; · &lt;a href="https://arxiv.org/abs/2512.13564" rel="noopener noreferrer"&gt;Memory in the Age of AI Agents — survey (arXiv:2512.13564)&lt;/a&gt; · &lt;a href="https://arxiv.org/abs/2603.07670" rel="noopener noreferrer"&gt;Memory for Autonomous LLM Agents — survey (arXiv:2603.07670)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>machinelearning</category>
      <category>devtools</category>
    </item>
    <item>
      <title>How We Built an Agentic-Task Detector for LLM Routing</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Tue, 14 Jul 2026 04:18:47 +0000</pubDate>
      <link>https://dev.to/lynkr/how-we-built-an-agentic-task-detector-for-llm-routing-4eb4</link>
      <guid>https://dev.to/lynkr/how-we-built-an-agentic-task-detector-for-llm-routing-4eb4</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, the open-source LLM router whose agentic detector this post dissects. Every snippet below is real, shipping code — &lt;a href="https://github.com/Fast-Editor/Lynkr/blob/main/src/routing/agentic-detector.js" rel="noopener noreferrer"&gt;read the whole file here&lt;/a&gt;, it's 350 lines.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;"Fix the auth bug in session.js."&lt;/p&gt;

&lt;p&gt;Eight words. Every token-count heuristic on earth routes this to the small, cheap model — it's &lt;em&gt;short&lt;/em&gt;. And every one of them is wrong, because those eight words are about to unleash a grep → read → edit → test loop with exact-string file edits, the precise workload where small models fumble tool calls and kill sessions.&lt;/p&gt;

&lt;p&gt;The inverse request — three paragraphs asking for a detailed comparison of locking strategies — &lt;em&gt;looks&lt;/em&gt; expensive and routes safely to a free local model, because it's pure text generation. Size and stakes are nearly uncorrelated in coding-agent traffic. So the router's real job is detecting &lt;strong&gt;agentic intent&lt;/strong&gt;, and this post is a tour of how Lynkr's detector does it: the signals, the weights, the classification ladder — and the embarrassing false positive that almost made the whole thing useless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not "agentic: yes/no" — a ladder
&lt;/h2&gt;

&lt;p&gt;The first design decision: agentic-ness isn't boolean. The detector classifies requests into four types, each with a minimum tier floor and a score boost fed into the &lt;a href="https://dev.to/lynkr/how-a-13-dimension-complexity-scorer-decides-which-model-gets-your-request-e95"&gt;complexity scorer&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AGENT_TYPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;SINGLE_SHOT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;minTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIMPLE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;scoreBoost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;// request-response, no tools&lt;/span&gt;
  &lt;span class="na"&gt;TOOL_CHAIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;minTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MEDIUM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;scoreBoost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// read -&amp;gt; edit -&amp;gt; test&lt;/span&gt;
  &lt;span class="na"&gt;ITERATIVE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;minTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMPLEX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="na"&gt;scoreBoost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// retry loops, debugging cycles&lt;/span&gt;
  &lt;span class="na"&gt;AUTONOMOUS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;minTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;REASONING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;scoreBoost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// "figure it out", full autonomy&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;minTier&lt;/code&gt; is a floor, not a suggestion: even if every other dimension scores low, an ITERATIVE request cannot route below the COMPLEX tier. Mid-debugging-loop is the worst possible moment to hand the session to a 7B model.&lt;/p&gt;

&lt;h2&gt;
  
  
  The six signals
&lt;/h2&gt;

&lt;p&gt;Each request accumulates a score from six independent signals. The interesting part is &lt;em&gt;why&lt;/em&gt; each one exists:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tool count&lt;/strong&gt; (up to +25). Many tools attached usually means the client is prepared for multi-step work. &lt;em&gt;Usually.&lt;/em&gt; This signal is also the source of the great false positive — hold that thought.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Agentic tools specifically&lt;/strong&gt; (up to +25). Not all tools are equal evidence. &lt;code&gt;Bash&lt;/code&gt;, &lt;code&gt;Write&lt;/code&gt;, &lt;code&gt;Edit&lt;/code&gt;, &lt;code&gt;Task&lt;/code&gt;, git and test runners form an explicit set — these mutate state, and their presence signals mutation work. A request that can only &lt;code&gt;Read&lt;/code&gt;/&lt;code&gt;Grep&lt;/code&gt;/&lt;code&gt;WebSearch&lt;/code&gt; sits in a separate read-only set and earns nothing here. Two requests with five tools each can be night and day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Prior tool results&lt;/strong&gt; (up to +30 — the heaviest signal). If the conversation already contains &lt;code&gt;tool_result&lt;/code&gt; blocks, you're not predicting an agentic loop — you're &lt;em&gt;inside&lt;/em&gt; one. More than five results means a deep loop with accumulated exact state (file contents, error strings); downgrading the model now throws away the context discipline keeping that loop convergent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Language patterns&lt;/strong&gt; (up to +25 each). Regexes over the last user message:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;tool-chain&lt;/em&gt;: "then use", "after that", "step 2"&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;iterative&lt;/em&gt;: "keep trying", "until", "retry", "debug"&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;autonomous&lt;/em&gt;: "figure out", "make it work", "on your own", "whatever it takes"&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;multi-file&lt;/em&gt;: "across the codebase", "refactor entire", "everywhere"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus a combination rule: "implement" alone is +10-ish planning noise, but "implement" &lt;em&gt;and&lt;/em&gt; "test/verify/make sure" in the same request is +15 — build-and-verify phrasing is a reliable tell of real work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Conversation depth&lt;/strong&gt; (up to +20). Fifteen-plus messages means established context and momentum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Prompt length&lt;/strong&gt; (+10). The weakest signal, deliberately — see the opening paragraph.&lt;/p&gt;

&lt;p&gt;Score ≥ 25 → the request is agentic. The classification ladder then applies both thresholds &lt;em&gt;and&lt;/em&gt; signal combinations — AUTONOMOUS needs score ≥ 60, or an explicit autonomous phrase with score ≥ 40. A phrase alone doesn't do it; a high score without autonomous language doesn't either, unless it's overwhelming.&lt;/p&gt;

&lt;h2&gt;
  
  
  The false positive that almost sank it
&lt;/h2&gt;

&lt;p&gt;Early versions had a humiliating problem: &lt;strong&gt;every single Claude Code request scored agentic.&lt;/strong&gt; Including "hello."&lt;/p&gt;

&lt;p&gt;Why? Claude Code attaches its full tool loadout — Read, Write, Edit, Bash, Grep, Glob, Task, and friends — to &lt;em&gt;every&lt;/em&gt; request, even a greeting. Signals 1 and 2 saw 11+ tools, four of them mutating, on everything. Every request cleared the threshold, every request routed to expensive tiers, and the router's entire value proposition — savings — evaporated. The detector was technically working and practically useless.&lt;/p&gt;

&lt;p&gt;The fix ships as &lt;strong&gt;client profiles&lt;/strong&gt;: known harnesses (Claude Code, Cursor, Codex CLI) have documented baseline loadouts, and the tool-count signals score only the tools &lt;em&gt;beyond&lt;/em&gt; that baseline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Signals 1 &amp;amp; 2 score only tools BEYOND the harness's baseline loadout —&lt;/span&gt;
&lt;span class="c1"&gt;// Claude Code's 11 always-attached tools shouldn't count as "agentic&lt;/span&gt;
&lt;span class="c1"&gt;// intent" on their own.&lt;/span&gt;
&lt;span class="nx"&gt;toolsForScoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clientProfiles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;effectiveTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crucially, signals 3–6 still use the full payload — prior tool results and conversational language are &lt;em&gt;genuine&lt;/em&gt; evidence regardless of which harness sent them. Only the tool-presence signals get the subtraction, because only they are polluted by the harness's constant.&lt;/p&gt;

&lt;p&gt;And for traffic from harnesses we've never seen? A guard: if &lt;em&gt;every&lt;/em&gt; attached tool looks like a standard baseline and there are 10+ of them, the tool-count signals zero out rather than fire:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientProfiles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allToolsAreBaseline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;rawTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Unknown harness that looks like Claude Code / Cursor / Codex —&lt;/span&gt;
  &lt;span class="c1"&gt;// zero out the tool-count signals to avoid the same trap.&lt;/span&gt;
  &lt;span class="nx"&gt;toolsForScoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;scoringNote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unknown_harness_guard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better to under-detect and lean on the five uncorrupted signals than to re-create the everything-is-agentic bug for unknown clients.&lt;/p&gt;

&lt;p&gt;One subtle consequence, preserved as a comment in the source: with the baseline subtracted, tool counts rarely reach the AUTONOMOUS threshold on their own — so the &lt;em&gt;autonomous phrase pattern&lt;/em&gt; becomes the primary path to the top classification. The signal design acknowledges its own post-fix physics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it still gets wrong
&lt;/h2&gt;

&lt;p&gt;Honesty section. Known limitations, from the code itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It reads only the last user message.&lt;/strong&gt; "Do what I described above" carries the intent of an earlier message the regexes never see. Conversation-depth and tool-result signals partially compensate — but pattern detection is myopic by design (scanning full history was too noisy).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regexes can't tell mention from intent.&lt;/strong&gt; "Why did the retry loop break?" trips the iterative pattern despite being a read-only question. In practice this fails &lt;em&gt;safe&lt;/em&gt; — over-routing a question up-tier costs cents, under-routing an edit session down-tier costs the session — but it's still a false positive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;English only.&lt;/strong&gt; The patterns are English regexes; agentic intent in other languages leans entirely on the structural signals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every detection returns its full evidence — score, signal list with weights, classification, and a &lt;code&gt;scoringNote&lt;/code&gt; explaining any baseline subtraction — so when the router misjudges, the telemetry shows exactly which signal lied. Debuggability was a design requirement: a routing layer you can't interrogate is a routing layer you'll eventually rip out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways if you're building anything similar
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Subtract the constant before reading the signal.&lt;/strong&gt; Whatever your equivalent of "the harness always attaches 11 tools" is — find it and remove it, or every request looks the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate "prepared for tools" from "already using tools."&lt;/strong&gt; Attached tools are weak evidence; &lt;code&gt;tool_result&lt;/code&gt; blocks in the conversation are near-proof.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail toward the expensive model.&lt;/strong&gt; Asymmetric costs mean your threshold should be calibrated so mistakes over-spend pennies rather than break sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the detector explain itself.&lt;/strong&gt; A score without a signal list is a black box you'll never be able to tune.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole detector is 350 lines of dependency-free JavaScript: &lt;a href="https://github.com/Fast-Editor/Lynkr/blob/main/src/routing/agentic-detector.js" rel="noopener noreferrer"&gt;src/routing/agentic-detector.js&lt;/a&gt;. Steal it, or tell me which of your prompts it would misjudge — the failure cases are the roadmap.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>node</category>
    </item>
    <item>
      <title>Choosing a Local Tier for Your Coding Agent (July 2026 Edition)</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Wed, 08 Jul 2026 00:14:16 +0000</pubDate>
      <link>https://dev.to/lynkr/choosing-a-local-tier-for-your-coding-agent-july-2026-edition-2196</link>
      <guid>https://dev.to/lynkr/choosing-a-local-tier-for-your-coding-agent-july-2026-edition-2196</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, the open-source router used in the config examples. The benchmark figures below are third-party or vendor-reported (flagged where vendor-only) — I haven't independently benchmarked these models yet; the point of this post is to help you match models to request classes and test on your own workload.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;June 2026 was the busiest month for open-weight coding models in recent memory: GLM-5.2, MiniMax M3, Kimi K2.7 Code, Gemma 4, and NVIDIA's Nemotron 3 Ultra all landed within weeks. If you route your coding agent's simple requests to a local model — the "cloud architect, local coder" pattern — your options just changed meaningfully.&lt;/p&gt;

&lt;p&gt;Here's how I'd map the current field onto routing tiers, by hardware budget and by what each model can &lt;em&gt;safely&lt;/em&gt; own.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the trap: "best open model" ≠ "your local tier"
&lt;/h2&gt;

&lt;p&gt;The headline model of the month, &lt;a href="https://techsy.io/en/blog/best-open-source-llms-2026" rel="noopener noreferrer"&gt;GLM-5.2&lt;/a&gt;, scores 62.1% on SWE-bench Pro — above GPT-5.5. It is also a 744B-parameter MoE whose 2-bit quant alone wants ~245 GB of memory. That's an open-&lt;em&gt;weight&lt;/em&gt; model, not a local model; for self-hosters it's a $40k-rig proposition (&lt;a href="https://aiweekly.co/node/5306" rel="noopener noreferrer"&gt;one published build&lt;/a&gt; runs it on four RTX PRO 6000s). The same goes for DeepSeek-V4 Pro and MiniMax M3: superb models you'll realistically consume via API, where they belong in your COMPLEX/REASONING tiers, not your local one.&lt;/p&gt;

&lt;p&gt;Your local tier is decided by a harsher question: &lt;strong&gt;what fits in your VRAM and still makes reliable tool calls?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The local field, by hardware budget
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;~16 GB RAM (ordinary laptop): Gemma 4 12B.&lt;/strong&gt; Released June 3 as a dense 12B that genuinely fits consumer RAM (&lt;a href="https://www.sitepoint.com/local-llms-are-getting-easier-the-complete-guide-2026/" rel="noopener noreferrer"&gt;SitePoint's guide&lt;/a&gt;). Apache-2.0-class licensing with no usage clauses. This is a SIMPLE-tier model: explanations, one-liners, commit messages, "what does this error mean." I would not hand it an Edit tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;24 GB GPU (RTX 3090/4090 class): Qwen3.6-27B — still the default answer.&lt;/strong&gt; The community's consensus "local Claude" since April: within a few points of frontier models on SWE-bench Verified (77.2 reported vs Claude's 80.9 — &lt;a href="https://codersera.com/blog/qwen-3-6-as-local-claude-code-replacement-2026/" rel="noopener noreferrer"&gt;analysis&lt;/a&gt;), Apache-2.0, runs quantized on a single 24 GB card or a ~$2k build. Its known weakness is exactly the one that matters for agents: tool-call reliability drifts in long contexts — fine as a &lt;em&gt;supervised&lt;/em&gt; MEDIUM tier, risky as an unsupervised COMPLEX one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic multi-file edits on similar hardware: Devstral Small 2.&lt;/strong&gt; Purpose-built for multi-file, tool-driven coding rather than chat (&lt;a href="https://www.kdnuggets.com/top-7-coding-models-you-can-run-locally-in-2026" rel="noopener noreferrer"&gt;KDnuggets roundup&lt;/a&gt;). If your traffic is edit-heavy, it can arguably take MEDIUM-tier mutation requests that I'd keep away from general chat models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Autocomplete-shaped work: Codestral 22B&lt;/strong&gt; is fast and good at it — but mind the non-commercial license before using it for work.&lt;/p&gt;

&lt;p&gt;One rule that keeps proving out (&lt;a href="https://pinggy.io/blog/best_open_source_self_hosted_llms_for_coding/" rel="noopener noreferrer"&gt;Pinggy's guide&lt;/a&gt;): &lt;strong&gt;within the same memory budget, a bigger model at Q4 usually beats a smaller one at Q8.&lt;/strong&gt; Quantization choice matters nearly as much as model family.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping to tiers
&lt;/h2&gt;

&lt;p&gt;Putting that together into a routing config (Lynkr shown; the mapping logic applies to any router):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 24 GB GPU + API keys for the hard stuff&lt;/span&gt;
&lt;span class="nv"&gt;TIER_SIMPLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ollama:gemma4:12b            &lt;span class="c"&gt;# trivia, explanations, greetings&lt;/span&gt;
&lt;span class="nv"&gt;TIER_MEDIUM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ollama:qwen3.6:27b           &lt;span class="c"&gt;# code questions, supervised edits&lt;/span&gt;
&lt;span class="nv"&gt;TIER_COMPLEX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek:deepseek-v4-flash  &lt;span class="c"&gt;# tool-heavy mutations, via API&lt;/span&gt;
&lt;span class="nv"&gt;TIER_REASONING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek:deepseek-v4      &lt;span class="c"&gt;# architecture, multi-step planning&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why V4 Flash for COMPLEX: it's the first open-weight model teams report dropping into real agentic pipelines as a frontier substitute &lt;em&gt;on price&lt;/em&gt; (&lt;a href="https://openrouter.ai/blog/insights/the-open-weight-models-that-matter-june-2026/" rel="noopener noreferrer"&gt;OpenRouter's June analysis&lt;/a&gt;) — the cheapest "won't break the session" option right now. Kimi K2.7 Code (vendor-reported 58.6% SWE-bench Pro at ~30% fewer reasoning tokens) and GLM-5.2 are strong API-tier alternatives; all the June day-one numbers are vendor-reported, so treat them as directional until LiveBench catches up.&lt;/p&gt;

&lt;p&gt;The key discipline: &lt;strong&gt;the boundary between MEDIUM and COMPLEX should not be "how big is the request" but "will tools mutate state."&lt;/strong&gt; Local models in this class handle read-and-explain reliably; exact-match edits and bash execution are where they still break sessions — I wrote up those failure modes &lt;a href="https://dev.to/lynkr/routing-down-is-easy-knowing-when-not-to-is-hard-why-cheap-models-break-your-coding-agent-4g33"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed vs three months ago
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The floor rose.&lt;/strong&gt; A 16 GB laptop now runs a genuinely useful SIMPLE tier (Gemma 4). Six months ago that tier meant 3B models that couldn't be trusted with a paragraph.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The open-weight ceiling now beats proprietary on some coding benchmarks&lt;/strong&gt; (GLM-5.2 &amp;gt; GPT-5.5 on SWE-bench Pro) — but at server scale, which &lt;em&gt;strengthens&lt;/em&gt; the hybrid pattern: open models via cheap APIs up top, small open models on your metal below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MoE won.&lt;/strong&gt; Every serious June release is Mixture-of-Experts. For self-hosters this cuts both ways: better quality-per-active-param, but total memory footprints that keep the top tier out of reach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Licensing is consolidating&lt;/strong&gt; around MIT (DeepSeek) and Apache-2.0 (Qwen, Gemma) for the models you'd actually build on.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Test on your traffic, not on benchmarks
&lt;/h2&gt;

&lt;p&gt;Every number above is someone else's workload. The honest way to pick your local tier: route a week of your real traffic through whatever candidates fit your hardware, and count &lt;em&gt;session survival&lt;/em&gt; — how often the local model's tool calls held up — not just benchmark deltas. That's a one-line config change per candidate, and your own telemetry will contradict at least one thing this post told you.&lt;/p&gt;

&lt;p&gt;Lynkr is Apache-2.0, self-hosted, and treats every model above as a first-class routing tier: &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;github.com/Fast-Editor/Lynkr&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>ollama</category>
    </item>
    <item>
      <title>Routing Down Is Easy. Knowing When Not To Is Hard: Why Cheap Models Break Your Coding Agent</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Wed, 08 Jul 2026 00:08:36 +0000</pubDate>
      <link>https://dev.to/lynkr/routing-down-is-easy-knowing-when-not-to-is-hard-why-cheap-models-break-your-coding-agent-4g33</link>
      <guid>https://dev.to/lynkr/routing-down-is-easy-knowing-when-not-to-is-hard-why-cheap-models-break-your-coding-agent-4g33</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, an open-source router whose design decisions this post explains. The failure modes described are patterns widely reported across router issue trackers and local-LLM forums — the examples are representative reconstructions, not captured transcripts. The problem is real either way; ask anyone who's routed a coding agent to a 7B model.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Everyone who gets their first LLM router working does the same thing within the hour: point the expensive coding agent at a free local model and watch the bill drop to zero.&lt;/p&gt;

&lt;p&gt;Then the agent tries to edit a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The graveyard of downgraded sessions
&lt;/h2&gt;

&lt;p&gt;If you browse the issue tracker of any Claude Code router — or r/LocalLLaMA on any given week — you'll find the same story in a hundred variations. The routing works perfectly. The &lt;em&gt;session&lt;/em&gt; dies anyway. The killers, in rough order of frequency:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Malformed tool arguments.&lt;/strong&gt; The agent decides to call &lt;code&gt;Edit&lt;/code&gt;, and the model produces arguments that are &lt;em&gt;almost&lt;/em&gt; JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"file_path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/auth.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"old_string"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"if (token) {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"new_string"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"if (token &amp;amp;&amp;amp; !expired) {"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One missing brace. The harness rejects the call, the model retries, produces a different malformation, and you're three turns deep into fixing nothing. Frontier models emit structurally valid tool calls with boring reliability; sub-10B models do it &lt;em&gt;most&lt;/em&gt; of the time — and "most of the time," at 30 tool calls per session, means every session breaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Stale string matching.&lt;/strong&gt; &lt;code&gt;Edit&lt;/code&gt;-style tools require the &lt;code&gt;old_string&lt;/code&gt; to match the file exactly. Small models paraphrase from memory instead of quoting — they'll "remember" the line as &lt;code&gt;if (token) {&lt;/code&gt; when the file says &lt;code&gt;if (accessToken) {&lt;/code&gt;. The edit fails, the model re-reads the file, burns 2,000 tokens, tries again with a different paraphrase. This is the single most reported failure, because it &lt;em&gt;looks&lt;/em&gt; like the router's fault and is actually a capability cliff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Hallucinated context.&lt;/strong&gt; Ask a small model to run tests and it may confidently call &lt;code&gt;Bash&lt;/code&gt; with &lt;code&gt;npm test -- --grep "auth"&lt;/code&gt; in a repo that uses pytest. It's not being stupid — it's pattern-completing from training data instead of the conversation, because instruction-following degrades faster than fluency as models shrink.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The infinite loop.&lt;/strong&gt; The subtlest one: the model calls &lt;code&gt;Read&lt;/code&gt; on the same file five times in a row, or greps, reads, greps the same term again. Weak models lose the thread of &lt;em&gt;what they already know&lt;/em&gt; in long agentic contexts. Nothing errors — the session just stops converging while tokens burn.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable part: &lt;strong&gt;none of these are the router's bug, and all of them are the router's fault.&lt;/strong&gt; The router made a judgment — "this request is cheap-model-safe" — and the judgment was wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the obvious heuristics misjudge
&lt;/h2&gt;

&lt;p&gt;Most routing setups decide with static rules: token thresholds, keyword lists, scenario slots. These fail in a specific, predictable way: &lt;strong&gt;they measure the request's size, not its stakes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Fix the auth bug in session.js" is eight words. Every token-based rule on earth routes it to the small model. But those eight words unleash a read-grep-edit-test loop — the exact workload where small models faceplant. Meanwhile, "explain the difference between optimistic and pessimistic locking, with examples" looks expensive (long answer, technical vocabulary) and is actually &lt;em&gt;perfectly&lt;/em&gt; cheap-model-safe: it's pure text generation, no tool calls, no exact string matching, nothing to break.&lt;/p&gt;

&lt;p&gt;Size and stakes are almost uncorrelated in agentic traffic. That's the whole problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "stakes-aware" routing looks like
&lt;/h2&gt;

&lt;p&gt;When I built &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;'s router, most of the design ended up being about &lt;em&gt;when not to save money&lt;/em&gt;. The parts that matter:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weight the tools, not just their count.&lt;/strong&gt; A request where &lt;code&gt;Grep&lt;/code&gt; and &lt;code&gt;Read&lt;/code&gt; are in play is research — paraphrase-tolerant, failure-tolerant, ideal for a local model. A request where &lt;code&gt;Bash&lt;/code&gt;, &lt;code&gt;Write&lt;/code&gt;, or &lt;code&gt;Edit&lt;/code&gt; will fire is a mutation with exact-match requirements. Lynkr assigns each tool a risk weight (&lt;code&gt;Bash&lt;/code&gt; 0.9, &lt;code&gt;Write&lt;/code&gt; 0.8, &lt;code&gt;Edit&lt;/code&gt; 0.7 … &lt;code&gt;Grep&lt;/code&gt; 0.2) and scores the request's &lt;em&gt;effective&lt;/em&gt; toolset. Two requests with five tools each can land tiers apart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat mid-session as a signal.&lt;/strong&gt; If the conversation already contains three tool results, you're inside an agentic flow with accumulated exact-state (file contents, error strings). Downgrading the model mid-flow throws away the one thing that was keeping the loop convergent. Prior tool usage and conversation depth push requests &lt;em&gt;up&lt;/em&gt;-tier even when the latest message is short.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subtract the harness baseline.&lt;/strong&gt; Claude Code ships ~14 tool schemas with every request — including "hello." Count them naively and everything looks agentic, so nothing ever routes local and you save nothing. Score only the tools the request could plausibly use, and the safe majority routes down while the risky minority stays up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some patterns override everything.&lt;/strong&gt; Greetings and "what does X do" questions force-route local, always. Security-sensitive analysis force-routes to the strong tier, always — a JWT architecture question is short, toolless, and precisely the wrong place to save four cents.&lt;/p&gt;

&lt;p&gt;The result on my own traffic: 70–90% of requests route to free local models — but they're the &lt;em&gt;right&lt;/em&gt; 70–90%, which is the entire difference between "my bill dropped" and "my agent broke."&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways, router-agnostic
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Route research down, mutations up.&lt;/strong&gt; If your router can't tell a &lt;code&gt;Grep&lt;/code&gt; request from an &lt;code&gt;Edit&lt;/code&gt; request, it isn't routing — it's gambling on which sessions break.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never downgrade mid-loop.&lt;/strong&gt; Model consistency across an agentic sequence is worth more than the marginal savings of one cheap turn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure session survival, not just cost.&lt;/strong&gt; A routing setup that saves 60% and breaks one session in five is more expensive than the bill it replaced — you're paying in re-runs and rage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The ceiling is rising.&lt;/strong&gt; Local models' tool-calling improves every quarter; the set of safely-downgradable requests grows with it. A router with per-tool judgment gets to expand that set gradually. A token threshold has to guess again from scratch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The router's job was never "pick the cheapest model." It's "pick the cheapest model &lt;em&gt;that won't break the session&lt;/em&gt;" — and those five extra words are where all the engineering lives.&lt;/p&gt;

&lt;p&gt;The scorer described here is ~1,000 lines of readable Apache-2.0 JavaScript: &lt;a href="https://github.com/Fast-Editor/Lynkr/blob/main/src/routing/complexity-analyzer.js" rel="noopener noreferrer"&gt;src/routing/complexity-analyzer.js&lt;/a&gt;. Steal the design, or file an issue telling me where it misjudges — the failure cases are the interesting part.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>The 5% Router Tax: What Hosted LLM Gateways Charge For (and How to Self-Host It)</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Sun, 05 Jul 2026 08:48:56 +0000</pubDate>
      <link>https://dev.to/lynkr/the-5-router-tax-what-hosted-llm-gateways-charge-for-and-how-to-self-host-it-513</link>
      <guid>https://dev.to/lynkr/the-5-router-tax-what-hosted-llm-gateways-charge-for-and-how-to-self-host-it-513</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, the self-hosted gateway discussed in the second half. OpenRouter and Requesty are good products — this post is about understanding what you're paying for so you can decide whether you need to.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hosted LLM routers had a huge 2026 — OpenRouter alone pushes 25 trillion tokens a week. The pitch is real: one API key, 400+ models, automatic failover. The price is a &lt;strong&gt;~5% fee on every token you route&lt;/strong&gt; (5.5% on OpenRouter credits, 5% on Requesty), plus a subtler cost: every prompt, every file your coding agent reads, every secret that leaks into a context window transits their infrastructure.&lt;/p&gt;

&lt;p&gt;For a hobby project, 5% of a small bill is nothing and the convenience wins. For an agentic coding workload — where teams routinely spend $500–$2,000 per engineer per month — 5% is real money, and the data-transit question stops being academic. So it's worth asking precisely: &lt;strong&gt;what does the hosted router actually do for that fee, and which parts can you self-host?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the fee buys
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unified API across providers&lt;/strong&gt; — one format in, translated per-provider out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failover&lt;/strong&gt; — a provider 500s, your request retries elsewhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model marketplace&lt;/strong&gt; — new models available the day they launch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consolidated billing&lt;/strong&gt; — one invoice instead of six provider accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(Sometimes) smart routing&lt;/strong&gt; — OpenRouter's &lt;code&gt;auto&lt;/code&gt; router picks a model per-request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Items 1, 2, and 5 are software. Items 3 and 4 are genuinely hard to self-host — if you want day-one access to every new model with zero account setup, the marketplace earns its fee. But most coding workloads use a handful of models, not four hundred.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts a hosted router structurally can't give you
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local models as a tier.&lt;/strong&gt; No hosted router will route your easy requests to the Ollama instance on your own machine — free, private, zero latency to first byte on cached weights. For coding traffic, where (in my instrumented sessions) 70–90% of requests are simple enough for a good local model, this is the single biggest cost lever, and it's only available to something running on your side of the wire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your data staying home.&lt;/strong&gt; Self-hosted means prompts, code, and keys never transit a third party. For anyone with a compliance requirement — or code they'd rather not ship to a router's logs — this isn't a preference, it's a prerequisite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token optimization before the bill.&lt;/strong&gt; A hosted router bills you for the tokens you send it — it has no incentive to shrink them. A self-hosted proxy can strip unusable tool schemas (measured: −53% on tool-heavy requests) and compress JSON tool results (measured: 3,458 → 427 tokens on a grep result) &lt;em&gt;before&lt;/em&gt; any provider bills you. That's not a routing saving; it stacks on top of routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No availability dependency.&lt;/strong&gt; Hosted routers go down (OpenRouter's outages have their own HN threads) and offer no SLA at consumer tiers. A local proxy fails independently of anyone's status page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What self-hosting costs you
&lt;/h2&gt;

&lt;p&gt;Honesty cuts both ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You run a process.&lt;/strong&gt; &lt;code&gt;npm install -g lynkr &amp;amp;&amp;amp; lynkr init &amp;amp;&amp;amp; lynkr start&lt;/code&gt; — but it's yours now: updates, logs, the works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You manage provider accounts.&lt;/strong&gt; Two or three API keys instead of one. The consolidated invoice is genuinely gone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model lag.&lt;/strong&gt; A new provider means waiting for support (or a PR) instead of it appearing in a dropdown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nobody to email.&lt;/strong&gt; Self-hosted support is a GitHub issue tracker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If those trade-offs read as "fine," the math is straightforward: the 5% fee disappears, the local-tier routing removes the easy majority of requests from your bill entirely, and compression shrinks what's left.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hybrid that actually makes sense
&lt;/h2&gt;

&lt;p&gt;This isn't either/or. A pattern I see working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Coding tool → self-hosted proxy (Lynkr)
                ├─ SIMPLE/MEDIUM  → local Ollama/llama.cpp   (free)
                ├─ COMPLEX        → direct provider API keys  (no fee)
                └─ exotic models  → OpenRouter               (5% on the long tail only)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep a hosted router as &lt;em&gt;one backend&lt;/em&gt; for the long tail of models you rarely need, route the bulk directly or locally, and let the proxy's classifier decide per-request. You get the marketplace when you want it without paying the tax on your entire volume.&lt;/p&gt;

&lt;p&gt;Lynkr is Apache-2.0, self-hosted, supports 13 providers including Ollama, llama.cpp, LM Studio, Bedrock, Azure, Databricks — and OpenRouter itself as a tier: &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;github.com/Fast-Editor/Lynkr&lt;/a&gt;. Benchmarks with methodology are in the repo; run them on your own workload before believing anyone's percentages, including mine.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>selfhosted</category>
      <category>llm</category>
    </item>
    <item>
      <title>How a 13-Dimension Complexity Scorer Decides Which Model Gets Your Request</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Sun, 05 Jul 2026 08:48:40 +0000</pubDate>
      <link>https://dev.to/lynkr/how-a-13-dimension-complexity-scorer-decides-which-model-gets-your-request-e95</link>
      <guid>https://dev.to/lynkr/how-a-13-dimension-complexity-scorer-decides-which-model-gets-your-request-e95</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, the open-source proxy whose internals this post walks through. All code shown is real and Apache-2.0 — &lt;a href="https://github.com/Fast-Editor/Lynkr/blob/main/src/routing/complexity-analyzer.js" rel="noopener noreferrer"&gt;read it here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The most expensive default in AI coding tools is that &lt;strong&gt;model choice is a setting, not a decision&lt;/strong&gt;. You pick a model once; every request — "what does git stash do?" and "refactor this auth module" alike — goes there. Routing each request to the cheapest model that can actually handle it is worth 50%+ of most bills, but it only works if the "can actually handle it" judgment is reliable. Get it wrong downward and a small model fumbles your file edits; get it wrong upward and you've saved nothing.&lt;/p&gt;

&lt;p&gt;Here's how Lynkr makes that judgment, in enough detail that you could reimplement it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just count tokens?
&lt;/h2&gt;

&lt;p&gt;The obvious heuristics fail in both directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Long request → big model"&lt;/strong&gt; fails on a 60k-token context that's mostly grep output around a trivial question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Short request → small model"&lt;/strong&gt; fails catastrophically on "fix the auth bug in session.js" — eight words that unleash a tool-heavy agentic session a 7B model will faceplant on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Token count is &lt;em&gt;one&lt;/em&gt; signal. The failure cases all come from treating it as the only one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture: weighted dimensions, then overrides
&lt;/h2&gt;

&lt;p&gt;Every request gets a 0–100 score from 13 dimensions in four groups. The weights are configurable; these are the defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DIMENSION_WEIGHTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Content Analysis (35%)&lt;/span&gt;
  &lt;span class="na"&gt;tokenCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;promptComplexity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// avg sentence length/structure&lt;/span&gt;
  &lt;span class="na"&gt;technicalDepth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// technical keyword density&lt;/span&gt;
  &lt;span class="na"&gt;domainSpecificity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// security/ML/distributed/db/frontend/devops&lt;/span&gt;
  &lt;span class="c1"&gt;// Tool Analysis (25%)&lt;/span&gt;
  &lt;span class="na"&gt;toolCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;toolComplexity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// which tools, not how many&lt;/span&gt;
  &lt;span class="na"&gt;toolChainPotential&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// "first...then", "step 2", sequencing language&lt;/span&gt;
  &lt;span class="c1"&gt;// Reasoning Requirements (25%)&lt;/span&gt;
  &lt;span class="na"&gt;multiStepReasoning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;codeGeneration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;analysisDepth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// trade-off/comparison markers&lt;/span&gt;
  &lt;span class="c1"&gt;// Context Factors (15%)&lt;/span&gt;
  &lt;span class="na"&gt;conversationDepth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;priorToolUsage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// tool_results already in the conversation&lt;/span&gt;
  &lt;span class="na"&gt;ambiguity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few design decisions worth stealing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not all tools are equal.&lt;/strong&gt; A request that can &lt;code&gt;Grep&lt;/code&gt; is not like a request that can &lt;code&gt;Bash&lt;/code&gt;. Each tool carries a hand-tuned risk weight — &lt;code&gt;Bash&lt;/code&gt; 0.9, &lt;code&gt;Write&lt;/code&gt; 0.8, &lt;code&gt;Edit&lt;/code&gt; 0.7, down to &lt;code&gt;Grep&lt;/code&gt; at 0.2. A request whose available toolset averages 0.8 is an agentic mutation session; one averaging 0.25 is read-only research. Same tool &lt;em&gt;count&lt;/em&gt;, completely different stakes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subtract the harness baseline.&lt;/strong&gt; Claude Code ships ~14 tool schemas with &lt;em&gt;every&lt;/em&gt; request, including "hello". If you count them naively, everything looks agentic and nothing routes local. The scorer subtracts the client's constant baseline and scores only the &lt;em&gt;effective&lt;/em&gt; tools the request could plausibly use — one of those fixes that sounds trivial and changed everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conversation history is a signal.&lt;/strong&gt; Three &lt;code&gt;tool_result&lt;/code&gt; blocks already in the conversation means you're mid-agentic-flow — this is not the moment to downgrade models and break the session's momentum. &lt;code&gt;priorToolUsage&lt;/code&gt; and &lt;code&gt;conversationDepth&lt;/code&gt; push mid-session requests up-tier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ambiguity cuts the other way.&lt;/strong&gt; "file X, line 42, this error" is specific — a small model can act on it. "Something feels slow sometimes" needs interpretation before action. Specificity markers (paths, line numbers, error strings) &lt;em&gt;lower&lt;/em&gt; the score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overrides: the classifier knows what it can't know
&lt;/h2&gt;

&lt;p&gt;Two pattern lists short-circuit the whole scoring pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Force-local:&lt;/strong&gt; greetings, acknowledgments, "what does X do" one-liners. Score 0, never leave the machine, no cloud tokens ever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Force-cloud:&lt;/strong&gt; security-critical analysis, architecture decisions, anything matching high-risk patterns. Straight to the top tier regardless of how cheap it looks. A JWT-vs-cookies security question is short and toolless — every naive heuristic routes it local. This is the wrong request to save $0.004 on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of the regex dimensions, an AST pass (tree-sitter) scores actual code structure in the payload — cyclomatic signals beat keyword counting when real code is present.&lt;/p&gt;

&lt;h2&gt;
  
  
  From score to model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;score &amp;lt; threshold        → SIMPLE   (e.g. ollama:qwen2.5:7b, free)
threshold..~65           → MEDIUM   (e.g. ollama:qwen2.5-coder, free)
above                    → COMPLEX  (your API key: Sonnet, GPT-4o...)
reasoning markers heavy  → REASONING (o3, DeepSeek R1...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The threshold moves with a single mode switch — &lt;code&gt;aggressive&lt;/code&gt; (60) routes more local, &lt;code&gt;conservative&lt;/code&gt; (25) routes more to the cloud, default is 40. Multi-turn conversations score with a recency-weighted sliding window, so a short follow-up ("now add tests") inherits the complexity of the work it refers to instead of scoring as a trivial one-liner.&lt;/p&gt;

&lt;p&gt;Crucially, &lt;strong&gt;the classifier only chooses among models you listed&lt;/strong&gt;. It's not an autonomous agent picking providers — you define the tiers, it picks the tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does it work?
&lt;/h2&gt;

&lt;p&gt;In my instrumented sessions, 70–90% of requests score SIMPLE or MEDIUM and run free on local models, while tool-heavy and security-flagged requests reliably escalate. The failure mode everyone fears — cheap model breaking an agentic session — is exactly what the tool weights, baseline subtraction, and prior-tool-usage dimensions exist to prevent.&lt;/p&gt;

&lt;p&gt;Is 13 hand-weighted dimensions the optimal design? Almost certainly not — a learned router trained on outcome data would beat it eventually. But it's transparent (every routing decision logs its per-dimension breakdown), it's tunable, it runs in-process in microseconds, and it never sends your prompts to a third-party classifier API.&lt;/p&gt;

&lt;p&gt;The whole thing is readable in one sitting: &lt;a href="https://github.com/Fast-Editor/Lynkr/blob/main/src/routing/complexity-analyzer.js" rel="noopener noreferrer"&gt;src/routing/complexity-analyzer.js&lt;/a&gt;. Steal the design or use the proxy — either outcome means fewer frontier-model tokens spent on &lt;code&gt;git stash&lt;/code&gt; questions.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>node</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The 21,000-Token Typo: Where Agentic Coding Budgets Actually Die</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Sun, 05 Jul 2026 08:48:24 +0000</pubDate>
      <link>https://dev.to/lynkr/the-21000-token-typo-where-agentic-coding-budgets-actually-die-1pa4</link>
      <guid>https://dev.to/lynkr/the-21000-token-typo-where-agentic-coding-budgets-actually-die-1pa4</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I maintain &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;, an open-source proxy mentioned at the end. The first 80% of this post is tool-agnostic and the takeaways apply whether or not you ever use it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's a &lt;a href="https://www.cyfrin.io/blog/expensive-and-slow-for-small-changes-why-ai-coding-agents-can-be-overkill" rel="noopener noreferrer"&gt;documented case&lt;/a&gt; of a coding agent burning &lt;strong&gt;21,000+ input tokens to fix a one-line README typo&lt;/strong&gt;. Not a bug. Not a runaway loop. That's the normal cost structure of agentic coding, and once you see why, you can't unsee it on your own bill.&lt;/p&gt;

&lt;p&gt;Stanford's Digital Economy Lab &lt;a href="https://digitaleconomy.stanford.edu/news/how-are-ai-agents-spending-your-tokens/" rel="noopener noreferrer"&gt;measured it&lt;/a&gt;: agentic tasks consume on the order of &lt;strong&gt;1000x the tokens of ordinary code chat&lt;/strong&gt;, and the &lt;em&gt;same task with the same agent&lt;/em&gt; can vary 30x in cost depending on how the session unfolds. Teams running heavy automation report $500–$2,000 per engineer per month. So where does it go?&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of one "small" agentic task
&lt;/h2&gt;

&lt;p&gt;Say you ask your agent to fix a typo. Here's what actually crosses the wire:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn 1:&lt;/strong&gt; Your one-line prompt... plus the system prompt, plus ~14 tool schemas (Write, Edit, Bash, Grep, Git — a couple thousand tokens before anyone thinks).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn 2:&lt;/strong&gt; The agent greps for the file. The result comes back as JSON — paths, line numbers, match context, metadata. A modest grep is easily 1,000–3,000 tokens. It's now in the context &lt;strong&gt;and gets re-sent on every subsequent turn&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn 3:&lt;/strong&gt; The agent reads the file. Add the full file contents to the context. Re-sent every turn from now on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn 4:&lt;/strong&gt; The edit itself — the cheapest part of the entire session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn 5:&lt;/strong&gt; Verification: re-read, maybe run a linter, another JSON blob of output.&lt;/p&gt;

&lt;p&gt;Five turns, and your one-line fix carried: 5x the tool schemas, 4x the grep results, 3x the file contents. Input tokens dominate output roughly &lt;strong&gt;25:1&lt;/strong&gt; in typical sessions. You're not paying for intelligence — you're paying for &lt;em&gt;cargo&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three structural leaks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Leak 1: Tool schemas on every request.&lt;/strong&gt; The agent might use two tools this session. You ship fourteen schemas every turn anyway, because the client doesn't know which ones matter. Measured on a realistic Claude Code request: schemas the request couldn't use accounted for &lt;strong&gt;53% of billed input tokens&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leak 2: Raw JSON in the context window.&lt;/strong&gt; JSON is the least token-efficient format your context will ever hold — keys repeated per element, quotes, braces, whitespace. A 60-match grep result: ~3,400 tokens raw, &lt;strong&gt;427 after conversion to a tabular token-oriented format&lt;/strong&gt; with redundant fields stripped. Nothing lost that the model needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leak 3: Frontier models on non-frontier requests.&lt;/strong&gt; "What does git stash do?" does not need the same model as "refactor this auth module." But your client sends both to the same place, because model choice is a config setting, not a per-request decision. In my instrumented sessions, &lt;strong&gt;70–90% of requests scored as simple or medium complexity&lt;/strong&gt; — they'd be fine (and free) on a local model.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do about it — tool-agnostic
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instrument before optimizing.&lt;/strong&gt; Log tokens per request by category (schemas / tool results / conversation). You cannot fix a leak you haven't sized. Most people find their intuition about their own spend is wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never let raw JSON accumulate in a context window.&lt;/strong&gt; Compact it, tabularize it, or summarize it. Tabular JSON is nearly free compression — same information, a fraction of the tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep sessions short and contexts clean.&lt;/strong&gt; Every tool result you leave in the context is a recurring charge, billed again on every turn until the session ends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match model to request, not to workflow.&lt;/strong&gt; Route the easy 80% somewhere cheap or local; reserve the frontier model for the requests that actually exercise it. Bring your own API keys and the routing is entirely within your control.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The plumbing version
&lt;/h2&gt;

&lt;p&gt;Everything above can be done manually. I got tired of doing it manually, so I built it into a proxy: &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt; sits between your coding tool (Claude Code, Cursor, Codex CLI) and your providers, strips unusable tool schemas, compresses JSON tool results, caches semantically, and scores each request on 13 dimensions to route it to a tier you define — local Ollama for the easy stuff, your API keys for the hard stuff. Self-hosted, Apache-2.0, no markup, zero client changes.&lt;/p&gt;

&lt;p&gt;But the numbers above aren't about my tool. They're about a cost structure every agentic workflow shares. The 21,000-token typo isn't an outlier — it's the default. Measure yours.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>llm</category>
    </item>
    <item>
      <title>Lynkr vs claude-code-router: Static Rules vs a Complexity Classifier</title>
      <dc:creator>Lynkr</dc:creator>
      <pubDate>Sun, 05 Jul 2026 08:48:08 +0000</pubDate>
      <link>https://dev.to/lynkr/lynkr-vs-claude-code-router-static-rules-vs-a-complexity-classifier-38nd</link>
      <guid>https://dev.to/lynkr/lynkr-vs-claude-code-router-static-rules-vs-a-complexity-classifier-38nd</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I'm the author of &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;. claude-code-router is a genuinely good project that pioneered this category — this is a technical comparison of two different approaches, not a takedown. Where CCR is the better choice, I say so.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you want to keep the Claude Code harness but route requests to other models, you have two main self-hosted options today: &lt;a href="https://github.com/musistudio/claude-code-router" rel="noopener noreferrer"&gt;claude-code-router&lt;/a&gt; (CCR, ~35k stars, the incumbent) and &lt;a href="https://github.com/Fast-Editor/Lynkr" rel="noopener noreferrer"&gt;Lynkr&lt;/a&gt;. They solve the same problem with fundamentally different architectures, and which one fits you depends on how much you want to configure versus delegate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core difference in one paragraph
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CCR routes by scenario rules you write.&lt;/strong&gt; It has slots — &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;background&lt;/code&gt;, &lt;code&gt;think&lt;/code&gt;, &lt;code&gt;longContext&lt;/code&gt; (triggered above a token threshold), &lt;code&gt;webSearch&lt;/code&gt;, &lt;code&gt;image&lt;/code&gt; — and you assign a model to each. It's predictable, transparent, and entirely under your control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lynkr routes by scoring the request itself.&lt;/strong&gt; Every request gets a 0–100 complexity score computed from 13 weighted dimensions — token count, technical keyword density, tool complexity, multi-step reasoning markers, conversation depth, ambiguity, and so on — and lands in a tier (&lt;code&gt;SIMPLE&lt;/code&gt;/&lt;code&gt;MEDIUM&lt;/code&gt;/&lt;code&gt;COMPLEX&lt;/code&gt;/&lt;code&gt;REASONING&lt;/code&gt;) you've mapped to models. You configure the tiers once; the classifier decides per-request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where CCR wins
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maturity and ecosystem.&lt;/strong&gt; 35k stars, ~730k monthly npm downloads, 20+ provider transformers, custom JS plugins, a web UI, and in-session &lt;code&gt;/model&lt;/code&gt; switching. If you hit a weird provider quirk, someone has already hit it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictability.&lt;/strong&gt; A rule is a rule. If you want &lt;em&gt;"long contexts always go to Gemini"&lt;/em&gt;, CCR expresses that in one line and never surprises you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code specialization.&lt;/strong&gt; CCR does one client deeply. Lynkr supports Claude Code, Cursor, Codex CLI, Cline, and Continue — breadth costs some depth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where the rule-based approach breaks down
&lt;/h2&gt;

&lt;p&gt;Browse CCR's issue tracker (~1,000 open issues) and one complaint dominates: &lt;strong&gt;tool-calling breakage on downgraded models&lt;/strong&gt; — failed file edits, broken git operations, agents going in circles. The root cause usually isn't CCR's code. It's that static rules can't see &lt;em&gt;what the request needs&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A short prompt ("fix the auth bug in session.js") looks cheap by token count — but it's an agentic, tool-heavy task that a small local model will fumble.&lt;/li&gt;
&lt;li&gt;A long context triggers the &lt;code&gt;longContext&lt;/code&gt; rule — but if it's 60k tokens of grep output around a trivial question, an expensive long-context model is wasted money.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Token counts and scenario names are proxies. The thing you actually care about — &lt;em&gt;can a cheap model handle this without breaking the session?&lt;/em&gt; — requires looking at the request's structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Lynkr does differently
&lt;/h2&gt;

&lt;p&gt;Three things, all absent from CCR by design (it aims to be a lean router):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The complexity classifier.&lt;/strong&gt; Requests with agentic signals (write/edit/bash tool availability, prior tool results in the conversation, sequential-step language) score into higher tiers even when they're short. Trivia stays local even when the context is long. Force-patterns short-circuit both ways: greetings never hit the cloud; security-critical analysis never gets downgraded. The design goal is exactly the failure mode above — &lt;em&gt;route down only when the answer will still work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Token optimization on the wire.&lt;/strong&gt; Lynkr strips tool schemas the request can't use (measured: &lt;strong&gt;53% fewer tokens&lt;/strong&gt; on a realistic 14-tool Claude Code request) and compresses large JSON tool results before they hit the model (measured: 3,458 → 427 tokens on a 60-match grep result). CCR forwards requests as-is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Semantic caching.&lt;/strong&gt; Paraphrased repeat questions are served from an embedding cache in ~171ms with zero tokens billed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;claude-code-router&lt;/th&gt;
&lt;th&gt;Lynkr&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Routing logic&lt;/td&gt;
&lt;td&gt;Scenario rules + token threshold&lt;/td&gt;
&lt;td&gt;13-dimension complexity score → tiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;Per-scenario, per-provider (flexible, verbose)&lt;/td&gt;
&lt;td&gt;Pick 4 tier models via &lt;code&gt;lynkr init&lt;/code&gt; wizard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool-schema stripping&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (−53% measured)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON tool-result compression&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (TOON + field stripping)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semantic cache&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clients&lt;/td&gt;
&lt;td&gt;Claude Code (deep)&lt;/td&gt;
&lt;td&gt;Claude Code, Cursor, Codex CLI, Cline, Continue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provider transformers/plugins&lt;/td&gt;
&lt;td&gt;20+, custom JS&lt;/td&gt;
&lt;td&gt;13 providers built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ecosystem maturity&lt;/td&gt;
&lt;td&gt;~35k stars, huge community&lt;/td&gt;
&lt;td&gt;Young (~500 stars), one maintainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In-session model switching&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;/model&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;No (automatic per-request)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;Apache-2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Which should you use?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You want explicit control and a battle-tested ecosystem&lt;/strong&gt; → CCR. It's the safe default and its community is unmatched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You're tired of tuning rules, or your cheap-model sessions keep breaking&lt;/strong&gt; → try Lynkr. The classifier exists precisely because static rules degrade on agentic workloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your bill is dominated by tool output and repeated context&lt;/strong&gt; → Lynkr, regardless of routing preference; the compression and caching layers work even if you route everything to one model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are self-hosted, free, and take five minutes to try. Run your own workload through each and compare the token logs — that's the only benchmark that matters. Mine are reproducible here: &lt;a href="https://github.com/Fast-Editor/Lynkr/blob/main/BENCHMARK_REPORT.md" rel="noopener noreferrer"&gt;github.com/Fast-Editor/Lynkr&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>claude</category>
    </item>
  </channel>
</rss>
