8 min de leitura

Registro de tentativas de agentes de IA que revela efeitos duplicados

O registro de tentativas de agentes de IA associa cada tentativa a uma única ação pretendida, preserva resultados desconhecidos e revela efeitos repetidos durante uma investigação.

Registro de tentativas de agentes de IA que revela efeitos duplicados

Uma repetição de agente não é uma segunda cópia de uma ação. É uma segunda tentativa de concluir uma ação declarada, e a trilha de auditoria precisa preservar essa distinção. Se seus registros mostram apenas uma sequência de chamadas HTTP semelhantes, você fez a recuperação e a repetição parecerem a mesma coisa.

Essa diferença importa principalmente quando a ação altera o mundo: criar um chamado, revogar acesso, registrar um pagamento, publicar uma implantação ou executar um comando por SSH. O agente pode receber um timeout depois de o destino já ter agido. Também pode repetir após uma falha local, antes de qualquer byte sair da máquina. Esses casos exigem respostas diferentes, mas muitos sistemas registram ambos como request failed, retrying.

Já vi equipes investigarem supostas ações duplicadas comparando manualmente horários e cargas úteis. Isso é um substituto ruim para um modelo de eventos. Crie a relação em cada registro no momento em que a ação ocorrer. O investigador deve poder selecionar uma operação e ver sua intenção, todas as tentativas, o motivo de cada tentativa posterior e o resultado que finalmente resolveu a questão.

Uma repetição pertence a uma operação, não a uma linha de registro

Toda ação de agente que produz efeitos colaterais precisa de duas identidades: um ID de operação para o resultado pretendido e um ID de tentativa para uma execução. O ID de operação permanece desde o momento em que o agente decide o que pretende fazer até você encerrar ou reconciliar essa intenção. Cada chamada de rede ou execução SSH recebe um novo ID de tentativa.

Suponha que um agente pretenda desativar uma conta. Ele cria a operação op_7f2c. A primeira solicitação, att_01, chega à API de identidade, mas a conexão é encerrada antes que uma resposta chegue. Uma segunda solicitação, att_02, pode ser uma tentativa de recuperação justificada. Os dois registros precisam apontar para op_7f2c; att_02 deve apontar diretamente para att_01 como a tentativa que o desencadeou.

Não use o ID da conversa como ID da operação. Uma conversa de agente pode conter muitas ações, e uma ação pode sobreviver à conversa quando um supervisor retoma o trabalho. Também não use apenas um hash da solicitação. Um hash descreve bytes, enquanto uma operação descreve o efeito pretendido. Duas solicitações podem diferir em detalhes de transporte inofensivos e ainda pertencer a uma mesma operação. Por outro lado, bytes idênticos podem criar duas ações pretendidas distintas quando o agente os envia deliberadamente duas vezes.

Use uma identidade de operação quando o agente assumir um compromisso como «desativar a conta A», «criar um incidente para o alerta B» ou «executar esta migração uma vez no host C». Registre essa intenção em campos estruturados. Um resumo em linguagem natural é útil para as pessoas, mas não pode ser a única identidade, porque a redação muda entre execuções do agente.

Uma hierarquia clara é esta:

  • Uma sessão identifica uma execução de processo do agente.
  • Uma operação identifica um efeito externo pretendido.
  • Uma tentativa identifica uma execução concreta.
  • Uma observação identifica uma evidência recebida depois, como um callback, uma verificação de leitura após escrita ou uma decisão do operador.

Essa hierarquia resolve um caso incômodo que aparece com frequência: um agente envia uma solicitação, sofre um timeout e então pergunta a outro endpoint se a ação aconteceu. A consulta não é uma repetição. É uma observação associada à operação original. Tratá-la como outra tentativa esconde a evidência mais útil na categoria errada.

Desconhecido é um resultado, não uma mensagem de erro

Um timeout produz incerteza, não uma prova de falha. Seu registro precisa ter um estado para essa incerteza e mantê-lo até que evidências posteriores o resolvam.

Muitas bibliotecas de cliente juntam vários eventos em uma única exceção: conexão recusada, falha de DNS, corpo de resposta que chegou tarde demais e conexão reiniciada depois de o servidor confirmar uma gravação. Essa conveniência pode ser aceitável para o fluxo de controle da aplicação. Como registro final de auditoria, é inaceitável. Os registros precisam declarar o que o chamador observou e evitar afirmações sobre o destino que o chamador não pode sustentar.

Para uma tentativa, separe a observação local do estado resolvido da operação. Uma tentativa pode estar em not_sent, sent_no_response, response_received ou execution_error. A operação pode estar em open, succeeded, failed, unknown ou cancelled. Os nomes variam, mas a separação é indispensável.

not_sent significa que o cliente parou antes do envio. Uma falha local ao consultar uma credencial pode se encaixar aqui. Repeti-la não pode duplicar um efeito remoto porque nenhuma solicitação remota foi enviada.

sent_no_response significa que o chamador enviou a ação, mas não tem uma resposta utilizável. Este é o estado perigoso. Uma repetição automática só pode ser segura se o destino tiver um mecanismo confiável de desduplicação ou se a própria ação não puder criar um efeito duplicado.

response_received não significa sucesso automaticamente. O servidor pode devolver um erro de validação, uma resposta de conflito ou uma resposta de sucesso que descreve um trabalho assíncrono. Armazene o status, a impressão digital relevante da resposta e qualquer referência de operação fornecida pelo destino. Depois, defina o estado da operação com base no contrato daquela API específica.

Evite escrever failed quando você quer dizer unknown. A palavra deixa os painéis mais organizados, mas informa ao próximo agente ou operador que deve repetir uma ação que talvez já tenha acontecido. Durante um incidente, esse único campo desonesto pode transformar uma ação equivocada em uma sequência delas.

A semântica HTTP não torna uma ação de negócio segura para repetir

Os métodos HTTP descrevem semântica de protocolo, não garantias do seu negócio. A RFC 9110 diz que um método é idempotente quando o efeito pretendido de várias solicitações idênticas é igual ao efeito de uma só. Ela considera PUT, DELETE e os métodos seguros idempotentes, enquanto POST não é idempotente por padrão.

Essa orientação é útil, mas os engenheiros costumam extrapolá-la. Uma solicitação DELETE pode ser idempotente no protocolo porque excluir um recurso inexistente deixa o recurso inexistente. Sua pergunta de auditoria pode ser outra: o agente excluiu a conta correta, acionou a limpeza downstream duas vezes e usou uma autoridade diferente na segunda chamada? O rótulo do protocolo não responde a essas perguntas.

PUT também causa problemas. Um PUT que define um recurso com uma representação fixa geralmente tolera repetições. Um endpoint PUT que dispara uma notificação, aloca um registro ou executa uma integração a cada recebimento não oferece a segurança que as pessoas presumem. Leia o contrato documentado do destino e teste o comportamento com uma perda forçada de resposta. O nome do método não é uma evidência.

Os endpoints POST frequentemente aceitam um token de idempotência. Envie um token estável derivado do ID da operação, não do ID da tentativa. Se att_01 e att_02 tiverem tokens diferentes, você anulou justamente o recurso que deveria protegê-lo da repetição.

Um envelope de solicitação pode ser assim:

{
  "operation_id": "op_7f2c9c",
  "attempt_id": "att_01",
  "idempotency_key": "op_7f2c9c",
  "intent": {
    "kind": "disable_account",
    "subject_ref": "user:1842"
  },
  "destination": {
    "method": "POST",
    "route_template": "/v1/accounts/{id}/disable",
    "authority_ref": "vault:identity-prod"
  },
  "request_fingerprint": "sha256:...",
  "dispatch_state": "sent_no_response"
}

Não registre o cabeçalho de autorização, o cookie de sessão, o material privado de SSH nem um corpo que contenha segredos. Registre uma referência à credencial e uma impressão digital da representação canônica da solicitação. Uma impressão digital ajuda os investigadores a comparar tentativas sem transformar a trilha de auditoria em outro repositório de segredos.

O destino precisa respeitar o token de idempotência para impedir efeitos repetidos. Quando isso acontecer, registre a referência devolvida pelo destino e indique se a resposta veio de um resultado anterior armazenado. Quando não acontecer, o token será apenas um cabeçalho inerte, e sua política de repetição precisa agir de acordo.

Uma repetição SSH pode repetir mais de um comando

O SSH torna a contabilização de tentativas mais difícil porque uma conexão pode transportar sintaxe de shell, pipelines, redirecionamentos e comandos que são concluídos parcialmente. Uma sessão SSH com falha não informa quais partes do comando remoto foram executadas.

Considere este comando:

create-user deployer \u0026\u0026 install-key deployer /tmp/new.pub \u0026\u0026 restart-service api

Se o cliente perder a conexão depois do envio, uma repetição pode falhar porque o usuário já existe, instalar uma chave duas vezes se o auxiliar fizer append ou reiniciar um serviço pela segunda vez. O \u0026\u0026 do shell controla apenas o comportamento dentro de uma execução. Ele não protege uma nova conexão que execute novamente a string inteira.

Registre o comando exato somente quando ele não contiver segredos. Caso contrário, armazene uma forma de exibição com os dados ocultados e uma impressão digital canônica. Registre o alias do host ou a referência da chave do host, a referência da conta remota, o diretório de trabalho quando relevante, o status de saída quando recebido e o limite da execução. O limite deve indicar se o auxiliar iniciou o comando e se recebeu um status de saída, não apenas se o chamador local informou um erro.

O padrão mais seguro é um script remoto com um marcador de operação que o script verifica antes de agir. O marcador precisa ficar em um local que o sistema de destino consiga ler atomicamente. Uma transação de banco de dados, um registro de implantação ou um arquivo criado exclusivamente podem funcionar, dependendo do ambiente. Um cache local do agente não prova nada depois de uma falha do processo ou de uma segunda execução do agente.

Por exemplo, um script de implantação pode aceitar OPERATION_ID, gravá-lo em um registro de release antes da ativação e devolver o resultado existente se o registro já estiver presente. O evento de auditoria captura então tanto o ID da operação local quanto o ID do registro remoto. Isso cria uma ponte entre o registro do agente e as evidências no host.

Não classifique comandos arbitrários do shell como repetíveis só porque são «na maioria das vezes seguros». Categorize as famílias de comandos. A coleta somente leitura pode ser repetida livremente. Comandos que definem estado precisam de uma condição explícita de convergência. Comandos que acrescentam dados, movimentam valores financeiros, destroem dados ou enviam notificações precisam de um registro remoto de desduplicação ou de uma decisão humana depois de um resultado desconhecido.

Toda tentativa posterior precisa de um motivo declarado e de um pai

Repita sem compartilhar credenciais
O Sallyport injeta as credenciais HTTP, para que os agentes possam agir sem receber o segredo utilizado.

Um evento de repetição deve indicar a tentativa que o causou e a condição que justificou uma nova tentativa. retry_count: 2 é fraco demais. Ele informa que houve chamadas anteriores, mas não identifica qual chamada falhou, se o agente mudou alguma coisa ou se uma pessoa aprovou a continuação.

Use um conjunto controlado de motivos e anexe os detalhes de apoio separadamente. Motivos úteis incluem connection_not_established, rate_limited, destination_5xx, response_lost_after_dispatch, credential_refreshed e operator_requested. Não permita que o agente invente uma justificativa em prosa que pareça tranquilizadora, mas não possa ser agrupada nem revisada.

Para cada repetição, preserve estas relações:

{
  "operation_id": "op_7f2c9c",
  "attempt_id": "att_02",
  "retry_of_attempt_id": "att_01",
  "retry_reason": "response_lost_after_dispatch",
  "retry_decision": "destination_idempotency_confirmed",
  "attempt_budget_remaining": 1,
  "request_fingerprint": "sha256:...",
  "prior_request_fingerprint": "sha256:..."
}

As duas impressões digitais normalmente devem ser iguais. Se forem diferentes, registre o motivo. Um cabeçalho de timestamp alterado pode ser esperado. Uma conta, um valor, um nome de host, uma rota ou uma autoridade diferente não é uma repetição no sentido comum. É uma nova operação ou uma intenção alterada manualmente, e a trilha de auditoria precisa dizer isso.

É aqui que os sistemas de agentes costumam enganar a si mesmos. O modelo lê um erro, altera um parâmetro para «corrigi-lo» e chama a solicitação seguinte de repetição. Essa é uma nova decisão, com um novo efeito possível. Associá-la como repetição disfarça uma mudança de plano e torna a revisão quase impossível.

Limite o orçamento de tentativas por operação e registre a decisão sobre esse orçamento. Repetir uma resposta de limite de taxa depois do atraso indicado pelo destino é diferente de repetir uma gravação desconhecida após um timeout. No primeiro caso, geralmente existe uma resposta remota inequívoca. No segundo, é preciso ter evidências de idempotência ou fazer uma reconciliação antes de repetir.

Tokens de idempotência e identidades de auditoria têm funções diferentes

Um token de idempotência informa ao destino que envios repetidos devem ser tratados como uma única operação. Um ID de operação de auditoria informa aos seus investigadores quais tentativas pertencem a uma mesma intenção. Use os dois quando possível, mas nunca finja que um substitui o outro.

O token pode ser limitado a uma rota, um comerciante, um período, ou uma conta específica. Algumas APIs mantêm tokens apenas por um período limitado. Algumas devolvem a resposta original para uma duplicata; outras devolvem um conflito. Algumas rejeitam um token reutilizado quando o corpo da solicitação muda. Esses detalhes pertencem ao contrato do conector e à sua suíte de testes.

O ID da operação tem uma função mais ampla. Ele conecta a sessão do agente, as evidências de aprovação, a construção da solicitação, as tentativas de transporte, a resposta remota e a reconciliação posterior. Ele deve continuar válido mesmo quando uma API de fornecedor não oferece idempotência, quando a ação usa SSH ou quando um operador executa manualmente a recuperação final.

Não gere um novo ID de operação depois de uma reinicialização apenas porque a memória do processo desapareceu. Persista as operações pendentes antes do envio. Na recuperação, inspecione cada operação não resolvida e escolha um de três caminhos: reconciliar usando evidências remotas, repetir sob uma garantia de idempotência documentada ou encaminhar a decisão a uma pessoa. Uma reinicialização é um evento de engenharia, não uma autorização para esquecer a incerteza.

Uma recomendação popular, mas errada, é repetir toda gravação que falhou usando backoff exponencial. O backoff reduz a pressão sobre um serviço em dificuldade. Ele não transforma uma gravação desconhecida em uma gravação segura. A possibilidade de repetir a ação e o comportamento de desduplicação do destino determinam se outra tentativa é aceitável.

A reconciliação encerra a incerteza sem reescrever o histórico

Verifique primeiro um novo processo
Por padrão, um novo processo de agente precisa de autorização de sessão antes de iniciar chamadas externas.

Reconciliação significa reunir evidências posteriores sobre uma operação não resolvida. Não significa editar a primeira tentativa até que ela pareça bem-sucedida.

Imagine que um agente crie um incidente com uma referência fornecida pelo cliente no corpo da solicitação. O POST inicial termina em sent_no_response. Antes de repetir, o agente consulta os incidentes usando essa referência. Se encontrar um registro correspondente, acrescente um evento de observação que cite o ID da operação original, a impressão digital da consulta, o identificador remoto devolvido e os critérios de correspondência. Depois, encerre a operação como succeeded por meio de reconciliação.

Se a consulta não encontrar nada, tenha cuidado. A ausência prova pouco quando a API tem atraso de replicação, demora na indexação da busca ou filtros fracos. Registre a observação negativa com o horário e o endpoint utilizado. Repita somente se o contrato do destino disser que o token de idempotência continua válido, ou espere e peça uma decisão.

Se a consulta encontrar dois registros correspondentes, não marque a operação como succeeded e siga em frente. Encerre-a como duplicate_effect_confirmed, preserve os dois identificadores remotos e crie uma operação de correção separada. A correção não deve compartilhar o ID da operação original porque tem um efeito pretendido diferente.

Mantenha eventos somente de acréscimo em vez de linhas de status mutáveis como fonte de verdade. Você pode projetar um status atual conveniente para uma interface, mas as evidências precisam preservar as transições: intenção criada, tentativa enviada, resposta perdida, consulta realizada, registro remoto encontrado, operação resolvida. O investigador precisa da sequência, incluindo a repetição equivocada, se ela ocorreu.

Um registro que evidencie adulterações acrescenta outra propriedade: permite verificar que um processo posterior não removeu silenciosamente a primeira tentativa desconhecida. O Sallyport registra sessões de agentes e ações individuais em um registro de auditoria criptografado, encadeado por hash e sem acesso de escrita, e sp audit verify verifica a cadeia offline sobre o texto cifrado. Isso ajuda a preservar a linha do tempo, mas o esquema de eventos ainda precisa das relações entre operação e tentativa descritas aqui.

A delegação do agente precisa de um único dono da operação

Associe as tentativas às execuções do agente
O diário de Sessões mostra a execução do processo do agente por trás de uma ação, com revogação imediata quando necessário.

Subagentes facilitam efeitos duplicados porque cada processo pode acreditar que é dono da tarefa. Dê a um único processo a propriedade do ID da operação e exija que cada trabalhador delegado carregue esse ID em seu contexto de ação.

Um planejador pode pedir que um trabalhador reúna informações e que outro execute uma ação. As chamadas de coleta de informações devem receber suas próprias operações porque representam intenções separadas. O trabalhador de execução deve receber o ID da operação original somente quando agir sobre o mesmo efeito declarado. Suas chamadas individuais usam novos IDs de tentativa e identificam o processo de trabalho que as realizou.

Não permita que os trabalhadores repitam independentemente uma gravação desconhecida enquanto o processo pai também a repete. O pai precisa receber o estado de envio do trabalhador antes de decidir o que fazer. Se o trabalhador sair inesperadamente, marque a operação como não resolvida e faça a reconciliação. A ausência do resultado de um filho não é um convite para que o supervisor reproduza o comando.

Os registros de aprovação por sessão também pertencem à cadeia de evidências. Quando um processo de agente recebe autoridade para realizar um grupo de chamadas, registre a identidade do processo, o horário de aprovação e o horário de revogação separadamente do resultado da ação. A aprovação explica quem tinha permissão para tentar. Ela não estabelece se o destino executou a ação.

Para operações sensíveis, exija uma aprovação por chamada para a própria repetição quando a primeira tentativa tiver resultado desconhecido. As pessoas tomam decisões melhores quando o cartão de aprovação mostra a intenção original, o estado de envio anterior e o método de recuperação planejado. Um aviso genérico dizendo «permitir chamada de API» esconde justamente o fato que deveria fazê-las parar para pensar.

A visão de investigação deve mostrar uma linha do tempo, não uma pilha de solicitações

O investigador precisa de uma única página ou consulta da operação, que comece com a intenção e termine com o resultado mais bem sustentado. Registros de solicitações ordenados por horário obrigam o revisor a reconstruir a hierarquia sob pressão, muitas vezes entre vários sistemas com relógios ligeiramente diferentes.

Mostre o estado da operação no topo, mas deixe as evidências disponíveis abaixo. Cada tentativa deve exibir seu número, estado de envio, tentativa pai, motivo, referência da autoridade, destino, impressão digital da solicitação, resumo da resposta e duração. Cada observação deve mostrar o que foi verificado e por que essa evidência alterou ou não alterou o estado.

Não esconda solicitações duplicadas porque o efeito final foi inofensivo. Uma duplicação inofensiva hoje pode se tornar um efeito caro depois que uma API mudar ou uma integração adicionar um webhook. O registro deve permitir distinguir «o agente repetiu corretamente e o destino fez a desduplicação» de «o agente enviou a solicitação duas vezes e teve sorte».

Trate uma alteração no corpo da solicitação durante a recuperação como uma bifurcação explícita. A operação original permanece aberta ou recebe seu resultado resolvido. A ação alterada recebe um novo ID de operação e uma relação como supersedes_operation_id. Esse registro diz a verdade: o agente não apenas repetiu, ele mudou o que pretendia fazer.

Crie um teste de falha forçada antes de confiar no projeto. Faça o destino confirmar uma ação de teste idempotente conhecida e depois descarte a resposta enviada ao chamador. Confirme que a próxima execução do agente mantém o ID da operação original, usa o mesmo token de destino, registra a primeira tentativa como desconhecida, realiza a reconciliação ou repetição documentada e encerra a operação com evidências. Se seu teste não consegue responder a esses pontos, um incidente também não conseguirá.

O primeiro campo que procuro em um registro de ação de agente não é um status HTTP. É o ID estável da operação. Sem ele, toda investigação de repetição começa como um palpite. Com ele, você pode fazer as perguntas que importam: o que o agente pretendia, o que saiu da máquina, o que mudou entre as tentativas e quais evidências sustentam o resultado final.

FAQ

As repetições de agentes de IA são sempre um problema de segurança?

Elas podem ser tentativas legítimas de recuperação, mas somente se o registro as associar a uma tentativa anterior e documentar o que aconteceu antes da repetição. Sem essa relação, o investigador não consegue saber se o agente se recuperou de um timeout ou executou o mesmo efeito duas vezes.

Qual identificador deve permanecer igual durante uma repetição do agente?

Use um identificador de operação estável para a ação de negócio pretendida e atribua um novo identificador de tentativa a cada tentativa de transporte. O identificador da operação permanece igual entre as tentativas, enquanto o identificador de tentativa nunca deve se repetir.

Um timeout significa que uma solicitação de API falhou?

Não. Um timeout significa apenas que o chamador não recebeu uma resposta utilizável. O serviço remoto pode ter recusado a solicitação, concluído a ação uma vez ou concluído mais de uma vez se o chamador alterou a solicitação entre as tentativas.

As chaves de idempotência eliminam a necessidade de registros de repetição?

A idempotência reduz efeitos duplicados em um destino que a implementa, mas não documenta a decisão do agente de repetir nem prova que o destino respeitou a solicitação. Mantenha um registro de ações mesmo quando a API aceita um token de idempotência.

Como os registros devem indicar um resultado desconhecido?

Registre o resultado real como desconhecido até reconciliá-lo. Não escreva failed apenas porque o agente perdeu a resposta e não escreva succeeded sem uma confirmação do destino ou outra evidência posterior de que a ação foi concluída.

Quando um agente deve parar de repetir uma ação?

Repita somente quando a ação tiver uma identidade de operação estável, um motivo explícito para a repetição e um limite definido de tentativas. Para ações irreversíveis sem suporte à idempotência, pare depois de um resultado desconhecido e exija uma decisão humana ou uma verificação de reconciliação.

Um código de status HTTP é suficiente para um registro de auditoria de um agente de IA?

Não. Um código de status descreve uma troca HTTP, enquanto o registro da ação precisa incluir o efeito pretendido, a referência da credencial, o destino, a relação entre tentativas, as evidências da resposta e o estado final resolvido. Os registros HTTP, sozinhos, geralmente omitem os fatos necessários ao investigador.

Como funcionam as repetições quando um agente delega tarefas a subagentes?

O processo pai é o dono do identificador da operação e o fornece ao trabalho executado pelos filhos. Um filho pode criar seus próprios identificadores de tentativa, mas deve preservar o identificador da operação pai e declarar sua função na execução.

Posso editar um registro de repetição depois de descobrir o resultado?

Preserve o evento original e acrescente um evento de correção ou reconciliação que faça referência a ele. Registros mutáveis permitem reescrever silenciosamente o histórico justamente quando um incidente exige uma linha do tempo confiável.

Que evidências um investigador precisa depois de efeitos duplicados em uma API?

Eles precisam da intenção original, de todas as tentativas em ordem, das credenciais ou da autoridade usada, das impressões digitais das solicitações, das respostas observadas, dos motivos das repetições e do resultado final reconciliado. Também precisam de provas de que softwares posteriores não puderam alterar esses registros silenciosamente.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov