Paginação de API para agentes de IA: descoberta com limites
A paginação de API para agentes de IA precisa de orçamentos de páginas, cursores opacos, novas tentativas seguras e relatórios que indiquem exatamente o que o agente não inspecionou.

Um agente que chama um endpoint de lista sem definir um orçamento de páginas não está fazendo descoberta. Está iniciando um procedimento remoto sem fim definido e torcendo para que a conta, o limite de taxa e o conjunto de resultados continuem favoráveis. O erro oposto é igualmente prejudicial: buscar a primeira página, encontrar uma resposta plausível e tratá-la silenciosamente como se fosse o sistema inteiro.
A paginação muda o que um agente pode afirmar com honestidade. Um item retornado prova que esse item existe. Não prova que não há outros. A ausência de um item prova muito pouco, a menos que o agente consiga mostrar o escopo inspecionado, a ordenação usada e o motivo pelo qual o servidor indicou que a travessia terminou.
Já vi agentes transformarem uma solicitação inofensiva, como «encontre tokens de acesso obsoletos», em milhares de chamadas porque ninguém informou onde a descoberta deveria terminar. Também já vi um inventário de uma única página levar a uma tentativa de limpar contas que estavam na página dois. A solução não está em escrever prompts mais inteligentes. Dê ao agente um contrato de travessia com limites e faça o relatório final expor essa fronteira.
Chamadas de descoberta precisam de um orçamento explícito
Toda chamada de descoberta paginada precisa de limites que o agente não possa ampliar silenciosamente. Defina o número máximo de páginas, o número máximo de registros retornados, um prazo e uma margem para o limite de taxa antes da primeira solicitação. Os valores adequados dependem da tarefa, mas os limites são sempre necessários.
Trate a descoberta como uma fase separada da ação. Durante a descoberta, o agente reúne identificadores e fatos. Ele não deve excluir, alternar ou modificar objetos apenas porque uma página contém algo suspeito. Quando tiver evidências suficientes, pode apresentar um plano com escopo definido ou iniciar uma fase de ação autorizada separadamente.
Um contrato útil tem quatro partes:
- O endpoint e todos os filtros, incluindo a ordenação quando a API permitir.
- Um tamanho de página e um limite máximo de páginas ou registros.
- Uma condição de conclusão definida pela API, como a ausência de um cursor seguinte.
- Uma condição de parada antecipada, como encontrar um objeto específico ou esgotar o orçamento disponível.
Não confunda limite de registros com limite de páginas. Se o serviço permite 100 registros por página e o agente tem um limite de 500 registros, cinco chamadas podem bastar. Se o serviço reduzir o tamanho efetivo da página por causa de filtros ou permissões, a mesma tarefa pode precisar de mais chamadas. Uma boa implementação verifica os dois limites depois de cada resposta.
Por exemplo, um agente encarregado de localizar um repositório chamado billing-service poderia parar assim que recebesse uma correspondência exata, caso o filtro e a ordenação do endpoint tornem essa conclusão segura. Um agente encarregado de identificar todos os repositórios sem proteção de branches não pode parar na primeira correspondência. Essa tarefa exige uma enumeração completa ou um resultado explicitamente parcial.
A palavra «todos» deve ter um custo. O agente só pode usá-la depois que a travessia chegar à condição terminal do servidor sem atingir seu orçamento de páginas, registros, tempo ou erros. Se um desses limites for acionado, o relatório deve dizer «varredura parcial» e indicar a fronteira.
O tamanho da página controla custos, não a completude
O parâmetro limit, per_page ou page_size informa ao serviço quantos registros tentar retornar em uma resposta. Ele não informa quanto da coleção o agente precisa inspecionar. Defini-lo no máximo reduz algumas viagens, mas pode tornar cada resposta cara o bastante para causar timeout, exceder o orçamento de contexto ou esconder detalhes importantes em meio a muitos dados irrelevantes.
Comece com a menor página que permita tomar a decisão. Se o agente precisa de uma conta exata, normalmente é melhor solicitar 20 registros resumidos do que 1.000 objetos completos. Se precisa montar um inventário, use um tamanho de página maior somente depois de confirmar que o endpoint retorna uma representação limitada e útil.
Os campos importam tanto quanto o tamanho da página. Muitas APIs oferecem fields, include, expand ou mecanismos semelhantes. Uma passagem de descoberta deve solicitar identificadores, nomes, estado, timestamps e a propriedade que orienta a decisão. Busque detalhes completos apenas para os candidatos que precisam de inspeção. Isso reduz o tráfego e deixa menos texto incidental para o modelo interpretar de forma equivocada.
Use um formato de solicitação como este quando o provedor oferecer paginação por cursor:
GET /v1/projects?state=active&limit=50&sort=id HTTP/1.1
Authorization: Bearer injected-by-gateway
Accept: application/json
E espere um formato de saída que separe os registros do estado de continuação:
{
"data": [
{"id": "prj_104", "name": "billing-service", "state": "active"}
],
"next_cursor": "eyJvcmRlciI6ImlkIiwicG9zIjoiMTA0In0"
}
O agente deve registrar que solicitou 50 registros e recebeu um. Não deve deduzir que a travessia terminou a partir do tamanho reduzido do array. O único sinal útil de conclusão neste exemplo é a ausência de next_cursor ou seu valor nulo documentado.
Evite uma regra arbitrária como «use sempre 100». O tamanho máximo varia entre APIs, e alguns serviços contabilizam objetos filhos expandidos ou bytes da resposta em limites diferentes. Solicite o máximo documentado apenas quando a tarefa se beneficiar disso. Em varreduras amplas, um tamanho médio costuma produzir checkpoints melhores, novas tentativas mais fáceis e relatórios que uma pessoa consegue auditar.
Preserve os cursores como estado opaco do servidor
Um cursor não é um offset com um nome sofisticado. O servidor é dono do seu significado, e o agente deve copiá-lo byte a byte na próxima solicitação. Ele pode codificar uma posição de ordenação, um identificador de snapshot, um limite de permissão ou uma assinatura. O fato de parecer Base64 não dá permissão para decodificá-lo, editá-lo ou fabricá-lo.
O loop seguro é simples: solicite a primeira página com filtros e parâmetros de ordenação estáveis, salve o cursor retornado pela resposta e envie a mesma consulta com esse cursor. Mantenha todos os parâmetros originais, salvo quando a documentação da API disser explicitamente o contrário. Alterar o filtro entre solicitações pode invalidar o cursor ou, pior, produzir um conjunto de resultados plausível, mas descontínuo.
request = { state: "active", limit: 50, sort: "id" }
seen_ids = set()
pages = 0
while pages < 10 and len(seen_ids) < 500:
response = GET /v1/projects with request
record response status, request, and response cursor
for item in response.data:
if item.id in seen_ids:
report "duplicate record encountered" with item.id
stop or apply the provider's documented recovery method
seen_ids.add(item.id)
pages += 1
if response.next_cursor is absent:
report "complete"
break
request.cursor = response.next_cursor
else:
report "partial: traversal budget reached"
A verificação de duplicatas não é enfeite. Coleções mutáveis podem mudar enquanto o agente as percorre, e existem implementações de paginação defeituosas. Uma duplicata nem sempre significa que o serviço falhou, mas significa que o agente deve parar de fingir que tem uma enumeração limpa. Se o provedor oferecer um token de snapshot, um parâmetro as_of ou um modo de consistência documentado, use-o em tarefas que levarão a uma ação consequente.
A expiração do cursor precisa de uma regra explícita. Alguns serviços fazem cursores de curta duração; outros os vinculam a uma sessão ou os invalidam quando uma consulta muda. Ao receber uma resposta de cursor expirado, o agente deve preservar o erro e então reiniciar a partir de um checkpoint estável ou encerrar a varredura como incompleta. Não deve avançar pulando registros ao adivinhar um novo cursor.
Um reinício também pode criar uma falsa sensação de completude. Se os registros mudaram entre a primeira passagem e o reinício, uma lista combinada pode conter lacunas ou duplicatas. Informe o reinício e a condição usada para retomar, como created_at >= last_observed_timestamp. Se não houver um método estável de retomada, informe que a coleção mudou durante a travessia e não use o resultado como lista de exclusão.
A paginação por offset sofre desvios quando as coleções mudam
A paginação por offset usa um número como offset=200&limit=50 ou page=5&per_page=50. É fácil de programar e explicar, por isso continua comum. Também se torna pouco confiável quando novos registros chegam ou registros antigos desaparecem enquanto o agente percorre a coleção.
Suponha que a primeira página retorne os registros 1 a 50 em ordem do mais recente para o mais antigo. Antes de o agente solicitar a segunda página, chegam dez registros novos. offset=50 agora começa depois dos registros recém-inseridos e se sobrepõe a objetos que o agente já viu. Se registros desaparecerem da primeira página, o mesmo offset pode pular objetos que subiram de posição. O agente não consegue corrigir isso apenas deduplicando IDs, porque a deduplicação detecta repetições, mas não omissões.
Se a API permitir uma ordenação estável, selecione uma com um desempate determinístico. Apenas created_at muitas vezes não basta, pois vários registros podem compartilhar o mesmo timestamp. Uma ordenação como created_at,id, quando documentada pelo provedor, permite registrar uma marca d'água e retomar com mais cuidado. Se a API fornecer somente um offset, sem snapshot ou ordenação estável, seja conservador nas conclusões extraídas de várias páginas.
Para uma tarefa que exige uma resposta completa, use uma destas abordagens, em ordem decrescente de confiança:
- Peça ao serviço um snapshot, um job de exportação ou um cursor que documente uma visão estável.
- Restrinja a consulta a um intervalo de tempo imutável e use uma ordenação estável documentada.
- Execute uma segunda varredura e compare os identificadores, informando qualquer divergência.
- Peça a uma pessoa que aprove um escopo mais estreito e bem definido, em vez de fazer uma alteração ampla.
Não transforme uma interface ruim em um fluxo destrutivo. O agente ainda pode usar páginas por offset para amostragem, localizar um objeto específico ou produzir um inventário parcial. Não deve usar uma varredura instável por offset como prova de que encontrou todas as credenciais, projetos ou usuários correspondentes.
A conclusão deve vir do protocolo, não de uma suposição
Diferentes APIs expressam o estado da paginação em lugares diferentes. Um corpo JSON pode conter next_cursor, has_more ou uma URL para a próxima página. Outras APIs usam o cabeçalho HTTP Link. A RFC 8288 define Web Linking e o parâmetro rel, usado para relações como next; o cabeçalho fornece uma relação, mas não garante que o corpo da resposta tenha um campo de cursor conhecido.
Um agente precisa de uma regra de conclusão específica para cada endpoint. Escreva-a ao lado da definição da solicitação. Por exemplo: «Conclua quando next_cursor for nulo». Ou: «Conclua quando nenhuma relação Link tiver rel="next"». Não escreva: «Conclua quando retornarem menos de 100 registros». Esse atalho falha com páginas filtradas, redução por permissões, limites do serviço e APIs que retornam páginas deliberadamente irregulares.
Um cabeçalho Link típico pode ter esta aparência:
Link: </v1/events?limit=100&cursor=a6f3>; rel="next",
</v1/events?limit=100&cursor=first>; rel="first"
O agente deve selecionar apenas a relação que conhece. Não deve concatenar o cabeçalho, presumir que o link first é um checkpoint seguro para reinício ou inferir que a ausência de um link last significa que não existe uma página final. A documentação da própria API rege seu contrato de paginação; a RFC 8288 apenas descreve como as relações de link circulam nos cabeçalhos HTTP.
Algumas APIs retornam has_more: true com uma página vazia. Isso parece absurdo até que se encontra um filtro de permissões, uma exclusão concorrente ou um índice atrasado. Se a API documentar esse comportamento, continue com o token de continuação enquanto o orçamento permitir e registre a página vazia. Se não documentar, pare e sinalize uma resposta de paginação inconsistente. Continuar indefinidamente porque has_more permanece verdadeiro é um erro de programação, não persistência.
Também diferencie uma resposta terminal de um status HTTP bem-sucedido. 200 OK diz que aquela solicitação foi concluída com sucesso. Não diz que a coleção terminou. Um 404 pode significar um cursor expirado, um endpoint incorreto ou um recurso que desapareceu. Preserve o status, o corpo da resposta e o último cursor no registro da execução para que uma pessoa consiga identificar o que ocorreu.
Um resultado parcial precisa de uma declaração de limite
Um agente deve relatar a descoberta como uma pessoa cuidadosa escreveria uma nota de incidente: informe o que foi solicitado, o que foi observado e o que não foi inspecionado. A maioria dos relatórios ruins de agentes falha na última parte. Eles listam as descobertas, mas omitem o cursor, o limite ou o erro que torna essas descobertas incompletas.
Use um formato de relatório que uma pessoa possa utilizar sem reconstruir a sessão:
Scope: GET /v1/projects?state=active&sort=id
Requested page size: 50
Pages fetched: 10
Records received: 487
Completion: partial
Stop reason: page budget reached
Last continuation cursor: eyJvcmRlciI6ImlkIiwicG9zIjoiNTg3In0
Observed finding: 12 projects matched the review rule
Uninspected scope: records after the last continuation cursor
Action taken: none
A última linha importa. Uma execução de descoberta deve dizer se alterou alguma coisa. Quem revisar o relatório nunca deve precisar inferir se o agente apenas listou objetos ou agiu sobre eles.
Não exponha um cursor sensível em uma transcrição de chat se o provedor o tratar como uma capacidade bearer ou se seu conteúdo puder revelar a estrutura da conta. Armazene o token exato nos metadados protegidos da execução e apresente uma impressão digital ou um prefixo redigido no relatório voltado para pessoas. O agente ainda precisa de estado suficiente para retomar ou auditar a travessia, mas as pessoas não precisam ver tokens de continuação espalhados por tickets e terminais.
A linguagem controla o risco aqui. «Não encontrei registros correspondentes nos primeiros 500 inspecionados» é preciso. «Não existem registros correspondentes» só é preciso depois de uma travessia completa em uma visão suficientemente estável. A diferença parece minuciosa até que uma decisão de limpeza ou conformidade dependa dela.
Limites de taxa e novas tentativas precisam de regras próprias
A paginação amplia os erros de limite de taxa porque uma única solicitação se transforma em um loop. Um agente que recebe 429 Too Many Requests não deve bombardear o endpoint com o mesmo cursor. Respeite Retry-After quando o servidor o fornecer, contabilize a espera no prazo da execução e pare quando o orçamento de novas tentativas acabar.
Para falhas transitórias, como um timeout ou uma resposta 5xx, repita a mesma página antes de avançar. Se a API oferecer um identificador de idempotência ou de solicitação para chamadas de lista, use-o conforme a documentação. Nunca avance para o próximo cursor depois de uma resposta incerta apenas porque a solicitação pode ter sido concluída. Isso cria uma lacuna silenciosa.
Uma política limitada de novas tentativas poderia estabelecer:
- Repetir a página atual no máximo duas vezes após falhas transitórias de transporte ou do servidor.
- Respeitar
Retry-Afterpara limites de taxa quando o prazo restante permitir. - Não repetir falhas de autenticação ou autorização sem uma mudança no estado de autorização.
- Parar diante de dados de paginação malformados, cursor repetido ou resposta de continuação não documentada.
Um cursor repetido merece atenção especial. Se a página três retornar o mesmo next_cursor que o agente enviou, continuar pode criar um loop infinito. Compare cada cursor novo com o cursor enviado e com um conjunto de cursores anteriores. Pare quando houver repetição, salvo se o provedor documentar um caso em que isso seja esperado, algo raro que deve ser tratado por uma regra específica do provedor.
O agente deve preservar metadados de resposta suficientes para diagnosticar uma nova tentativa sem armazenar segredos. Registre o código de status, o caminho da solicitação, cabeçalhos selecionados que não sejam sensíveis, o número sequencial da página, a impressão digital do cursor, timestamps e um resumo do corpo da resposta, se a política permitir. Não cole cabeçalhos de autorização, tokens bearer completos ou URLs com credenciais nos logs apenas porque uma solicitação falhou.
Um exemplo de falha mostra por que a primeira página é perigosa
Considere um agente encarregado de desativar toda integração inativa mais antiga que uma data definida. O endpoint de integrações usa por padrão 25 itens, ordena pela atualização mais recente e fornece next_cursor apenas quando existem mais páginas. O agente busca a primeira página, encontra três integrações inativas e as desativa. Depois informa que limpou as integrações inativas.
Esse relatório está errado de duas formas. O agente não inspecionou todas as integrações e agiu durante a descoberta. O fato de ter encontrado três candidatos não diz nada sobre a página dois em diante. Pior: desativar itens altera updated_at, o que pode reordenar a coleção se o endpoint usar sua ordenação padrão. O agente tornou sua própria travessia menos estável.
Uma execução mais segura começa com um filtro explícito e uma ordenação estável, se a API oferecer suporte:
GET /v1/integrations?status=inactive&updated_before=2024-01-01&limit=50&sort=id HTTP/1.1
O agente reúne IDs entre as páginas sem modificá-los. Para apenas quando o servidor não emitir um cursor seguinte ou quando o orçamento de descoberta for atingido. Depois, informa um conjunto completo ou parcial de candidatos. Uma solicitação de ação separada pode usar os IDs reunidos, de preferência depois que uma pessoa conferir a quantidade e o escopo.
Se o endpoint de lista não oferecer uma ordenação estável, o agente deve dizer isso. Ainda pode reunir candidatos, mas não deve afirmar que obteve um conjunto completo e livre de condições de corrida. O conselho popular de «agir enquanto encontra os itens» parece eficiente porque economiza uma segunda passagem. Ele está errado para listas mutáveis em que a ação altera a posição na ordenação, a elegibilidade ou as permissões.
O mesmo padrão se aplica a descobertas de segurança, contas de usuários, registros de implantação e artefatos de build. Primeiro leia, estabeleça o escopo e depois altere. Há exceções para contenção urgente, como revogar uma credencial comprometida e identificada pelo nome, mas isso não é uma tarefa de limpeza paginada. É uma ação direcionada com um identificador conhecido.
Mantenha credenciais e observabilidade fora do agente
Um agente não deve precisar do segredo da API apenas para paginar. O componente que executa as solicitações HTTP pode injetar credenciais, exigir autorização humana quando necessário e registrar a sequência real de solicitações. Assim, o agente se concentra na construção e interpretação da consulta, sem lidar com tokens que permitiriam fazer chamadas sem limite em outros lugares.
Para equipes que usam o Sallyport, as chamadas HTTP podem passar pelo gateway de ações enquanto as credenciais permanecem no cofre criptografado, e o diário de Atividades registra cada chamada. Esse registro ajuda uma pessoa revisora a comparar a quantidade de páginas declarada pelo agente com as solicitações realmente executadas, mas não substitui os orçamentos de páginas nas instruções do agente.
Mantenha a política de travessia próxima da definição da tarefa. Especifique endpoints permitidos, filtros, campos, número máximo de páginas, comportamento de novas tentativas e a declaração de limite obrigatória. Uma camada de autorização de uso geral não consegue decidir se uma varredura de um repositório termina após uma página ou se um inventário de conformidade precisa de todas as páginas.
O diário de sessões e a trilha de atividades por chamada do Sallyport podem tornar prática a revogação e a revisão quando uma execução sai do rumo. Ainda assim, o agente precisa receber instruções para parar diante de um formato de cursor não reconhecido, de um orçamento esgotado ou de uma resposta da API que contradiga o contrato documentado do endpoint. Registrar uma coleta incorreta depois do fato é melhor do que não ter evidências, mas não desfaz chamadas desnecessárias nem uma ação incorreta.
Teste a travessia com cenários hostis de paginação
A paginação no caminho feliz esconde os defeitos que importam. Antes de confiar em um fluxo de agente, teste-o com cenários que retornem uma primeira página vazia com cursor, uma página curta com mais resultados, um item duplicado, um cursor repetido, um cursor expirado e uma resposta de limite de taxa entre duas páginas normais.
O comportamento esperado deve ser simples e específico. O agente continua depois de uma página vazia somente quando o estado de continuação documentado indicar que deve continuar. Ele deduplica ou para diante de IDs repetidos conforme o requisito de consistência da tarefa. Nunca inventa um cursor depois de uma expiração e informa cobertura parcial quando um limite de segurança encerra a execução.
Use esta tabela de aceitação ao revisar um loop de chamadas de ferramenta:
| Cenário | Resultado esperado |
|---|---|
| 12 registros, sem cursor seguinte | Concluir após uma solicitação |
| 12 registros, com cursor seguinte | Continuar apesar da página curta |
| Mesmo cursor retornado duas vezes | Parar e informar um loop de paginação |
429 com Retry-After | Esperar apenas dentro do prazo e repetir a página atual |
| Cursor rejeitado por expiração | Reiniciar apenas por um checkpoint documentado ou informar resultado incompleto |
Inspecione as chamadas brutas e também o texto final. Um relatório bem escrito pode esconder um cursor pulado ou uma solicitação extra depois da condição de parada. O log de execução deve mostrar uma solicitação inicial, cada solicitação de continuação, qualquer nova tentativa do mesmo cursor e nenhuma chamada depois da resposta terminal.
Defina um orçamento padrão pequeno para trabalhos exploratórios e exija uma mudança explícita na tarefa para uma enumeração ampla. Essa única restrição evita as duas falhas que mais desperdiçam tempo: agentes que varrem para sempre e agentes que confundem silenciosamente a primeira página com a resposta completa.
FAQ
O que a paginação significa para um agente de IA que usa uma API?
Paginação é a forma como o protocolo divide uma coleção em partes. O agente deve tratar cada parte como evidência parcial, e não como a coleção completa, a menos que tenha chegado a um cursor terminal documentado ou a outra condição explícita de conclusão.
Quantas páginas de uma API um agente autônomo deve buscar?
Isso depende do tamanho das respostas do endpoint, dos limites de taxa e da ação que o agente pretende executar. Para descoberta, comece com um orçamento de páginas deliberadamente pequeno e amplie-o apenas quando a tarefa exigir uma cobertura maior. Não deixe o agente decidir que toda lista merece uma varredura sem limite.
O agente deve interpretar ou modificar um cursor de API?
Um cursor é um token opaco de continuação emitido pelo servidor. Salve-o e envie-o novamente exatamente como foi recebido, incluindo codificação e maiúsculas e minúsculas. Interpretar, modificar ou reconstruir o cursor pode fazer o agente pular registros ou gerar uma solicitação inválida.
Uma página curta da API significa que não há mais resultados?
Não. Uma página com menos registros do que o solicitado ainda pode ter um cursor seguinte, especialmente quando o serviço aplica filtros, controles de acesso ou limites internos. Continue apenas quando o sinal de continuação documentado indicar que há mais dados.
É melhor solicitar o maior tamanho de página possível?
Use o maior tamanho de página compatível apenas quando a documentação do endpoint, o custo do payload e o limite de taxa tornarem isso sensato. Páginas grandes reduzem o número de viagens, mas podem aumentar timeouts, uso de memória e o custo de buscar campos que a tarefa nunca precisou.
O que um agente deve informar depois de uma busca paginada parcial?
O relatório deve informar o endpoint, o filtro, o tamanho de página solicitado, o número de páginas buscadas, os registros retornados, o status terminal e qualquer cursor ou limite de página que tenha interrompido a execução. Se a execução terminou cedo, diga que o resultado é parcial e evite palavras como «todos» ou «nenhum».
O que um agente deve fazer quando um cursor expira?
Repita a mesma solicitação com o mesmo cursor se a documentação da API permitir. Se o serviço retornar um cursor expirado ou inválido, reinicie a partir de um ponto de verificação estável ou restrinja a consulta. Depois, informe que os resultados podem ter mudado durante o reinício da varredura.
Qual é a diferença entre paginação por cursor e paginação por offset?
A paginação por offset solicita uma posição numérica, como offset=200; a paginação por cursor usa um token fornecido pelo servidor e associado à travessia atual. Offsets são fáceis de entender, mas sofrem desvios quando registros são inseridos ou excluídos. Cursores costumam funcionar melhor com coleções que mudam, quando o provedor os implementa corretamente.
Um agente pode repetir solicitações GET paginadas com segurança?
Uma solicitação GET pode ser segura para repetir em termos de HTTP, mas o conteúdo da lista ainda pode mudar entre páginas. Os agentes devem registrar a consulta e os limites observados, usar um token de snapshot quando disponível e evitar decisões destrutivas baseadas em uma varredura que não possam descrever como completa.
Um gateway de API pode resolver sozinho a segurança da paginação?
Um gateway pode fazer a chamada HTTP mantendo as credenciais fora do agente, mas não consegue inferir se uma tarefa precisa de duas páginas ou de duzentas. Mantenha credenciais e aprovações no gateway e defina orçamentos de páginas, condições de parada e relatórios honestos nas instruções operacionais do agente.