8 min de leitura

Parâmetros destrutivos de API: valide antes de excluir

Parâmetros destrutivos de API exigem mais do que JSON válido. Verifique propriedade da conta, IDs imutáveis, escopo, atualidade, aprovações, retentativas e evidências de auditoria.

Parâmetros destrutivos de API: valide antes de excluir

Agentes de IA fazem chamadas destrutivas de API com facilidade demais quando uma solicitação parece sintaticamente correta. Um corpo JSON válido, um nome de conta conhecido e uma busca bem-sucedida não provam que o agente está prestes a excluir o objeto certo. Antes que uma solicitação externa remova, revogue, desconecte, cancele ou sobrescreva dados, valide a identidade, a propriedade, o escopo e a atualidade diretamente no serviço.

Já vi engenheiros cuidadosos interpretarem uma solicitação como «excluir este ambiente de teste», enquanto a API a interpretava como «excluir todos os ambientes desta organização». Em geral, o código não tinha um bug no sentido estrito. Ele aceitava um seletor formado de maneira vaga, resolvia um nome na conta errada ou confiava em dados obtidos antes na execução. Um agente autônomo comete esses erros comuns mais rápido e com mais confiança.

Este não é um caso para pedir ao modelo que seja mais cuidadoso. Coloque uma barreira determinística entre a solicitação proposta pelo agente e a solicitação autenticada. Por padrão, essa barreira deve rejeitar ambiguidades e fazer com que uma pessoa aprove o alvo e o efeito reais.

Uma solicitação bem formada ainda pode indicar o objeto errado

Uma solicitação só fica segura o suficiente para ser enviada depois que você estabelece quatro fatos separados: o recurso é do tipo correto, seu identificador imutável é o pretendido, ele pertence à conta principal aprovada e a operação afetará o conjunto aprovado. As equipes costumam misturar esses fatos em uma única busca. É nesse atalho que as exclusões dão errado.

Considere um serviço que expõe um nome de exibição e um ID:

{
  "id": "env_7d3a",
  "name": "staging",
  "account_id": "acct_blue",
  "state": "active"
}

Um agente que busca por staging encontrou um candidato, não uma autorização para excluí-lo. Muitas contas têm um ambiente staging. Mesmo dentro de uma conta, os nomes podem ser reutilizados depois que um objeto antigo desaparece. A única solicitação de ação segura é aquela construída com o ID imutável retornado e verificada contra um ID de conta principal esperado.

A distinção importa ainda mais quando uma API oferece um caminho principal como /accounts/{account_id}/environments/{environment_id}. Verifique os dois segmentos. Não deduza a propriedade porque o ID apareceu em uma resposta de busca anterior ou porque o agente colocou o mesmo nome de conta no plano. A conta principal no URL da ação faz parte da fronteira de autorização.

O tipo do recurso merece uma verificação própria. As APIs costumam usar um endpoint de busca compartilhado ou retornar registros mistos. Um resultado chamado staging pode ser um ambiente, um projeto, um grupo de acesso ou um modelo salvo. Se o serviço tiver endpoints de exclusão diferentes, selecione o endpoint somente depois de verificar o tipo retornado. Não construa um endpoint concatenando uma string de tipo produzida pelo modelo.

Por fim, defina o efeito esperado antes de inspecionar os candidatos. «Remover a implantação antiga» pode significar excluir um registro de implantação, interromper um trabalho em execução, revogar um token emitido para ele ou excluir todo o ambiente. Esses efeitos não podem compartilhar uma operação genérica de delete. Deixe o verbo solicitado e o tipo do objeto explícitos no contrato da ação.

Os nomes ajudam as pessoas, mas os IDs controlam a solicitação

Use um ID imutável para endereçar um recurso, mas mostre à pessoa que aprova contexto humano suficiente para detectar uma escolha errada. Um cartão de aprovação que diga apenas env_7d3a incentiva a aprovação automática. Um que diga apenas staging cria ambiguidade. Mostre os dois ao operador, junto da conta principal e da consequência da operação.

Um registro de alvo útil tem esta aparência:

{
  "operation": "delete_environment",
  "account": {"id": "acct_blue", "name": "Blue Team"},
  "target": {"id": "env_7d3a", "name": "staging", "type": "environment"},
  "expected_state": "active",
  "effect": "permanently removes this environment and its managed resources"
}

O nome de exibição da conta ajuda o operador a perceber que o agente foi parar no tenant errado. O nome do recurso ajuda a reconhecer o objeto. Os IDs tornam a solicitação inequívoca. O efeito declarado evita uma falha comum de aprovação: a pessoa pensa ter aprovado uma ação reversível de interrupção, mas o provedor removerá dados.

Não resolva um nome usando o primeiro resultado da busca. Os endpoints de busca frequentemente ordenam por relevância, retornam correspondências parciais ou usam paginação. Se a tarefa fornecer um nome exato, exija exatamente um candidato depois de filtrar pela conta principal e pelo tipo esperado. Zero candidatos deve causar falha. Mais de um candidato também. Pedir ao agente que escolha um não resolve o problema, porque ele não tem evidências para distingui-los.

O tratamento de maiúsculas e minúsculas também precisa de uma regra específica do serviço. Alguns provedores diferenciam maiúsculas de minúsculas; outros normalizam os nomes. Não normalize os nomes por conta própria e presuma que o provedor agirá da mesma forma. Use o recurso retornado pelo provedor como autoridade e mantenha o rótulo exato retornado no registro de aprovação.

Tags, rótulos e descrições são contexto, não identidade. Eles mudam com frequência e os usuários podem escrever praticamente qualquer coisa neles. Uma tag como temporary=true pode restringir uma lista analisada, mas não deve substituir a associação a uma conta ou um ID de recurso imutável.

O escopo precisa ser concreto antes que o agente peça aprovação

Uma operação destrutiva tem um escopo mesmo quando o corpo da solicitação contém apenas um ID. O escopo inclui a conta principal, os recursos selecionados, os recursos filhos que o provedor remove automaticamente e qualquer filtro que amplie a seleção. Torne esse escopo concreto antes de pedir a aprovação de alguém.

A exclusão de um único objeto tem um contrato simples: um ID imutável, uma conta principal esperada e um tipo de recurso. A exclusão em massa precisa de outro contrato. Primeiro, ela deve produzir um conjunto resolvido; depois, obter aprovação para esse conjunto ou para um resumo limitado que uma pessoa possa inspecionar. Enviar um seletor diretamente a um endpoint destrutivo deixa o serviço externo decidir o escopo depois que a aprovação já ocorreu.

Suponha que um agente proponha esta solicitação:

{
  "account_id": "acct_blue",
  "filter": {"label": "cleanup-candidate"},
  "delete": true
}

Esse corpo esconde o único fato de que o operador precisa: quais recursos correspondem ao filtro agora. Expanda o filtro por meio de uma chamada de listagem somente leitura, rejeite qualquer paginação que não tenha sido totalmente inspecionada e normalize o resultado em IDs. Depois, mostre uma contagem e uma pequena amostra com nomes. Se o conjunto for maior que o limite aprovado, interrompa o processo e exija uma nova instrução.

Nunca permita que a ausência de um filtro signifique «todos». Nos esquemas de solicitação, diferencie uma lista vazia obrigatória de um seletor ausente. Melhor ainda, proíba que endpoints destrutivos aceitem filtros na interface de ações do agente. Faça o gateway aceitar apenas uma lista de IDs resolvidos para operações em massa.

Uma estrutura prática é:

{
  "operation": "delete_resources",
  "account_id": "acct_blue",
  "resource_type": "snapshot",
  "resource_ids": ["snap_104", "snap_105"],
  "selection_observed_at": "2025-03-08T14:32:11Z"
}

Rejeite um array resource_ids vazio, a menos que o fluxo permita isso explicitamente. Rejeite IDs duplicados. Rejeite IDs de outra conta. Aplique um limite máximo compatível com a operação aprovada pela pessoa. Um limite não substitui a análise, mas impede que um loop malformado transforme uma limpeza de dois recursos em um incidente envolvendo mil recursos.

As exclusões em cascata também fazem parte do escopo. Se excluir um projeto também excluir repositórios, chaves de implantação, ambientes ou registros de cobrança, informe isso antes da aprovação. Se o provedor só expuser os detalhes da cascata depois de uma chamada preliminar, preserve essa resposta e exija que o agente a apresente. «Excluir o projeto» é vago demais quando o projeto tem objetos dependentes.

Leia o serviço duas vezes quando o tempo puder mudar o alvo

Uma leitura preliminar verifica a intenção, mas não congela o objeto. O recurso pode mudar, trocar de conta ou desaparecer entre a validação e a exclusão. Para operações sensíveis, leia o alvo imediatamente antes da mutação e use o controle de concorrência oferecido pelo serviço.

O HTTP fornece um mecanismo padrão para esse padrão. A RFC 9110 define solicitações condicionais com If-Match: o servidor executa o método solicitado somente se a representação atual corresponder a uma tag de entidade fornecida pelo cliente. Um GET pode retornar um ETag, e um DELETE posterior pode enviar exatamente esse valor.

GET /v1/accounts/acct_blue/environments/env_7d3a HTTP/1.1
Authorization: Bearer [injected credential]

HTTP/1.1 200 OK
ETag: "v42"
Content-Type: application/json

{"id":"env_7d3a","account_id":"acct_blue","name":"staging","state":"active"}

Depois de comparar o corpo com o alvo aprovado, envie:

DELETE /v1/accounts/acct_blue/environments/env_7d3a HTTP/1.1
If-Match: "v42"
Authorization: Bearer [injected credential]

Se o serviço retornar 412 Precondition Failed, trate isso como uma barreira de proteção que funcionou. Não peça ao agente para repetir a exclusão sem uma condição. Busque o recurso novamente, compare-o com os fatos aprovados e peça uma nova aprovação se algum fato relevante tiver mudado. Um conflito de versão é evidência de que a aprovação antiga talvez não se aplique mais.

Alguns serviços usam números de revisão, timestamps de atualização, campos de geração ou tokens de solicitação em vez de ETags HTTP. Use o mecanismo documentado pelo provedor. Se ele não oferecer nenhum, reduza o intervalo entre a leitura final e a gravação, torne a ação serial e aceite que não será possível provar que o alvo permaneceu inalterado. Essa limitação deve influenciar a decisão de permitir exclusões sem supervisão.

Não confunda um GET bem-sucedido com permissão para modificar. A credencial de leitura pode enxergar mais do que a credencial de gravação pode alterar, e a autorização pode mudar independentemente do estado do objeto. A resposta da mutação ainda determina se o provedor aceitou a solicitação.

A validação pertence à fronteira das credenciais

Revogue uma execução de risco
Aprove uma execução do agente e revogue a sessão instantaneamente quando o trabalho mudar.

A validação feita apenas em um prompt do agente ou em código gerado é consultiva. O componente que mantém ou injeta a credencial precisa impor as verificações, porque ele é o último ponto capaz de impedir uma solicitação de saída.

Essa fronteira deve receber uma proposta de ação estruturada, não um URL livre e cabeçalhos arbitrários. Uma definição de ação restrita pode exigir campos como ID da conta, ID do recurso, método, tipo esperado e versão esperada. Ela pode construir o caminho de saída a partir de segmentos validados e rejeitar parâmetros de consulta que ampliem o escopo.

Não aceite um URL completo de um agente para depois tentar extrair dele alguma garantia de segurança. Codificação de URL, chaves de consulta repetidas, nomes de host alternativos e normalização de caminhos transformam isso em uma disputa entre analisadores. Aceite campos tipados, valide cada um de acordo com o contrato do provedor e construa o URL por conta própria. A mesma regra vale para os corpos das solicitações. Gere uma estrutura conhecida em vez de repassar um bloco cujos campos não foram inspecionados.

Uma barreira mínima pode impor esta sequência:

  1. Confirme que a operação solicitada existe em uma lista permitida e que seu método é destrutivo por definição.
  2. Resolva cada alvo declarado com uma chamada de leitura feita sob a mesma conta principal.
  3. Compare o ID, o tipo, a conta principal e o estado exigido retornados com a proposta estruturada.
  4. Obtenha aprovação para o efeito resolvido, verifique novamente a atualidade e envie a mutação.
  5. Registre o resultado, incluindo o ID da solicitação do provedor quando ele for retornado.

Mantenha a lista permitida pequena. Uma saída genérica chamada raw_http anula todas as verificações deste artigo, porque o agente pode reintroduzir destinos, métodos e corpos arbitrários. Engenheiros adicionam essas saídas quando falta um endpoint e depois esquecem que elas existem, até que contornam as barreiras que julgavam ter criado.

As credenciais devem permanecer fora do contexto do agente. O agente precisa do resultado de uma ação permitida, não de um token bearer que possa copiar para um comando curl, um log ou uma integração de terceiros. O Sallyport segue esse modelo em suas ações HTTP: mantém a credencial em seu cofre criptografado, executa a solicitação por conta própria e devolve o resultado ao agente.

DELETE não significa que a solicitação seja simples ou reversível

Os nomes dos métodos HTTP não informam todo o efeito de negócio. A RFC 9110 diz que DELETE pede a um servidor de origem que remova a associação entre um recurso alvo e sua funcionalidade atual. A RFC não promete que os dados desaparecerão imediatamente, que os dados relacionados permanecerão ou que uma nova tentativa será inofensiva na sua API específica.

A documentação do provedor precisa definir o efeito real. Algumas APIs marcam um objeto para remoção posterior. Algumas criam um tombstone. Outras o desassociam de uma conta principal. Há também as que removem objetos filhos em cascata. Leia os códigos de resposta e as notas sobre o ciclo de vida do endpoint antes de classificar uma operação como de baixo risco.

Não envie um corpo com DELETE a menos que o provedor o documente explicitamente. A RFC 9110 afirma que o conteúdo recebido em uma solicitação DELETE não tem semântica geralmente definida e pode fazer com que implementações rejeitem a solicitação. Uma API de exclusão que dependa de filtros no corpo pode ser válida para aquele provedor, mas merece testes adicionais pelo caminho de cliente documentado. Isso não deve servir de desculpa para repassar seletores livres de um agente.

As retentativas exigem o mesmo cuidado. Um timeout de rede cria um resultado desconhecido: o provedor pode ter concluído a exclusão depois que o cliente parou de esperar. Repetir imediatamente pode gerar registros enganosos, provocar um segundo efeito em um endpoint mal projetado ou excluir um recurso substituto se a nova tentativa resolver o alvo pelo nome.

Trate um resultado desconhecido com a regra «inspecionar primeiro». Consulte o ID imutável exato sob a conta principal exata. Se o objeto não existir mais e o modelo de exclusão do provedor permitir essa interpretação, registre a operação como concluída, com a primeira resposta marcada como incerta. Se ele ainda existir, inspecione seu estado e o histórico de solicitações do provedor, quando disponível, antes de decidir se deve tentar novamente. Reutilize uma chave de idempotência nas operações que oferecem suporte a ela, mas não invente idempotência quando o provedor não a oferece.

Um 204 No Content apenas diz que o servidor aceitou e concluiu a interação HTTP conforme definida por aquele endpoint. Isso não prova que toda a limpeza posterior terminou. Se a próxima ação do agente depender de a exclusão estar completa, consulte o status documentado da operação ou o estado do recurso, em vez de tratar o corpo vazio da resposta como uma garantia.

A aprovação deve mostrar consequências, não o transporte bruto

Registre cada chamada de exclusão
Os registros de atividade preservam cada chamada HTTP, inclusive a solicitação destrutiva que foi realmente executada.

As pessoas tomam decisões melhores quando a aprovação descreve o efeito em termos comuns e inclui os identificadores necessários para a verificação. Mostrar um método, um caminho e um corpo JSON é útil para um engenheiro de API, mas transfere trabalho demais de interpretação para a pessoa que deveria detectar um alvo incorreto.

Para um único recurso, a aprovação deve dizer o que mudará, nomear a conta principal, mostrar o nome e o ID do recurso e mencionar efeitos irreversíveis ou em cascata. Para uma operação em massa, mostre a contagem, uma amostra limitada, a regra de seleção usada para criar a lista e o fato de que a ação final usa os IDs congelados, não a regra.

Não peça uma aprovação ampla no início de uma execução longa do agente para usá-la em todas as exclusões posteriores. O conjunto de alvos muda conforme o agente descobre recursos. Vincule a aprovação a uma sessão e à ação resolvida. Se o processo do agente mudar, a aprovação não deve acompanhar silenciosamente um novo processo que pode ter código ou instruções diferentes.

O problema oposto é a fadiga de aprovações. Pedir que alguém clique para cada leitura inofensiva ensina essa pessoa a clicar sem ler e dá a uma exclusão perigosa o mesmo destaque visual. Mantenha as leituras sem interação quando for apropriado, exija autorização de sessão para um agente que acabou de iniciar e reserve a confirmação por ação para credenciais ou ações com efeito destrutivo. Quem vê menos solicitações consegue analisar melhor as que importam.

O registro de aprovação precisa de uma expiração clara. Quanto mais tempo um agente espera depois da validação, menos significa a verificação preliminar. Se a ação não puder ser executada prontamente, faça uma nova resolução e peça aprovação outra vez. Isso pode parecer rígido durante uma tarefa de limpeza. Ainda custa menos do que explicar por que uma aprovação de uma hora atrás foi aplicada a um recurso que havia sido recriado.

As evidências de auditoria devem reconstruir a decisão sem expor segredos

Mantenha as credenciais de exclusão fora do agente
Mantenha as credenciais de APIs destrutivas no cofre criptografado do Sallyport, fora do contexto do agente.

Um registro de auditoria útil responde a mais do que «uma solicitação aconteceu?». Ele deve permitir reconstruir o que o agente propôs, o que o serviço informou antes da mutação, o que uma pessoa aprovou, o que o gateway enviou e o que o serviço retornou.

Capture os campos normalizados, não apenas uma string de solicitação bruta. Registre o nome da ação, a identidade da sessão do agente, o ID da conta principal, os IDs dos recursos, as versões esperadas, o timestamp da seleção, o efeito aprovado, o horário da aprovação, o método e o caminho enviados, o status da resposta e o ID da solicitação do provedor. Armazene hashes ou formas redigidas do material da solicitação quando ele puder conter valores sensíveis. Um registro de auditoria que copie cabeçalhos de autorização criou um segundo armazenamento de credenciais.

Mantenha a resposta preliminar ou um resumo protegido por integridade dela. Sem isso, um revisor posterior não conseguirá determinar se o agente excluiu o objeto errado porque a validação falhou, porque o objeto mudou depois da validação ou porque o serviço externo se comportou de maneira diferente da documentada. A diferença determina o que precisa ser corrigido.

A evidência contra adulteração importa quando a mesma máquina executa o agente e o gateway de ações. Um registro de texto mutável pode ser editado pelo processo que causou o incidente. O Sallyport gera seus diários de sessões e atividades a partir de um registro de auditoria criptografado e encadeado por hash, e sp audit verify pode verificar essa cadeia offline sem uma chave do cofre. Isso não transforma uma aprovação ruim em uma boa, mas torna mais difícil ocultar alterações posteriores no registro.

Teste os registros tanto em solicitações malsucedidas quanto nas bem-sucedidas. Rejeições, aprovações expiradas, conflitos de versão e IDs malformados mostram se os controles realmente bloquearam o trabalho. Um diário cheio de sucessos informa muito pouco sobre a capacidade da barreira de recusar uma solicitação perigosa.

Crie ações destrutivas como contratos restritos

A ação de API mais segura é estreita e previsível. Ela aceita uma operação conhecida, exige uma conta principal e um ID de objeto conhecidos, executa uma verificação preliminar e tem um efeito declarado. Interfaces genéricas parecem produtivas até que um agente faça uma solicitação inesperada e sua única defesa seja torcer para que um operador perceba um parâmetro sutil.

Comece inventariando as ações que podem excluir, revogar, alternar, desativar, sobrescrever, publicar ou gerar cobranças. Para cada ação, registre os campos de alvo imutáveis, os campos da conta principal, os estados permitidos, o comportamento em cascata, o mecanismo de atualidade, o comportamento de retentativa e o texto da aprovação. Se não conseguir declarar esses fatos, ainda não ofereça a ação a um agente autônomo.

Depois, envie entradas incorretas deliberadas pela barreira: um ID de recurso válido sob a conta errada, um nome de exibição correspondente com dois resultados, um ETag desatualizado, uma lista em massa vazia, um filtro ausente, um alvo recriado com o mesmo nome e um timeout depois do envio. Essas entradas revelam se a fronteira valida o significado ou apenas valida o JSON.

Não resolva a ambiguidade fazendo o agente escrever um plano mais longo. Torne a ambiguidade impossível de representar no contrato da ação. Um agente pode propor uma intenção e reunir evidências. A fronteira das credenciais deve decidir se as evidências identificam um único efeito permitido, neste momento e sob esta conta. Essa divisão cria um sistema que você pode inspecionar quando a solicitação é rotineira e no qual pode confiar quando não é.

FAQ

A validação do formato é suficiente antes que um agente de IA exclua um recurso?

Não. Um identificador plausível só prova que a solicitação tem o formato correto. A verificação preliminar precisa confirmar que o objeto existe, pertence à conta ou ao projeto pretendido, tem o nome e o tipo esperados e está dentro do escopo aprovado.

Como confirmar que o ID de um recurso de API pertence à conta correta?

Primeiro, peça ao serviço externo a representação atual do recurso e compare os IDs imutáveis com os campos aprovados pelo operador. Não permita que o agente trate um resultado de busca, um nome de exibição ou uma resposta antiga armazenada em cache como prova de identidade.

Uma aprovação de exclusão deve mostrar nomes de recursos ou IDs?

Use os IDs na ação, mas mostre às pessoas o ID e um rótulo reconhecível, como o nome da conta, o caminho do projeto, o tipo do recurso e o estado atual. Os nomes ajudam a detectar erros de intenção; os IDs evitam correspondências ambíguas.

Posso confiar em um dry run de API para operações destrutivas?

Eles só são seguros quando o provedor os documenta claramente e executa o mesmo caminho de autorização e validação da solicitação real. Uma simulação local que apenas imprime o que aconteceria é útil para depuração, mas não prova que o provedor aceitará a solicitação ou afetará os objetos esperados.

O que fazer se o recurso mudar depois que o agente o validar?

Trate isso como evidência desatualizada. Leia o recurso novamente imediatamente antes da mutação, inclua um token de versão, como um ETag, quando a API oferecer suporte, e falhe se o objeto tiver mudado. Não é possível eliminar todas as condições de corrida, mas você pode tornar a janela perigosa pequena e visível.

Por que filtros vazios são perigosos em solicitações automatizadas de exclusão?

Uma lista vazia deve interromper a execução, a menos que a pessoa tenha aprovado explicitamente uma operação que possa afetar zero alvos. Valores de escopo vazios são um caminho clássico para exclusões amplas, porque muitas APIs ou wrappers de comandos interpretam a ausência como «todos».

Um agente de IA pode repetir com segurança uma solicitação DELETE que falhou?

Não. Retentativas após um timeout exigem tratamento específico para a operação. Use uma chave de idempotência quando o provedor oferecer suporte, verifique o estado do objeto antes de tentar novamente e nunca presuma que uma resposta não recebida significa que o provedor não fez nada.

Qual é a diferença entre excluir um recurso e fazer uma exclusão em massa?

Uma solicitação para excluir o banco de dados nomeado tem um alvo estreito e claro. Já uma solicitação para excluir todos os bancos que correspondem a uma tag, tudo em uma conta ou todos os objetos anteriores a uma data tem escopo mais amplo e exige uma contagem explícita, uma amostra e uma aprovação separada.

O que um registro de auditoria deve guardar para uma exclusão conduzida por IA?

Registre a sessão do agente, a solicitação normalizada, a resposta preliminar usada na comparação, a aprovação, o método e o caminho exatos enviados, a resposta e um resumo estável do material sensível. Mantenha os segredos fora do diário, preservando evidências suficientes para reconstruir a decisão.

Preciso de um mecanismo de políticas para controlar chamadas destrutivas de API feitas por agentes?

Boas barreiras de proteção não precisam de uma linguagem de regras genérica. Verificações fixas de associação à conta, identidade exata do recurso, escopo permitido, atualidade e aprovação explícita cobrem as falhas que causam a maior parte dos danos e continuam compreensíveis durante um incidente.

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