AI model releases April 2026, read from 34 lines of routing code
April 2026 dropped seven frontier models on the industry in under three weeks: Gemma 4 on April 2, Llama 4 Scout and Maverick on April 5, Claude Mythos (held back) on April 7, GPT-5.4 on April 10, Gemini 3.1 Ultra on April 12, Claude Opus 4.7 GA on April 14, Grok 4.20 on April 17, DeepSeek V3.2 on April 18. Every SERP roundup lists specs, benchmarks, and pricing. None of them cover the side of the story I actually shipped: what a running Mac assistant had to do so that any of those models reached a user without a new notarized binary. For Fazm the answer is three small functions, 34 lines total, and zero releases in April.
April 2026 frontier releases
One release every two and a half days
The model list is the one thing you cannot hardcode in a consumer app anymore. The release cadence in April 2026 is fast enough that any app shipping with pinned provider IDs is already a week behind the SDK by the time it reaches the App Store.
April 2026 by the numbers, Fazm side
Fazm did not ship a single release in April 2026 to absorb the month's model launches. The three numbers that matter are how many releases there were, how many lines of Fazm code they touched, and how many of them required the app to be re-built. The third number is zero.
Line counts include blank lines and comments. Function bodies are roughly 35 lines (updateModels), 11 lines (emitModelsIfChanged), 12 lines (the set_model branch inside handleQuery).
How a new model reaches a running Fazm session
The Claude Agent SDK is on the left. The ACP bridge and Swift app are the hub. The user's picker is on the right. The path from left to right does not touch a single file on disk that is not already installed.
Left: SDK streams models. Hub: bridge + app classify. Right: floating bar picker.
The three-hop path, drawn
When a user mid-conversation presses a hotkey to change the active model, Fazm does not create a new ACP session. It switches the existing one via session/set_model. The diagram below traces the exact messages.
User hotkey -> session/set_model -> next reply
updateModels, the 35-line Swift router
The entire Scary / Fast / Smart classification lives in this function. The only hardcoded strings are the three substrings in modelFamilyMap. Any model id the SDK reports that contains any of them lands in the right slot with the right label.
emitModelsIfChanged, the 11-line bridge
The ACP SDK hands the bridge an availableModels array on every session/new response. The bridge filters the non-selectable default entry, JSON-serializes the list, compares it to the last one it emitted, and only sends a 'models_available' message to the Swift app when the list actually changed. Cheap to call, idempotent, and silent when nothing moved.
The 12-line hot-swap branch
Inside handleQuery in the ACP bridge, the 'reuse existing session' branch reads the session's current model, compares it to the requested one, and only calls session/set_model when they differ. The log line 'switched model X -> Y' is the string to grep for in stderr when you want to confirm a mid-conversation swap actually happened.
Verify the claims against the repo
The three function paths above are visible in the public repository. Running the commands below against a fresh clone reproduces the file names and line numbers cited on this page.
Day by day through April 2026
What happened on each release date, what Fazm's routing code had to do about it, and what changed in the installed app binary. The short version is: Fazm did not ship in April. The long version is below.
2026-04-02 - Google Gemma 4 open-source family
Four variants up to 31B, Apache 2.0. A pinned-ID Mac app needs code to surface any new Gemma id. Fazm's path: none, because the ACP SDK only surfaces models the active bridge speaks to.
2026-04-05 - Meta Llama 4 Scout + Maverick
Open-weight MoE with 1M and 10M token context windows. Self-hostable at 400B. Again, routing through Fazm happens via whichever SDK the bridge connects to; the Scary/Fast/Smart labels still hold as long as the family name is in the model id.
2026-04-07 - Claude Mythos (restricted)
Anthropic's ten-trillion-parameter internal model, held back for safety review. Not in availableModels yet. emitModelsIfChanged does not emit what the SDK does not report; no Fazm change required.
2026-04-10 - OpenAI GPT-5.4 (Standard / Thinking / Pro)
1.05M token context, 33 percent fewer claim errors than GPT-5.2. Not routed through Fazm today (the bridge uses the Claude Agent SDK). A future bridge addition extends the modelFamilyMap tuple, not the updateModels function body.
2026-04-12 - Google Gemini 3.1 Ultra
Native multimodal reasoning with real-time processing. Same routing story as GPT-5.4: orthogonal to the Scary/Fast/Smart tuple today, but the architecture is unchanged by a new provider.
2026-04-14 - Anthropic Claude Opus 4.7 GA
The ACP SDK starts returning 'opus' in availableModels. emitModelsIfChanged detects the changed JSON, sends models_available to the Swift app, updateModels substring-matches 'opus' into order 2 (Smart, Opus, latest). No app binary rebuild. No Sparkle release. No notarization.
2026-04-17 - xAI Grok 4.20
Real-time web access improvements. Routed independently of ACP; relevant here only to note that the April 2026 release cadence is roughly one frontier model every two days, which is why the 'cleanup, not release' pattern matters.
2026-04-18 - DeepSeek V3.2
~90 percent of GPT-5.4 quality at roughly $0.28 per million tokens. Not yet routed through Fazm, but the same architectural play applies: substring 'deepseek' can be added to modelFamilyMap in a single line if the bridge ever speaks to DeepSeek directly.
What each function absorbs
Five small Swift and TypeScript functions, each doing one thing. Lined up, they are the whole architecture for absorbing model releases without cutting app releases.
emitModelsIfChanged
Reads the Claude Agent SDK's availableModels list at session/new time, filters out the non-selectable 'default' pseudo-model, compares the serialized list to the last one emitted, and sends a models_available message to the app only when the list actually changed. Zero traffic on unchanged state.
updateModels
Receives the emitted list, substring-matches each modelId against three rows in modelFamilyMap (haiku=0, sonnet=1, opus=2), sorts the result, and mutates availableModels only when the list actually changed. A future 'claude-haiku-5-0' would land in the Scary slot with no code change.
session/set_model
Compares requestedModel to the ACP session's current model and calls the session/set_model endpoint when they differ. The ACP session is reused, not recreated. Message history is preserved. The next reply comes from the new model.
normalizeModelId
Collapses any legacy full id ('claude-opus-4-6') to its short alias ('opus') via substring match. A user's UserDefaults from a pre-April-18 install is rewritten on first launch after the upgrade. No settings reset, no model-not-found error.
One-time migration
ShortcutSettings init collapses any saved opus-family id to 'sonnet' for rate-limit sanity, and normalizes all other saved ids to their short aliases. A user who had 'claude-sonnet-4-6' selected wakes up with 'sonnet' selected the next launch. Same model, shorter id.
Pinned-ID Mac apps vs Fazm's three-function router
Row by row, what each side has to do when a new frontier model lands.
| Feature | Pinned-ID Mac apps | Fazm |
|---|---|---|
| New model ID appears in SDK | App ignores it until a release adds the string | emitModelsIfChanged fires models_available; UI renders it |
| Unknown family name in model ID | App fails lookup, drops to default | Substring match in modelFamilyMap, unknown falls back to order 99 but is still selectable |
| Mid-conversation model change | Kills session, loses message history | session/set_model on existing sessionId, history preserved |
| Legacy full ID in saved settings | Shows 'model not found' or resets to default | normalizeModelId collapses it to short alias, UserDefaults rewritten silently |
| New frontier release like Opus 4.7 | Requires new notarized binary + Sparkle tick + App Store review | Appears on next app launch via the already-installed binary |
| Lines of routing code total | Scattered across settings page, provider client, release branches | ~34 lines across three functions: updateModels (35), emitModelsIfChanged (11), set_model branch (12) |
Most pinned-ID apps get fine by cutting an AppStore release within 10-14 days. Fazm does not cut a release at all.
What this has to do with accessibility APIs
Nothing directly, and that is the point. Fazm reads the Mac's accessibility tree via AXUIElement / AXObserver rather than taking screenshots and OCR-ing them, which is how most browser-bound agents work. That choice governs how Fazm sees any app on the Mac, not which Claude model generates the next reply. The two layers are independent by design, which is why a month of frontier-model launches did not touch a single AX call and why a future macOS AX change would not touch the three routing functions.
Two layers, one app
Inference layer
emitModelsIfChanged, updateModels, session/set_model. Lives in the cloud. Absorbs every Anthropic model release with zero app changes.
Perception layer
AXUIElement, AXObserver, system permission prompts. Lives on the Mac. Gives the model real structural context from any app on screen, not pixels of a browser tab.
Want this routing pattern in your own Mac app?
Thirty minutes, live on my screen, walking through the exact Swift and TypeScript that absorbs a new LLM release without a new binary.
Book a call →Frequently asked questions
Which AI models were released in April 2026?
Public data aggregators (LLM Stats, Releasebot, devFlokers, buildfastwithai) track seven frontier launches in the month. OpenAI shipped GPT-5.4 in Standard, Thinking, and Pro variants with a 1.05M token context window. Anthropic shipped Claude Opus 4.7 to general availability at Opus 4.6 pricing, plus a held-back internal model called Mythos. Google DeepMind shipped Gemini 3.1 Ultra and an open Gemma 4 family under Apache 2.0. Meta open-sourced Llama 4 Scout and Maverick, the latter a 400B MoE with a 10M token context window. xAI pushed Grok 4.20 with real-time web access. DeepSeek shipped V3.2 at roughly $0.28 per million tokens. This page does not repeat those specs; it covers the architecture a consumer Mac assistant needs so that all seven land in the app without a binary release.
What is the downstream consumer-app problem that every SERP result skips?
The entire top 10 SERP for 'ai model releases april 2026' lists specs, benchmarks, and pricing. None of them describe what a consumer-facing desktop app has to do on its side when a new model drops. A Mac app that pins the string 'claude-opus-4-6' in compiled Swift exposes Opus 4.6 until the team ships a new notarized binary through Apple's process. A Mac app that pins 'gpt-5-turbo' in a dropdown stays on that model until someone cuts a release. Fazm's approach is to treat the model list as a stream, not a constant, so the Anthropic / ACP SDK can tell the running app about a new model and the user can use it before the code ever compiles.
What exactly are the three functions that make this work in Fazm?
emitModelsIfChanged at acp-bridge/src/index.ts:1271 reads the availableModels list from the ACP SDK every time a session opens, filters out the 'default' pseudo-model, and sends a 'models_available' message to the Swift app only when the serialized list actually changed. updateModels at Desktop/Sources/FloatingControlBar/ShortcutSettings.swift:178 receives that list and re-classifies each entry through the modelFamilyMap tuple: any modelId containing 'haiku' lands in slot 0 (Scary), 'sonnet' in slot 1 (Fast), 'opus' in slot 2 (Smart), anything else in slot 99 (unknown). session/set_model at acp-bridge/src/index.ts:1503 compares the user's requested model to the session's current model and, if they differ, calls the ACP endpoint to switch the model on the live session without creating a new one.
What does the substring-match in modelFamilyMap actually buy me?
It makes unknown future models work. If Anthropic ships 'claude-haiku-5-0' tomorrow, the SDK will include it in availableModels. The updateModels function loops through the modelFamilyMap tuple and finds that 'haiku' is a substring of the new modelId. The new model automatically gets the label 'Scary (Haiku, latest)', lands at order 0 in the UI, and shows up in the floating bar's model picker the next time the user opens it. No code change. Same for a future 'claude-sonnet-5-0' or 'claude-opus-5-0'. The only time the substring match falls back to order 99 is for a genuinely unknown family, and even then the model is still selectable in the UI; it just doesn't get the three-letter label.
Why is mid-conversation hot-swap via session/set_model interesting?
Because a user's conversation is context. If a user has been chatting with Fazm on Sonnet for half an hour and decides the next question needs Opus-level reasoning, the naive implementation is to kill the ACP session, start a new one with Opus, and lose the entire message history. Fazm avoids that by calling session/set_model on the existing sessionId. The ACP session stays alive, the message history stays intact, and the next reply is generated by the new model. Code path: handleQuery at acp-bridge/src/index.ts:1499-1509. The key line reads `await acpRequest('session/set_model', { sessionId, modelId: requestedModel })`.
Does Fazm care which provider the model came from?
Fazm uses the Claude Agent SDK via the ACP bridge, so at the time of writing the default path is Anthropic models (Haiku, Sonnet, Opus). The routing code does not encode any Anthropic-specific assumptions inside modelFamilyMap; the substring 'haiku' is only meaningful because Anthropic's naming convention uses family names in the modelId. A future change to route queries through a different SDK would extend the tuple, not rewrite the function. The architecture is the same: SDK streams the list, app re-sorts it, bridge calls set_model.
Where does Fazm's accessibility-API architecture enter this picture?
It doesn't. The model-routing code is about the cloud inference layer: which LLM generates the next reply. Fazm's accessibility-API architecture is about the local perception layer: how Fazm sees any app on the Mac via AXUIElement rather than by taking screenshots and OCR-ing them. Both layers are independent by design. A Claude model release touches the first layer and changes nothing about the second. A macOS update that breaks AX queries would touch the second and change nothing about the first. The April 2026 releases landed without a single AX call being modified.
Can I verify the functions and line numbers this page cites?
Yes, and you should. The Fazm repository is public at github.com/mediar-ai/fazm. Run `git grep -n emitModelsIfChanged acp-bridge/src/index.ts` to find the function definition at line 1271. Run `git grep -n 'func updateModels' Desktop/Sources/FloatingControlBar/ShortcutSettings.swift` to land at line 178. Run `git grep -n 'session/set_model' acp-bridge/src/index.ts` to see all seven call sites. The interesting one for mid-conversation hot-swap is line 1503 inside the 'Reusing existing ACP session' branch. All line numbers are post-commit as of 2026-04-19.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.