Per-state phone model routing

Safe hybrid enabled for the generated mfclaw law flow.

Configured path: caller PCM → Whisper Medium → RIFF FSM + Qwen3.5-Flash → Kokoro Bella. Gemini Live remains connected as the immediate backup.

Modes

turn_modeOwnerUse
liveGemini LiveConsent and confirmation gates.
llmWhisper → RIFF/Qwen → KokoroFreeform intake and message collection.
deterministicRIFF resolverMenus and locked choices.
Cost boundary: Whisper, Qwen, and Kokoro are cheaper in isolation, but this comparison mode may cost about the same as Gemini-only or slightly more because Gemini still receives audio and can generate the queued backup. Real savings require local endpointing and lazy Gemini invocation only after primary failure.

FSM configuration

defaults:
  llm:
    classes:
      gemini_fast: gemini-2.5-flash
      qwen_fast: qwen3.5-flash
  turn_routing:
    enabled: true
    states:
      cap_start_claim__stage_identity:
        turn_mode: llm
        llm: qwen_fast
        stt_model: mlx-community/whisper-medium.en-mlx
        tts_voice: kokoro:af_bella
        backup: live
        backup_model: inherit
      cap_start_claim__confirm:
        turn_mode: live

Edit data/site_ingest/mfclaw/overlay.yaml, then regenerate the pack and flow:

.venv/bin/python -m riff.business_pack.importers.website data/site_ingest/mfclaw --out packs/generated
.venv/bin/python -m riff.business_pack compile packs/generated/mfclaw.pack.yaml --out-dir flows

Law states on Qwen

Operation

Boot warms MLX Whisper, Kokoro Bella, and the rolling faster-whisper comparison model in the phone process. Inspect readiness:

curl -s http://127.0.0.1:8767/healthz | jq .text_turn_warmup

The authenticated /receptionist.html console shows Gemini and rolling Whisper caller rows and labels Qwen agent output.

ControlDefault
RIFF_TEXT_LLM_STT_TIMEOUT_S2.0 seconds
RIFF_TEXT_LLM_TIMEOUT_S4.0 seconds
RIFF_TEXT_LLM_MAX_AUDIO_S12.0 seconds
RIFF_TURN_MODE_ROUTING=0Emergency rollback to Gemini

Evidence

A local synthetic law identity turn captured name and callback number, advanced to matter collection, and produced local speech. One Apple Silicon run measured 484 ms Whisper, 1,326 ms Qwen/RIFF, and 2,002 ms total after endpoint including TTS. This is a readiness check, not an SLA.

No external phone call is run automatically. OTA validation requires explicit human GO.

Markdown source and full failure semantics