LiteLLM: o tradutor invisível entre Claude Code e qualquer API
Por que o Claude Code não fala com a Zhipu diretamente, o que o LiteLLM faz e quando vale o proxy.
O problema
Depois de colocar o Claude Code rodando com a Zhipu no artigo anterior, eu comecei a me perguntar: mas afinal, o que é esse tal de LiteLLM? Eu simplesmente copiei o arquivo de configuração config.yaml de um tutorial, a coisa funcionou, mas eu não fazia ideia do que estava acontecendo no meio do caminho entre o programa claude e a API (a ponte de comunicação) da Zhipu. Isso me incomodava — não porque tivesse dado errado, mas porque quando eventualmente desse algum problema, eu não saberia nem por onde começar a debugar (ou seja, investigar e corrigir o erro).
A pergunta por trás disso é bem simples: o Claude Code fala um dialeto (o formato de mensagem próprio da empresa Anthropic). A Zhipu fala outro dialeto (muito parecido com o da OpenAI, mas com algumas particularidades). Como é que essas duas pontas conseguem conversar sem que nenhuma delas saiba da existência da outra?
A resposta é usar um proxy no meio do caminho — que nada mais é do que um intermediário ou tradutor. Entender como esse tradutor funciona virou um pré-requisito para qualquer ajuste fino que eu quisesse fazer depois.
Levei umas duas horas só mapeando esse caminho da informação até ele fazer sentido — e boa parte do tempo eu passei desconfiando de mim mesmo, achando que era “muito simples pra ser só isso”. E pior que era simples mesmo!
A fragmentação que ninguém explica
Se você já tentou usar mais de um modelo de Inteligência Artificial no seu código, com certeza esbarrou nisto: cada empresa inventou o seu próprio formato de pedido (o que no mundo técnico chamamos de schema ou estrutura de dados).
- A Anthropic usa um formato.
- A OpenAI usa outro formato diferente.
- O Google (Gemini) usa um terceiro formato.
- As empresas chinesas (Zhipu, DeepSeek) tentam imitar o formato da OpenAI, mas colocam suas próprias variações.
O Claude Code foi construído para falar apenas o dialeto da Anthropic. Tentar apontar ele direto para a API da Zhipu é como mandar uma carta em português para alguém que só lê chinês — a mensagem até chega, mas a Zhipu devolve um erro e você fica sem saber quem errou. (Spoiler: nenhum dos dois errou. Eles só não falam a mesma língua.)
O tradutor no meio
É aqui que entra o LiteLLM. Ele funciona como um proxy — um aplicativo intermediário que roda localmente, dentro da sua própria máquina, “ouvindo” em um endereço específico (no meu caso, a porta localhost:4001, que funciona como se fosse um ramal interno do seu computador).
O fluxo funciona como uma linha de montagem:
Você → Claude Code → LiteLLM (localhost:4001) → API da Zhipu → GLM
Vamos ao passo a passo do que acontece em cada pedido (ou request):
- O Claude Code monta uma mensagem no formato que a Anthropic entende.
- Em vez de mandar essa mensagem direto para a internet na
api.anthropic.com, ele envia para o LiteLLM que está rodando na sua máquina. - O LiteLLM recebe o texto no formato da Anthropic, traduz na hora para o formato que a Zhipu entende, e aí sim faz o envio de verdade para a internet.
- A resposta da Zhipu chega de volta no formato dela; o LiteLLM traduz novamente para o formato da Anthropic e entrega o resultado para o Claude Code.
Resultado: o Claude Code acha que conversou perfeitamente com a Anthropic. A Zhipu acha que recebeu um pedido normal. Nenhum dos dois precisa saber da existência do outro. Isso é o que a TI chama de abstração — que não é esconder as coisas com termos bonitos, mas sim tirar a complexidade do seu caminho para que tudo funcione.
O caso do Thinking Mode
O exemplo mais prático de por que essa tradução não é tão simples é o Thinking Mode (aquele parâmetro de “Esforço” de raciocínio que você configura no Claude Code).
Quando você pede para o modelo aplicar mais esforço na resposta, a Anthropic envia uma instrução chamada budget_tokens (um limite de fichas/palavras para o modelo “pensar”) dentro de um bloco chamado thinking:
{
"model": "claude-3-5-sonnet",
"thinking": { "budget_tokens": 4096 }
}
O problema é que a Zhipu não faz a menor ideia do que seja esse budget_tokens. Se esse parâmetro chegasse do jeito que está, a API da Zhipu daria um erro na hora.
O LiteLLM resolve isso de duas formas, dependendo de como você o configura: ou ele traduz essa intenção para algo equivalente que a Zhipu entenda, ou ele simplesmente descarta a informação sem quebrar nada. É por isso que no arquivo config.yaml existe aquela linha drop_params: true — ela avisa ao nosso intermediário: “se aparecer algum parâmetro de configuração que o sistema de destino não suporte, jogue fora em silêncio em vez de travar tudo com um erro”.
Sem entender isso, eu ficaria totalmente perdido quando o “Esforço alto” parecesse não mudar nada na prática. Sabendo do funcionamento, tudo faz sentido: o parâmetro só está sendo ignorado porque a IA do outro lado não tem um botão equivalente.
Endpoint nativo vs LiteLLM — por que ainda usar o proxy
Aqui é onde a coisa fica interessante e onde eu quase cometi o erro de abandonar o LiteLLM sem necessidade. A própria Zhipu lançou um endpoint nativo (um endereço direto na web: /api/anthropic) que finge ser a API da Anthropic. Com ele, na teoria, o Claude Code funcionaria direto, sem precisar do nosso tradutor no meio.
Então por que eu continuo usando o LiteLLM? Por causa do plano de assinatura Developer (Coding) Plan. O endereço nativo da Zhipu não redireciona as chamadas para o endereço /api/coding/paas/v4 — que é a rota específica para os assinantes deste plano, ou seja, a rota que não gasta seus créditos avulsos.
Usar o endereço nativo me jogava direto no sistema pay-as-you-go (onde você paga por cada requisição individualmente), acabando com o meu saldo em pouco tempo. O LiteLLM me dá um controle total: eu consigo apontar a comunicação exatamente para o endereço que eu quero, mapeando cada modelo da forma correta. Eu contei como essa confusão de endereços me custou uma tarde inteira travado por erro de limite de requisições (RateLimit) no artigo sobre cotas e billing.
Se você não usa o plano de assinatura e só quer ver o sistema funcionando o mais rápido possível, o endereço nativo pode ser suficiente. Mas se você busca economia e controle, o proxy intermediário ainda vale muito a pena.
O que aprendi
A grande lição dessa experiência que serve para qualquer projeto de tecnologia é: uma camada de tradução bem feita é invisível, e é justamente essa invisibilidade que torna difícil consertar as coisas quando elas quebram.
Quando a minha configuração funcionou de primeira, eu não tinha entendido o porquê; quando precisei alterar uma opção, percebi que não sabia por onde a informação passava. A partir daquele momento, decidi mapear o caminho dos dados antes de ter problemas — desenhando as conexões e dando nome a quem envia o quê para quem. Fazer isso leva meia hora, mas economiza horas de testes e frustrações em qualquer integração de sistemas, não apenas com Inteligência Artificial.
Comentários
Carregando comentários…