Manifest: Gateway de IA

Saudações.

Apresento aos senhores um software excelente para integrar todas as contas de IA em um único ponto de contato de acesso à APIs LLM.

Links:

1 – O que é o Manifest

O manifest é um software, administrado pela web (navegador), para concentrar todas as suas assinaturas e APIs de IA num único sistema de roteamento – um gateway de APIs.

Propósito básico do Manifest: Rotear requisições entre vários provedores de modelos.

1.1 – Problema: Custos

O principal problema que ele resolve é custos.

Meu caso: Eu assino Claude Code e é decepcionante quando os créditos acabam pois eu desejo continuar o projeto usando o modelo OPUS no máximo mas não quero comprar a assinatura máxima. Se eu acionar sub-agentes para tarefas enormes os créditos desaparecem em minutos.

Quando isso ocorre eu tenho que ir para o OpenCode, usando a API que é MUITO MAIS CARA do que a assinatura considerando meu consumo de Mtok (mega tokens) por mês.

Pesquisando sobre uma forma de unir várias assinaturas do Claude num único sistema e apontar meu agente (Claude Code) para ele, encontrei dois softwares:

  • LiteLLM – O mais completo de todos, um pouco complicado de alinhar mas sem dúvida a melhor opção para empresas;
  • Manifest – O mais simples do mundo, une todos os serviços e se parece muito com o LiteLLM em funcionalidades, é mais bonito e muito amistoso, ótimo para uso individual e pequenas equipes.

Com eles várias contas podem ser aproveitas para contornar o “use-it-or-lose-it” (estude sobre non-rollover quota ou non-cumulative allowance), o que você não usa durante semanas não serve de crédito para a semana seguinte.

A única forma de economizar é gastar o máximo de cada janela.

Exemplos de uso prático:

  • Se uma empresa paga o assento do Claude plano Enterprise para cada funcionário, juntar todos os assentos numa única super-conta virtual permite balancear o consumo de créditos pelas contas;
  • Amigos podem se unir numa conta do manifest para alternar (cada dia um) o uso da super conta;

1.2 – Problema: RateLimit

Se a janela de créditos não for violada, isso não significa que você pode usar com paralelismo de agentes e sub-agentes, os provedores de IA implementam rate limiting impondo quantas requisições por segundo você pode utilizar na sua conta.

Isso é particularmente irritante, causa demoras na entrega, causam erros sem fallback (o agente para de trabalhar) – processos falham.

Já que sua conta está bloqueada por segundos ou minutos até que a janela de rate limit seja reiniciada, a melhor forma de resolver isso é:

  • Balanceamento: cada requisição pode ser enviada para contas diferentes, para alcançar 100 req/s numa API que limita a 10 req/s você precisa de 10 contas;
  • Redundância: quando uma API retornar erro de rate limit, ele utiliza outra conta até o desbloqueio da conta principal.

1.3 – Problema: Billing

Nem só de OPUS e GPT vive o agente de IA, modelos pequenos como GPT-OSS-120b são muito baratos e extremamente capazes de lidar com tarefas simples (contexto pequeno, poucas tools, prompt pontual) sem errar.

O roteamento baseado em cobrança visa usar APIs de provedores que cobram barato primeiro, e alternam entre APIs buscando sempre o menor custo por Mtok.

Se um provedor como o OpenCode Zen resolve dar um modelo gratuitamente por uma semana, melhor usar ele primeiro (custo $0), se ele der erro a requisição é repetida pelo gateway Manifest para outra API que tenha o mesmo modelo com custo mínimo ($ 0.002).

Considerar o custo cria o fallback baseado em custo.

2 – Preparativos

Vamos rodar o Manifest em Docker e preparar o ambiente.

2.1 – Rede

Crie a rede Docker “network_public“:

Bash
# Rede de containers
docker network create network_public \
    -d bridge \
    -o com.docker.network.bridge.name=br-net-public \
    -o com.docker.network.driver.mtu=1500 \
    -o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
    --subnet 10.249.0.0/16 \
    --gateway 10.249.255.254;

2.2 – Acesso HTTPs

Você precisa usar HTTPs para que o Manifest forneça uma API para seus agentes e ferramentas de IA.

Instale o Traefik e configura o DNS, vou usar o FQDN “manifest.dominio.com” nos exemplos, troque-o pelo nome que você apontou para o IP do servidor.

2.3 – Banco de dados Postgres

Vou criar o banco de dados PostgreSQL central, fora da stack do Manifest.

Vou usar a imagem pgvector (debian trixie + postgres 18 + pgvector).

O nome do serviço será “pgvector-main” e as credenciais iniciais serão exclusivas do administrador (user postgres).

Bash

# Variaveis
    NAME="pgvector-main";

# Argumentos do postgres (usado somente no primeiro boot)
    POSTGRES_USER="postgres";
    POSTGRES_PASSWORD="tulipasql";
    POSTGRES_DB="admin";

# Imagem
    IMAGE="pgvector/pgvector:pg18-trixie";
    docker pull $IMAGE;

# Volume
    # obs: pg18 usa pasta principal interna: /var/lib/postgresql
    DATADIR=/storage/$NAME;
    mkdir -p          $DATADIR;
    chown -R 999:999  $DATADIR;

# Renovar/rodar:
    docker rm -f $NAME 2>/dev/null;
    docker run \
        -d \
        --restart            always \
        --name               $NAME \
        --hostname           $NAME.intranet.br \
        \
        --cpus                2.0 \
        --cpu-shares         1024 \
        --memory               2g \
        --memory-swap          2g \
        --memory-reservation   1g \
        --shm-size             1g \
        \
        --network            network_public \
        --ip                 10.249.130.1 \
        --ip6                2001:db8:10:249::130:1 \
        --mac-address        02:cf:f1:30:00:01 \
        \
        --tmpfs              /run:rw,noexec,nosuid,size=64m \
        --tmpfs              /tmp:rw,exec,suid,size=64m \
        \
        -v $DATADIR:/var/lib/postgresql \
        \
        -e POSTGRES_USER=$POSTGRES_USER \
        -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
        -e POSTGRES_DB=$POSTGRES_DB \
        -e PGDATA=/var/lib/postgresql/data/pgdata \
        \
        --health-cmd="pg_isready -U postgres" \
        --health-interval=5s \
        --health-timeout=5s \
        --health-retries=10 \
        \
        --entrypoint "docker-entrypoint.sh" \
        \
        $IMAGE \
            postgres \
                --timezone=America/Sao_Paulo \
                --log_timezone=America/Sao_Paulo \
                --max_connections=150 \
                --superuser_reserved_connections=3 \
                --shared_buffers=384MB \
                --effective_cache_size=768MB \
                --work_mem=4MB \
                --maintenance_work_mem=96MB \
                --temp_buffers=8MB \
                --wal_buffers=16MB \
                --min_wal_size=512MB \
                --max_wal_size=2GB \
                --checkpoint_completion_target=0.9 \
                --checkpoint_timeout=10min \
                --wal_compression=on \
                --wal_level=replica \
                --random_page_cost=1.1 \
                --effective_io_concurrency=200 \
                --default_statistics_target=100 \
                --max_worker_processes=4 \
                --max_parallel_workers=2 \
                --max_parallel_workers_per_gather=1 \
                --max_parallel_maintenance_workers=2 \
                --autovacuum=on \
                --autovacuum_max_workers=2 \
                --autovacuum_naptime=30s \
                --autovacuum_vacuum_threshold=50 \
                --autovacuum_vacuum_scale_factor=0.05 \
                --autovacuum_analyze_threshold=50 \
                --autovacuum_analyze_scale_factor=0.05 \
                --autovacuum_vacuum_cost_delay=2ms \
                --autovacuum_vacuum_cost_limit=400 \
                --statement_timeout=120000 \
                --idle_in_transaction_session_timeout=300000 \
                --lock_timeout=30000 \
                --log_destination=stderr \
                --logging_collector=off \
                --log_min_duration_statement=2000 \
                --log_line_prefix="%t [%p] %u@%d " \
                --log_checkpoints=on \
                --log_connections=off \
                --log_disconnections=off \
                --log_lock_waits=on \
                --log_temp_files=10240 \
                --log_autovacuum_min_duration=1000 \
                --shared_preload_libraries=pg_stat_statements \
                --track_activities=on \
                --track_counts=on \
                --track_io_timing=on \
                --track_functions=pl \
                --ssl=off \
                --port=5432 \
                --listen_addresses="*" \
                --max_wal_senders=3 \
                --hot_standby=on;

2.4 – Criar banco de dados do Manifest

Primeiro, entre no container do pgvector-main direto no shell do Postgres (PSQL):

Bash
# Entrar no container e depois no psql com usuario admin 'postgres'
# Alternativa:
#    docker exec -it pgvector-main bash
#        psql -U postgres
docker exec -it pgvector-main bash -c 'psql -U postgres';

Uma vez no terminal PSQL, vamos criar a conta de usuário do “manifest” e o banco de dados “manifest“:

pgvector-main => psql >_
-- Criar usuario:
    CREATE USER manifest
        WITH PASSWORD 'tulipasql'
        LOGIN;

-- Criar banco de dados
    CREATE DATABASE manifest
        WITH 
        OWNER = manifest
        ENCODING = 'UTF8'
        TABLESPACE = pg_default
        IS_TEMPLATE = False
        CONNECTION LIMIT = -1;
      
-- Conectar no banco:
    \c manifest;

-- Adicionar extensao stats (opcional):
    CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

-- Conceder todos os privilégios no banco 'manifest' para o usuario 'manifest'
    GRANT ALL PRIVILEGES ON DATABASE manifest TO manifest;

-- Conceder privilégios no schema público
    GRANT ALL ON SCHEMA public TO manifest;

-- Garantir privilégios em tabelas futuras
    ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES    TO manifest;
    ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO manifest;
    ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO manifest;

-- Verificar se o usuário foi criado
    \du manifest;

-- Verificar se o banco foi criado
    \l manifest;

-- Verificar privilégios no banco
    \l+ manifest;

-- Sair
    \q

2.5 – Instalando o Manifest

Gere uma chave secreta para a criptografia interna do Manifest:

Bash
# Gerar chave alteatoria de 16 digitos (128 bits de seguranca):
openssl rand -hex 16;
    # 31fa0954c638cea5db263aad8a488357

# A chave preenche a variavel de ambiente $BETTER_AUTH_SECRET
BETTER_AUTH_SECRET="31fa0954c638cea5db263aad8a488357";

Rodando container Manifest chamado “manifest“:

Bash
# Variaveis
    NAME="manifest";
    FQDN="manifest.dominio.com";
    IMAGE="manifestdotbuild/manifest:latest";

# Acesso ao banco de dados
    # Formato: postgresql://user:senha@endereco_servidor:porta/banco_de_dados
    DATABASE_URL="postgresql://manifest:tulipasql@pgvector-main:5432/manifest";

# Variaveis do manifest
    PORT=2099;
    BETTER_AUTH_URL="https://$FQDN";
    SEED_DATA=false;
    NODE_ENV=production;
    MANIFEST_MODE=selfhosted;
    BETTER_AUTH_SECRET="31fa0954c638cea5db263aad8a488357";

# Atualizar imagem
    docker pull $IMAGE;

# Renovar/rodar:
    docker container  stop  $NAME 2>/dev/null;
    docker container  rm    $NAME 2>/dev/null;
    docker container  run \
        -d \
        --user               root \
        --restart            always \
        --name               $NAME \
        --hostname           $NAME.intranet.br \
        \
        --cpus                4.0  \
        --memory               2g \
        --memory-swap          2g \
        --memory-reservation   1g \
        --shm-size             1g \
        \
        --network            network_public \
        --ip                 10.249.91.1 \
        \
        -p 2099:2099   \
        \
        --tmpfs /run:rw,noexec,nosuid,size=512m \
        --tmpfs /tmp:rw,exec,suid,mode=1777,dev,size=512m \
        \
        -e DATABASE_URL=$DATABASE_URL \
        -e PORT=$PORT \
        -e BETTER_AUTH_SECRET=$BETTER_AUTH_SECRET \
        -e BETTER_AUTH_URL=$BETTER_AUTH_URL \
        -e SEED_DATA=$SEED_DATA \
        -e NODE_ENV=$NODE_ENV \
        -e MANIFEST_MODE=$MANIFEST_MODE \
        \
        -e OLLAMA_HOST="http://host.docker.internal:11434" \
        -e PROVIDER_TIMEOUT_MS=180000 \
        -e STREAM_WARMUP_MS=15000 \
        -e MANIFEST_ENCRYPTION_KEY="" \
        -e EMAIL_PROVIDER="" \
        -e EMAIL_API_KEY="" \
        -e EMAIL_DOMAIN="" \
        -e EMAIL_FROM="" \
        -e MANIFEST_TELEMETRY_DISABLED=0 \
        \
        -e GOOGLE_CLIENT_ID="" \
        -e GOOGLE_CLIENT_SECRET="" \
        -e GITHUB_CLIENT_ID="" \
        -e GITHUB_CLIENT_SECRET="" \
        -e DISCORD_CLIENT_ID="" \
        -e DISCORD_CLIENT_SECRET="" \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=web,websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=$PORT" \
        \
        $IMAGE;

# Acesso no navegador:
    echo;
    echo "Acesso ao Manifest:";
    echo "   Web.......:   https://$FQDN";
    echo;

Se você ja tem o banco de dados como serviço e quiser subir apenas o Manifest via Compose, arquivo YML:

YAML – manifest-docker-compose.yml
# Ancoras com variaveis organizadas
x-env-postgres: &env-postgres
  DATABASE_URL: "postgresql://manifest:tulipasql@pgvector-main:5432/manifest"

x-env-manifest: &env-manifest
  PORT: 2099
  BETTER_AUTH_SECRET: "31fa0954c638cea5db263aad8a488357"
  BETTER_AUTH_URL: "https://manifest.dominio.com"
  SEED_DATA: "false"
  NODE_ENV: production
  MANIFEST_MODE: selfhosted
  OLLAMA_HOST: "http://host.docker.internal:11434"
  PROVIDER_TIMEOUT_MS: 180000
  STREAM_WARMUP_MS: 15000
  MANIFEST_ENCRYPTION_KEY: ""
  EMAIL_PROVIDER: ""
  EMAIL_API_KEY: ""
  EMAIL_DOMAIN: ""
  EMAIL_FROM: ""
  MANIFEST_TELEMETRY_DISABLED: 0
  GOOGLE_CLIENT_ID: ""
  GOOGLE_CLIENT_SECRET: ""
  GITHUB_CLIENT_ID: ""
  GITHUB_CLIENT_SECRET: ""
  DISCORD_CLIENT_ID: ""
  DISCORD_CLIENT_SECRET: ""

# Redes
networks:
  network_public:
    external: true

# Servico manifest
services:
  manifest:
    image: manifestdotbuild/manifest:latest
    container_name: manifest
    hostname: manifest.intranet.br
    user: root
    restart: always

    deploy:
      resources:
        limits:
          cpus: "4.0"
          memory: 2g
        reservations:
          memory: 1g

    shm_size: 1g

    networks:
      network_public:

    ports:
      - "2099:2099"

    tmpfs:
      - /run:rw,noexec,nosuid,size=512m
      - /tmp:rw,exec,suid,mode=1777,size=512m

    environment:
      <<: *env-postgres
      <<: *env-manifest

    labels:
      traefik.enable: "true"
      traefik.http.routers.manifest.rule: "Host(`manifest.dominio.com`)"
      traefik.http.routers.manifest.entrypoints: "web,websecure"
      traefik.http.routers.manifest.tls: "true"
      traefik.http.routers.manifest.tls.certresolver: "letsencrypt"
      traefik.http.services.manifest.loadbalancer.server.port: "2099"

Acesse no navegador: https://manifest.dominio.com/

3 – Configurando

Agora precisamos preencher o Manifest com contas e chaves para uso.

3.1 – Contas de provedores

O primeiro passo é cadastrar os acessos dos provedores que você possui.

Existem dois tipos de configuração, ambos coexistem:

  • Contas de assinaturas: No menu “PROVIDERS” > “Subscriptions“, aqui você faz login em suas assinaturas que limitam o uso por cota;
    • Cobrança fixa mensal, limite na janela (horas, diária, semanal);
    • Melhores provedores: Anthropic, OpenCode Go, OpenAI;
  • Contas de API: No menu “PROVIDERS” > “Usage-based“, cadastre as chaves de API dos provedores que geram chaves de API que drenam um saldo pre-pago;
    • Cobrança por requisição ou por quantidade de tokens;
    • Melhores provedores: OpenRouter, OpenCode Go, DeepSeek;

CUIDADO: contas da Anthropic e OpenAI não curtem muito quando você as utiliza para outras finalidades fora do aplicativo oficial. Sujeito a bloqueio e banimento.

3.2 – Harnesses

Agora vamos no menu “Harnesses“: Um software com agente de IA é um harness (arreio do cavalo, o modelo é o cavalo).

Você irá configurar quais softwares o Manifest irá atender, ele será seu provedor e tudo que chegar a ele será roteado até o provedor final.

Procedimentos para criar a conta cliente (harness):

  • Clique em “Connect Harness” , um botão no canto superior direito;
  • Clique no select “Type” e escolha em qual software irá usar, isso ajusta a API do Manifest a receber requisições e responder no formato mais adequado ao seu software, exemplo: “OpenCode”;
  • Em “Harness name” informe o nome dessa conta cliente, exemplo “OpenCode-VPS”;
  • DESMARQUE o “Autofix“, embora ele arrume alguns erros, isso é feito enviando seus pedidos para uma API externa que captura todos os seus dados, não recomendo;
  • Marque “Enable logs“, isso te ajuda a investigar erros e analisar requisições e respostas para debug e investigações.
  • Clique em “Create“.

Procedimentos para configurar a conta:

  • Entre na conta recem criada e vá na guia “Routing“;
  • Na caixa “Default“, adicione pelo menos 1 modelo, observe:
    • Guia “Subscription” filtra contas de assinatura;
    • Guia “Usage-based” filtra contas de API;
  • Use “Add fallback” para adicionar o mesmo modelo usando provedores diferentes;

Ainda na conta, pegue a configuração no menu “Settings“:

  • API Key: Caso seu agente precise apenas da URL e da chave;
  • Setup: Fornece código de exemplo para configurar o agente.

Exemplo de configuração para OpenCode:

JSON ~/.config/opencode/opencode.json
{
    "$schema": "https://opencode.ai/config.json",
    "provider": {

        "manifest": {
            "npm": "@ai-sdk/openai-compatible",
            "name": "Manifest",
            "options": {
                "baseURL": "https://manifest.dominio.com/v1",
                "apiKey": "mnfst_sua_chave_aqui_jamais_compartilhe"
            },
            "models": {
                "auto": {
                    "name": "Manifest Auto"
                }
            }
        }

    },
    "model": "manifest/auto"
}

Com essa configuração o OpenCode enxerga “Manifest” como provedor, possuindo um único modelo chamado “auto“.

4 – Testando sua chave de harness

Agora vamos verificar se tecnicamente uma chave funciona.

4.1 – Verificando modelos disponíveis

Use para analisar os modelos disponíveis, principalmente o último comando que extrai modelos gratuitos (free) ou com preços reduzidos (contributor).

Bash
# Variavel com a chave (obtida do menu Settings da conta harness)
export MANIFEST_KEY="mnfst_sua_chave_aqui_jamais_compartilhe";
export MANIFEST_URL="https://manifest.dominio.com/v1";

# lista básica
curl \
    -s "$MANIFEST_URL/models" \
    -H "Authorization: Bearer $MANIFEST_KEY" | jq .;
    # Resposta:
    #     {
    #         "object": "list",
    #         "data": [
    #           {
    #               "id": "auto",
    #               "object": "model",
    #               "created": 0,
    #               "owned_by": "manifest"
    #           },
    #           {
    #               "id": "openrouter/moonshotai/kimi-k3.1-pro",
    #               "object": "model",
    #               "created": 0,
    #               "owned_by": "openrouter"
    #           },
    #           ...
    #           {
    #               "id": "openrouter/anthropic/claude-haiku-5.5",
    #               "object": "model",
    #               "created": 0,
    #               "owned_by": "openrouter"
    #           },
    #           ...
    # }

# Mostrar somente os ids (nome de identificacao para a requisicao)
curl \
    -s "$MANIFEST_URL/models" \
    -H "Authorization: Bearer $MANIFEST_KEY" | jq -r '.data[].id';
    # Resposta:
    #     auto
    #     ...
    #     openrouter/moonshotai/kimi-k3.1-pro
    #     ...
    #     openrouter/anthropic/claude-haiku-5.5
    #     ...

# com capacidades e custo
curl \
    -s "$MANIFEST_URL/models?capabilities=true&cost=true" \
    -H "Authorization: Bearer $MANIFEST_KEY" | jq .;
    # Resposta:
    #     {
    #         "object": "list",
    #         "data": [
    #             {
    #                 "id": "auto",
    #                 "object": "model",
    #                 "created": 0,
    #                 "owned_by": "manifest"
    #             },
    #             {
    #                 "id": "openrouter/moonshotai/kimi-k3.1-pro",
    #                 "object": "model",
    #                 "created": 0,
    #                 "owned_by": "openrouter",
    #                 "capabilities": {
    #                     "input_modalities": [
    #                         "text",
    #                         "image",
    #                         "video"
    #                     ],
    #                   "output_modalities": [
    #                       "text"
    #                   ],
    #                   "features": [
    #                       "tools",
    #                       "stream"
    #                   ]
    #                 },
    #                 "cost": {
    #                     "input": 2,
    #                     "output": 10
    #                 }
    #             },
    #             ...
    #             'openrouter/anthropic/claude-haiku-5.5'
    #                 "id": "openrouter/anthropic/claude-haiku-5.5",
    #                 "object": "model",
    #                 "created": 0,
    #                 "owned_by": "openrouter",
    #                 "capabilities": {
    #                     "input_modalities": [
    #                         "text",
    #                         "image"
    #                      ],
    #                      "output_modalities": [
    #                          "text"
    #                       ],
    #                      "features": [
    #                          "tools",
    #                          "stream"
    #                      ]
    #                 },
    #                 "cost": {
    #                     "input": 0.09999999999999999,
    #                     "output": 0.5
    #                 }
    #             },
    #             ...
    #         ]
    #     }

# Mostrar somente modelos gratuitos ou de custo reduzido
curl \
    -s "$MANIFEST_URL/models" \
    -H "Authorization: Bearer $MANIFEST_KEY" \
        | jq -r '.data[].id' \
        | egrep -i '(free|contributor)';
    # Resposta:
    #     openrouter/recursive/flint-v1.0:free
    #     openrouter/nvidia/nemotron-3.5-super-vl:free
    #     openrouter/meta/muse-spark-1.3-contributor
    #     openrouter/meta/muse-spark-1.2-contributor
    #     openrouter/nvidia/nemotron-3.5-lightning:free
    #     ...
    #     openrouter/free
    #     ...
    #     opencode-go/muse-spark-1.3-contributor-subscription
    #     opencode-go/muse-spark-1.2-contributor-subscription
    #     ...

4.2 – Testando inferência

Agora vamos mandar um prompt para um modelo via manifest.

Bash
# Variavel com a chave (obtida do menu Settings da conta harness)
export MANIFEST_KEY="mnfst_sua_chave_aqui_jamais_compartilhe";
export MANIFEST_URL="https://manifest.dominio.com/v1";
export MANIFEST_CHAT="$MANIFEST_URL/chat/completions";

# Payload JSON a enviar para o modelo
JSON='{
    "model": "openrouter/free",
    "stream": false,
    "messages": [
        { "role": "system", "content": "Você é maluco, resposta curta" },
        { "role": "user",   "content": "Por qual motivo o céu é azul?" }
     ]
}';

# Exibir pedido a ser enviado:
 echo "$JSON" | jq .;
 
# Enviar para processamento do modelo via Manifest:
curl \
    -s "$MANIFEST_CHAT" \
    -X POST \
    -H "Authorization: Bearer $MANIFEST_KEY" \
    -H "Content-Type: application/json" \
    -d "$JSON" \
        | jq .;

    # Resposta
    #   {
    #       "id": "gen-1792873503-4FsgnKzbnlLZETppbo8O",
    #       "object": "chat.completion",
    #       "created": 1792873503,
    #       "model": "nvidia/nemotron-3-ultra-550b-a55b:free",
    #       "provider": "Nvidia",
    #       "system_fingerprint": null,
    #       "service_tier": null,
    #       "choices": [
    #          {
    #              "index": 0,
    #              "logprobs": null,
    #              "finish_reason": "stop",
    #              "native_finish_reason": "stop",
    #              "message": {
    #                  "role": "assistant",
    #                  "content": "Espalhamento da luz solar.",
    #                  "refusal": null,
    #                  "reasoning": "The user is asking \"Why is the sky blue?\"",
    #                  "reasoning_details": [
    #                    {
    #                      "type": "reasoning.text",
    #                      "text": "I need to answer the current question directly.",
    #                      "format": "unknown",
    #                      "index": 0
    #                    }
    #                  ]
    #              }
    #            }
    #       ],
    #       "usage": {
    #           "prompt_tokens": 31,
    #           "completion_tokens": 90,
    #           "total_tokens": 121,
    #           "cost": 0,
    #           "is_byok": false,
    #           "prompt_tokens_details": {
    #               "cached_tokens": 0,
    #               "cache_write_tokens": 0,
    #               "audio_tokens": 0,
    #               "video_tokens": 0
    #           },
    #           "cost_details": {
    #               "upstream_inference_cost": 0,
    #               "upstream_inference_prompt_cost": 0,
    #               "upstream_inference_completions_cost": 0
    #           },
    #           "completion_tokens_details": {
    #               "reasoning_tokens": 65,
    #               "image_tokens": 0,
    #               "audio_tokens": 0
    #           }
    #       }
    #   }

Terminamos por hoje!

Patrick Brandão, patrickbrandao@gmail.com

“Aquilo a que chamamos acaso não é,
não pode deixar de ser,
senão a causa ignorada de um efeito conhecido.“
Voltaire