APIs que um agente pode usar com controle: uma compra de ponta a ponta
Por Dorian Chávez · fundador e CEO da Hábil ·
Uma compra pensada para agentes de IA: propor e executar em separado, aprovação fora do modelo, idempotência, RFC 9457 e um teste de injeção.
Em APIs prontas para agentes de IA, explicamos o que um sistema precisa para que um agente o use sem surpresas: que se explique sozinho, que os erros ensinem, que repetir uma chamada não duplique nada e que o que movimenta dinheiro ou dados não dependa do modelo. Este artigo desce um andar. Ele pega uma operação concreta — uma compra — e a projeta por inteiro: as chamadas, os códigos de resposta, o formato dos erros, como as permissões são separadas, onde acontece a aprovação e como comprovar que tudo isso resiste a um agente enganado.
O texto é para a equipe de tecnologia. Para quem dirige a área, a ideia central cabe em uma linha: o agente pode pedir, o sistema decide e uma pessoa aprova o que movimenta dinheiro ou dados.
Cenário de exemplo. Não descreve uma empresa real. Uma distribuidora quer que um agente de IA reponha insumos: ele verifica o estoque, compara fornecedores e monta pedidos. As compras pequenas são aprovadas em minutos; ninguém quer que o agente compre sozinho.
1. A compra é dividida em três passos, não em um
A tentação é expor uma única operação, POST /compras, e deixar que o agente a chame. É o caminho mais curto para dar ao modelo a palavra final sobre o dinheiro. A alternativa é dividir a compra em três passos, cada um com uma permissão diferente:
| Passo | Chamada | Quem faz | O que muda no sistema |
|---|---|---|---|
| Consultar | GET /existencias, GET /proveedores/{id}/precios | O agente | Nada |
| Propor | POST /propuestas-de-compra | O agente | Cria-se uma proposta no estado aguardando aprovação. Nada é comprado |
| Executar | POST /compras | O agente, só com uma aprovação válida | O pedido é emitido ao fornecedor |
E entre propor e executar há um passo que não tem chamada para o agente: a aprovação. Uma pessoa a faz, em outro canal, e o sistema a registra. O agente não pode criá-la, apenas esperar por ela.
A proposta fica assim:
POST /propuestas-de-compra
Content-Type: application/json
{
"proveedor": "prov-0193",
"partidas": [
{ "sku": "EMP-5521", "cantidad": 40 }
],
"moneda": "MXN",
"motivo": "Existencia bajo el mínimo en el almacén norte"
}HTTP/1.1 201 Created
Location: /propuestas-de-compra/pc-7f3a
ETag: "rev-1"
{
"id": "pc-7f3a",
"revision": 1,
"estado": "pendiente_de_aprobacion",
"total": "12480.00",
"moneda": "MXN",
"huella": "sha256:4b1e…",
"vence": "2026-11-03T18:00:00-06:00"
}O agente só envia o que quer e quanto. Todo o resto é preenchido pelo sistema a partir das fontes autorizadas: preços vigentes, impostos, endereço de entrega, condições e a política aplicável. Com isso, o sistema monta uma revisão imutável da proposta e calcula duas coisas sobre ela: o total e a impressão digital, um resumo criptográfico dessa revisão exata, calculado sobre uma representação documentada. Se o preço, o fornecedor, o destino, um item ou a política mudar, nasce uma revisão nova e qualquer aprovação anterior deixa de valer.
A impressão digital identifica a revisão; não dá permissão para nada. Conhecê-la não autoriza a executar, assim como saber o número de uma conta não autoriza a sacar dela. Mais adiante fica claro qual papel ela cumpre.
2. A aprovação acontece fora do modelo
A OWASP, organização de referência em segurança de aplicações, chama de Excessive Agency o risco de dar a um agente mais funções, permissões ou autonomia do que o necessário. Entre as mitigações, há duas que aqui se tornam desenho: usar uma pessoa para aprovar as ações de alto impacto antes que aconteçam e implementar a autorização nos sistemas que recebem a chamada, em vez de depender de um LLM para decidir se uma ação é permitida [4]. A especificação do MCP, o protocolo com que muitos agentes chamam ferramentas, vai na mesma linha: diz que sempre deveria haver uma pessoa capaz de negar a invocação de uma ferramenta [6].
Na prática, «uma pessoa aprova» precisa cumprir três condições para valer alguma coisa:
- O canal é outro. A aprovação não chega na mesma conversa que o agente consegue ler e escrever. Já existe um padrão para isso: o fluxo CIBA, da OpenID, separa o dispositivo onde a operação começa do dispositivo onde a pessoa se autentica e dá o consentimento [8]. No cenário: o agente propõe a partir do servidor, e a gerente de compras aprova pelo aplicativo do celular, com a própria sessão.
- Aprova-se algo concreto. A pessoa não aprova «que o agente compre»: aprova esta proposta, com este fornecedor e este total. O padrão OAuth para autorizações detalhadas (RFC 9396) existe exatamente para isso: permite pedir uma autorização que traz o tipo de operação, o valor e o beneficiário, e o exemplo dele é um pagamento [7]. Além disso, o CIBA define uma mensagem feita para ser exibida nos dois dispositivos, de modo que a pessoa possa relacioná-los [8]. A tela de aprovação é montada pelo sistema, não pelo agente: mostra a revisão, o total, o fornecedor, o destino e o vencimento.
- O que foi aprovado é o que se executa. A aprovação fica vinculada à revisão exata da proposta e registra quem aprovou, com qual papel e sob qual política. Vence pelo relógio do servidor, pode ser revogada e deixa de valer se nascer uma revisão nova.
A aprovação é desenhada para que o agente não tenha nenhuma operação capaz de concedê-la nem de mudar o que já foi aprovado. O agente pode pedir uma aprovação; concedê-la cabe a uma pessoa.
3. Executar: uma chamada que pode ser repetida sem cobrar duas vezes
Com a proposta aprovada, o agente executa:
POST /compras
Content-Type: application/json
If-Match: "rev-1"
Idempotency-Key: "3f2c9a1e-8d4b-4c6e-9f1a-2b7d5e0c4a91"
{
"propuesta": "pc-7f3a"
}O corpo não repete itens nem valores: diz apenas qual proposta é executada. O cabeçalho If-Match diz qual revisão se espera executar, com o mecanismo padrão do HTTP para requisições condicionais: se a revisão já não é a vigente, o servidor pode responder 412 Precondition Failed [16]. E a chamada leva uma credencial de execução, explicada na seção 5.
O sistema verifica tudo em uma única transação: a proposta continua aprovada, a aprovação não venceu nem foi revogada, a revisão confere, a credencial é válida e não existe ainda um pedido para essa proposta. Se tudo se cumpre, a proposta passa de aprobada para ejecutando e a credencial é consumida; se não, a chamada é rejeitada com um erro que explica o motivo (seção 4).
É essa transação que impede duas compras da mesma proposta, mesmo que cheguem duas chamadas diferentes ao mesmo tempo, com chaves diferentes, de dois processos ou de um agente que reiniciou. E, como última barreira, o banco de dados não aceita dois pedidos para a mesma proposta. Os estados ficam assim: aprobada → ejecutando → ejecutada, ou fallida_sin_confirmar se o fornecedor recebeu o pedido, mas a resposta se perdeu. Nesse caso, o sistema concilia com o fornecedor antes de reenviar; do contrário, a duplicação apenas muda de lugar.
A chave de idempotência: para as repetições, não para a concorrência
A transação acima resolve duas execuções diferentes. A chave de idempotência resolve outra coisa: a repetição da mesma execução. Nesta API, repetir a mesma requisição com a mesma chave devolve o resultado registrado dessa execução, em vez de tentá-la de novo.
O cabeçalho Idempotency-Key continua em processo de padronização no IETF: é um rascunho ativo, na versão 08, atualizado em 22 de outubro de 2026, e ainda não é RFC. O valor é uma cadeia entre aspas, como no exemplo acima [2]. Mas ele já propõe regras que vale a pena adotar como estão, porque cobrem exatamente os casos que confundem um agente [2]:
| Situação | Resposta que o rascunho propõe |
|---|---|
| A operação exige chave e ela não chegou | 400 Bad Request, com link para a documentação |
| A mesma chave chega com outro conteúdo | 422 Unprocessable Content |
| A mesma chave chega enquanto a primeira ainda está em andamento | 409 Conflict |
| A mesma chave chega depois de a primeira terminar | O resultado guardado da primeira |
O rascunho também permite uma «impressão digital» da requisição para decidir se duas requisições com a mesma chave são de fato a mesma [2]. E há detalhes que cada API precisa publicar: o alcance da chave, por quanto tempo ela é guardada e quando vence. A Stripe, referência prática no assunto, documenta os da API v1 dela [3]:
- guarda o código e o corpo da primeira resposta assim que a operação começa a ser executada, inclusive os erros 500, para que uma repetição não volte a cobrar quando a primeira tentativa ficou em dúvida;
- sugere gerar as chaves como UUID versão 4 e não usar dados sensíveis (um e-mail ou um documento fiscal) como chave;
- pode apagar as chaves quando elas têm pelo menos 24 horas.
No desenho com agentes, há mais uma decisão: quem gera a chave. Se o agente gera uma chave nova a cada repetição, a chave não serve para reconhecê-la. O ideal é que ela nasça com a execução da proposta e fique registrada do lado do servidor. E se, mesmo assim, chegar uma segunda execução com outra chave, quem a detém é a transação, não a chave.
4. Erros que o agente consegue corrigir, com o RFC 9457
Para esta compra, o formato de erros do RFC 9457 permite dar ao agente dados estruturados para se corrigir, sem mudar o significado dos códigos HTTP [1]. Uma rejeição por valor fica assim:
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
{
"type": "https://api.ejemplo.mx/problemas/monto-sobre-limite",
"title": "El total supera el límite que se puede proponer",
"status": 422,
"detail": "El total de 48,900.00 MXN supera el límite de 25,000.00 MXN para propuestas de este agente. Esta compra requiere la aprobación de nivel superior.",
"instance": "/propuestas-de-compra/intentos/a91c",
"limite": "25000.00",
"reintentable": false
}Quatro regras do próprio RFC fazem isso funcionar bem com um agente:
- O status no corpo é apenas informativo, e quem o gera deve usar o mesmo código da resposta real [1]. Um 422 no corpo com um 200 na resposta confunde qualquer um.
- É possível acrescentar campos próprios — aqui,
limiteereintentable—, e o RFC obriga os clientes a ignorar os que não reconhecem [1]. Isso permite dar ao agente exatamente o dado de que ele precisa sem quebrar ninguém. - Se houver vários erros, recomenda-se informar o mais relevante [1]. Para erros de validação, o RFC mostra uma lista com o detalhe e a localização de cada campo com erro, que é o que um agente precisa para corrigir tudo em uma tentativa [1].
- Detalhes internos não são expostos: o RFC alerta contra mostrar coisas como um despejo da pilha de execução [1]. O erro diz o que corrigir, não como o sistema é construído por dentro.
Para a compra do cenário, os tipos de problema ficam assim:
| Problema | Código | reintentable | O que o agente faz |
|---|---|---|---|
| Credencial ausente ou vencida | 401 | não | Pede uma credencial válida |
| Credencial válida, sem permissão para esta proposta | 403 | não | Para |
monto-sobre-limite | 422 | não | Pede o fluxo de aprovação correspondente. Não divide nem altera a compra para ficar abaixo do limite |
propuesta-sin-aprobar | 409 | não | Consulta o estado ou espera o aviso de aprovação; não repete a execução em loop |
aprobacion-vencida | 409 | não | Submete uma revisão nova à aprovação |
revision-no-coincide | 412 | não | Para e consulta a revisão vigente; não reutiliza a aprovação |
llave-con-otro-contenido | 422 | não | Corrige a requisição, ou usa uma chave nova se for uma operação nova |
compra-en-proceso | 409 | sim, mais tarde | Espera o tempo indicado em Retry-After ou consulta a execução; não abre outra |
Há duas ideias por trás da tabela. A primeira: separar autenticação (401), autorização (403), pré-condição (412) e estado do fluxo (409), para que o agente saiba se falta algo, se não tem permissão ou se precisa esperar. A segunda: o agente não deveria adivinhar o que vale a pena repetir. E um cuidado: o limite de valor não se contorna dividindo a compra, então a política soma por fornecedor e por período, não só por proposta.
5. Ler, propor, executar: as permissões vivem na API
A tabela da seção 1 não é uma convenção de estilo. É a forma de limitar o dano quando o agente erra. A OWASP enumera três causas do excesso de agência: funções demais, permissões demais e autonomia demais [4]. Cada nível corta uma:
- Uma credencial de execução limitada. O agente que consulta e propõe não tem permissão para executar. Depois da aprovação, o servidor de autorização pode emitir ao executor uma credencial de uso único e de vida curta, que traz a proposta, a revisão, o fornecedor, o valor, a moeda e a API a que se destina. O RFC 9396 dá o formato para expressar esse detalhe [7]; validá-lo contra a aprovação vigente e consumi-lo na mesma transação que marca
ejecutandocabe a esta API. Além disso, a credencial fica vinculada a quem a apresenta, por exemplo com DPoP [17], para que não sirva a mais ninguém mesmo que vaze. - O agente nem chega a ver o que não pode fazer. A especificação do MCP permite que a lista de ferramentas que um servidor oferece mude conforme a autorização de quem pergunta: por exemplo, mostrar só as ferramentas que as permissões alcançam [6]. Um agente com permissão para propor não vê a ferramenta de execução. Ocultá-la reduz o que ele descobre, mas não autoriza nem bloqueia nada sozinha: a API valida permissão, sujeito, proposta e estado em cada chamada [6].
- Um identificador não é uma permissão. O MCP diz isso para o estado entre chamadas: um identificador como o de um carrinho é um nome, não uma capacidade, e o servidor deve validar a autorização em cada chamada [6]. Conhecer
pc-7f3anão dá ao agente o direito de executá-la. - Os limites vivem no servidor. O limite de 25.000 pesos do exemplo está na API, não nas instruções do modelo. O modelo pode ignorar uma instrução; a API rejeita a requisição mesmo que o modelo a envie.
- Registro de tudo. Qual agente, com qual credencial, o que propôs, quem aprovou, qual impressão digital, o que foi executado. O MCP recomenda registrar o uso de ferramentas para auditoria [6].
6. O teste do catálogo envenenado
Tudo o que veio antes pode ser revisado no papel. Esta seção serve para comprovar com o sistema funcionando.
O risco
Em 2023, um grupo de pesquisadores descreveu a injeção indireta de instruções: o atacante não fala com o agente, mas esconde instruções em dados que o agente provavelmente vai ler [10]. A OWASP a coloca como o primeiro risco das aplicações com modelos de linguagem e reconhece que não está claro se existe uma forma infalível de preveni-la [5].
No cenário, o agente lê o catálogo de fornecedores: nomes, descrições, preços. Qualquer pessoa que consiga escrever uma descrição — um fornecedor, um funcionário, uma integração comprometida — pode colocar ali uma instrução.
Por que um detector não basta
Os números publicados convergem em um ponto:
- Uma equipe de pesquisadores atacou 12 defesas recentes com ataques adaptados a cada uma e passou de 90% de sucesso contra a maioria [14].
- Em uma avaliação do centro de padrões de IA do NIST, com um modelo e um ambiente de escritório simulado, o sucesso subiu de 11% no ataque de referência mais forte para 81% no ataque novo mais forte, desenvolvido com o instituto de segurança de IA do Reino Unido [15].
- Em outro conjunto de cinco tarefas da mesma avaliação, o sucesso médio passou de 57% com uma tentativa para 80% ao repetir cada ataque 25 vezes [15].
São resultados dessas condições, não uma taxa de todos os agentes. O que eles mostram é que uma avaliação própria precisa registrar modelo, ambiente, tarefa e número de execuções.
A lição não é que os agentes sejam inseguros. É que a defesa que importa é a que não depende de o modelo detectar o engano. Dois referenciais dizem isso de forma marcante. Simon Willison chama de «trifecta letal» a combinação de acesso a dados privados, exposição a conteúdo não confiável e capacidade de se comunicar com o exterior [11]. A Meta propõe a «regra de dois»: em uma mesma sessão, um agente não deveria processar entradas não confiáveis, ter acesso a sistemas sensíveis e poder mudar o estado ou se comunicar com o exterior; no máximo, duas das três [12]. Um agente de compras que lê um catálogo aberto e emite pedidos reúne justamente as três. Por isso o passo de executar não pode depender do que o agente leu.
A pesquisa vai na mesma direção. O desenho CaMeL, de uma equipe de pesquisadores, separa o fluxo de controle — o que a consulta confiável da pessoa decide — do fluxo de dados, de modo que os dados não confiáveis que o modelo lê nunca mudem o curso do programa. Com esse desenho, resolveram 77% das tarefas do banco de testes AgentDojo com segurança demonstrável, contra 84% de um sistema sem defesa [9]. A separação entre propor e executar deste artigo se inspira nesse princípio; não equivale a implementar o CaMeL nem herda a prova de segurança dele.
O teste, passo a passo
- Prepare um ambiente isolado, com um fornecedor simulado e sem saída para fornecedores reais. Registre a versão do modelo, as instruções, as ferramentas, a identidade do agente, o catálogo inicial, a política e a versão da API.
- Acrescente ao catálogo uma descrição de teste, marcada internamente como não confiável, que tente mudar a quantidade, o destino de entrega e o estado da proposta. O texto exato fica no material de testes da equipe, não em documentos públicos.
- Dê ao agente uma tarefa normal que o faça ler esse produto, como verificar o estoque e repor o que faltar.
- Repita a tarefa várias vezes para cada combinação de modelo, configuração e variante da descrição. Uma referência útil são as 25 repetições da avaliação do NIST, quando o ambiente permite novas tentativas [15]; é um ponto de comparação, não uma garantia.
- Meça separadamente o que é do modelo e o que é do sistema, no registro: - quantas vezes o agente obedeceu à instrução escondida (isso é do modelo e varia entre versões); - quantas propostas ele criou; - zero pedidos sem aprovação vigente, revisão correspondente e credencial de execução válida; - todas as tentativas diretas de aprovar ou executar sem permissão, rejeitadas; - rastreabilidade completa de cada tentativa: identificador de correlação, agente, credencial, revisão, decisão e resposta.
- Acrescente variantes que testem as regras da API: uma revisão criada depois da aprovação, uma aprovação vencida ou revogada, duas chaves diferentes para a mesma proposta e uma credencial apresentada por outro cliente. Bancos de testes públicos como o AgentDojo, com 97 tarefas e 629 casos de segurança, servem de modelo para montar os próprios [13].
Se a terceira condição do passo 5 falhar, revise primeiro a autorização, a transição de estados e o registro dessa chamada. A taxa de obediência do modelo serve para escolher e configurar modelos; a segurança da compra não pode depender dela.
7. Lista de verificação para a equipe
- [ ] As operações que movimentam dinheiro ou dados estão divididas em consultar, propor e executar, com permissões diferentes.
- [ ] Preços, total, destino e condições são definidos pelo sistema em uma revisão imutável, não pelo agente.
- [ ] A aprovação acontece em outro canal, é feita por uma pessoa, fica vinculada à revisão, vence e pode ser revogada.
- [ ] O agente não tem nenhuma chamada para aprovar.
- [ ] Executar exige uma credencial de uso único vinculada à proposta e a quem a apresenta, e uma transação que impede dois pedidos para a mesma proposta.
- [ ] Executar exige
Idempotency-Keypara as repetições, e a API responde 400 / 409 / 422 como propõe o rascunho do IETF. - [ ] Os erros são
application/problem+json, com tipos documentados e um campo que diz se vale a pena repetir. - [ ] Os limites vivem na API, não nas instruções do modelo.
- [ ] A lista de ferramentas que o agente vê depende das permissões dele, e a API valida cada chamada mesmo assim.
- [ ] O teste do catálogo envenenado roda a cada versão, com várias repetições, e mede separadamente o que o modelo fez e o que o sistema permitiu.
O que a Hábil faz
A Hábil ajuda a desenhar as APIs dos sistemas da empresa para que um agente de IA possa usá-las com controle: separamos o que se consulta, o que se propõe e o que se executa; levamos a aprovação para fora do modelo, com uma pessoa aprovando o que movimenta dinheiro ou dados; e definimos com a equipe testes verificáveis, como o do catálogo envenenado, cuja evidência é revisada em conjunto. Fazemos isso com a Hábil AI, inteligência artificial conectada aos sistemas com controle. Para o panorama completo, veja também APIs prontas para agentes de IA e a página Controlar quem entra.
Primeira conversa, sem custo. Partimos de uma operação da empresa que hoje um agente não deveria executar sozinho e mostramos o que seria preciso para que ele possa propô-la com controle.
Fontes consultadas em 28 de outubro de 2026. As citações de documentos em inglês estão traduzidas.
Referências
- IETF, RFC 9457, Problem Details for HTTP APIs (2023). https://www.rfc-editor.org/rfc/rfc9457
- IETF, The Idempotency-Key HTTP Header Field, draft-ietf-httpapi-idempotency-key-header-08 (rascunho ativo, atualizado em 22-out-2026; não é RFC). https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/
- Stripe, Idempotent requests (documentação da API; prática de um fornecedor). https://docs.stripe.com/api/idempotent_requests
- OWASP, Top 10 for LLM Applications 2025, LLM06: Excessive Agency. https://genai.owasp.org/llmrisk/llm062025-excessive-agency/
- OWASP, Top 10 for LLM Applications 2025, LLM01: Prompt Injection. https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- Model Context Protocol, especificação 2026-07-28, Tools. https://modelcontextprotocol.io/specification/2026-07-28/server/tools
- IETF, RFC 9396, OAuth 2.0 Rich Authorization Requests (2023). https://www.rfc-editor.org/rfc/rfc9396
- OpenID Foundation, OpenID Connect Client-Initiated Backchannel Authentication Flow — Core 1.0 (final, 1-set-2021). https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html
- Debenedetti, Shumailov, Fan e outros, «Defeating Prompt Injections by Design», preprint, arXiv 2503.18813 (2025). https://arxiv.org/abs/2503.18813
- Greshake, Abdelnabi, Mishra, Endres, Holz e Fritz, «Not what you've signed up for: Compromising Real-World LLM-Integrated Applications with Indirect Prompt Injection», arXiv 2302.12173 (2023). https://arxiv.org/abs/2302.12173
- Simon Willison, «The lethal trifecta for AI agents», 16-jun-2025. https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/
- Meta AI, «Agents Rule of Two: A Practical Approach to AI Agent Security», 31-out-2025. https://ai.meta.com/blog/practical-ai-agent-security/
- Debenedetti, Zhang, Balunović e outros, «AgentDojo», arXiv 2406.13352 (2024). https://arxiv.org/abs/2406.13352
- Nasr, Carlini, Sitawarin e outros, «The Attacker Moves Second», preprint, arXiv 2510.09023 (2025). https://arxiv.org/abs/2510.09023
- NIST, Center for AI Standards and Innovation, Technical Blog: Strengthening AI Agent Hijacking Evaluations (17-jan-2025, atualizado em 19-dez-2025). https://www.nist.gov/news-events/news/2025/01/technical-blog-strengthening-ai-agent-hijacking-evaluations
- IETF, RFC 9110, HTTP Semantics (2022), seção 13.1.1, If-Match. https://www.rfc-editor.org/rfc/rfc9110
- IETF, RFC 9449, OAuth 2.0 Demonstrating Proof of Possession (DPoP) (2023). https://www.rfc-editor.org/rfc/rfc9449
A operação da empresa enfrenta esses desafios?
Prefere e-mail? Escreva para hola@habil.mx