C.W.K.
Stream
Lesson 10 of 10 · published

The Adapter Pattern for Multi-Provider Code

~14 min · providers, adapter

Level 0Apprentice
0 XP0/100 lessons0/14 achievements
0/120 XP to next level120 XP to go0% complete

One narrow boundary, many implementations

The way to handle multiple providers without rewriting your stack: define an adapter interface that captures the streaming-call surface, then implement it per provider. The rest of your code (routes, store, frontend) calls the adapter, never the provider SDK directly.

What the adapter covers

  • Streaming call (system prompt, messages, tools, tool_choice, sampler params, max_tokens, optional reasoning budget).
  • Event yield: token deltas, tool-call deltas, finish reason, usage data.
  • Error normalization (429s, 5xx, content-policy refusals).

What the adapter doesn't cover

  • Application logic (routing, history, RAG).
  • Storage.
  • UI.

Keep the adapter narrow. The temptation is to abstract everything; resist. The cwkPippa codebase uses exactly this pattern — see backend/adapters/base.py.

Code

Minimal adapter interface (sketch)·python
class Adapter(Protocol):
    async def stream(
        self,
        *,
        system: str,
        messages: list[Message],
        tools: list[Tool] | None = None,
        tool_choice: ToolChoice = "auto",
        temperature: float = 0.2,
        max_tokens: int = 1024,
        thinking_budget: int | None = None,
    ) -> AsyncIterator[Event]:
        ...

class ClaudeAdapter:
    async def stream(self, **kw) -> AsyncIterator[Event]:
        ...  # talks to anthropic SDK

class OpenAIAdapter:
    async def stream(self, **kw) -> AsyncIterator[Event]:
        ...  # talks to openai SDK

class GeminiAdapter:
    async def stream(self, **kw) -> AsyncIterator[Event]:
        ...  # talks to gemini SDK

Exercise

Sketch an adapter interface for your codebase that covers exactly the streaming-call surface and nothing more. Implement it for two providers. Verify the rest of your code is unchanged.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.