Pular para o conteúdo
fernando.moretes.com
BlogEstudosCursosE-booksOpen SourcePodcasts
Loading…
Fernando Azevedo

Arquiteto de TI Especialista

Arquitetura, AWS, IA em produção, sistemas financeiros e FinOps, escritos a partir do que foi operado, com os números.

  • LinkedIn
  • GitHub
  • E-mail

Conteúdo

  • Blog
  • Estudos de arquitetura
  • Cursos
  • E-books
  • Open Source
  • Podcasts
  • Assuntos
  • Trilhas

Ferramentas

  • Moretes Architect MCP
  • Well-Architected self-check
  • Arquitetura deste site
  • Números públicos
  • Histórico de estudo

Sobre

  • Comunidade
  • IA Builder
  • Perfil
  • Currículo (CV)
  • Trabalhe comigo
  • Media kit
  • RSS do blog
  • RSS dos estudos
  • Artigos narrados (podcast)
  • llms.txt
  • Termos, privacidade e uso de IA

(c) 2026 Fernando Francisco Azevedo

Blog/Artigo
RSSMarkdownLLMs
IA & AgentesNotas de Campo

O agente caiu depois da mudança. Você deve repetir?

27 de out. de 2026 14 minAvançado Com apoio de IA000 visualizações00 reproduções
Ouvir artigo

16:31 · voz do Fernando

O momento mais difícil de uma automação costuma estar entre duas confirmações: o sistema de destino aceitou a mudança, mas o executor ainda não registrou que terminou. Reiniciar o agente resolve a disponibilidade do processo; não resolve a dúvida sobre o efeito anterior. Neste laboratório, eu derrubo o processo exatamente nesse intervalo e inspeciono o que sobrevive. A decisão seguinte depende de evidências persistentes, não da confiança do modelo.

O que foi verificado

Implementação
lab-security-remediation, tag v0.4.0; testes locais executados em 27/10/2026.
Resultado observado
22 testes passaram. No exercício com recibo: versão 2, um recibo e nenhuma segunda mudança após recuperação e repetição.
Escopo
SQLite local, alvo sintético, revisão simulada. Nenhuma credencial ou chamada AWS necessária.
Não demonstrado
Não comprova execução exatamente uma vez em APIs remotas, resistência a perda de energia ou autorização pronta para produção.

Comece pela pergunta que o log não responde

Imagine uma ferramenta que corrige uma configuração. Ela recebe uma proposta revisada, verifica a versão do alvo e aplica a mudança. Antes de devolver sucesso, o processo termina. O cliente vê uma interrupção. O alvo talvez já tenha mudado. Uma linha de log dizendo que a chamada começou não permite escolher entre essas possibilidades.

Neste exercício, o alvo é apenas uma linha SQLite que representa um bucket sintético. A propriedade blockPublicAccess serve como estado didático; não é uma chamada ao S3. A proposta identifica a operação e a versão esperada. Um registro de intenção, chamado ledger, guarda o pedido revisado. Um recibo registra que aquele pedido produziu aquela versão do alvo.

Essa separação permite formular uma pergunta verificável: qual evidência liga esta operação a esta mudança? Ver a configuração desejada não responde quem a mudou. Encontrar um processo reiniciado não responde se o processo anterior concluiu. Uma mensagem de erro no cliente descreve a observação do cliente, e não necessariamente a realidade do destino.

Onde a evidência precisa sobreviver

Arquitetura do laboratório local. As tabelas estão no mesmo arquivo SQLite, mas intenção, efeito e conclusão usam transações distintas. A atualização do alvo e seu recibo são atômicos entre si.

Local CLI
  • Reviewed executor
  • Recovery reader
SQLite · separate commits
  • Operation ledger
  • Target + receipt
  • Audit events

Prepare uma execução que outra pessoa consiga repetir

Use Node.js 22.13 ou posterior, com node:sqlite disponível. O código-fonte da tag é a referência deste exercício; não presuma que a versão publicada no npm seja a mesma. A instalação de dependências não é necessária para executar este laboratório. Faça o clone em uma pasta nova, confira a tag e rode os testes antes de alterar qualquer cenário.

Escolha nomes de banco novos em cada repetição completa. Um banco reaproveitado preserva histórico, e esse histórico muda o resultado esperado. Preserve também a proposta original: gerar outra depois da mudança pode criar um digest diferente para o mesmo identificador e deve resultar em conflito, não em uma autorização implícita para executar novamente.

Os comandos com falha intencional estão separados dos comandos de inspeção. Em um script com set -e, capture explicitamente o código 86 para que a interrupção esperada não encerre sua investigação. O teste de incerteza retorna 2, outro resultado previsto. Esses códigos fazem parte da evidência; não devem desaparecer em um || true indiscriminado.

Preparação: código fixado e testes locais
bash
git clone https://github.com/fernando-moretes/lab-security-remediation.git
cd lab-security-remediation
git checkout v0.4.0
node --version
npm test

Experimento 1: o efeito existe; a confirmação se perdeu

Crie o banco e exporte a proposta. O comando run com --approve simula uma revisão explícita e grava a intenção. O ponto after-target encerra o processo depois do commit que atualiza o alvo e escreve o recibo, antes de marcar a operação como concluída. Não é uma exceção capturada dentro de uma única função: o CLI termina e os comandos seguintes abrem o banco em outros processos.

Depois da queda, inspecione três coisas juntas: o status da operação, a versão do alvo e a existência do recibo. Na execução de 27 de outubro, a operação estava pending, o alvo estava na versão 2 com blockPublicAccess: true, e havia um único recibo associado ao digest da proposta. Essa combinação demonstra por que repetir só porque o ledger está pendente seria uma decisão mal informada.

Queda intencional: run retorna 86; continue com inspect
bash
node bin/cli.mjs durable init ./receipt.sqlite
node bin/cli.mjs durable plan ./receipt.sqlite > receipt-proposal.json
node bin/cli.mjs durable run ./receipt.sqlite receipt-proposal.json --approve --crash after-target
# Expected exit: 86
node bin/cli.mjs durable inspect ./receipt.sqlite
node bin/cli.mjs durable recover ./receipt.sqlite synthetic-finding-001
node bin/cli.mjs durable run ./receipt.sqlite receipt-proposal.json --approve
node bin/cli.mjs durable inspect ./receipt.sqlite

Recuperar o registro não exige repetir o efeito

O comando recover consulta a operação, o recibo e o estado atual. Neste caso, muda a classificação para reconciled e registra a decisão no histórico. Ele não altera o alvo. A repetição da proposta original também retorna reconciled, com retryable: false. Na inspeção final, a versão permanece 2 e a quantidade de recibos permanece 1.

Esses são os invariantes que vale conferir. O teste não consiste apenas em procurar a palavra sucesso na saída. Compare o efeito observável antes e depois da recuperação. Compare também antes e depois da repetição. Se a versão tivesse aumentado de novo, um status aparentemente correto esconderia uma segunda execução.

O recibo é evidência histórica, não um selo permanente de saúde. Se o alvo sofrer uma mudança posterior, o histórico da operação anterior pode continuar válido enquanto o estado atual diverge. A implementação expõe driftAfterReceipt para distinguir essas perguntas. Restaurar o estado desejado, quando necessário, exige uma nova decisão revisada sobre o estado atual.

Resultados observados nos dois experimentos

InspeçãoCom reciboSem recibo, com drift
Depois da interrupção / driftpending; versão 2; 1 recibopending; versão 2; 0 recibos
Recuperaçãoreconciled; saída 0uncertain; saída 2
Reenvio da proposta originalreconciled; versão permanece 2uncertain; versão permanece 2
Chamadas à nuvem00

Experimento 2: o estado parece certo; a autoria é desconhecida

Agora use outro banco. Interrompa a execução em after-intent, antes de aplicar o efeito. Em seguida, use o comando didático drift para mudar o alvo por outro caminho. Ao recuperar, a propriedade desejada estará verdadeira e a versão será 2, assim como no primeiro experimento. A diferença decisiva é a ausência de recibo.

O resultado observado é uncertain, retryable: false, com código de saída 2. Reenviar a proposta original mantém essa classificação e não modifica novamente o alvo. O sistema não deduz autoria a partir de coincidência de valores. Esse comportamento troca disponibilidade automática por uma decisão que pode ser investigada.

Não apague a operação para destravar a fila. Isso elimina a memória usada para reconhecer a duplicata. Preserve o banco, a proposta e os resultados; investigue a mudança e defina o próximo passo como uma nova decisão. O laboratório não oferece um botão mágico de resolução administrativa, nem deve sugerir que editar o ledger manualmente seja um procedimento seguro.

A configuração final coincide, mas o recibo não existe
bash
node bin/cli.mjs durable init ./uncertain.sqlite
node bin/cli.mjs durable plan ./uncertain.sqlite > uncertain-proposal.json
node bin/cli.mjs durable run ./uncertain.sqlite uncertain-proposal.json --approve --crash after-intent
# Expected exit: 86
node bin/cli.mjs durable drift ./uncertain.sqlite true
node bin/cli.mjs durable inspect ./uncertain.sqlite
node bin/cli.mjs durable recover ./uncertain.sqlite synthetic-finding-001
# Expected exit: 2, status: uncertain
node bin/cli.mjs durable run ./uncertain.sqlite uncertain-proposal.json --approve
# Expected exit: 2; no additional target change

Três commits explicam as janelas de falha

A implementação persiste a intenção revisada em uma transação. Em outra, compara a versão esperada e grava o alvo junto com o recibo. Em uma terceira, marca a conclusão no ledger. O recibo e a mudança são atômicos entre si; a execução completa não é uma transação única. Essa escolha cria deliberadamente a janela que acabamos de testar.

BEGIN IMMEDIATE serializa os escritores no arquivo local, com espera de contenção limitada. O armazenamento usa WAL e synchronous=FULL. Essas escolhas dão semântica transacional ao exercício, mas os testes de encerramento de processo não equivalem a testes de energia, disco, corrupção ou sistema de arquivos de rede. O custo da serialização também importa: um único arquivo local não representa escalabilidade distribuída.

A suíte cobre outras fronteiras: queda antes do commit do alvo, antes do commit de conclusão e depois da conclusão; processos concorrentes; identificadores repetidos com payload diferente; propostas sem revisão e alterações de estado. Os 22 testes que passaram são verificações dessas propriedades no laboratório, não uma porcentagem de disponibilidade ou uma taxa de sucesso de um agente em produção.

Visão C4 do desenho

Uma pessoa executa um laboratório de recuperação e inspeciona evidências sintéticas. O modelo não chama serviços AWS nem precisa de um LLM.

Containers

C4

CLI

Node.js

Processos independentes para plan, run, inspect e recover.

C4

Persistent store

SQLite local file

Operações, alvo, recibos e histórico persistidos no mesmo arquivo.

Componentes

C4

Proposal validation

Valida o pedido, a revisão simulada e a versão esperada.

C4

Conditional mutation

Atualiza alvo e recibo no mesmo commit.

C4

Recovery classifier

Lê evidências e registra a classificação sem executar a mutação.

O que muda quando a ferramenta chama AWS

Em uma integração real, gravar intenção em um banco e chamar uma API remota são operações em sistemas diferentes. O commit local não engloba a API. O laboratório coloca alvo e recibo juntos justamente para tornar a evidência inspecionável; transportar o desenho para a nuvem exige reavaliar essa fronteira.

A AWS Builders' Library explica o valor de um identificador explícito fornecido pelo cliente para reconhecer a intenção de repetição. Confira o contrato de idempotência da operação concreta: escopo, validade do token, comportamento com parâmetros diferentes e resposta em chamadas repetidas. Não derive uma garantia universal porque outro serviço aceita um token.

Para cada ferramenta mutável, registre quais evidências remotas estão disponíveis, quanto tempo permanecem consultáveis e quem resolve um resultado inconclusivo. Quando o destino não oferece uma prova suficiente, mantenha um estado de incerteza visível. Adicionar uma fila, um framework de agentes ou um servidor MCP não fecha sozinho o intervalo entre efeito e confirmação.

Também separe a autorização atual da evidência histórica. --approve neste laboratório é apenas uma simulação local de revisão. Um serviço real precisa verificar identidade, escopo e validade antes da mutação; uma aprovação revogada não deve virar permissão de nova execução só porque existe um registro antigo. Uma consulta de recuperação e uma tentativa de mutação exigem decisões distintas.

Decisão: incerteza é um resultado operacional

Aceito
Contexto

O cliente pode perder a resposta depois de um efeito confirmado no alvo.

Decisão

Usar evidência persistente para reconciliar; bloquear repetição quando não for possível atribuir o efeito à operação. No laboratório, recover nunca altera o alvo.

Consequências
  • Exige um responsável por investigar estados incertos.
  • Retenção de recibos e propostas faz parte do contrato de recuperação.
  • Pode exigir intervenção mesmo quando o estado atual parece desejável.

Checklist para revisar sua própria ferramenta

  1. 1

    Defina a intenção

    Escolha um identificador estável para a mesma operação e uma regra explícita para payload divergente. Salve a proposta original e a versão do contrato.

  2. 2

    Localize o commit real

    Marque onde o alvo muda e onde a confirmação é persistida. Provoque uma interrupção entre eles, sem recursos de produção.

  3. 3

    Compare efeitos

    Observe versão, recibos e histórico antes e depois do replay. Um status de sucesso isolado não demonstra ausência de duplicata.

  4. 4

    Exercite a ambiguidade

    Faça outro ator alterar o alvo sem recibo da operação. Verifique que valor coincidente não se transforma em autoria presumida.

  5. 5

    Defina retenção e operação

    Documente a janela em que a evidência existe, o responsável pela investigação e o procedimento de cópia consistente do banco. Feche os processos antes de copiar o arquivo do laboratório.

Leitura pelos pilares Well-Architected

Excelência operacional

Transforme uncertain em uma fila de investigação com responsável e evidências mínimas. A recuperação precisa de runbook e exercício, além de observabilidade.

Segurança

A revisão local não autentica ninguém. Em produção, proteja o ledger, minimize dados sensíveis e revalide a autorização da próxima mutação.

Confiabilidade

Teste a perda da confirmação, não somente indisponibilidade antes da chamada. Separe reconhecimento de duplicata, reconciliação e nova tentativa autorizada.

Eficiência de performance

Meça contenção e tempo de reconciliação na arquitetura real. Serialização de escritores no SQLite não é evidência de throughput distribuído.

Otimização de custos

Os exercícios não fazem chamadas AWS. Para uma implementação remota, estime armazenamento de evidências e consultas de recuperação; não invente economia a partir deste teste local.

Sustentabilidade

Evitar efeitos e tentativas redundantes reduz trabalho desnecessário, mas o laboratório não mede energia nem emissões. Não converta essa hipótese em um número.

Armadilhas que o exercício torna visíveis

  • Repetir toda chamada interrompida sem consultar a evidência do efeito.
  • Tratar o valor final desejado como prova de que esta operação o produziu.
  • Gerar uma nova proposta depois da mudança e chamar isso de repetição da original.
  • Apagar recibos ou ledger sem uma política que preserve a janela de reconhecimento de duplicatas.
  • Apresentar uma transação SQLite local como garantia de execução exatamente uma vez em serviços remotos.

Replay para diagnóstico e retry de mutação são coisas diferentes

Para compartilhar um caso reproduzível, leve a versão do código, o estado inicial sintético, a proposta, o ponto de interrupção, os códigos de saída e as inspeções antes e depois. Uma captura de terminal ajuda a comunicar; os arquivos e comandos permitem verificar. Remova credenciais e dados reais antes de abrir uma issue.

A evidência pública associada a este artigo contém os resultados dos dois cenários. A proposta é abrir discussão sobre um contrato concreto: qual observação permitiria reconciliar, qual permitiria tentar novamente e qual exige investigação? Uma contribuição pequena, como acrescentar um caso de falha com resultado esperado, pode ser mais útil do que adicionar mais uma ferramenta ao catálogo.

Se quiser experimentar, execute os dois cenários no repositório e descreva qual fronteira de falha você testaria em seguida. Para trazer isso à sua arquitetura AWS, comece por uma única operação mutável e documente seu contrato de idempotência e recuperação. A partir daí, o teste deixa de ser uma demonstração genérica de agente e passa a ser uma propriedade que a equipe consegue revisar.

Referências

Observed local results: October 27, 2026 (JSON)Source and exercise, lab v0.4.0Executable recovery testsAWS Builders' Library: Making retries safe with idempotent APIsSQLite transactionsNode.js SQLite API

A pergunta para levar à revisão

Antes de autorizar uma nova tentativa, peça a evidência que distingue efeito confirmado, efeito ausente e efeito desconhecido. Neste laboratório, um recibo permite reconciliar sem executar de novo; sua ausência diante de drift exige parar. O valor do exercício é tornar essa decisão reproduzível e discutível por outra pessoa.

#AI Agents#Idempotency#Crash Recovery#MCP#Security
Compartilhar:LinkedInWhatsAppXBaixar em Markdown
Fonte analisada: Persistent ledger and crash recovery lab v0.4.0
Próximo passo
Agentes de IA em produção na AWSComo eu desenho, oriento e audito agentes que vão ao ar, com os números e as fontes.Ver o IA BuilderTrilha Arquiteto de IA, gratuitaFundamentos, LLMs, RAG, tools, MCP e arquitetura na AWS, em aulas curtas e interativas.Começar a trilha

Continue lendo

IA & AgentesOAuth no AWS MCP Server: Comparativo de Estratégias de Autenticação para AgentesO suporte OAuth nativo no AWS MCP Server muda o jogo para quem estava improvisando autenticação de agentes com credenciais estáticas ou fluxos Cognito customizados. Mas 'suporte OAuth' não é uma decisão de arquitetura, é um ponto de partida. Neste artigo, faço um bake-off honesto entre quatro estratégias de autenticação para agentes de IA em ambientes financeiros, com trade-offs reais, números plausíveis e uma recomendação direta.Ler IA & AgentesQuatro padrões de engenharia que separam multiagente de prompt chainO Google publicou os quatro padrões de engenharia que apareceram nos vencedores do AI Agents Challenge. Nenhum deles é sobre modelo: são interface de ferramenta, mensageria assíncrona, validação estrutural e roteamento barato antes da inferência. Reviso cada um com o que muda ao levá-lo para AgentCore, EventBridge e Bedrock, e onde o protótipo do desafio não sobrevive à produção.Ler IA & AgentesAWS WAF no AgentCore Gateway: Segurança de Produção para IA AgênticaA disponibilidade geral do AWS WAF para o Amazon Bedrock AgentCore Gateway marca uma inflexão importante: workloads de IA agêntica agora podem receber proteções de borda consistentes sem instrumentação por agente. Analiso o que essa integração realmente entrega, onde ela ainda deixa lacunas e como estruturar uma postura de segurança madura para sistemas agênticos em produção.Ler
AnteriorAmazon Quick em rede privada: os dois planos do PrivateLink e onde eles vazam
Gostou desta análise? Receba a próxima.

Deep dives de arquitetura, AWS, IA e mercado: direto no seu email. Grátis.

Sem spam · cancele quando quiser

Pergunte ao Fernando sobre isto

Uma resposta focada sobre este artigo, do meu assistente de IA, baseada no meu trabalho.

Participe da conversa

Entre para comentar

Confirme seu e-mail para participar, você também recebe a newsletter. Sem senha.

Neste artigo
Comece pela pergunta que o log não respondeArquiteturaPrepare uma execução que outra pessoa consiga repetirExperimento 1: o efeito existe; a confirmação se perdeuRecuperar o registro não exige repetir o efeitoResultados observados nos dois experimentosExperimento 2: o estado parece certo; a autoria é desconhecidaTrês commits explicam as janelas de falhaC4O que muda quando a ferramenta chama AWSDecisão: incerteza é um resultado operacionalChecklist para revisar sua própria ferramentaWell-ArchitectedAntipadrõesReplay para diagnóstico e retry de mutação são coisas diferentesReferênciasA pergunta para levar à revisão