Seu agente chama uma API. A API retorna um 429. Seu agente tenta novamente imediatamente, recebe outro 429, tenta de novo, e agora você tem um loop que bombardeia um serviço limitado até a execução falhar ou a conta disparar. Ninguém escreveu esse loop de propósito. Ele surge da versão ingênua de “lidar com o erro,” e é a coisa mais comum que os desenvolvedores perguntam no fórum de discussão do Anthropic SDK.
A recuperação de erros é a parte da construção de agentes que separa uma demonstração limpa de algo sobre o qual você pode acionar alguém. O modelo não é o problema. O problema é o que seu código faz quando uma chamada de ferramenta retorna lentamente, é limitada ou está quebrada. Faça a recuperação corretamente e uma dependência instável se torna uma breve pausa que o usuário nunca percebe. Faça errado e um 500 se transforma em um incidente. Este guia aborda os quatro padrões que carregam a maior parte da carga: novas tentativas com backoff, tempos limite, disjuntores e chaves de idempotência. Em seguida, mostra como testá-los contra um mock, antes que um usuário encontre as falhas para você. Para uma visão mais ampla de como os agentes falham, comece com por que os agentes de IA falham em produção.
Você não pode testar a recuperação contra uma API saudável
Aqui está a armadilha. Sua dependência funciona bem em desenvolvimento. Você escreve seu agente, as chamadas são bem-sucedidas, a demonstração é limpa e você implanta. O código de recuperação nunca foi executado, porque uma API saudável nunca retorna os erros que deveria tratar. A primeira vez que sua lógica de backoff é executada é em produção, contra uma interrupção real, com usuários reais observando. Esse é o pior lugar para descobrir um erro de digitação em um loop de novas tentativas.
Então a regra é simples. Para testar a recuperação, você produz as falhas de propósito. Crie um mock da API que o agente chama, programe-o para retornar um 429, um 500, um tempo limite ou um corpo malformado, aponte o agente para ele e observe o que ele faz. A falha se torna algo que você aciona em um teste, em vez de algo que o aciona às 3 da manhã. O Apidog cria esse mock e roteiriza as respostas, e isso é detalhado na seção de testes no final.
Nova tentativa com backoff exponencial e jitter
Uma nova tentativa é a primeira linha de defesa, e a versão ingênua é a armadilha. Capture o erro, chame novamente imediatamente. Contra um pequeno problema transitório, isso funciona. Contra um serviço sob carga, isso piora as coisas, porque cada cliente que falha tenta novamente no mesmo instante e a debandada mantém o serviço inoperante.
Duas soluções se complementam. O backoff exponencial espaça as tentativas: espera 1 segundo, depois 2, depois 4, depois 8, dobrando até um limite. O serviço ganha espaço para se recuperar em vez de uma parede de novas tentativas imediatas. O jitter adiciona um desvio aleatório a cada espera para que mil clientes que falharam no mesmo momento não tentem novamente no mesmo instante. Sem ele, o backoff ainda produz ondas sincronizadas.
Limite duas coisas: o atraso, para que você não espere minutos entre as tentativas, e a contagem de tentativas, para que uma falha permanente desista em vez de tentar novamente para sempre. De três a cinco tentativas cobrem quase todos os erros transitórios. Além disso, você geralmente está tentando novamente algo que não terá sucesso. O Anthropic SDK faz parte disso para suas próprias chamadas: ele tenta novamente erros de conexão e códigos de status específicos com backoff exponencial, e você define o limite com uma opção de `max-retries`. Ele não cobre as outras APIs que as ferramentas do seu agente acessam, então você deve envolvê-las você mesmo. Equipes que movimentam dinheiro através de suas novas tentativas aprendem isso cedo, e nossa análise da lógica de nova tentativa para APIs de alto risco mostra onde uma nova tentativa descuidada causa danos reais.
Defina um tempo limite em cada chamada
Uma nova tentativa só ajuda se a requisição falhar. O caso mais desagradável é uma requisição que nunca retorna: uma dependência aceita sua conexão, mas depois trava. Sem tempo limite, a chamada da ferramenta bloqueia e toda a execução fica paralisada por trás de um socket morto. Nenhum erro, nenhuma recuperação, apenas um agente travado queimando tempo de relógio e orçamento de tokens em nada.
Toda chamada de saída precisa de um tempo limite. Defina um tempo limite de conexão para estabelecer a conexão e um tempo limite de leitura para aguardar a resposta, e então um orçamento total para toda a execução do agente para que uma cadeia de chamadas lentas, mas legais, não possa superar a paciência do usuário. Quando um tempo limite é acionado, trate-o como qualquer outro erro que pode ser tentado novamente: recue e tente novamente, até seu limite.
Escolha os números a partir da latência real, não por suposições. Defina cada tempo limite acima do p99 da dependência com margem. Muito apertado e você aborta chamadas que teriam sido bem-sucedidas. Muito frouxo e uma dependência travada amarra o agente muito além do ponto de utilidade. Dê às respostas de streaming seu próprio orçamento, já que uma conclusão longa é legitimamente lenta e um tempo limite fixo curto a mata no meio da transmissão.
Acione um disjuntor quando uma dependência estiver inoperante
O backoff lida com um serviço que está temporariamente ocupado. É a ferramenta errada para um serviço que está completamente inoperante. Se uma dependência estiver falhando há um minuto, a próxima requisição quase certamente falhará também, e tentar novamente acumula mais carga sobre algo já quebrado enquanto o usuário espera por uma falha que você poderia ter previsto.
Um disjuntor resolve isso com três estados. Fechado é normal: as requisições fluem e o disjuntor conta as falhas. Quando as falhas ultrapassam um limite, ele dispara para aberto: para de enviar requisições e falha rapidamente por um período de resfriamento, para que você não pague o tempo limite em cada chamada para um serviço inoperante. Após o período, ele passa para meio-aberto e permite uma única sonda. Se a sonda for bem-sucedida, o disjuntor fecha e o tráfego é retomado; se falhar, ele abre novamente e espera.
Para um agente, o disjuntor transforma “a API de pagamento está fora do ar” em uma falha rápida e limpa sobre a qual o agente pode raciocinar, em vez de quarenta tempos limites lentos que esgotam o orçamento de tokens e o tempo. Conecte-o por dependência, não globalmente, para que uma API de pesquisa inoperante não impeça o agente de usar uma API de faturamento saudável.
Torne as novas tentativas seguras com chaves de idempotência
Cada padrão até agora assume que tentar novamente é seguro. Muitas vezes não é. Seu agente envia POST /charge, o servidor o processa e a resposta atinge o tempo limite no retorno. O agente nunca viu o sucesso, então ele tenta novamente, e agora o cliente é cobrado duas vezes. A nova tentativa fez exatamente o que você pediu. O design era o erro.
Uma chave de idempotência fecha a lacuna. O cliente gera uma chave única por ação lógica e a envia com a requisição, geralmente como um cabeçalho Idempotency-Key. O servidor registra a chave no primeiro recebimento e, se vir a mesma chave novamente, retorna o resultado original em vez de realizar o trabalho duas vezes. Agora, uma nova tentativa é segura por construção: o segundo POST /charge com a mesma chave é uma operação nula que devolve a primeira cobrança.
A chave deve permanecer estável em todas as novas tentativas da mesma ação e mudar entre diferentes ações. Gere-a uma vez ao construir a requisição, não dentro do loop de nova tentativa, ou cada tentativa receberá uma chave nova e a deduplicação nunca será acionada. Qualquer chamada de ferramenta que cria ou altera estado (cobranças, pedidos, e-mails, registros) precisa de uma. Nosso guia sobre chaves de idempotência aborda a geração e o tratamento no lado do servidor em detalhes.
Sobreviva aos limites de taxa e ao loop RateLimitError
Os limites de taxa merecem tratamento próprio porque vêm com instruções. Uma resposta de limite de taxa excedido geralmente chega como um 429, contendo um cabeçalho Retry-After que informa exatamente quanto tempo esperar, em segundos ou como uma data. Respeite-o. Se o servidor disser para esperar 30 segundos e você tentar novamente em 2, você receberá outro 429, e terá construído o loop RateLimitError que preenche o fórum de discussão do SDK: capture o limite, tente novamente muito cedo, seja limitado ainda mais, repita até a execução falhar. Um tópico separado do SDK aborda o mesmo problema que os desenvolvedores enfrentam aqui.
A solução é deixar o servidor definir o ritmo. Quando você recebe um 429, leia o Retry-After e espere pelo menos esse tempo antes de tentar novamente. Se o cabeçalho estiver ausente, retorne ao backoff exponencial com jitter. Limite as tentativas para que um limite sustentado resulte em uma falha limpa em vez de uma espera infinita. O Anthropic SDK já respeita o Retry-After para suas próprias chamadas; o trabalho é aplicar a mesma regra às outras APIs com limite de taxa que seu agente acessa.
Há um lado proativo também. Se um provedor permite um número definido de requisições por minuto, meça suas próprias chamadas com um bucket de tokens para que você permaneça abaixo do limite em vez de descobri-lo sendo limitado. A recuperação lida com os limites que você atinge; o ritmo o impede de atingi-los.
Como testar o caminho de recuperação
Agora, junte tudo. Os padrões acima são tão bons quanto a sua prova de que funcionam, e a prova é um teste que força as falhas que uma API saudável não lhe dará. O formato se repete em todos os cenários:
- Simule a dependência. Crie um mock da API que a ferramenta do seu agente chama, para que você controle cada código de status, cabeçalho, corpo e atraso, e nenhuma cobrança ou e-mail real seja disparado durante o teste.
- Programe uma sequência. Roteirize o mock para responder a uma série de chamadas em ordem: primeiro um 429 com
Retry-After: 2, depois um 500, depois um 200 com um corpo válido. Um endpoint, três respostas roteirizadas, um arco completo de recuperação em uma única execução. - Direcione o agente para o mock. Aponte a ferramenta do agente para a URL do mock em vez do serviço real e execute o cenário de ponta a ponta.
- Afirme o comportamento. Verifique o que importa: o agente esperou pelo menos 2 segundos após o 429 antes de tentar novamente, tentou novamente após o 500, teve sucesso na terceira chamada e nunca excedeu seu limite de tentativas.
Esse cenário prova o backoff e o Retry-After em uma única passagem. Adicione um segundo cenário para o caminho de desistência: roteirize o mock para falhar todas as vezes e afirme que o agente para no limite e retorna um erro limpo em vez de entrar em loop. Adicione um terceiro para o disjuntor: faça falhar chamadas suficientes em sequência e afirme que o agente dispara e falha rapidamente em vez de pagar um tempo limite em cada tentativa.
A verificação de idempotência é a que as pessoas pulam, e é a que economiza dinheiro. Roteirize o mock para aceitar uma chamada mutável, descartar a resposta para que o agente pense que falhou, e então aceitar a nova tentativa. Agora, afirme a forma da requisição: ambas as requisições carregaram a mesma Idempotency-Key, e o mock viu uma ação lógica, não duas. Uma nova chave na nova tentativa, ou uma chamada duplicada, significa que você encontrou um envio duplo antes que um cliente o fizesse. O método mais amplo para testar agentes que chamam suas APIs configura o harness de ponta a ponta.
A lista de verificação de recuperação de erros
Antes que um agente vá para produção, verifique esta lista:
- Toda chamada de saída possui um tempo limite de conexão, um tempo limite de leitura e um orçamento total de execução.
- As novas tentativas usam backoff exponencial com jitter, limitado tanto no atraso quanto na contagem de tentativas.
- As respostas 429 leem e respeitam o
Retry-After, com backoff como alternativa. - Um disjuntor é acionado por dependência para que um serviço inoperante falhe rapidamente em vez de entrar em loop.
- Toda chamada que altera o estado carrega uma chave de idempotência estável que sobrevive a novas tentativas.
- O caminho de desistência retorna um erro limpo, não uma espera infinita.
- Cada um destes é comprovado por um teste que força a falha contra um mock, não presumido.
Marque todos os sete e seu agente se recuperará propositalmente em vez de por sorte.
Onde o Apidog se encaixa (e onde não)
Mantenha a função da ferramenta honesta. O Apidog não é uma framework de agente, um host de modelo ou um tempo de execução. Ele não constrói, executa ou orquestra seu agente, e não avalia a saída do modelo. O que ele possui é a camada de API que seu agente chama, que é exatamente onde a recuperação é ganha ou perdida.

Isso lhe confere três funções. Ele simula as dependências que seu agente acessa, para que você tenha um substituto controlável em vez do serviço ao vivo. Ele programa as respostas de falha (429 com Retry-After, 500, tempo limite, corpo malformado) que uma API real não produzirá sob demanda, para que você possa ensaiar a recuperação. E ele valida as requisições que o mock recebe (chave de idempotência presente e estável, formato correto, contagem de chamadas esperada) para que um envio duplo ou um cabeçalho descartado falhe em um teste em vez de prejudicar um cliente. Esse é o encaixe honesto: o Apidog simula as falhas que seu agente precisa sobreviver e verifica o que ele envia de volta.
Perguntas frequentes
O Anthropic SDK não lida com as novas tentativas para mim? Para suas próprias chamadas, sim. O SDK tenta novamente certos erros com backoff exponencial e respeita o Retry-After, e você define o limite com uma opção de `max-retries`. Ele não cobre as outras APIs que as ferramentas do seu agente chamam. Essas precisam dos mesmos padrões aplicados por você.
Quando preciso de uma chave de idempotência? Em qualquer chamada que crie ou altere o estado: cobranças, pedidos, mensagens enviadas, novos registros. Chamadas somente leitura são seguras para tentar novamente sem uma. Gere a chave uma vez por ação para que ela permaneça estável em todas as novas tentativas.
Ensaie uma falha esta semana
Você não precisa construir todos os quatro padrões de uma vez. Escolha o que mais prejudicaria, geralmente o loop de limite de taxa ou uma nova tentativa não idempotente, e ensaie-o contra um mock. Programe o 429, descarte uma resposta e observe o que o agente envia. Na primeira vez em que você vir um backoff limpo e uma única chave de idempotência onde temia uma cobrança dupla, você confiará no agente por uma razão melhor do que uma demonstração impecável.
Baixe o Apidog para simular as falhas, roteirizar a sequência e afirmar o que seu agente faz quando a API resiste.
