We started with one OpenAI key. Twelve months later we were calling four models from three providers. Here's the migration story — what broke, what surprised us, and what I'd do differently.
Where we started
A simple FastAPI service. One OPENAI_API_KEY in env. Every LLM feature in the product called GPT-4o. It worked great. It worked for a long time.
The cracks showed up in three places:
- Cost. Long-context summarisation on GPT-4o was eating 60% of our LLM bill for 15% of requests.
- Resilience. A 20-minute OpenAI degraded-status page took our summarisation down with it.
- Capability gaps. Our review-classification task needed Claude's structured output, which GPT handled inconsistently.
What migration looked like
Step 1 was not "rewrite everything". It was "put a gateway in front".
# Before:
# client = OpenAI(api_key=os.environ["OPENAI_KEY"])
# After:
client = OpenAI(
api_key=os.environ["GATEWAY_KEY"],
base_url="https://api.agentoken.co/v1" # <- only this changed
)
The SDK didn't change. The request shape didn't change. We just pointed base_url somewhere else.
Step 2 was re-tagging which model each feature actually needed:
| Feature | Before | After | Why |
|---|---|---|---|
| Chat completion | GPT-4o | GPT-4o | default |
| Long summarisation | GPT-4o | Claude 3.5 Haiku | cheaper, longer context |
| Classification | GPT-4o | GPT-4o-mini | trivial task |
| Structured extraction | GPT-4o | Claude 3.5 Sonnet | better JSON reliability |
Step 3 was routing by task. The gateway's model field became per-feature config, not a global constant.
What actually changed
Cost dropped ~35% in the first month. Not because we negotiated anything, but because cheap tasks stopped burning frontier tokens.
One outage stopped being a product outage. When OpenAI had a degraded window, summarisation automatically fell over to Claude. Users didn't notice.
Debugging got easier. One dashboard now shows every request: which feature, which model, how many tokens, latency. Before this was three separate billings and a spreadsheet.
What surprised me: nothing broke. Because the SDK contract was preserved, the migration took one afternoon. I'd mentally budgeted a week.
What I'd do differently
I'd put the gateway in on day one. The temptation is to wait until multi-model is "real" — but the moment you add a second feature, you're already multi-model, you're just doing it by hand.
If you're starting a new AI product today, one OpenAI-compatible gateway key is the default shape. Direct provider accounts are an optimisation, not a starting point.
Agent Token is the gateway we ended up on. Same OpenAI SDK, one bill across GPT / Claude / Gemini, automatic failover.
Curious who else has done this migration — what did your cost per request look like after?
Top comments (0)