NovoConecte qualquer agente ao UberLLM: uma chave, todos os modelos, pelo preço de tabela ou menos.
UberLLM

API de Respostas

POST https://api.uberllm.dev/v1/responses oferece a API de Respostas da OpenAI em todos os modelos de chat do catálogo. Use-a a partir do OpenAI SDK (client.responses.create), Codex CLI, ou qualquer aplicativo com um modo "Responses". As requisições passam pelo mesmo roteamento, retries, limites de chave e faturamento que /v1/chat/completions, e cada chamada é listada em Dashboard → Atividade com seu custo.

curl https://api.uberllm.dev/v1/responses \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4.1-flash",
    "instructions": "Answer in one short sentence.",
    "input": "What is the capital of France?"
  }'
from openai import OpenAI

client = OpenAI(base_url="https://api.uberllm.dev/v1", api_key="ull_...")
r = client.responses.create(model="deepseek/deepseek-v4.1-flash", input="Say hi")
print(r.output_text)

Sem estado armazenado

UberLLM não guarda respostas para você continuar depois. Toda resposta tem "store": false, e você envia a conversa inteira em input em cada chamada: mensagens anteriores do usuário, os itens de saída do modelo e os resultados das suas ferramentas. O Codex CLI já funciona dessa forma.

Estes são recusados com um 400 (code: unsupported_parameter) que nomeia o campo:

  • previous_response_id e conversation
  • background: true
  • itens de entrada do tipo item_reference
  • templates de prompt armazenados (prompt)

GET /v1/responses/{id} e as outras rotas de resposta armazenada não existem.

Requisição

Campo O que acontece
model Qualquer ID de modelo de chat, alias ou sufixo :floor / :nitro, como nas conclusões de chat.
input Uma string, ou uma lista de itens (abaixo).
instructions Enviado ao modelo como a mensagem do sistema.
stream true para eventos enviados pelo servidor.
max_output_tokens O limite de saída.
temperature, top_p, seed, stop Passado ao modelo.
tools, tool_choice, parallel_tool_calls Veja Ferramentas abaixo.
reasoning.effort Passado como o esforço de raciocínio do modelo (modelos que pensam).
text.format text, json_object, ou json_schema (saída estruturada).
metadata Suas próprias tags, mostradas na linha de Atividade, como nas conclusões de chat.
provider, models Opções de roteamento do UberLLM, como nas conclusões de chat (Modelos e roteamento).
store, include, prompt_cache_key, service_tier, truncation Aceito e não utilizado. O raciocínio criptografado é sempre retornado.

Itens de entrada

Item Torna-se
message com o papel user, assistant, system ou developer Uma mensagem de chat. developer é enviado como system. Partes do conteúdo input_text, output_text, input_image (image_url: uma URL https ou data:) e input_file (file_data ou file_url).
function_call A chamada de ferramenta do assistente, mantida em ordem.
function_call_output O resultado da ferramenta. Imagens em uma saída são enviadas na próxima vez do usuário.
custom_tool_call, custom_tool_call_output Uma chamada para uma ferramenta personalizada (de formato livre), e seu resultado.
reasoning O raciocínio anterior do modelo, devolvido ao modelo na próxima vez.
web_search_call e outros registros de ferramentas hospedadas Ignorado.

Itens id são aceitos e ignorados. file_id (arquivos enviados) não é suportado em input_image / input_file: envie o arquivo inline ou por URL.

Ferramentas

  • function: {"type": "function", "name", "description", "parameters", "strict"}. A chamada do modelo retorna como um item function_call com call_id, name e arguments (uma string JSON). Responda com um item function_call_output contendo o mesmo call_id.
  • custom (entrada de formato livre, como o apply_patch do Codex): o modelo recebe a ferramenta com uma entrada de string e a gramática em format.definition como sua descrição. A chamada retorna como um item custom_tool_call com o input bruto.
  • namespace (ferramentas MCP do Codex): cada ferramenta interna é oferecida ao modelo sob seu namespace e nome unidos (mcp__github__get_issue); a chamada retorna com name e namespace separados novamente.
  • Ferramentas hospedadas (web_search, file_search, code_interpreter, image_generation, computer_use, mcp) rodam nos próprios servidores da OpenAI. Elas são deixadas de fora da requisição e o modelo responde sem elas.

tool_choice aceita "auto", "none", "required", ou {"type": "function", "name": "…"}.

Resposta

{
  "id": "resp_…",
  "object": "response",
  "created_at": 1793333237,
  "status": "completed",
  "model": "deepseek/deepseek-v4.1-flash",
  "output": [
    {"type": "reasoning", "id": "rs_…", "summary": [],
     "content": [{"type": "reasoning_text", "text": "…"}], "encrypted_content": "ull1:…"},
    {"type": "message", "id": "msg_…", "status": "completed", "role": "assistant",
     "content": [{"type": "output_text", "text": "Paris.", "annotations": []}]},
    {"type": "function_call", "id": "fc_…", "status": "completed",
     "call_id": "call_…", "name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}
  ],
  "usage": {
    "input_tokens": 43, "input_tokens_details": {"cached_tokens": 0},
    "output_tokens": 23, "output_tokens_details": {"reasoning_tokens": 0},
    "total_tokens": 66, "cost_usd": 0.0000184
  },
  "store": false
}
  • Um item reasoning aparece quando o modelo retorna seu raciocínio. Envie-o de volta na próxima input como está: encrypted_content carrega o raciocínio para que os modelos que precisam dele na próxima vez o recebam.
  • status é incomplete quando a resposta atingiu max_output_tokens (incomplete_details.reason: "max_output_tokens") ou um filtro de conteúdo ("content_filter").
  • usage.cost_usd é o valor cobrado pela chamada. Respostas não-streaming também o carregam no cabeçalho X-UberLLM-Cost-USD, e toda resposta tem X-Request-Id, o ID de sua linha de Atividade.
  • As configurações que você enviou (instructions, tools, temperature, max_output_tokens…) são ecoadas de volta como a OpenAI faz.

Streaming

Com "stream": true a resposta são eventos enviados pelo servidor, cada um com type e um sequence_number começando em 0:

  1. response.created, response.in_progress
  2. Para cada item de saída: response.output_item.added, depois seus deltas, depois response.output_item.done com o item finalizado:
    • texto: response.content_part.added, response.output_text.delta…, response.output_text.done, response.content_part.done
    • raciocínio: response.reasoning_text.delta…, response.reasoning_text.done
    • chamada de função: response.function_call_arguments.delta…, response.function_call_arguments.done
    • chamada de ferramenta personalizada: response.custom_tool_call_input.done
  3. response.completed (ou response.incomplete) com a resposta completa e seu usage, incluindo cost_usd.

Enquanto um modelo lento está iniciando, : ping linhas de comentário mantêm a conexão aberta. Todo cliente SSE as ignora.

Erros

Uma requisição recusada antes do início do streaming recebe um status HTTP e o envelope de erro da OpenAI, o mesmo que para as conclusões de chat (401, 402 sem crédito, 404 modelo desconhecido, 429; veja Erros). Se algo falhar depois que o streaming tiver começado, ele termina com response.failed, cujo response.error tem code e message. Um streaming que para antes de o modelo terminar também termina com response.failed, nunca com response.completed, para que os clientes tentem novamente em vez de manterem metade de uma resposta.