LiteLLMLiteLLM 1.101 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
20 small wins to finish your pathNext lesson

Why one interface: every provider speaks differently

Two model providers can do the same job and still disagree on where instructions go and where the answer is. Code written for one breaks on the other.

A request and its answer in the shape of OpenAI's Chat Completions API:

Example
openai_request = {
    "model": "gpt-4o-mini",
    "messages": [
        {"role": "system", "content": "You sort support tickets."},
        {"role": "user", "content": "I was charged twice"},
    ],
}
openai_reply = {"choices": [{"message": {"role": "assistant", "content": "billing"}}]}

The same request for Anthropic's Messages API. The system instruction moves out of messages into its own field, max_tokens is required, and the answer comes back as a list of content blocks:

Example
anthropic_request = {
    "model": "claude-sonnet-4-5",
    "max_tokens": 100,
    "system": "You sort support tickets.",
    "messages": [{"role": "user", "content": "I was charged twice"}],
}
anthropic_reply = {"content": [{"type": "text", "text": "billing"}]}
Example
print(openai_reply["choices"][0]["message"]["content"])
print(anthropic_reply["content"][0]["text"])

Same answer, two different paths to reach it. Multiply that by request fields, streaming formats, error types, token counting and prices, and an app that can switch between providers carries a translation layer for each one.

What LiteLLM does

LiteLLM takes every request in the OpenAI shape and returns every answer in it, translating to and from each provider underneath. Changing provider becomes changing a string: "openai/gpt-4o-mini" to "anthropic/claude-sonnet-4-5". On top of that one interface it adds what every production app ends up writing: retries, fallbacks, caching, cost tracking and a shared gateway.

Try it yourself
  • Write the path to the answer for a reply shaped like {"output": [{"content": [{"text": "billing"}]}]}.
  • List three fields a provider could rename that would break the code above.
  • Write a function answer_text(reply) that handles both shapes. How long would it get with ten providers?

Little by little, you're building something great.