Claude Fable é incansavelmente proativo
Claude Fable é incansavelmente proativo
11 de junho de 2026
Após dois dias de experiência com Claude Fable 5, acho que a melhor maneira de descrevê-lo é incansavelmente proativo. Ele conhece muitos truques e utilizará praticamente qualquer um deles para atingir seu objetivo.
Vou ilustrar isso com um exemplo. Eu estava hackeando o Datasette Agent hoje quando notei uma falha: uma barra de rolagem horizontal que não deveria estar lá no prompt de bate-papo do menu de salto. Tirei esta captura de tela:

Então comecei um novo claude sessão no meu datasette-agent checkout, arrastei a captura de tela e disse:
Look at dependencies to help figure out why there is a horizontal scrollbar here
Tive um palpite de que a causa estava na dependência do Datasette Agent (provavelmente o próprio Datasette) e sabia que o Fable era bom em pesquisar códigos de dependência, seja inspecionando arquivos instalados em seu próprio ambiente virtual site-packages ou referenciando um checkout local no disco. Dizer para começar com dependências pareceu uma boa aposta.
Me distraí com uma tarefa doméstica e me afastei do computador.
Quando voltei, alguns minutos depois, vi minha máquina abrir uma janela do navegador no meu Firefox normal e depois navegue até a caixa de diálogo em questão. Eu não havia dito ao Claude Code para usar qualquer automação de navegador e tinha certeza de que não era possível acionar movimentos do mouse ou atalhos de teclado em uma janela, então como foi fazer isso?
Observei fascinado enquanto ele continuava com suas explorações e depois o vi abrir uma janela do Safari em vez do Firefox. Também peguei este instantâneo do terminal Claude:

O que estava fazendo lá com uv run --with pyobjc-framework-Quartz?
Acontece que o Fable criou seu próprio padrão para fazer capturas de tela das janelas do navegador. Ele estava usando Python para iterar por todas as janelas disponíveis em minha máquina e, em seguida, filtrar as janelas do Safari com strings esperadas, como "textarea" no nome da janela. Ele usou isso para encontrar o número da janela – um número inteiro como 153551 – que poderia então usar com o screencapture Ferramenta CLI para obter um PNG.
OK, tudo bem, essa é uma maneira legal de fazer capturas de tela. Mas do que estava tirando screenshots?
Acontece que ele estava escrevendo suas próprias páginas HTML para tentar recriar o bug, depois abrindo o Safari e capturando capturas de tela.
Aqui está a página /tmp/textarea-scrollbar-test.html que ele criou e a captura de tela tirada com screencapture -x -o -l 153551 /tmp/safari-cases.png:

(Tenho muitas abas abertas!)
OK, posso ver como ele está abrindo páginas de teste e fazendo capturas de tela, mas como diabos isso acionou o diálogo modal que deveria estar em teste? Isso só está disponível por meio de um clique ou atalho de teclado, e não consegui ver um mecanismo para executá-los no Safari.
Acabei descobrindo o que isso tinha feito.
Claude estava rodando em uma pasta que continha o código-fonte do aplicativo. Ele sabe o suficiente sobre o Datasette para poder executar um servidor de desenvolvimento local. Acontece que ele estava editando os próprios modelos do Datasette para adicionar JavaScript que acionaria o atalho de teclado correto assim que a janela fosse aberta, adicionando código como este:
script>
window.addEventListener("load", function () {
setTimeout(function () {
document.dispatchEvent(new KeyboardEvent("keydown", {key: "https://simonwillison.net/", bubbles: true}));
}, 1200);
});
script>
1,2 segundos após a abertura da janela, este código aciona uma simulação / key, que é o atalho de teclado para abrir a caixa de diálogo modal.
Restava um desafio. Para entender o que estava acontecendo, Claude precisava executar JavaScript na página para fazer medições por si só.
Ele escreveu seu próprio aplicativo web personalizado para capturar informações via CORS, depois executou-o como um servidor local e abriu uma página com JavaScript que faria POST diretamente nele!
Aqui está o aplicativo web Python que ele escreveu, usando o pacote http.server da biblioteca padrão:
from http.server import HTTPServer, BaseHTTPRequestHandler class H(BaseHTTPRequestHandler): def do_POST(self): n = int(self.headers.get("Content-Length", 0)) open("/tmp/diag.json", "w").write(self.rfile.read(n).decode()) self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() def do_OPTIONS(self): self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Access-Control-Allow-Headers", "*") self.end_headers() def log_message(self, *a): # quiet pass HTTPServer(("127.0.0.1", 9999), H).serve_forever()
Tudo o que isso faz é aceitar uma solicitação POST cheia de JSON e gravá-la no /tmp/diag.json arquivo. Ele envia Access-Control-Allow-Origin: * cabeçalhos (incluindo de OPTIONS solicitações) para que o código em execução em outro domínio ainda possa se comunicar com ele.
Então Claude injetou este código no modelo que estava carregando em um navegador:
const host = document.querySelector("navigation-search");
const ta = host.shadowRoot.querySelector("textarea");
const cs = getComputedStyle(ta);
fetch("http://127.0.0.1:9999/diag", {
method: "POST",
body: JSON.stringify({
dpr: window.devicePixelRatio,
scrollWidth: ta.scrollWidth, clientWidth: ta.clientWidth,
whiteSpace: cs.whiteSpace, width: cs.width,
}),
});
Isso fez medições do dentro do Web Component e os enviou ao servidor, que os gravou em um arquivo em disco, que Claude pôde então ler.
Tendo descoberto todos esses truques, Fable… atingiu uma barreira de proteção invisível e se rebaixou para Opus. Felizmente, a Opus teve acesso à transcrição completa e pôde continuar usando os truques pioneiros de Fable, e logo depois encontrou, testou e verificou a correção.
Eu pedi ao Opus para:
Write a report in /tmp/automation-report.md where you note down all of the tricks you have used in this session to test against real browsers on my computer, include runnable code examples
O que produziu este relatório, que foi inestimável para reunir os detalhes do que aconteceu para este post.
Também compartilhei a transcrição completa do terminal da sessão do Código Claude.
Uma revisão de tudo o que fez
Com base em uma captura de tela e um prompt de uma linha, Claude Fable 5 + Claude Code:
- Descobri a receita para executar o servidor de desenvolvimento local (com variáveis de ambiente falsas necessárias para executá-lo)
- Iniciamos uma sessão do Playwright Chrome
- Ativada a configuração de barras de rolagem visíveis para o Chrome
defaults write com.google.chrome.for.testing AppleShowScrollBars Always(desligou novamente mais tarde) - Percorreu o Firefox e o WebKit no Playwright também, sem conseguir recriar o bug
- Descobri que meu navegador padrão era o Safari
- Construiu um
textarea-scrollbar-test.htmlDocumento HTML - Abri isso no Firefox real (não no Playwright)
- Encontrei isso
osascript -e 'tell application "System Events" to tell process "firefox" to id of window 1'foi bloqueado porque “osascript não tem acesso de assistência” - Descobri isso
uv run --with pyobjc-framework-Quartz pythonsolução alternativa, descrita acima - Adicionado JavaScript aos modelos do site para acionar o
/chave - Construiu seu próprio pequeno servidor web Python CORS para capturar dados JSON
- Reescrevi o modelo para capturar esses dados e enviá-los ao servidor
- Criei um script através do DOM shadow do Web Component para obter as informações necessárias
- Modificou seu modelo personalizado para hackear uma possível correção
- Confirmado que a correção hackeada funcionou
- Relatado sobre como resolver o problema
Como eu disse, incansavelmente proativo!
Eu realmente preciso trancar essa coisa
Por um lado, observar o Fable se esforçando ao máximo para obter as informações necessárias para depurar o que era, no final das contas, uma correção CSS de duas linhas, foi fascinante.
Mas por outro lado… este é um lembrete robusto de que os agentes de codificação podem fazer qualquer coisa você pode fazer digitando comandos em um terminal – e os modelos de fronteira conhecem todos os truques do livro e, evidentemente, alguns que ninguém jamais escreveu antes.
Se Fable estivesse agindo de acordo com instruções maliciosas – um ataque de injeção imediata escondido no código ou em um tópico de problema, ou algo que eu colei descuidadamente em meu terminal – é alarmante pensar até onde isso poderia ir para exfiltrar dados ou causar outras formas de danos.
Executar agentes de codificação fora de uma sandbox sempre foi uma má ideia – é meu principal candidato a um incidente de desastre do Challenger, conforme descrito por Johann Rehberger em The Normalization of Deviance in AI.
Fable é indiscutivelmente mais inteligente e, portanto, mais desconfiado de instruções potencialmente maliciosas. Mas essa inteligência é uma faca de dois gumes: se for faz seja subvertido por instruções, a quantidade de dano que ele pode causar devido à sua proatividade implacável é assustadora.
