Arquitetura de IA

Leitura após escrita em agentes de IA

Aprenda a impedir que agentes de IA leiam estado antigo logo após uma escrita, repitam ações ou tomem decisões com dados ainda não propagados no sistema.

A atualização funcionou; a consulta seguinte ainda mostra o passado

Um agente atualiza o responsável por uma oportunidade no CRM. A API confirma a gravação. Segundos depois, o fluxo consulta uma lista de oportunidades sem responsável. O registro continua ali porque essa consulta usa um índice atualizado de forma assíncrona.

O agente interpreta a presença como falha, tenta atribuir novamente e abre uma segunda tarefa. A escrita original estava correta. A leitura usada para decidir a etapa seguinte ainda não refletia a mudança.

Esse intervalo aparece em bancos replicados, índices de busca, caches, relatórios, APIs compostas e sistemas SaaS. Ele pode durar milissegundos ou vários segundos. Para a operação, o problema é simples: uma confirmação de escrita e uma consulta posterior podem representar momentos diferentes do mesmo objeto.

A arquitetura precisa oferecer uma garantia de leitura após escrita para os pontos em que o agente depende da mudança que acabou de fazer. Sem essa garantia, ausência aparente vira nova ação, estado antigo vira contexto e uma integração saudável começa a produzir duplicidade.

O problema é específico

A página sobre reconciliação em agentes de IA trata a recuperação quando intenção, execução e sistema oficial podem ter divergido. Este guia atua antes: ele define como uma execução deve avançar depois que uma escrita foi aceita, mas ainda pode não aparecer em todas as formas de leitura.

Também existe uma diferença em relação à idempotência. A chave idempotente protege a repetição do mesmo efeito. A leitura após escrita protege a próxima decisão contra um estado antigo. Os dois controles se completam.

Considere três perguntas separadas:

  1. a escrita foi aceita pelo destino?
  2. qual versão foi aceita?
  3. a consulta seguinte consegue observar essa versão?

Um retorno 200 pode responder a primeira pergunta sem responder à terceira.

Mapeie os caminhos de escrita e leitura

O agente raramente grava e consulta pela mesma rota física.

Uma atualização pode seguir:

agente → API de comandos → banco principal

A verificação pode seguir:

agente → API de busca → cache → índice secundário

Ou:

agente → API regional → réplica de leitura

Documente para cada etapa sensível:

  • endpoint de escrita;
  • recibo devolvido;
  • identificador do objeto;
  • versão, ETag ou horário confirmado;
  • endpoint usado na leitura seguinte;
  • origem real dessa leitura;
  • modelo de consistência;
  • índice, cache ou réplica envolvidos;
  • atraso esperado de propagação;
  • método de leitura forte, quando existe;
  • condição para esperar, bloquear ou escalar.

Sem esse mapa, a equipe costuma resolver o sintoma com um sleep fixo. Às vezes funciona. Depois falha sob carga, em outra região ou durante uma atualização do fornecedor.

Trate o recibo da escrita como evidência

Uma escrita aceita deveria devolver informação suficiente para acompanhar o objeto.

Exemplo:

{
  "opportunity_id": "OP-7421",
  "owner_id": "USR-19",
  "version": 38,
  "updated_at": "2026-10-15T09:42:18Z",
  "request_id": "req_8f31",
  "status": "accepted"
}

Persista esse recibo junto ao estado da execução. A próxima etapa passa a procurar a versão 38 da oportunidade OP-7421, e não apenas uma oportunidade parecida com responsável preenchido.

Campos úteis incluem:

  • ID estável do objeto;
  • versão monotônica;
  • ETag;
  • ID da operação;
  • chave de idempotência;
  • estado de aceitação;
  • horário observado no servidor;
  • token de sessão ou consistência;
  • origem da confirmação.

Se a API devolve o objeto atualizado, use essa resposta para decisões locais imediatas que não exigem uma nova consulta. Ainda assim, não trate o recibo como prova de que índices, relatórios e sistemas derivados já foram atualizados.

Escolha a garantia por decisão

Aplicar consistência forte em toda leitura pode aumentar custo, latência e contenção. Aceitar consistência eventual em todo lugar deixa decisões críticas expostas. A unidade correta é a decisão.

Leitura forte do objeto principal

Use quando a etapa seguinte precisa confirmar a versão corrente antes de executar uma consequência.

No Amazon DynamoDB, tabelas e índices secundários locais podem oferecer leitura fortemente consistente quando a operação habilita ConsistentRead. Índices secundários globais e streams permanecem eventualmente consistentes. Consultar o índice errado depois da escrita pode devolver o passado mesmo quando a tabela principal já contém a versão nova.

Consistência de sessão

Use quando o armazenamento fornece um token que preserva a relação entre a escrita e as leituras seguintes.

No Azure Cosmos DB, a consistência de sessão oferece a garantia de ler as próprias escritas dentro da sessão. O servidor devolve um token atualizado após a escrita. Se outro worker continuar o fluxo, ele precisa receber o token correspondente. Trocar de processo sem propagar esse contexto pode perder a garantia.

Consulta eventual com espera limitada

Use quando o caminho de leitura não oferece garantia forte e a consequência pode aguardar.

O fluxo consulta até encontrar a versão esperada ou atingir um limite. Durante a espera, o estado continua como escrita_aceita_aguardando_visibilidade. Ele não volta para não_executado.

Estado local pendente

Use quando o agente precisa continuar outras partes do trabalho sem fingir que a propagação terminou.

Registre a mudança aceita como pendente de visibilidade. A camada local pode impedir uma segunda ação sobre o mesmo objeto e mostrar a condição para operação. O sistema oficial continua sendo a autoridade final.

Nunca transforme ausência temporária em autorização

Depois de uma escrita, uma consulta eventual pode devolver:

  • o objeto antigo;
  • nenhum objeto;
  • uma lista sem o item atualizado;
  • um total anterior;
  • uma projeção parcial;
  • um cache ainda válido pela política técnica, mas vencido para aquela decisão.

Nenhum desses resultados autoriza automaticamente uma nova escrita.

Use estados explícitos:

escrita_preparada
escrita_enviada
escrita_aceita
aguardando_visibilidade
versao_confirmada
propagacao_excedida
conflito_detectado
exige_reconciliacao

A ausência depois de uma confirmação deve cair em aguardando_visibilidade ou propagacao_excedida. Voltar para escrita_preparada apaga a evidência de que o destino já aceitou a operação.

Propague versão, token e contexto entre workers

Um agente pode escrever num processo e continuar em outro. Fila, retry, scheduler e orquestrador precisam carregar o vínculo causal.

Um envelope mínimo pode conter:

{
  "work_item_id": "assign-owner:OP-7421",
  "object_id": "OP-7421",
  "expected_version": 38,
  "write_request_id": "req_8f31",
  "idempotency_key": "assign-owner:OP-7421:USR-19",
  "session_token": "<token quando aplicável>",
  "accepted_at": "2026-10-15T09:42:18Z",
  "visibility_deadline": "2026-10-15T09:42:48Z"
}

Cada consumidor precisa preservar esses campos até a confirmação. Remover o token numa serialização, recriar a chave idempotente ou consultar só pelo texto da oportunidade rompe a continuidade.

Não coloque tokens sensíveis em logs abertos. Trate credenciais e artefatos de sessão conforme a classificação do fornecedor e a política de segredos.

Use comparação de versão antes de alterar novamente

Mesmo depois que a versão 38 aparece, outra pessoa pode ter produzido a versão 39. O agente não deveria sobrescrever a mudança mais recente apenas porque conseguiu confirmar a própria escrita.

Operações condicionais ajudam:

atualize owner_id para USR-22
somente se version = 38

Se o destino informar conflito, o fluxo lê o estado atual, preserva a alteração concorrente e reavalia a intenção. A versão protege duas falhas diferentes:

  • leitura antiga logo após a escrita;
  • escrita nova baseada em uma leitura antiga.

ETag, compare-and-set, número de versão e precondições HTTP podem oferecer essa barreira. A capacidade exata depende da API usada.

Faça polling com limite operacional

Quando só existe leitura eventual, use uma política delimitada.

Exemplo:

versão esperada: 38
prazo de visibilidade: 30 segundos
tentativas máximas: 6
intervalos: 1s, 2s, 4s, 6s, 8s, 9s
consulta: objeto por ID no caminho mais autoritativo disponível
resultado ausente: continuar aguardando
versão menor: continuar aguardando
versão igual ou maior: confirmar e avançar
prazo excedido: bloquear nova escrita e reconciliar

O intervalo deve nascer de medição do sistema real. Não copie os números do exemplo para produção.

Backoff reduz pressão durante atraso. Jitter evita que muitos agentes consultem ao mesmo tempo. Um prazo absoluto impede que retries internos prolonguem a espera indefinidamente.

O polling precisa observar o objeto certo. Repetir a mesma consulta em um índice atrasado não cria uma garantia que o índice não oferece.

Exemplo: atribuição de oportunidade no CRM

Uma rotina identifica oportunidades sem responsável e sugere distribuição.

Entrada

opportunity_id: OP-7421
current_version: 37
current_owner: vazio
approved_owner: USR-19

Escrita

A API aceita a atribuição e devolve version = 38.

Leitura insegura

O agente consulta imediatamente a lista sem responsável. O índice ainda mostra OP-7421. O fluxo conclui que a atribuição falhou e tenta novamente.

Leitura segura

O fluxo:

  1. persiste ID, versão 38, chave idempotente e recibo;
  2. marca a unidade como aguardando_visibilidade;
  3. consulta o objeto por ID numa rota capaz de confirmar a versão;
  4. propaga token de sessão quando o armazenamento exige;
  5. aceita versão 38 ou superior;
  6. verifica se o responsável ainda é USR-19;
  7. só então prepara a próxima ação;
  8. se o prazo expira, envia a unidade para reconciliação sem repetir a atribuição.

Se uma pessoa alterar o responsável e criar versão 39 durante o intervalo, o agente não restaura USR-19. Ele registra conflito e devolve o caso à regra atual.

Laboratório sintético

Uma simulação local reproduziu um índice que permaneceu na versão 37 durante duas leituras depois de a fonte principal aceitar a versão 38.

O fluxo inseguro interpretou a lista antiga como ausência da mudança e preparou uma segunda atribuição. O fluxo protegido manteve o recibo, aguardou a versão mínima e confirmou uma única intenção depois da terceira leitura.

O exercício valida a máquina de estados e a regra de decisão. Ele não mede o tempo de propagação de um CRM real nem demonstra garantia de um fornecedor.

Casos de teste mínimos:

  1. escrita aceita e leitura atual imediata;
  2. escrita aceita e duas leituras antigas;
  3. escrita aceita e objeto ausente no índice;
  4. token de sessão perdido na troca de worker;
  5. versão mais nova criada por uma pessoa;
  6. timeout depois da escrita;
  7. prazo de visibilidade excedido;
  8. retry com a mesma chave idempotente;
  9. retry com chave diferente, que deve ser bloqueado;
  10. cache devolvendo objeto anterior;
  11. leitura forte indisponível naquele tipo de índice;
  12. propagação concluída depois de a intenção perder validade.

Observabilidade para encontrar leituras antigas

Registre:

  • versão enviada;
  • versão aceita;
  • versão lida;
  • rota da leitura;
  • tipo de consistência solicitado;
  • token ou sessão usados, sem expor segredo;
  • tempo até visibilidade;
  • quantidade de consultas;
  • cache ou índice envolvido;
  • decisões bloqueadas;
  • conflitos posteriores;
  • repetições impedidas;
  • unidades encaminhadas à reconciliação.

Uma mensagem operacional útil seria:

OP-7421: atribuição aceita na versão 38; busca ainda retorna 37 após 12 segundos; nova escrita bloqueada; próxima verificação em 6 segundos; dono da integração: Comercial Ops.

“Dado inconsistente” é diagnóstico curto demais. O alerta precisa mostrar objeto, versões, consequência, ação e responsável.

Erros de implementação

Dormir por um tempo fixo

Atrasos variam com carga, região, cache e manutenção. Um sono de cinco segundos só esconde a ausência de uma condição verificável.

Consultar a mesma lista que disparou a ação

Listas e buscas costumam usar índices derivados. Confirme o objeto por ID e versão no caminho mais autoritativo disponível.

Usar o horário do worker como versão

Relógios podem divergir. Prefira versão ou token emitido pelo destino. O guia sobre clock skew em agentes de IA detalha esse risco.

Repetir a escrita para “garantir”

Uma resposta antiga não prova falha. Repetição sem chave idempotente pode duplicar tarefa, mensagem, cobrança ou reserva.

Manter token apenas na memória do processo

A troca de worker perde a garantia. Estado necessário à continuidade precisa atravessar fila e checkpoint de forma protegida.

Confirmar qualquer versão mais nova sem conferir conteúdo

Versão 39 mostra que houve mudança. Ela não prova que a intenção original continua válida. Compare os campos que sustentam a próxima decisão.

Aplicar consistência forte a tudo

O custo aparece sem melhorar decisões tolerantes a atraso. Classifique quais leituras exigem atualidade e quais aceitam propagação.

Checklist de implementação

  • [ ] A escrita devolve ID, versão, ETag ou recibo verificável?
  • [ ] O fluxo persiste essa evidência antes de avançar?
  • [ ] A leitura seguinte usa a mesma unidade de objeto?
  • [ ] A origem da consulta é conhecida?
  • [ ] Índices, caches e réplicas estão documentados?
  • [ ] A decisão exige leitura forte, sessão ou espera limitada?
  • [ ] Tokens de sessão atravessam workers quando necessário?
  • [ ] Ausência temporária não libera nova escrita?
  • [ ] A chave idempotente permanece igual entre tentativas?
  • [ ] Escritas posteriores usam condição de versão?
  • [ ] O prazo de visibilidade é medido e limitado?
  • [ ] O fluxo possui estado próprio para propagação excedida?
  • [ ] A reconciliação recebe recibo, versões e tentativas?
  • [ ] Alertas mostram consequência e responsável?
  • [ ] Testes simulam índice atrasado, cache e mudança concorrente?

A próxima decisão precisa enxergar a própria mudança

Um agente pode receber confirmação legítima e, logo depois, consultar uma representação antiga do mesmo objeto. A falha surge quando a arquitetura trata essa leitura como verdade suficiente para repetir ou desfazer uma ação.

A proteção combina recibo de escrita, identidade do objeto, versão esperada, rota de leitura conhecida, token de sessão quando aplicável, polling limitado, idempotência e comparação condicional. Assim, o agente distingue três estados que parecem iguais numa interface apressada: mudança não executada, mudança aceita ainda em propagação e mudança substituída por outra versão.

Fontes oficiais verificadas em 15 de outubro de 2026:

As garantias variam por serviço, operação, índice, região e cliente. Confirme a documentação e teste o caminho efetivamente usado antes de liberar consequências em produção.