Comprei um PC com GPU pra rodar executor 'grátis'. Acabou sendo o config mais caro em 40 trials.
"Pra deixar coding agent barato: usa um modelo forte pra orquestrar, e um modelo barato (ou local de graça) pra executar." Hoje essa é a receita default. Quase todo mundo no Twitter dev BR e gringo está repetindo isso.
Eu acreditei. Montei um PC com GPU especificamente pra rodar Qwen 3.5-9B localmente como executor, Ollama em cima, Tailscale pra acessar de qualquer lugar. Aí coloquei o Opus 4.7 como orquestrador no Claude Code, com uma tool delegate_to_executor chamando o Qwen local. Token do Qwen: zero dólar.
A ideia era óbvia: o orquestrador caro só pensa, o executor grátis trabalha. Conta da Anthropic deveria cair.
A conta subiu.
Em 3 tarefas distintas de coding (recuperação de breakage, refactor, feature-add), essa config "Opus + Qwen local" foi a mais cara da nuvem em todas as três. Mais cara que Opus solo. Mais cara que Opus + Haiku. O PC com GPU continua útil, só não pelo motivo que comprei.
Resolvi medir direito antes de sair postando "minha experiência foi assim". 40 trials no total, 4 configs, 3 tarefas, juíz determinístico (mypy + ruff + pytest exit code, sem LLM julgando). Conta total de Anthropic API nas 40 trials: $35.98. Barato pra um paper.
O paper completo está no Zenodo, código no GitHub, links no fim. Esse post é o resumo do que aconteceu e por quê.
Os 4 arms que rodei
| arm | orquestrador | executor | divisão |
|---|---|---|---|
| A | Opus 4.7 | (solo) | um modelo faz tudo |
| B | Opus 4.7 | Qwen 3.5-9B (local, Ollama) | Opus planeja, Qwen edita |
| C | Opus 4.7 | Haiku 4.5 (sub-loop Anthropic) | Opus planeja, Haiku edita |
| D | Haiku 4.5 | (solo) | um modelo barato faz tudo |
Mesmas tools nos 4: str_replace_editor (view/create/str_replace) e bash com timeout de 120s. As arms B e C ganham uma tool extra delegate_to_executor. Prompt caching da Anthropic ligado igual em todas (system, tools e última user message com cache_control: ephemeral). Nada de temperature nem seed, então variância entre trials é só amostragem mesmo.
As 3 tarefas
Todas rodando no repo typer no commit b210c0e (v0.26.8, MIT). Cada trial começa com git checkout -- . && git clean -fd pra resetar.
- T1 — Recuperação de breakage: AST injeta 25 erros (10 mypy + 10 ruff + 5 falhas de coleta do pytest). O agent tem que voltar pra verde.
- T2 — Refactor: Mover
get_params_from_functiondetyper/utils.pypra um módulo novotyper/_param_extractor.py, atualizar todos os imports, testes continuam passando. - T3 — Feature-add: Implementar
get_version_banner(prefix, uppercase) -> str, re-exportar detyper/__init__.py, passar um arquivo de teste com fingerprint SHA-256.
Resultados (mediana success-only, n=3 por célula)
| arm | task | n_sucesso/total | wall (s) | iters | custo ($) | success rate |
|---|---|---|---|---|---|---|
| A Opus solo | T1 | 3/3 | 253 | 36 | 1.74 | 1.00 |
| A Opus solo | T2 | 3/4 | 233 | 26 | 1.11 | 0.75 |
| A Opus solo | T3 | 3/3 | 69 | 6 | 0.17 | 1.00 |
| B Opus+Qwen | T1 | 3/4 | 484 | 38 | 2.27 | 0.75 |
| B Opus+Qwen | T2 | 3/3 | 443 | 27 | 1.38 | 1.00 |
| B Opus+Qwen | T3 | 3/3 | 348 | 12 | 0.42 | 1.00 |
| C Opus+Haiku | T1 | 3/3 | 400 | 28 | 1.67 | 1.00 |
| C Opus+Haiku | T2 | 3/3 | 275 | 20 | 0.92 | 1.00 |
| C Opus+Haiku | T3 | 3/3 | 145 | 11 | 0.38 | 1.00 |
| D Haiku solo | T1 | 3/4 | 758 | 89 | 0.30 | 0.75 |
| D Haiku solo | T2 | 3/4 | 507 | 70 | 0.23 | 0.75 |
| D Haiku solo | T3 | 3/3 | 208 | 29 | 0.08 | 1.00 |
Negrito = melhor na coluna. Olha a linha do arm B. Em toda tarefa o custo ($) é o pior das arms de nuvem (2.27 / 1.38 / $0.42). Token do Qwen custa zero. Opus + Qwen sai mais caro que Opus sozinho, sempre.
Por que o "grátis" sai caro
Compara o consumo de token do lado do Opus (input + cache_read_input) entre as arms:
| arm | T1 (Opus in + cache_r) | T2 | T3 |
|---|---|---|---|
| A (Opus solo) | 534.586 | 226.474 | 13.320 |
| B (Opus + Qwen) | 733.142 | 313.914 | 62.864 |
| C (Opus + Haiku) | 421.622 | 159.640 | 44.016 |
Razão B-sobre-A (só o lado do Opus): 1,38× em T1, 1,39× em T2, 5,26× em T3.
Token do Qwen é zero. Mas o Opus em si está lendo de 1,4 a 5,3 vezes mais token do que leria sozinho.
O motivo é mecânico, não filosófico. Quando o Opus chama delegate_to_executor, o Qwen devolve um sumário do stdout (cortado em 4000 chars na minha implementação). Esse sumário cai no contexto do Opus. O prompt cache da Anthropic marca a última mensagem com cache_write, e na próxima rodada ela vira cache_read. Em 30 a 80 iterações, o Opus acaba relendo o "o que o Qwen fez" várias e várias vezes.
Cada releitura é cobrada na taxa de cache_read ($1.50 por milhão de token = 10% da taxa de input do Opus). O executor sai de graça. O orquestrador, não. Parece óbvio quando escrevo, mas a palavra "grátis" em uma frase tem o poder de desligar o raciocínio humano. O meu, pelo menos.
Botando direto: o custo do orquestrador é proporcional a quantas vezes ele relê o que o executor devolveu, não ao volume de token que o executor mesmo gastou. Soa mais como conversa de gerente intermediário do que descoberta de LLM, mas é o que os dados dizem.
Por que T3 estourou pra 5,3×
T3 é a menor tarefa, umas 6 iterações. É justamente nela que o B/A vai pra 5,3×, e tem explicação no cache.
O contexto base (system + tools + prompt inicial) é cache_write na primeira rodada e depois cache_read barato. Em tarefa longa (T1, T2), esse base é uma fração pequena do input acumulado. Em tarefa curta, esse base é fração grande do input acumulado. Aí o overhead de "sumário do executor sendo relido + base sendo relido toda rodada" domina tudo. T3 explode justamente por isso.
E o oposto também acontece. A arm C (Opus + Haiku) tem cache_read footprint menor que o Opus solo em T1 e T2 (0,79× e 0,70× do A). O Haiku trabalha de verdade, o Opus tem menos coisa pra refazer, e o sumário do Haiku é mais útil que o do Qwen.
Quando orquestração ganharia (casos que eu mesmo eliminei)
Pra ser justo, esse experimento foi montado de um jeito que penaliza a arm B:
- Retorno do executor é free-form (sumário stdout do Qwen até 4000 chars). Se você prende o retorno em "manda 1 diff estruturado e mais nada", o contexto acumulado do Opus encolhe.
- Tarefas são sequenciais (T1, T2, T3 não dá pra paralelizar dentro de 1 trial). Tarefas onde dá pra mandar "edita esses 3 lugares em paralelo" podem pagar pelo overhead de orquestração.
Rodar a arm B de novo com retorno apertado é o próximo experimento. Eu aposto que T3 inverte. T1 fica em aberto.
O que mudou pra mim como engenheiro
Olhando esses 40 trials, eis o que eu mudei no meu setup de coding agent:
- Tarefa que termina em poucas iterações → Opus solo é o mais barato da nuvem. T3: $0.17, 69 segundos, 6 iterações, melhor da nuvem. "Opus é caro" é frame de chamada única. Em loop iterativo, eficiência por iteração paga.
- Tarefa que precisa de dezenas de iterações → o modelo com menor custo por iteração ganha em dólar. T1: Haiku solo é 5,5× mais barato que a melhor cloud arm. Custa 25% de chance de falhar, então o custo esperado com retry vira 4,2×.
- Pra cloud-only balanceada → Opus + Haiku é a mais segura. Empata com Opus solo em T1, ganha T2 em custo, perde só em T3 por pouco.
- Se for usar Qwen local "de graça", restringe o tamanho do retorno do executor estruturalmente. Stdout free-form passa a conta pro
cache_readdo orquestrador.
"Forte + barato" tem uma superfície de design bem mais estreita do que as manchetes sugerem. Sem combinar o que o executor retorna e em que volume, você reproduz o padrão "orquestrador fica caro". Eu reproduzi essa coisa três vezes desconfiando de erro de medida antes de aceitar.
Limites
Pra não vender mais do que medi:
- n=3 por célula. P-value do Mann-Whitney U usa aproximação normal onde 0,050 é o piso pra amostras pequenas — significa "tão diferentes quanto essa amostra consegue mostrar". Confia no Cliff's delta, não exagera nas diferenças de p-value.
- As 3 tarefas estão todas no repo typer. Generalizar precisa rodar em outras codebases. O harness, o injetor de breakage, o runner e a análise estão todos MIT no repo. Reproduzir custa pouco.
- System prompt do orquestrador é assimétrico ("não edita direto, delega") — espelha um deploy real, mas é um confounder.
Reproduzir
Ubuntu 22.04 com Python 3.10+, uv 0.4+, SDK Python da Anthropic 0.83+. A arm B usa Ollama 0.4+ rodando qwen3.5:9b. Se pular a arm B, Ollama não precisa.
git clone https://github.com/kenimo49/free-executor-paradox
cd free-executor-paradox
# roda arm A em T3, 1 trial
python scripts/runners/runner.py --arm A --task T3 --trial 1
README e PDF têm o setup completo de reprodutibilidade.
Fechando
A discussão de custo em agentic coding tende a focar no preço por token do executor. O termo dominante é, na real, quanto o orquestrador relê e quantas vezes. Qwen aqui é só um exemplo do padrão. Todo "executor local grátis" que sair daqui pra frente vai bater no mesmo problema. Token do executor sendo grátis não torna cache_read do orquestrador grátis.
Escrevi como paper porque número é mais difícil de discutir do que vibe. O desfecho mais legal seria alguém responder "deu o mesmo na minha codebase" ou "deu o contrário na minha, e foi por isso".
- Paper (Zenodo, acesso aberto): https://doi.org/10.5281/zenodo.20978074
- Código + dados + harness (MIT): https://github.com/kenimo49/free-executor-paradox
- Release v1.0.0: https://github.com/kenimo49/free-executor-paradox/releases/tag/v1.0.0