The fast server isn’t the one with the biggest tok/s number. It’s the one that still emits a valid tool call on the fortieth turn of an agent loop.Any OpenAI-compatible server can answer a chat request. The ones that matter for agentic work are the ones that hold up under sustained, structured, multi-turn pressure — continuous batching, a paged KV cache, and a tool-call parser that doesn’t drift. That’s why this stack runs
vllm-mlx.
The landscape
Why vllm-mlx
Three properties decide it:- Prefix + paged KV cache. Multi-turn and tool-loop workloads re-send a growing, mostly-unchanged context. Reusing the already-prefilled prefix instead of re-running it is the biggest real-world speedup there is — and it’s what makes a local model tolerable as an agent backend.
- Continuous batching. Concurrent callers fold into one GPU forward pass instead of serializing.
- OpenAI-shaped tool calling. Every caller on the workstation already speaks the OpenAI API, so the model is a drop-in for the cloud providers in the same router.
Rapid-MLX: evaluate, don’t switch on hype
Rapid-MLX is real, actively developed, and — importantly — a hardened derivative ofvllm-mlx, not a rival
engine. Its headline speed multipliers are author-reported and should be
discounted. Its genuinely interesting feature is tool-call auto-repair: it
detects malformed tool output and reshapes it back into a valid tool_calls
structure, plus a prompt cache. Because it shares DNA with the current backend,
the right move is a scoped A/B on tool-calling reliability under multi-round
load — not a swap chasing a tokens-per-second headline.
Tool calling is the real failure mode
The number-one way a local agent breaks isn’t speed — it’s a tool call that doesn’t parse. Two things cause most of it:- Parser mismatch. The server’s tool-call parser has to match the model’s
chat template. The wrong parser produces correct-looking JSON that the server
mangles, or silently drops the call. This stack defaults to the
hermesparser, which in vllm-mlx reads the<tool_call>XML its resident Qwen-family models emit; a different model family needs its own parser. - Quantization drift under long loops. A 4-bit model can format tool calls perfectly for the first several turns and then start emitting subtly invalid structure deep into an agentic trace. This is where auto-repair earns its keep.
- No parser at all for the model’s format. This is the one that gets
misdiagnosed as a bad model. A large open-weights model emitted its own
channel markup as raw text in the assistant
contentfield, withfinish_reason: stopand notool_callsarray — the call was semantically correct and the serving layer simply dropped it, because the server ships no parser for that format (verified 2026-07-26/27). It leaks into ordinary completions too. This is the same failure class as an agent runtime leaking raw<function=…>markup into a summary: the reasoning was fine, the plumbing lost it.
Per-model tool-call verification is a required gate, not a nice-to-have.
Before a model is used for agent work, send a real tool-calling request to
/v1/chat/completions through the deployed server and confirm a populated
tool_calls array — across several turns, not one. Read content on the same
response: if it holds anything that looks like call markup, the parser is
missing, no matter how healthy the HTTP status looks. A model that cannot emit
a structured tool call through this server is disqualified for agent work no
matter how good it is, because the agent never sees the call.Per-model configuration divergence is the intended end state, not a smell.
A tool-call parser, a reasoning parser, and a chat-template flag are properties
of the model’s own output format. Forcing every model through one shared
setting is what produces silent leaks; a per-model toggle is the correct shape,
and a catalog that looks inconsistent across models is usually just accurate.
Related
Apple Silicon stack
The
llama-swap + vllm-mlx stack these backends slot into.Models & quantization
The quants whose tool formatting the parser has to keep up with.
AI development pipeline
How local serving is routed alongside the cloud providers.
Benchmarking
Where backend claims get measured instead of believed.
Verifying the instrument
Proving which weights a server actually loaded before you trust its numbers.