“Sabe qual é a melhor coisa no Rust? Que ele não deixa você compilar gambiarras. Sabe qual é a pior coisa? Que tudo que você escreve no início é uma gambiarra.” — Sr. Siriguejo (provavelmente)
O que é melhor do que um agente de IA? Um agente de IA reescrito em Rust.
Se você está na internet há mais de cinco minutos, conhece o meme. Não importa o projeto: um editor de texto, um servidor DNS, uma calculadora de IMC. Alguém sempre aparece nos comentários dizendo “você deveria reescrever isso em Rust”. É o Rewrite It In Rust — RIIR para os íntimos — e é tão inevitável quanto a gravidade.
Pois bem, eu vou fazer isso de verdade. Vou portar 8.300 linhas de um agente de IA de Python para Rust. Mas não porque o meme pediu (ok, talvez um pouco). Vou fazer porque preciso de uma cobaia.
A tese
Passei algumas semanas escrevendo sobre falhas silenciosas, sobre as cinco defesas contra alucinações, sobre como um LLM pode gerar código que compila, passa os testes e ainda assim está errado. Eu até lhe dei um nome: desenvolvimento adversarial. Nunca confie, sempre verifique.
Muita teoria. Agora é hora de colocar isso à prova.
Precisava de um projeto com três características: um escopo definido (nada de um aplicativo novo com requisitos em constante mudança), uma fonte confiável de verdade (o código Python que já funciona) e com complexidade suficiente para que as alucinações do LLM tenham espaço para aparecer. Um port puro e direto atende aos três requisitos. O input e o output esperado já existem. Se a versão em Rust não se comportar exatamente como a versão em Python, há um bug. Simples assim.
E já que vou portar algo, por que não aproveitar para aprender Rust de verdade? O borrow checker, ownership, lifetimes… Passo anos lendo sobre tudo isso sem botar a mão na massa. Se em vez de estudar tutoriais pela milésima vez, eu me jogasse em um projeto real, outra seria a história.
O paciente
Chama-se nanobot. É um agente de IA pessoal derivado do OpenClaw: uma ferramenta que conecta LLMs (Claude, GPT, DeepSeek, o que vier) a canais de chat — Telegram, Discord, Slack, email — e os equipa com habilidades. Ele pode ler e editar arquivos, executar comandos, fazer buscas na web, programar tarefas com cron e ainda manter uma memória persistente entre as conversas.
E funciona. Tem meses que funciona. Em Python.
Qual é o problema? Ele é single-threaded. Processa uma mensagem por vez. Se você enviar três mensagens seguidas, ele as coloca em fila como o caixa de um mercado no sábado ao meio-dia. Usa apenas 50 MB de RAM para, basicamente, rotear JSON entre APIs. E o código tem aquelas técnicas de error handling que dão vergonha alheia: return f"Erro: {str(e)}" para todo lado.
Traduzindo: funciona, mas é uma gambiarra ambulante. Candidato perfeito.
Por que Rust (além do meme)
Eu poderia consertar isso no Python. Poderia colocar mais asyncio, tipar melhor os erros com exceções personalizadas, otimizar a memória. Seria o mais sensato.
Mas isso não me dá um test bench para o desenvolvimento adversarial. Um refactor em Python não tem uma fonte externa de verdade — o “antes” e o “depois” compartilham linguagem, bibliotecas e os mesmos vieses do LLM. Já portar para outra linguagem resolve isso. Se o output do Rust for diferente do output do Python para o mesmo input, algum está mentindo. E é exatamente esse o tipo de verificação que eu quero testar.
Além disso, Rust tem propriedades que tornam o experimento mais interessante:
- O compilador como primeira defesa. Nulls, type mismatch, data races: categorias inteiras de bugs que no Python passam despercebidos mas que, no Rust, não passam pela compilação. Quantas alucinações de LLM o compilador barra antes de atingir um teste? Quero medir isso.
- Concorrência real.
tokiopermite um spawn por conversa. Em Python isso é um calvário. É a melhoria funcional que justifica o port. - Binário estático. Um executável de 10 MB em vez de um
pip installcom 47 dependências. Para distribuição, não tem preço. - Porque é legal. Ok, isso não é um motivo técnico. Mas não me importo.
A aventura (e o convite)
RustyClaw — assim se chama o port — será um experimento documentado publicamente. Cada módulo portado será um post. Com dados reais: quantos tokens consumi, quanto custou, quantas vezes a IA alucinou, quanto tempo demorei lutando com o borrow checker. Sem maquiagem.
Se eu gastar 3 horas em algo que no Python faria em 10 minutos, vou contar. Se o LLM inventar um crate que não existe (spoiler: vai acontecer), será documentado. Se, ao final do port, ficar claro que não valeu a pena, vou admitir.
Todo mundo diz “usei IA para escrever código”. Ninguém publica quanto custou, quantas vezes a IA mentiu e se o resultado aguentou no ambiente de produção. É exatamente isso que vou fazer.
E quero que você me acompanhe. Porque vai ser uma aventura — com brigas contra o compilador, momentos de “POR QUE não compila se é ÓBVIO?”, e pequenas vitórias quando um teste diferencial passar no verde. Vai ser divertido. Ou pelo menos, honesto.
A stack (o lembrete)
Se você é pythonista, a coluna da esquerda será familiar. Se você é rustacean, a da direita. Se não é nenhum dos dois, bem-vindo ao caos.
| Camada | Python (nanobot) | Rust (rustyclaw) |
|---|---|---|
| Runtime async | asyncio | tokio |
| HTTP | httpx | reqwest |
| Roteamento de LLM | litellm | Não existe — roteador próprio |
| Telegram | python-telegram-bot | teloxide |
| Discord | websockets (raw) | tokio-tungstenite (raw) |
| Config | pydantic | serde + figment |
| CLI | typer | clap |
| Erros | str(e) | anyhow + thiserror |
| Logging | loguru | tracing |
| Copiloto IA | — | Claude Code + Codex |
| Task runner | make | just |
| Issues | — | linear CLI |
A linha que mais dói é LiteLLM. Em Python, ele roteia para mais de 100 provedores de LLM com uma única chamada. Em Rust não existe algo parecido. Teremos que construir um roteador próprio. A boa notícia é que 80% dos provedores são compatíveis com a API da OpenAI, então com async-openai + configuração de base_url custom cobrimos quase tudo. Anthropic exigirá uma implementação específica.
Por volta de ~300 linhas de código Rust. Parece tranquilo. Parece.
As três últimas linhas são o meta-stack: ferramentas que usarei durante o port. Claude Code para sessões interativas em que preciso “pensar alto” com o LLM. Codex para ports mecânicos, onde o contexto já está definido e prefiro velocidade. just em vez de make, porque quero testar algo que não depende de tabs literais para funcionar. E o CLI do linear para gerenciar o progresso sem sair do terminal.
A estratégia anti-alucinações (a parte séria)
É aqui que a teoria do desenvolvimento adversarial encontra a prática. Um LLM assistindo nesse tipo de port tem grande potencial de inventar coisas plausíveis.
O risco principal não é que o código falhe ao compilar. Rust não deixa você compilar lixo. O risco é que compile, passe os testes e funcione de maneira errada sem alertar. Exatamente a falha silenciosa que documentei há duas semanas.
Cinco camadas de defesa:
1. O compilador do Rust. Elimina nulls, type mismatch, data races. Primeira linha de defesa gratuita. Mas compilar não significa que esteja correto.
2. Testes diferenciais. Mesma entrada → nanobot Python → saída. Mesma entrada → rustyclaw Rust → saída. Se não forem idênticos, há um problema. A fonte de verdade é o código Python já funcional. Essa é a camada mais importante do experimento.
3. Rastreamento de proveniência. Cada arquivo portado terá um header com o arquivo-fonte em Python original, a sessão do LLM que o gerou e os resultados nos testes diferenciais. Rastreabilidade total.
4. Verificação de crates. Cada crate sugerido pelo LLM → verificação manual em crates.io e docs.rs. Os LLMs inventam crates que não existem e APIs que não funcionam assim. Tudo com a maior segurança do mundo, como quem afirma que Sydney é a capital da Austrália.
5. Log de incidentes. Cada alucinação detectada → issue com tag hallucination. Material para os posts e para não cometer os mesmos erros.
A regra de ouro:
O sistema de verificação precisa ser externo ao gerador.
Se o LLM gera o código, os testes e os fixtures, você estará validando ficção usando mais ficção. Os testes diferenciais contra o código Python original são a camada que quebra esse ciclo. E a vantagem de um port é que essa camada existe naturalmente.
Vale a pena?
Vamos à pergunta incômoda. Será que realmente vale a pena portar isso para Rust?
| Métrica | Python | Rust (estimado) | Vale a pena? |
|---|---|---|---|
| Latência de resposta | ~200ms overhead | ~5ms overhead | Não. O LLM leva entre 2 e 5 segundos de qualquer jeito. |
| RAM | ~50MB | ~5MB | Não. Meu servidor tem 8GB. |
| Concorrência | 1 mensagem por vez | N mensagens simultâneas | Sim. |
| Startup | ~2s | ~50ms | Meh. |
| Binário | pip install + 47 deps | Um executável | Sim. |
| Segurança de tipos | str(e) everywhere | Result<T, E> | Sim. |
| Que é legal | Não | Sim | Subjetivo. |
Três de sete. Sendo generoso, quatro. A melhoria na latência e no consumo de RAM é irrelevante porque o gargalo sempre será a chamada ao LLM. Concorrência, por outro lado, importa muito para múltiplos usuários. O binário estático é uma verdadeira melhoria. Já a segurança de tipos… depois de ver str(e) esconder bugs por meses, isso sim faz diferença.
Vale semanas de trabalho? Como port isolado, provavelmente não. Mas como banco de provas para desenvolvimento adversarial com dados reais publicados, acredito que sim. Ao final da série teremos números para decidir, não opiniões.
Os números, sem filtros
Cada sessão de trabalho será registrada em um CSV no repositório:
date,llm,model,module,tokens_in,tokens_out,cost_usd,duration_min,loc_python,loc_rust,hallucinations,tests_pass
---
LLM usado, tokens consumidos, custo, duração, linhas portadas, alucinações detectadas, testes aprovados. Tudo público. Tudo verificável.
Ao fim da série, qualquer pessoa poderá somar a coluna `cost_usd` e decidir se o RIIR valeu a pena. Qualquer um poderá contar as alucinações e avaliar se o desenvolvimento adversarial é eficaz ou só papo furado. Spoiler: não faço ideia de qual será o resultado. E é isso que torna tudo interessante.
## Me acompanhe
- **Repositório:** [github.com/frr149/rustyclaw](https://github.com/frr149/rustyclaw) — código, issues, tracking
- **Blog:** Cada fase terá seu post aqui, na série *RustyClaw: Rewrite It In Rust*
- **Backlog:** Público no Linear, visível nos issues do GitHub
O que é melhor que uma AGI? Uma AGI reescrita em Rust. Já diz o meme. Agora vamos descobrir.