How Doozer decides which AI model to use for each function, when, why, and for what — balancing quality against cost by the value of the work, learning from its own scores, and staying provider-diverse on purpose.
Doozer does not use one model for everything, and it does not chase the cheapest model. It uses the best model for each job — chosen intelligently, weighed by the value of the work against its cost, and refined by what the work actually scored. "The best man for the job", made mechanical.
Build Solid A rated sites — accurate, beautiful, tasteful, helpful,
valuable, useful — for every business that should have one. Par-create
decides who should have one. The scoring of what we build drives the resources
spent on the next build. The fleet average climbs generation over generation.
Solid A = weighted ≥ 85 across the six goals (dzQualityGoal(), tunable platform_settings.doozer_quality_goal). This is not a per-site retry loop — we build sites one after another, each using the current best-known strategy, and the results steer the next build. When a choice raises a niche's average we keep it; when a choice regresses it, we undo that choice and try another until the score climbs. Doozer builds because — and it gets better every generation, toward leading-edge, lead-generating sites at scale.
quality-autopilot.php)The unit of improvement is the niche — sites within a niche score alike, so a strategy that lifts one lifts them all. Each niche holds a niche_build_policy (the current strategy: model tier, deep-facts on/off, the baseline it's beating). qualityRatchetTick() (dz goal autopilot=1 go=1):
+ deep source-of-truth). Record the baseline to beat.
improved → commit (new baseline, keep climbing); regressed → revert the choice and mark that lever "tried, didn't help" so the next pass reaches for a different one; flat → hold, gather more data.
The router reads the niche policy (aiForJob($job, ['niche'=>...])) and escalates accordingly. dz goal reports fleet average, at-goal count, and per-niche standing worst-first — the niches the ratchet is working on.
First reading (July 2026): fleet 80.3, goal 85, 12/46 at goal. Weakest niche: restaurant (74, accuracy 67) — high fact density (menus/prices/specials) is where content invents things. Escalated. Real-estate (84/acc 88) and non-profits (84) are already near goal. The single biggest accuracy lever is reading the real website: prefer the free Jina source-of-truth cache over the paid, deprecated Firecrawl deep_research (v0 API) — same job, better accuracy, no cost. Retiring Firecrawl for enrichment is the recommended consolidation.
This is doctrine, not a setting. It encodes how much care goes into a Doozer site: the accuracy, the taste, the scoring, the deliberate balance of cost and quality — and the deliberate refusal to become dependent on any one AI house. Doozer builds because. It does not waste time, and it does not waste money — but it never trades away real value to save pennies.
Code: includes/ai-job-router.php (the engine), includes/ai-models.php (the model catalog + tiers + cost map), includes/site-scoring.php (the feedback). Operator surface: dz aimodels, dz aimodels pool=1.
"There is no reason to use a cheap model for even a slight loss in quality if
the value is still hundreds of times the cost."
So the question is never "what is cheapest." It is: is the quality I would give up by going cheaper worth more than the money I would save? If yes, GO HARD.
| Tier | Framing | Anthropic | OpenAI | xAI | |
|---|---|---|---|---|---|
| flagship | GO HARD | Opus 4.8 | GPT-5 | Grok 4 | Gemini 2.5 Pro |
| balanced | Solid A | Sonnet 5 | GPT-5 mini | Grok 4 Fast | Gemini 2.5 Flash |
| budget | Economy | Haiku 4.5 | GPT-5 nano | Grok 3 mini | Gemini Flash-Lite |
The tier resolves to the current best model in that class via aiModelResolve() — so when a new model ships, we update the catalog in one place and every job that asked for a class is upgraded. Pin a concrete id only to freeze a chore to a known model.
Every AI function declares four things (aiJobRegistry()):
job. A label is a label (spread ≈ 0.02: a cheap model nails it). Bespoke site copy is not (spread ≈ 0.15: the creative gap is real and worth paying for). Difficulty, not just value, decides.
The engine walks candidates best-quality-first (flagship → floor) and steps down to a cheaper model only when:
Δquality × value ≤ Δcost
The dollar value of the quality you'd lose vs the dollars you'd save. It stops at the first step where quality is worth more than the savings — that is the sweet spot. For a high-value output (a site that is a claimable lead), the pennies of cost delta never outweigh the quality, so it goes hard. For instrumentation (scoring) or trivia (classification), the cheap model is genuinely good enough.
Quality per tier starts from a difficulty-aware prior (1 − spread × tierPenalty, penalty: flagship 0, balanced 0.5, budget 1.0) and is then blended toward measured evidence as real scores accumulate.
design/Muse, strategy, oracle, enrichment, marketing, conversation, vision. These touch the customer or feed accuracy; their quality is worth far more than the cost delta.
insensitive and high-volume, so Solid A is the sweet spot.
volume; a cheap model is as good, and at volume the cost is what matters.
See it live: dz aimodels prints job → choice → model → value → est cost → why.
Priors are a starting belief, not the last word. Every scored site feeds aiRecordJobQuality(job, provider, model, score) into ai_model_quality, so the engine learns the real quality each model produces for each job — the score from one model vs another, over real Doozer sites. Content generation records which model wrote a site (businesses.custom_settings.content_model); when the six-goal scorer rates that site, the score is credited to the model that wrote it. Over time the decision sharpens from evidence, not assumption.
A small share of eligible calls (≈10%) is routed to an alternate provider of the same tier. This is deliberate: it keeps quality estimates fresh across houses, keeps every vendor warm and callable, and means Doozer is never hostage to one AI company's pricing, availability, or policy. If one house stumbles, the work keeps flowing. Diversity is resilience, and it is also honesty about the fact that different models genuinely produce different results for the same prompt.
The algorithm is the default, not a cage. Per call: ['hard' => true] forces flagship, ['tier' => ...] / ['provider' => ...] pin a choice. Per job: platform_settings.ai_job_tier.<job> and ai_job_provider.<job> (dz aimodels set job=<j> tier=<t> provider=<p>). Only callable models (API key present) are ever chosen, so it just works as keys come and go.
thinking content block first — code must scan content[] for the text block, never assume content[0]. Both callAnthropic and generateWithClaude do.
share of the completion budget on reasoning before the answer, so JSON/structured tasks need generous max_completion_tokens (the router path adds headroom).
googleapi_keys row to be callable.
generateContentFlexible) should set__lastContentModel too, so the learning loop captures every content route, not just generateWithClaude.
aiForJob():muse-family-generator, muse-recompute-palette, ai-classifier, anthropic-chat.
A Doozer site is built with care: real source material read and fact-checked, six goals measured, taste enforced. The model behind that work is chosen with the same care — the best tool for each job, paid for when the value is there, saved when it is not, learned from what it produced, and never locked to one vendor. That is how we create value without wasting time or money.