MTPLX 2.4.2

Released 2026-08-02. The agentic-cache release. If you run MTPLX under a coding agent , OpenCode, Pi, Claude Code, Cline, this release is about the slowdowns you could feel but not see: the session that gets slower the longer it runs, the tool call that triggers a mysterious multi-second pause, the warm session that suddenly re-prefills from zero. Each one was a real, named mechanism, and each is fixed or fenced here. It also lands an experimental DeepSeek-V4-Flash backend and a full documentation truth sweep.

Your warm session stops getting evicted mid-run

The session bank protects the state that makes follow-up turns fast. Two failure modes are closed:

  • Cross-session pressure could evict the session you were actively using. A long coding session's warm entry was LRU-evicted mid-run, forcing an 85.6k-token full re-prefill on the very next turn. Sessions that touched the bank within the last MTPLX_SESSION_BANK_ACTIVE_PIN_TTL_S seconds (default 600) are now eviction-last: cross-session pressure prefers idle victims. It is an activity window, not a pin, so a crashed request can never leak a reservation.
  • Per-turn sibling snapshots accumulated without bound. Agent turns can produce near-duplicate divergent snapshots (~1.7 GB each on a 27B session) that prefix-superseding could never reclaim. The bank now keeps the newest MTPLX_SESSION_BANK_PER_SESSION_MAX_ENTRIES (default 3) per session; live and protected entries are exempt.

/health now reports active sessions, the pin TTL, and recent evictions, so "what did the bank just do" has an answer.

Tool-turn commits stop being ghosts

Two background-commit pathologies made agent loops pay a cache tax on every tool turn:

  • The tool-rewrite async commit rendered a "canonical" history that matched neither what was generated nor what the client sent next. It could burn a full-history re-forward (26.8 s observed at 27-29k context) and never store a usable entry. It is now disabled pending a byte-proven canonical render (MTPLX_IDLE_POSTCOMMIT_TOOL_REWRITE re-enables it); store-on-prefill and block salvage already cover the lane.
  • Fast agent loops (next request arriving in under half a second) preempted every background commit before it landed, so the generation tail never got banked. A bounded foreground grace (MTPLX_POSTCOMMIT_FOREGROUND_GRACE_S, default 2 s) lets a nearly-finished commit land; the request that arrives after the window still wins immediately.

And an identity fix that multiplies both: the server now honors the x-session-affinity / x-session-id headers OpenCode sends on every request, so consecutive turns from the same session stop being treated as strangers.

Every serve keeps a durable trail, diagnosis stops being archaeology

2.4.1 added opt-in bit-exact request capture. 2.4.2 turns on the always-on companion: every serve writes per-request telemetry , timings, token counts, prefill/restore behavior, request ids, to ~/.mtplx/logs/request-log-<port>.jsonl (64 MB × 4 rotation). No prompt or completion content is recorded, and MTPLX_REQUEST_LOG_JSONL=off disables it. When an agent session goes wrong at 2 a.m., the evidence now exists by default.

Three helpers ship alongside: scripts/gauntlet_scoreboard.py summarizes a session against product bars (decode floor, TTFT, re-prefill hygiene); scripts/oc_tap.py is a transparent recording proxy for content-level wire truth (it also forces Connection: close toward the client, because keep-alive pools were observed silently dropping the first request after a server restart); scripts/oc_tap_diff.py shows exactly what a client rewrote between consecutive requests.

One contract fix caught on a live gauntlet: the bridge's convergence guard could be read by the model as a session-wide tool ban ("the system explicitly forbids additional tool calls"), stalling the session. The guard now states that editing and verification tools remain allowed and that it scopes to the current reply only.

Experimental: DeepSeek-V4-Flash

A from-scratch native backend for model_type: deepseek_v4 (Hyper-Connections, compressed sparse attention with learned gated pooling, hash-routed MoE layers, grouped output-LoRA), loading the published mlx-community checkpoints directly, plus an optional single-block MTP speculative lane when the checkpoint carries mtp.0.* draft weights. The speculative lane is gated on committed- sequence identity with AR and measured up to 2.28x at K=3 on the 2bit-DQ build. Checkpoints that declare MTP but ship no draft weights (the current mlx-community conversions) degrade cleanly to AR. The backend is labeled experimental; treat throughput as unoptimized. Contributed by @davidtai (#216).

The documentation now tells the truth

Seeded by #215 (a README workflow pointing at a script that never existed, removed in #218 by @PhilipJohnBasile), a three-sweep audit verified ~450 documentation claims against the code and fixed every confirmed drift across 27 files. The ones you might have hit:

  • INSTALL.md pointed performance-cold users at an MLX fork that was removed in v2.0.0. MTPLX runs on stock PyPI MLX, full stop.
  • turbo-verify.md called the turbo lane "experimental, off by default" , it has been the shipped default for the quantized 27B flagships since 2.0.0 and the 9B tier since 2.0.1, and wrongly excluded the 6-bit lane that ships.
  • The Anthropic client instructions (docs and the canonical example) pointed base_url at /v1, which 404s once the SDK appends /v1/messages. Use the server root.
  • /metrics was documented as offering "Prometheus-style text". It never did; it returns a JSON snapshot.
  • The README modes table hid Turbo entirely, so third-party benchmarks following it measured the wrong profile.
  • The Laguna memory requirement claimed 96 GiB with no code basis; the real preflight gate is ~85.3 GiB of unified memory.
  • Four diagnostic subcommands (profile thermal, profile eval-attribution, profile dispatch --trace, thermal fanmax-run) invoked scripts that do not exist in the distribution, and --dry-run printed the phantom paths. They now say honestly when the research-workspace tooling isn't present.
  • mtplx doctor certified Python 3.10 on a package that requires 3.11, and several of its remediation texts were unactionable.
  • Historical release notes that documented commands which never worked keep their record but gain bracketed corrections naming the working path.

Upgrade

  • App: Sparkle offers 2.4.2 (build 24200); the app re-provisions its runtime from the bundled wheel on next Start.
  • pip: pip install -U mtplx
  • Homebrew: brew upgrade mtplx

No defaults changed for non-agent workloads. The new session-bank and postcommit behaviors ship with conservative defaults and are fully env-tunable; set MTPLX_REQUEST_LOG_JSONL=off if you want no on-disk request trail.

Get it. Download the current DMG, or brew upgrade mtplx / pip install -U mtplx. Every published speed number with its conditions is on the benchmarks page; the archive of every version is on the releases page.