A local-first, two-tier router for on-device intent execution. Most things you ask a phone to do — set an alarm, dim the screen, toggle Wi-Fi, place a call — don't need a model to reason; they need a model to fill in a blank. A.L.F.R.E.D. sends those to a tiny on-device reflexer (a 2B model that fills a distilled command pattern in a single forward pass) and escalates the rest to a heavier thinker (an agent loop).
The result, in one line: a 2B reflexer with a distilled pattern matches a 17× larger free-form agent on binding (given the right intent, emitting the correct command — both 100%), while the same 2B without the pattern manages 30%. On a realistic device API, scale buys discovery, not convention — a big model can find the right setting, but not the undocumented value it expects ("total silence" =
2); a distilled pattern carries that convention.
- Two tiers. A router splits each request: deterministic, repeatable intents → reflexer; everything else → thinker.
- The reflexer is an executioner, not a generator. It executes a decision made once, offline — it does not decide what to do; it slot-fills a command shape supplied by a distilled pattern and runs it.
- Symbolic distillation. A strong teacher compresses device conventions into an inspectable JSON pattern once, offline; the cheap on-device model applies it forever. (Knowledge distillation into an artifact, not into weights — so it stays plug-and-play.)
See REPRODUCE.md. Quick start:
pip install -e .
make setup # stage example patterns into ./data/patterns
python thesis/figures/make_figures.py # regenerate all figures
tsx benchmarks/SET-2/run.ts --mode reflexer --model qwen-3.5-2b # needs a local modelA local OpenAI-compatible endpoint is required for model runs (see
REPRODUCE.md for the exact llama.cpp serving config: Q4, temp 0.2,
reasoning disabled). Figure generation and benchmark preflight need no model.
A.L.F.R.E.D. earns its keep by moving your repetitive, deterministic intents onto the on-device reflexer. To find which of your intents qualify, ask a coding agent:
"Run a full analysis of my session/usage and tell me which intents are good candidates for A.L.F.R.E.D. — i.e. where routing to a small local model would reduce my dependency on a higher model."
This touches personal usage, so the agent should ask before analyzing, keep the work local, and write nothing until you approve. The resulting shortlist of slot-fill intents is exactly the input to the symbolic-distillation step described above.
| Result | Number | Where |
|---|---|---|
| 2B + distilled pattern matches a 35B free-form agent | 100% = 100% (2B alone: 30%) | docs/findings_thinker_vs_reflexer.md |
| Best small executor: qwen-3.5-2b model sweep | 95.6% → 100% | docs/findings_reflexer_model_comparison.md |
| Clean API: a deep tool is an efficiency win | +65 pts, 2 calls instead of 9 | docs/findings_settings_distillation.md |
| Realistic API: even the 35B fails on conventions | 62.5% | docs/findings_settings_distillation.md |
| Cold-start distillation lifts the 2B | 25% → 76–80% | docs/findings_teacher_model.md |
| Teacher quality propagates (cloud vs local teacher) | 80% vs 60% | docs/findings_teacher_model.md |
| The honest bottleneck: routing, not execution | 66–85% | thesis §5.8 |
alfred/runtime/ router · reflexer · dispatcher · store · llm_client · validators
alfred/skills/ 14 mock skills (clock, media, device_settings, … docker, ffmpeg, …)
benchmarks/ SET-1 (clean API) · SET-2 (realistic Android API) · reports/
patterns/ distilled patterns (cloud vs local teacher) + expansion patterns
thesis/ the full bachelor thesis (PDF + LaTeX source)
docs/ findings reports
This is the public, runnable distillation of a larger private system. For privacy, the account-coupled skills (calendar, email, contacts, messaging, etc.) are not included; the published skills are self-contained mocks that exercise the same routing and binding paths.
If you use this work, please cite the thesis — see CITATION.cff.
MIT © 2026 David Zoidze.


