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:
- Site: https://manifest.build/
- Projeto: https://github.com/mnfst/manifest
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.

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“:
# 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).
# 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):
# 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“:
-- 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:
# 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“:
# 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:
# 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:
{
"$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).
# 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.
# 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
