MCP com Chrome: Automação com IA · Capítulo 11 de 16 · 30 min
Fazer a automação sobreviver à segunda-feira sem duplicar registro
Fluxo que repete um envio cria registro duplicado no CRM, e o caso caro é a requisição que funcionou e perdeu a resposta.
Este capítulo faz parte do curso gratuito MCP com Chrome: Automação com IA.
O que é: Automação idempotente é um roteiro de agente construído para poder repetir sem estragar: rodar a mesma ação duas vezes produz o mesmo resultado de rodar uma. O oposto gera dois leads, dois pedidos ou duas cobranças a partir de uma única intenção. Por que importa: O erro caro não é o roteiro que falha e avisa, é o que funcionou, perdeu a resposta e foi repetido às cegas, duplicando registro no CRM ou no financeiro. Esse tipo de falha passa despercebido até virar reconciliação manual. A sua decisão: Se automação que escreve em sistema de produção só entra com chave de idempotência e regra de desistência, ou se a operação convive com o risco de duplicidade silenciosa. O que delegar: A construção do roteiro, a espera por estado observável e o teste de repetição. O passo a passo para operar vem logo abaixo.
Glossário rápido
Idempotência
Propriedade de uma ação que, repetida, entrega o mesmo resultado de ter rodado uma vez. Consultar saldo é idempotente; sacar não é, a menos que alguém no caminho reconheça que aquele saque já aconteceu. É o carimbo de "já processado" que impede a segunda via de virar segunda cobrança.
Chave de idempotência
Identificador único gerado antes da primeira tentativa e repetido em todas as retentativas, para que o destino devolva o registro original em vez de criar um gêmeo. É como o número de protocolo de um atendimento: apresentar o mesmo número duas vezes não abre dois chamados.
Um fluxo aprovado pelo time na sexta costuma quebrar na segunda.
Um banner de cookies apareceu no meio do caminho. A rede ficou meio segundo mais lenta. Um botão desceu dois pixels porque o time de produto adicionou um selo de promoção. Nenhuma dessas coisas é anormal: é assim que a web se comporta. O que estava anormal era o roteiro, que assumia um mundo parado.
Existe um estrago pior que a quebra, porque ele não aparece como erro. O agente (o assistente de IA que opera o navegador por você) envia um formulário, a requisição chega ao servidor, o registro é criado, e a resposta se perde antes de voltar. O cliente vê apenas silêncio, conclui que falhou e repete. Agora existem dois leads idênticos no CRM, dois pedidos, duas cobranças.
O caso caro é a requisição que funcionou e cuja resposta se perdeu; a que falhou pelo menos avisa.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
Antes de qualquer regra, veja o mecanismo, que é simples. O tempo esgotado do lado do cliente não cancela nada do lado do servidor. Ele apenas encerra a espera. O efeito colateral no destino já aconteceu, e o cliente não tem como saber.
É por isso que a proteção contra duplicidade não pode morar na sua disciplina de não repetir. Ela precisa morar no protocolo da chamada.
Duas frases resolvem a maior parte do problema. Toda transição espera por um estado observável, nunca por um número de segundos. Toda escrita carrega uma chave de idempotência, de forma que repetir seja seguro por construção, e não por sorte.
Comece pela espera, porque é o erro mais comum e o mais barato de corrigir. Dormir três segundos parece razoável até você perceber que o número está errado nos dois sentidos ao mesmo tempo.
Na rede lenta, três segundos são curtos demais e o passo seguinte age sobre uma página que ainda não terminou de responder. Na rede rápida, são desperdício puro, multiplicado por centenas de passos até virar minutos de espera por execução.
import { expect } from "@playwright/test";
// ERRADO: espera cega. O número está errado nos dois sentidos ao mesmo tempo.
await page.click("#salvar");
await page.waitForTimeout(3000); // três segundos de esperança
await page.click("#continuar");
// CERTO: cada passo espera pelo ESTADO que prova que o anterior terminou.
// O localizador por papel e nome já aguarda o elemento ficar acionável.
await page.getByRole("button", { name: "Salvar cadastro" }).click();
// A asserção é o ponto de verificação: ela prova o efeito, não o tempo.
// O prazo máximo existe para desistir, e não para sincronizar.
await expect(page.getByText("Cadastro criado com sucesso")).toBeVisible({
timeout: 15000,
});
await page.getByRole("button", { name: "Continuar" }).click();Nem toda ferramenta traz espera automática embutida. No chrome-devtools-mcp, o único mecanismo de espera documentado na referência de ferramentas é o wait_for, que aguarda um texto aparecer na página e aceita um prazo opcional. Ou seja: cabe a quem escreve o roteiro intercalar a verificação entre as ações. Se você encadear clique com clique sem nada no meio, está apostando no tempo de resposta.
[1] AGIR clicar em "Salvar cadastro" (papel + nome acessível)
|
[2] VERIFICAR o texto "Cadastro criado" ficou visível no prazo?
|-- não ......> DESISTIR: parar, relatar passo, esperado e encontrado
|
[3] RELER novo snapshot: os identificadores antigos morreram
|
[4] ESCREVER uma vez, com Idempotency-Key fixa desta operação
|
[5] CONFIRMAR exatamente 1 registro no destino, com o id devolvidoA segunda fonte de fragilidade é onde você aponta. Um seletor CSS profundo descreve o caminho até o elemento dentro de uma estrutura que muda toda semana. Uma coordenada de pixel descreve onde o elemento estava numa janela daquele tamanho, naquele dia.
Papel, rótulo acessível e texto visível descrevem outra coisa: a intenção. Um botão chamado "Salvar cadastro" continua sendo esse botão depois do redesenho, porque o nome é justamente o que o produto não muda por acaso.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
A validade curta do identificador, medida no módulo 4, é o que decide a ancoragem do roteiro. Fixe o nome nos dois servidores, porque só o rótulo muda: no Playwright MCP é o identificador opaco no formato de letra e mais número (e5, e15); no chrome-devtools-mcp é o uid vindo do take_snapshot. Nos dois casos a regra do roteiro é idêntica: depois de qualquer transição, tire leitura nova antes de agir.
Agora a escrita. Uma operação é idempotente quando executá-la duas vezes produz o mesmo resultado que executá-la uma. Ler é idempotente por natureza. Criar registro não é, a menos que alguém no caminho saiba reconhecer que aquela criação já aconteceu.
A chave de idempotência é esse reconhecimento. Ela nasce antes da primeira tentativa, viaja em toda repetição e permite ao destino devolver o registro original em vez de criar um irmão gêmeo.
import { randomUUID } from "node:crypto";
// A chave nasce UMA vez, antes da primeira tentativa, e sobrevive às repetições.
// Se ela fosse gerada dentro do laço, cada repetição viraria um registro novo.
const chave = randomUUID();
async function enviarLead(dados, maxTentativas = 3) {
let espera = 500; // recuo exponencial: 500ms, depois 1s, depois 2s
for (let tentativa = 1; tentativa <= maxTentativas; tentativa++) {
try {
const resposta = await fetch("https://api.exemplo.com/leads", {
method: "POST",
headers: {
"Content-Type": "application/json",
// ESTA é a linha que impede a duplicidade. Sem ela, a repetição
// abaixo cria um segundo registro toda vez que a resposta se perde.
"Idempotency-Key": chave,
},
body: JSON.stringify(dados),
});
// 5xx é falha do servidor e vale repetir. 4xx é pedido malformado:
// repetir não conserta, então devolva o erro e pare.
if (resposta.status >= 500) throw new Error("falha temporária " + resposta.status);
return await resposta.json();
} catch (erro) {
if (tentativa === maxTentativas) throw erro;
await new Promise((seguir) => setTimeout(seguir, espera));
espera *= 2;
}
}
}A chave só protege se o outro lado a honrar. Cabeçalho de idempotência é contrato do destino, não mágica do cliente: se a API ignora o cabeçalho, ele vira enfeite e a duplicidade volta. Antes de confiar, leia a documentação do destino e teste enviando a mesma chave duas vezes de propósito, conferindo se voltou o mesmo identificador de registro.
// Quando o destino NÃO honra chave de idempotência (formulário de site,
// CRM antigo, planilha), a proteção passa a ser procurar antes de criar.
// A chave natural é a combinação de campos que identifica a operação no mundo real.
const chaveNatural = [dados.email, dados.origem, dataDeHoje].join("|");
// buscarPorChaveNatural e criarRegistro são as SUAS funções de leitura
// e escrita no destino. O ponto aqui é a ordem, não a implementação.
const existente = await buscarPorChaveNatural(chaveNatural);
if (existente) {
// Caminho da repetição segura: nada a fazer, e isso é sucesso, não erro.
console.log("Escrita já realizada nesta janela:", existente.id);
} else {
await criarRegistro({ ...dados, chaveNatural });
}Guarde a chave junto do estado da execução, não só na memória do processo. Se o roteiro morrer no meio e você reiniciar, a chave precisa ser a mesma para que a retomada não vire uma segunda escrita. Chave em variável de processo morre com o processo; chave gravada em arquivo ou em banco sobrevive à retomada.
Falta a parte que quase ninguém escreve: o que o agente faz quando o mundo não colabora. A tentação é deixar o modelo improvisar um caminho alternativo, e nesse improviso ele clica em coisas que você nunca autorizou.
Calibre a expectativa pelos números. O estudo do Online-Mind2Web mediu agentes em 300 tarefas cotidianas sobre 136 sites reais: o melhor concluiu 61,3% e a maioria ficou perto de 30%, enquanto humanos ficam perto do total. Placares comerciais de 2026 reportam números bem mais altos, com metodologias que não são comparáveis entre si.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
Desista quando o estado esperado não aparecer dentro do prazo, quando a página apresentar algo que o roteiro não descreve, ou quando a leitura nova não encontrar a âncora pelo nome. O relato de desistência tem três campos e nenhum a mais: em qual passo parou, o que esperava encontrar e o que encontrou no lugar. Com isso você conserta o roteiro em minutos; sem isso, você reexecuta às cegas.
O diálogo modal do JavaScript já apareceu duas vezes neste curso, e no roteiro agendado ele cobra mais caro: o script para sem erro nenhum, esperando algo que nunca vem, e você só descobre pelo relatório que não chegou. O chrome-devtools-mcp expõe handle_dialog e o Playwright MCP expõe browser_handle_dialog exatamente para isso. Preveja o tratamento no roteiro em vez de descobrir na madrugada.
$ node roteiro.mjs --run 1
passo 1 abrir formulário .............. ok (estado: campo "E-mail" visível)
passo 2 preencher e enviar ........... ok
passo 3 escrita protegida ............ criado id=1041 key=8f2c...a91
passo 4 confirmar na fonte ........... 1 registro
$ node roteiro.mjs --run 2
passo 3 escrita protegida ............ reconhecida id=1041 key=8f2c...a91
passo 4 confirmar na fonte ........... 1 registro
$ node roteiro.mjs --run 3
passo 3 escrita protegida ............ reconhecida id=1041 key=8f2c...a91
passo 4 confirmar na fonte ........... 1 registro
$ node roteiro.mjs --run 4 (execução sabotada: botão removido)
passo 2 verificar estado ............. FALHOU
DESISTIU no passo 2
esperava: botão com nome acessível "Salvar cadastro"
encontrou: formulário sem botão de envio na leitura mais recente
nenhuma escrita foi tentada# Três execuções seguidas do MESMO roteiro, com a MESMA chave.
# Se a proteção estiver correta, o destino termina com um registro só.
for i in 1 2 3; do
node roteiro.mjs --idempotency-key "lab-2026-07-19-a" | tee "run-$i.log"
done
# Conferência independente: o roteiro não pode ser juiz de si mesmo.
# Este script lê o destino e falha se encontrar mais de um registro.
node conferir-destino.mjs --key "lab-2026-07-19-a" --esperado 1Tarefa deste módulo. No perfil de laboratório que você montou no módulo 3, construa um fluxo de três a cinco passos com pelo menos uma escrita, contendo os três elementos obrigatórios: nenhuma espera por tempo fixo, ponto de verificação depois de cada passo, e chave de idempotência na escrita.
Rode três vezes seguidas, de propósito. Depois remova do ambiente um elemento que o roteiro espera (esconda o botão pelo DevTools, por exemplo) e rode de novo para forçar a desistência. O teste passou quando o destino termina com um registro só e a quarta execução para com a mensagem de desistência, sem escrever nada.
Sabote com intenção, um item por vez. Esconder o botão de envio testa a ancoragem. Estrangular a rede para uma condição lenta testa se sobrou alguma espera por tempo fixo disfarçada. Disparar um confirm() na página testa o tratamento de diálogo modal. Um roteiro que passa nas três sabotagens é um roteiro que você pode agendar sem medo.
Você concluiu este módulo quando: (1) as três execuções seguidas produziram exatamente UM registro de escrita no destino, verificado por uma conferência independente do próprio roteiro; (2) nenhuma execução falhou por elemento não encontrado, mesmo com o layout se comportando de forma diferente entre elas; (3) a execução sabotada terminou com uma mensagem explícita de desistência informando passo, esperado e encontrado, sem tentar caminho alternativo e sem escrever nada; e (4) você consegue apontar, no seu próprio roteiro, a linha exata que impede a duplicidade e explicar por que ela precisa estar fora do laço de retentativa.
A decisão executiva aqui é onde um agente pode escrever sem um humano olhando. Enquanto a taxa de conclusão de agentes em tarefas reais fica entre cerca de 30% e 60%, automação que toca dinheiro ou dado de cliente só deveria rodar sozinha com chave de idempotência e regra de desistência definidas antes, mais uma conferência independente do próprio roteiro. Estabeleça esse piso como condição de entrada em produção, e leia quem pede para pular a etapa como quem se oferece para reconciliar duplicidade na mão depois.
Seu caderno neste capítulo
Abrir o caderno completoSelecione um trecho do capítulo para destacar ou anotar. Nos vídeos e áudios, use Anotar este momento. No teclado, selecione com Shift e as setas e use Alt+Shift+D para destacar ou Alt+Shift+N para anotar.
Salvo neste navegador. Entre na sua conta para levar o caderno a outros aparelhos.
Entre na sua conta para compartilhar o que aprendeu e convidar alguém para estudar com você.
Conexões deste capítulo
Veja o que estudar antes e para onde seguir depois, explore os conceitos e compare abordagens em outros cursos. Sugestões marcadas como “sugerido pelo grafo” vêm dos assuntos em comum, não do índice do curso.
Estude antes
- Construir a identidade com tokens, CSS moderno e DESIGN.mdsugerido pelo grafoApresenta o conceito “CSS”, usado em “Fazer a automação sobreviver à segunda-feira sem duplicar registro”.
- CursoMCP para quem decidesugerido pelo grafo7 capítulos de “MCP com Chrome: Automação com IA” usam conceitos apresentados em “MCP para quem decide”.
- CursoNode.js: JavaScript no Servidorsugerido pelo grafo3 capítulos de “MCP com Chrome: Automação com IA” usam conceitos apresentados em “Node.js: JavaScript no Servidor”.
- CursoSetup Completo: do zero ao Claude Codesugerido pelo grafo3 capítulos de “MCP com Chrome: Automação com IA” usam conceitos apresentados em “Setup Completo: do zero ao Claude Code”.
Conceitos deste capítulo
O mesmo assunto em outros cursos
- Software e IA para executivosManter vários sistemas de acordo quando um deles caiExaminar conexões de Manter vários sistemas de acordo quando um deles cai
- Engenharia de Software para ExecutivosEvitar que a troca de um fornecedor pare a operaçãoExaminar conexões de Evitar que a troca de um fornecedor pare a operação
- Segundo cérebro com IAComo retomar o trabalho do agente de onde ele parouExaminar conexões de Como retomar o trabalho do agente de onde ele parou
- SO nativo de IAPor que não automatizar aindaExaminar conexões de Por que não automatizar ainda
Voltar ao capítulo anterior: Configurar o servidor MCP sem herdar um prazo de validade
Leve uma ideia para a prática
Escolha uma atividade no painel e volte a este curso quando quiser.
Atividades e evolução ficam reunidas no painel da sua conta.
Capítulos vizinhos em MCP com Chrome: Automação com IA
- 09Barrar o ataque que chega pela ferramenta que você instalou
- 10Configurar o servidor MCP sem herdar um prazo de validade
- 11Fazer a automação sobreviver à segunda-feira sem duplicar registro
- 12Descobrir o que a IA não vê na página que você vê
- 13Saber se um agente consegue operar o seu site