soluções web . agentes de IA

curitiba . pr  ·  atendemos remoto no brasil inteiro

typescript . n8n . supabase . claude code . codex . gemini . skills

agentes que executam, conversam e prestam contas

whatsapp[ 41 ] 99986 5410

« voltar ao blog

Trilha de auditoria de agentes de IA em Postgres: o schema que usamos

Todo piloto de agente passa. O que trava a escala é a pergunta que vem depois, feita pelo jurídico, pelo auditor ou pelo cliente grande: quem autorizou essa ação, com qual dado, quanto custou e como reverter? Sem uma resposta em vinte segundos, o projeto volta para o começo. A trilha de auditoria é o que transforma essa conversa de um mês de trabalho em uma consulta. Este artigo traz o esquema que usamos em Postgres, campo a campo, com o que ele resolve e o que ele deliberadamente não guarda.

O essencial

  • Trilha de agente não é log de aplicação. Log serve para depurar. Trilha serve para responder quem autorizou, com que dado e com qual efeito, meses depois.
  • Uma linha por ação, não por mensagem. A unidade é a ação com efeito no mundo: gravou, enviou, cobrou, agendou.
  • O custo entra na trilha. Tokens e valor por execução na mesma linha da ação, senão a conta do mês vira mistério em vez de relatório.
  • Dado pessoal não vira histórico eterno. A trilha guarda referência e resumo, não a conversa inteira, e tem prazo de descarte definido.
  • Sem particionamento, a tabela vira problema em um ano. Partição por mês e política de retenção desde o primeiro dia custam quase nada.

Log e trilha não são a mesma coisa

Log de aplicação é escrito para quem está depurando: verboso, descartável, organizado por tempo, apagado em duas semanas. Trilha de auditoria é escrita para quem vai perguntar meses depois: enxuta, imutável, organizada por entidade, guardada por anos. Usar o log como trilha é o atalho que parece funcionar até a primeira auditoria de verdade.

A distinção fica clara na pergunta de teste. “Por que o serviço caiu ontem às 3h” é log. “Quais decisões automáticas afetaram este cliente nos últimos seis meses, e quem as autorizou” é trilha. A segunda pergunta não é respondível varrendo arquivo de texto, e é justamente a que aparece quando o projeto cresce.

Agentes acrescentam uma terceira exigência que nem sistema tradicional tem: a decisão foi tomada por um modelo, e o modelo não é determinístico. Precisa ficar registrado qual modelo, qual versão da instrução, o que ele consultou e o que ele concluiu. Sem isso, não dá para explicar por que a mesma entrada produziu saídas diferentes em dois dias.

As perguntas que a trilha precisa responder

Um esquema de auditoria se projeta de trás para frente, a partir das perguntas que ele terá de responder. Estas são as sete que aparecem em todo projeto, e cada campo do esquema existe para atender pelo menos uma delas.

  • O que o agente fez, em termos de efeito no mundo, não em termos de chamada de função.
  • Sobre qual entidade, para que a busca por cliente, pedido ou contrato seja direta.
  • Com qual autorização, se foi regra automática, permissão prévia ou aprovação de uma pessoa nomeada.
  • Com base em quê, quais fontes foram consultadas antes de decidir.
  • Com qual modelo e qual instrução, incluindo a versão, porque as duas coisas mudam.
  • Quanto custou, em tokens e em dinheiro, por ação.
  • Como reverter, ou ao menos o que precisaria ser feito para desfazer.

O esquema

Uma tabela principal de ações, particionada por mês, e uma tabela auxiliar de aprovações. O desenho abaixo roda igual em Postgres puro e em Supabase, e cabe em uma migração.

create table agente_acao (
  id             bigserial,
  ocorrido_em    timestamptz  not null default now(),
  correlacao_id  uuid         not null,
  agente         text         not null,
  agente_versao  text         not null,
  modelo         text         not null,
  instrucao_hash text         not null,
  acao           text         not null,
  entidade_tipo  text,
  entidade_id    text,
  resultado      text         not null,
  autorizacao    text         not null,
  aprovado_por   text,
  fontes         jsonb        not null default '[]',
  entrada_resumo text,
  saida_resumo   text,
  tokens_entrada integer      not null default 0,
  tokens_saida   integer      not null default 0,
  custo_centavos integer      not null default 0,
  duracao_ms     integer,
  reversivel     boolean      not null default false,
  reversao_ref   text,
  erro           text,
  primary key (id, ocorrido_em)
) partition by range (ocorrido_em);

create index on agente_acao (entidade_tipo, entidade_id, ocorrido_em desc);
create index on agente_acao (correlacao_id);
create index on agente_acao (agente, ocorrido_em desc);
create index on agente_acao (resultado) where resultado <> 'ok';

Os quatro índices não são decoração. O primeiro atende a pergunta do titular de dado e a do auditor, que sempre chegam por entidade. O segundo reconstrói uma execução inteira. O terceiro alimenta relatório por agente. O quarto é parcial e cobre a consulta de incidente sem pagar o custo de indexar as linhas normais, que são a maioria.

Campo a campo, por que cada um existe

Cada coluna corresponde a uma pergunta real que alguém já fez em uma reunião. A tabela abaixo explica a intenção de cada uma, que é a parte que costuma se perder quando outra pessoa herda o projeto.

CampoPara que existeExemplo
correlacao_idAmarra todas as ações de uma mesma execuçãoUma conversa que gerou consulta, decisão e escrita
agente_versaoSaber qual versão do fluxo produziu aquiloatendimento@2026.08.14
instrucao_hashProvar qual instrução estava valendo, sem guardá-la inteiraResumo criptográfico do texto da instrução
acaoO efeito no mundo, em vocabulário do negócioordem_servico.criada
autorizacaoDistinguir regra automática de aprovação humanaregra, previa, humana
fontesO que foi consultado antes de decidirDocumento, consulta ao ERP, histórico
custo_centavosFechar a conta do mês por ação, não por fatura4
reversivelResponder na hora se dá para desfazerVerdadeiro para agendamento, falso para envio
reversao_refO identificador que permite desfazerNúmero do lançamento a estornar
Guardar o resumo criptográfico da instrução, e não o texto, evita transformar a trilha em cópia de propriedade intelectual.

Uma decisão de desenho que costuma gerar discussão: acao usa vocabulário de negócio, não nome de função interna. ordem_servico.criada continua legível daqui a três anos, quando a função que a implementava já terá sido renomeada duas vezes. A trilha precisa sobreviver ao código.

O que nunca gravar

Uma trilha de auditoria mal desenhada vira o maior repositório de dado sensível da empresa, com retenção longa e acesso amplo. É o oposto do objetivo. Existem cinco coisas que não entram, e a disciplina precisa estar no código, não na intenção.

  • A conversa inteira. Guarde referência ao registro original e um resumo curto. O histórico completo tem outro dono, outro prazo e outro nível de acesso.
  • Credencial, token ou chave. Nem no campo de entrada, nem no de erro, que é por onde eles costumam vazar sem que ninguém perceba.
  • Dado sensível por reflexo. Saúde, biometria, origem racial e opinião política têm tratamento próprio na lei e não devem ser copiados para uma tabela de auditoria.
  • O texto completo da instrução. Um resumo criptográfico prova qual versão estava valendo e ocupa 64 caracteres.
  • Documento de identificação por extenso, quando não for necessário. Um identificador interno resolve a maior parte dos casos de rastreio.

Erro comum

Gravar a resposta bruta do modelo no campo de erro “para investigar depois”. É por aí que entram nome, telefone e conteúdo de conversa numa tabela que ninguém revisou sob a ótica de proteção de dados, e que tem retenção de cinco anos.

Volume, partição e retenção

Trilha cresce rápido e cresce sempre. Um agente de atendimento com volume moderado gera de três a seis linhas por conversa, entre consulta, decisão e ação. Vinte mil conversas por mês viram algo entre 60 mil e 120 mil linhas mensais, e o problema não é o espaço em disco: é a consulta que fica lenta e a exclusão que trava a tabela.

3 a 6

linhas de trilha por conversa atendida

1 mês

tamanho de partição que usamos por padrão

< 1 s

alvo para a consulta por entidade

Particionar por mês resolve os três problemas de uma vez. A consulta recente toca uma partição pequena. O descarte de um período vira remoção de partição, que é instantânea, em vez de exclusão linha a linha, que gera bloqueio e inchaço. E a manutenção de índice fica confinada ao período ativo.

Sobre retenção: o prazo é decisão jurídica, não técnica, e precisa estar escrito. O que a engenharia entrega é o mecanismo que cumpre o prazo automaticamente. Uma rotina mensal que cria a partição do mês seguinte e remove a que passou do prazo cabe em vinte linhas e evita que a decisão vire uma tarefa manual esquecida.

Vale antecipar uma dúvida frequente sobre imutabilidade. Não basta prometer que ninguém altera a tabela: a garantia precisa vir do banco. O caminho que usamos é um papel de aplicação com permissão apenas de inserção e de leitura na tabela de ações, sem alteração nem remoção, e a remoção por prazo executada por uma rotina de manutenção separada, que só sabe apagar partição inteira. Com isso, uma linha alterada indevidamente deixa de ser possível por descuido e passa a exigir intervenção deliberada de quem administra o banco, o que já é um evento auditável em outro lugar.

As consultas que valem estar prontas

Trilha que só existe como tabela não é usada. O que a torna útil é ter três ou quatro consultas prontas, com nome, que qualquer pessoa do time consegue rodar sem escrever SQL na hora da urgência.

  1. Histórico de uma entidade. Tudo o que o agente fez sobre um cliente, pedido ou contrato, em ordem. É a consulta que responde ao titular de dado e ao auditor.
  2. Reconstrução de uma execução. Todas as linhas de um mesmo correlacao_id, do gatilho ao efeito. É a consulta de incidente.
  3. Custo por agente e por dia. Soma de custo_centavos agrupada, para que a fatura do mês nunca seja surpresa.
  4. Ações não reversíveis do período. Filtro por reversivel falso, para revisão periódica do que passou sem poder voltar atrás.
  5. Taxa de repasse humano. Proporção entre autorizacao humana e automática, que é o melhor indicador de se a regra de repasse está calibrada.

O que a trilha resolve na LGPD

A Lei Geral de Proteção de Dados dá ao titular o direito de saber com quem seus dados são compartilhados e de pedir revisão de decisões automatizadas que afetem seus interesses. A trilha é o mecanismo que torna essas duas obrigações operáveis, em vez de declarações num documento de política.

ObrigaçãoO que a trilha entregaO que ainda falta
Informar tratamento ao titularHistórico por entidade, em uma consultaProcesso de atendimento ao pedido
Revisão de decisão automatizadaQual decisão, com base em quê, por qual versãoFluxo de contestação com pessoa responsável
Registro de operaçõesQuem fez o quê, quando, com qual autorizaçãoInventário e mapeamento de dados
Resposta a incidenteEscopo do que foi acessado, por correlaçãoPlano de comunicação e prazo de notificação
Descarte após a finalidadeRemoção de partição por prazoDefinição jurídica do prazo
A trilha é infraestrutura de conformidade. Ela não substitui o programa de privacidade, ela o torna executável.

A pergunta do auditor não é se você tem política de governança. É se você consegue mostrar, em vinte segundos, o que o agente fez com o dado daquele cliente.

Aprovação humana e limite de custo

A trilha registra o passado. Duas peças vizinhas controlam o presente, e as três juntas formam a governança que um comitê de risco costuma pedir. A primeira é a aprovação humana em operação sensível. A segunda é o teto de custo.

Aprovação humana funciona melhor como fila do que como bloqueio. O agente prepara a ação inteira, grava a linha com autorizacao pendente, e uma pessoa confirma ou recusa. Preparar antes reduz o tempo da pessoa a um clique informado, o que faz a diferença entre um controle que é usado e um que todo mundo contorna.

Teto de custo precisa existir em dois níveis: por execução e por período. O primeiro impede que um caso patológico consuma o orçamento inteiro numa tarde. O segundo protege o mês. Como custo_centavos já está na trilha, o cálculo do consumido é uma soma, e o corte pode ser automático.

A tabela de aprovações

A segunda tabela guarda o pedido de aprovação e o que aconteceu com ele. Ela existe separada porque tem ciclo de vida próprio: nasce pendente, muda de estado, expira. A tabela de ações é imutável por natureza, e misturar um registro que muda com um que não muda estraga as duas garantias.

create table agente_aprovacao (
  id            bigserial primary key,
  criada_em     timestamptz not null default now(),
  correlacao_id uuid        not null,
  acao          text        not null,
  entidade_tipo text,
  entidade_id   text,
  proposta      jsonb       not null,
  risco         text        not null,
  estado        text        not null default 'pendente',
  decidida_em   timestamptz,
  decidida_por  text,
  motivo        text,
  expira_em     timestamptz not null
);

create index on agente_aprovacao (estado, expira_em)
  where estado = 'pendente';

Três campos merecem explicação. proposta guarda a ação já montada, pronta para executar, e não a intenção genérica: é isso que reduz a decisão humana a ler e confirmar. risco classifica em baixo, médio ou alto, e é o que permite rotear aprovação para papéis diferentes. expira_em existe porque pedido pendente sem prazo vira fila abandonada, e fila abandonada é o começo de todo controle que ninguém respeita.

Quando a decisão sai, a ação correspondente é gravada na tabela principal com autorizacao igual a humana e aprovado_por preenchido. As duas tabelas se encontram pelo correlacao_id, e a reconstrução da execução mostra a proposta, a decisão e o efeito na mesma linha do tempo.

Regra prática

Se a taxa de aprovação de um tipo de ação passa de 95 por cento durante um mês, aquele controle virou carimbo. Ou a regra de risco está calibrada errada, ou a ação pode ser automática com auditoria posterior. Nos dois casos, a decisão é de quem responde pelo processo, e a trilha entrega o número que sustenta a conversa.

Avaliação contínua sobre a mesma trilha

A trilha responde o que aconteceu. A avaliação contínua responde se o que aconteceu estava certo. As duas usam a mesma base, e é essa reutilização que torna a avaliação barata o suficiente para acontecer toda semana em vez de uma vez por trimestre.

O mecanismo é simples. Uma rotina sorteia uma amostra de execuções do período, agrupadas por correlacao_id, e submete cada uma a dois julgamentos: um automático, feito por um modelo com critério escrito, e um humano, sobre uma fatia menor. A concordância entre os dois é o que diz se o julgamento automático pode ser usado sozinho na semana seguinte.

Três indicadores costumam bastar no começo, e todos saem de campos que já existem. A taxa de repasse humano, que indica calibragem da regra de segurança. A taxa de erro por tipo de ação, que localiza onde o fluxo está frágil. E o custo médio por resultado útil, que é o único número que responde se o agente está ficando mais eficiente ou apenas mais falante.

Uma observação de método: avaliação feita apenas sobre os casos que deram errado engana. A amostra precisa incluir execuções normais, senão o time otimiza para o incidente do mês e degrada o comportamento comum sem perceber.

Erros comuns

  • Deixar a trilha para a fase dois. Ela é barata no desenho e cara no retrofit, porque exige reprocessar histórico que não existe.
  • Gravar por mensagem, não por ação. Gera volume enorme e não responde nenhuma das sete perguntas.
  • Permitir alteração e exclusão. Trilha alterável não é prova de nada. Permissão de escrita apenas para inserir, e leitura restrita.
  • Esquecer o custo. Sem valor por ação, a única visão de gasto é a fatura, e a fatura chega tarde demais para corrigir.
  • Não versionar a instrução. Sem saber qual texto estava valendo, o comportamento passado fica inexplicável.
  • Guardar tudo para sempre. Retenção infinita é passivo, não segurança.

Implantação em seis passos

  1. Liste as ações com efeito no mundo. Antes de criar tabela. Se a lista tem mais de vinte itens no primeiro agente, ela está descrevendo funções, não ações.
  2. Crie a tabela particionada e os índices. Com a partição do mês corrente e a do seguinte já criadas.
  3. Instrumente um fluxo só. O de maior volume. Rode uma semana e confira se as sete perguntas são respondíveis.
  4. Revise sob a ótica de dado pessoal. Leia cem linhas reais procurando o que não deveria estar ali. Sempre tem algo.
  5. Escreva as consultas nomeadas. E deixe acessíveis a quem vai precisar delas sob pressão.
  6. Automatize partição e descarte. Rotina mensal que cria a próxima e remove a vencida, com o prazo definido pelo jurídico.

Perguntas frequentes

Preciso de Postgres ou dá para usar outro banco?

O desenho funciona em qualquer banco relacional. Postgres é a escolha por três recursos que facilitam a vida: particionamento por intervalo nativo, coluna JSON com índice e índice parcial. Em SQL Server ou MySQL o mesmo esquema roda com ajustes de sintaxe.

Quanto tempo devo guardar a trilha?

É definição jurídica, não técnica, e varia com o setor e o tipo de dado. O papel da engenharia é entregar o mecanismo que cumpre o prazo escolhido automaticamente. O que não funciona é deixar sem prazo, porque retenção indefinida é passivo de proteção de dados.

A trilha não deixa o sistema lento?

Uma inserção por ação é irrelevante diante do tempo de uma chamada de modelo, que é ordens de grandeza maior. O que fica lento é consulta sobre tabela grande sem partição e sem índice, e é exatamente isso que o desenho deste artigo evita.

Devo guardar o prompt completo?

Não na trilha. Guarde o resumo criptográfico da instrução na linha da ação e mantenha as versões do texto em um repositório versionado. Assim você prova qual instrução estava valendo sem transformar a tabela de auditoria em cópia do seu próprio conteúdo.

Como registrar quando o agente decide não agir?

Com uma linha de ação própria, algo como repasse.humano ou acao.recusada, e o motivo no resumo de saída. A não ação é uma decisão, e é frequentemente a mais importante de auditar, porque é onde a regra de segurança aparece funcionando.

Isso serve para atender um pedido de titular de dado?

Serve como fonte da resposta, não como o processo inteiro. A consulta por entidade devolve o que o agente fez com o dado daquela pessoa. O atendimento ao pedido ainda exige um fluxo definido, com prazo, responsável e formato de resposta ao titular.

Vale usar uma ferramenta pronta de observabilidade de IA?

Vale, para depuração e avaliação de qualidade, que é o papel delas. Para auditoria, o registro precisa estar no seu banco, sob seu controle de retenção e acesso. As duas coisas convivem, e confundir uma com a outra é o que gera surpresa na primeira auditoria.

Próximo passo

Se você já tem um agente rodando, faça o teste mais rápido que existe: escolha um cliente atendido na semana passada e tente listar tudo o que o sistema decidiu sobre ele. Se levar mais de um minuto, a trilha ainda não existe, e ela é o que vai destravar a próxima fase do projeto.

Continuando pelo blog: O handoff é o produto trata da regra de repasse que a trilha registra, e Legado sem API mostra como chegar ao dado que o agente vai consultar.

Fontes e leitura

Quer fazer essa conta com o seu processo? Manda os três números no whatsapp, devolvemos a leitura.