MTPLX 2.4.0

The 35B speed release, plus the fan fix everyone hit.

The headline: 35B-A3B got a compiled decode stack

The 35B-A3B MoE model now runs a compiled decode route: target-prefix compilation, whole-MoE fusion, GDN post-conv fusion, and a row-owned router (thanks David Tai, #174). On top of that sits continuous batched serving with fixed-shape cohorts, ragged KV, and AR row-packing (#200). Single-stream serving stays exactly as fast as before; the new stack is where the batched and 35B lanes pick up their headroom.

Fans no longer stay stuck at max (#201)

If you ran 2.3.0 in Smart fan mode, you probably heard this bug. After a request finished, a failed fan restore was logged once and then forgotten, so the fans could stay pinned at max while the engine sat idle. Two real fixes:

There is also a new watchdog: if a fan lease is somehow held while the engine has been idle for two minutes, it gets dropped and logged loudly. If you ever see that log line, please paste it on #201.

Tool calling keeps getting more honest

Structured output can think as long as it wants, but not forever

An unclosed block inside constrained generation could legally run to the token limit and eat the whole response. The reasoning prelude is now bounded at 4000 characters by default, tunable via MTPLX_THINK_PRELUDE_MAX_CHARS (0 restores the old unbounded behavior). Your structured request now always produces the document it asked for (Jozef Kristek, #213).

The rest

Performance

Measured against released 2.3.0 on an M5 Max (27B Optimized Speed, turbo profile, verified max fans, alternating A/B runs): decode and prefill are flat within run-to-run noise, with the candidate reading about nine percent faster on 8k-prompt prefill in the clean window (564 vs 518 tok/s) and identical at 32k (622 vs 635 tok/s, both within spread). Decode held the 58 to 61 tok/s band on both builds. No pillar regressed.