A guided walkthrough. Do the steps in order. Each one has a small exercise.
python3 demo.py
Read scenario 1. Notice veo-3 is excluded because the user is on the creator plan. Everything else is sorted by price.
Open models.json. Each model has:
min_plan: which pricing tier unlocks it (this is your packaging decision)capabilities: what it can doendpoints: the vendors that sell it, with priority (fallback order) and costExercise: change veo-3’s min_plan from "pro" to "creator" and rerun. Veo now appears in scenario 1’s try order. You just changed packaging without touching code.
Open router/resolver.py.
_model_blockers() returns a reason if a model can’t do the job. That’s a hard constraint: filter it out..sort(...) at the bottom is the soft preference: among models that can, which do we try first?Exercise: in auto mode we sort by cost. What if you sorted by priority first instead? Would quality or margin change? (This is exactly the kind of tradeoff a PM owns.)
Open router/runner.py and read classify().
| Status | Meaning | Decision |
|---|---|---|
| timeout, 429, 5xx | Vendor is struggling | Retryable: try the next one |
| 400, 451 | Your request is the problem | Permanent: stop |
Exercise: in demo.py, change scenario 4’s "content_policy" to "rate_limit" and rerun. Watch it fail over instead of stopping.
python3 -m unittest -v
Open tests/test_router.py. Each test name reads like a requirement: test_permanent_error_stops_and_bills_nothing. Tests are acceptance criteria that run themselves.
Exercise: break something on purpose (make classify return RETRYABLE for everything), run the tests, and see which requirement fails. Then undo it.
Practice saying this out loud:
“We routed across several video models and vendors from one config file. Hard constraints filter, soft preferences order. Outages fail over, bad requests stop immediately, and users always pay the quoted price, so the cost of vendor unreliability shows up on our margin, where we can manage it, not on the customer’s bill.”