CSE Roadmap

Common tier · about 4 hours · 5 parts

Part 4 of 5 · 3 min read

Exercises

Easy

Easy 1: List the differences (20 minutes)

Write a table with at least six differences between StyleA and StyleB in wire.py (system prompt, required fields, reply shape, usage names, stop names, error body).

Done when: each row names the field on both sides.

Easy 2: Add a stop reason (15 minutes)

Imitation provider A can also return finish_reason: "content_filter". Add a neutral stop value "blocked" and map it, then test it. Check that other unknown values still give "other".

Done when: a test sends a request that makes the provider return it.

Hint

change the mapping table, and keep the neutral name in Response.stop.

Easy 3: Spot the leak (20 minutes)

Read a small piece of code (yours or an example you write) that calls a provider directly in ten places. List what would have to change to add a second provider, and which of those changes the adapter would remove.

Done when: you have a short list and a one-sentence conclusion.

Medium

Medium 1: Provider C (60 minutes)

Write a third imitation provider whose reply is plain text on the first line and a JSON usage object on the last line, with the system prompt as a first message that says [system] .... Write its adapter and tests without changing Router or the app code.

Done when: the whole existing test suite passes unchanged with C added.

Hint

the adapter is the only code that should mention the new format.

Medium 2: Ledger in the layer (60 minutes)

Make Router.complete write one ledger record (module 6) for each successful call with the provider's name, and one record with zero tokens for each failure. Test a fallback and read the records.

Done when: the ledger shows both providers in the right order.

Medium 3: Retry before fallback (60 minutes)

Use module 5's retry_call around each adapter so a provider gets up to 3 tries on retryable errors before the router moves on. Test with a provider that fails twice then succeeds, and one that always fails.

Done when: the first is answered by provider A on the third try, and the second falls back to B.

Hint

wrap adapter.complete in a lambda for retry_call, and treat ProviderError.retryable as your retry rule. retry_call retries ApiError objects, so convert or adapt is_retryable.

Hard

Hard 1: Messages and tools (120 minutes)

Extend the neutral types with tool calls: a response can contain tool_calls, and a request can contain tool results. Give both imitation providers different tool formats, write both adapters, and run module 4's loop unchanged against either.

Done when: the same scripted agent test passes with provider A and with provider B.

Hint

a neutral tool call needs an ID, a name and arguments. Each adapter maps these to its own shape and back.

Hard 2: Contract tests (120 minutes)

Write one test suite that runs against every adapter (use pytest.mark.parametrize): same requests, same expectations on the neutral response and the error mapping. Add a deliberately broken adapter to show the suite catches it.

Done when: the suite passes for good adapters and fails with a clear message for the broken one.

Hint

put the adapter classes in a list and parametrize on it.

Hard 3: Weighted routing (120 minutes)

Add a router mode that sends a configurable share of traffic (for example 10%) to provider B first, and records latency and failure per provider. Simulate 1,000 requests with provider B failing 5% of the time, and report the observed shares and failure rates.

Done when: shares are within 2 percentage points of the target on a seeded run.