Como definir limites, medir qualidade e iniciar um produto de extração sem perder controle
Uma operadora abre a fila de revisão. O extrator preencheu identificador, valor e moeda de uma fatura com aparência impecável. Ela aprova. Só depois percebe que a fatura pertence a outra organização. O texto estava certo; a associação ao tenant estava errada. Em um produto real, isso seria incidente de integridade e privacidade. Esta cena é sintética. Não descreve cliente nem falha observada.
O caso expõe uma ordem ruim de decisões: escolher o extrator antes de definir quem pode ver e alterar o resultado. Nenhuma melhoria de prompt corrige uma fronteira de autorização ausente. A tese deste capítulo é operacional: arquitetura AI-native começa com restrições e consequências verificáveis; autonomia do modelo é uma decisão dentro do sistema. Primeiro decidimos quais propriedades precisam sobreviver a um erro de extração. Depois testamos se IA acrescenta valor para documentos que regras simples não cobrem.
O artefato é o início do RelayOps, um produto didático de ingestão, extração e revisão de documentos entre organizações. Há brief de arquitetura, cenários de qualidade, três ADRs e CLI offline. Tudo começa em ponto zero: sem serviço implantado, piloto, cliente, demanda validada ou benchmark. Os arquivos são proposta e fixture, não evidência de operação.
Antes de desenhar caixas, fixamos um contrato: a identidade do tenant vem de um contexto autenticado controlado pelo servidor. O documento pode declarar a quem pertence, mas essa declaração nunca autoriza acesso. Se divergir do contexto, a importação falha. Um parser por regras propõe campos; um validador rejeita formatos inválidos; todo resultado aceito entra em needs_review. Só uma pessoa autorizada poderá aprovar em uma futura interface.
contexto esperado pela CLI: acme
arquivo de entrada (uma linha por campo):
Tenant: acme
Type: invoice
Invoice ID: INV-001
Amount: 12.00
Currency: USD
resultado: campos com linha e regra de origem; status needs_review
contexto esperado pela CLI: other
arquivo de entrada: examples/fixtures/invoice-valid.txt (declara Tenant: acme)
resultado: contract error: tenant mismatch; nenhuma aprovação
O primeiro caso usa o formato real da fixture e demonstra rastreabilidade local. O segundo testa rejeição quando o tenant esperado diverge do texto; a CLI recebe esse contexto por argumento, não autentica ninguém. Nenhum dos dois prova isolamento em banco, porque ainda não existe banco, API, autenticação, fila ou tela. Esta distinção acompanha a série: evidência de função local não será renomeada como evidência de produto.
Há uma sequência de provas a construir. Primeiro, o teste unitário verifica que extract rejeita o documento de outro tenant e que a proposta válida carrega linha e regra por campo. Depois, uma API precisará derivar tenant_id de sessão autorizada e impedir que request, documento ou modelo o sobrescrevam. Quando houver persistência, teste de integração deverá consultar as duas organizações antes e depois de cada tentativa, inclusive com retry e concorrência. Por fim, um exercício com operador deve mostrar que a revisão apresenta a proposta ao tenant certo e torna visível apenas o original permitido. Cada etapa cobre uma falha distinta. Passar cinco testes de parser hoje só autoriza a primeira afirmação. O desenho registra as demais para que ninguém confunda um objeto JSON correto com integridade de ponta a ponta.
RelayOps serviria a operadores B2B que importam documentos, conferem campos extraídos, corrigem e aprovam. Um gestor de operações seria comprador potencial: quer throughput previsível e custo total controlado. Pessoas e organizações citadas nos documentos recebem as consequências de vazamento, associação incorreta ou retenção longa. A palavra “potencial” importa: não entrevistamos comprador nem validamos demanda.
Um arquiteto de software responde pela estrutura e pelos trade-offs do sistema. Um staff engineer pode liderar decisões transversais e sua execução entre equipes. “AI-native architect” aqui descreve o julgamento exigido quando componentes probabilísticos participam do produto: escolher onde propostas de modelo entram, quais contratos as cercam, como medir tarefa e sistema, quando chamar humano e quem interrompe efeitos. Não é título profissional padronizado nem caminho de promoção. Usar IA para ajudar a projetar diagramas ou ADRs é outra atividade. Ela pode acelerar exploração, mas não transfere responsabilidade por autorização, evidência e operação ao modelo.
A pergunta orientadora não é “qual agente usar?”. É: qual capacidade exige interpretação ambígua e qual limite deve continuar determinístico? No RelayOps, interpretar um documento heterogêneo pode vir a justificar IA. Tenant, permissão, schema, estado, teto de gasto e envio externo não precisam de criatividade. O baseline sem IA também dá comparação: se regras mais revisão humana atendem ao trabalho, adicionar modelo precisa demonstrar ganho líquido.
Uma extração é uma proposta de dados. Seu schema estar válido significa que tipos e campos passaram pela validação. Uma revisão humana significa que alguém aceitou ou corrigiu o conteúdo. Nenhum evento isolado garante que documento pertence ao tenant correto, que valor representa o original, que job não foi perdido ou que custo é aceitável.
Pense em três camadas. Entrada: arquivo e identidade chegam de origens distintas; identidade vem do servidor, conteúdo do documento é dado não confiável. Proposta: regras, e talvez IA no futuro, produzem campos com provenance. Efeito: backend valida transições e grava um item revisável; aprovação humana muda estado. Essa divisão cria pontos de teste. Uma proposta ruim permanece visível; uma proposta que atravessa tenant é negada antes de tocar estado.
O AWS Well-Architected Framework, consultado em 27/09/2026, oferece perguntas para examinar trade-offs de segurança, confiabilidade, custo e operação. Ele não certifica este desenho. O capítulo de SLOs do Google SRE distingue indicador medido de objetivo escolhido. Daí a disciplina aqui: números abaixo são metas didáticas, ainda não resultados. A distinção entre workflow de etapas predefinidas e agente que dirige o processo aparece em Building effective agents, da Anthropic, publicado em 19/12/2024 e reconsultado em 27/09/2026. É orientação conceitual; APIs e tooling atuais exigem verificação própria.
Um requisito como “ser seguro e rápido” não decide arquitetura. Um cenário nomeia estímulo, ambiente, resposta e medida. A tabela é recorte humano de quality-scenarios.json, fonte completa dos cenários. Os números devem ser negociados com usuários e medidos em ambiente que represente a carga; não constituem SLO assumido ou atingido.
| Atributo | Estímulo e ambiente | Resposta esperada | Medida proposta e lacuna |
|---|---|---|---|
| Isolamento | Documento declara tenant B enquanto request autenticada é A | Rejeitar antes da persistência e registrar motivo sem conteúdo sensível | Zero escrita ou leitura cruzada por tentativa no teste adverso; falta API, DB e identidade reais |
| Tempo até revisão | 100 imports/h de faturas por uma hora | Mostrar item needs_review | p95 ≤120 s entre recibo e item visível, entre todos os imports aceitos; meta não medida |
| Perda de jobs | Worker falha após confirmação, com 1.000 imports sintéticos aceitos | Reprocessar ou sinalizar dead-letter | Zero jobs sem estado após reconciliação; fila durável ainda não existe |
| Recuperação | Worker reinicia durante job com mesma chave de idempotência | Retomar com um item revisável | Reconciliação em até 15 min, zero aprovações duplicadas; meta não medida |
| Qualidade de extração | Ao menos 100 documentos sintéticos rotulados e adjudicados | Campos rastreáveis ou fallback explícito | Precisão por campo ≥0,95 nos suportados e fallback 100%; metas não medidas |
| Gasto máximo | Tenant alcança teto didático durante mês sintético | Não iniciar nova chamada paga; manter revisão | US$ 100 por tenant/mês, somando processamento cobrado e estimativa de revisão em todos os documentos aceitos; meta provisória, sem aprovação ou medição |
Para cada medida, precisamos definir denominador, unidade, janela e método. “p95 em cinco documentos escolhidos à mão” teria pouco poder de decisão. “Zero erros” em fixtures também não provaria taxa de erro em documentos novos. Antes de estabelecer promessa externa, um piloto consentido precisa observar tipos de documento, duração da revisão, correções, gastos e incidentes, com logs minimizados.
O contexto mínimo mostra quem interage e quem é afetado. O desenho é proposta de arquitetura, não implantação.
No recorte de containers, a request síncrona autentica, autoriza, valida formato e devolve recibo. Extração é assíncrona porque pode levar mais tempo e sofrer retry. Intervenção humana é transição distinta; não deve ocorrer por completion do modelo.
Fronteira 1: operador → API. Credenciais e tenant autenticado vêm do servidor; texto do documento não tem autoridade. Fronteira 2: API → fila. Job carrega tenant atribuído pelo servidor, checksum e chave de idempotência futura. Fronteira 3: worker → store. Resultado é proposta; backend confere tenant, schema, versão e estado antes de gravar. Fronteira 4: revisão humana → aprovação. Permissão da pessoa, versão do item e mudança de estado são verificadas na transação. A CLI deste capítulo cobre só parte da terceira fronteira, em memória. Na produção, o isolamento precisa de testes com duas organizações, controle de acesso no banco, consulta escopada e observabilidade redigida.
O exemplo em examples/baseline.mjs usa Node.js 22+ e bibliotecas nativas. O README do exemplo registra ambiente verificado e comandos. Não há install, lockfile, chave de API nem rede porque não há dependência externa. O parser recebe texto Key: value; ele não é OCR, não lê PDF e não interpreta layouts arbitrários. Sua simplicidade é vantagem experimental: podemos enxergar quais erros a regra detecta antes de medir valor incremental de um modelo.
node --test examples/check-contracts.test.mjs
node examples/baseline.mjs examples/fixtures/invoice-valid.txt acme
node examples/baseline.mjs examples/fixtures/invoice-invalid.txt acme
node examples/baseline.mjs examples/fixtures/purchase-order.txt acme
Estes são comandos reproduzíveis, não transcrição de uma execução deste artigo. O teste e a verificação da sessão ficam no relatório de verificação do capítulo. O segundo argumento representa tenant autenticado, fornecido por caller confiável neste toy. Na aplicação, uma API teria de derivá-lo da autenticação e checar autorização. Passá-lo manualmente pela CLI não reproduz essa fronteira.
Uma fatura válida resulta em needs_review, campos invoice_id, amount, currency e provenance por linha/regra. Uma linha fora do contrato retorna contract error e status de processo diferente de zero. Um purchase_order pode ter tenant e tipo válidos, mas o extrator não conhece seus campos: retorna needs_review, fields: {} e issue “unsupported document type”. Esse fallback explícito é preferível a preencher campos plausíveis sem sustentação.
{
"tenant": "acme",
"documentType": "purchase_order",
"status": "needs_review",
"fields": {},
"issues": ["unsupported document type: purchase_order"],
"provenance": {}
}
O output acima ilustra o contrato para a fixture correspondente; confira o output real ao executar. Uma string de moeda de três letras valida formato, não existência ou adequação da moeda. Um número com duas casas valida sintaxe, não soma de itens nem preço. Provenance de linha demonstra de onde veio o texto, não que o documento seja verdadeiro. Em um produto, revisão deve apresentar original ao lado da proposta, oferecer correção e preservar versão auditável.
Ainda faltam autenticação real, upload seguro, fila durável, idempotência, store transacional, política de retenção, consentimento para piloto, controle de acesso, redaction em logs e operador de plantão. Também falta conjunto rotulado que represente documentos reais permitidos. Uma suíte verde da CLI verifica contrato local; não mede tempo até revisão, perda de jobs ou qualidade de IA. Essa lacuna determina as próximas entregas, em vez de ser escondida por diagrama.
O ADR-001 escolhe regras para faturas estreitas e revisão humana. Alternativas são usar IA desde a primeira importação ou fazer apenas digitação manual. Regras custam manutenção por tipo documental e não cobrem variação grande; a via manual custa tempo do operador. IA tem custo variável e pode ampliar cobertura, mas acrescenta avaliação, tratamento de dados e risco de saída incorreta. Gatilho de revisão: medir share de documentos não suportados, tempo de correção e erro por campo em conjunto consentido. Se a regra criar trabalho demais e uma proposta de IA melhorar tarefa com orçamento e integridade preservados, experimentar IA atrás do mesmo contrato. Rollback: desligar proposta IA, manter baseline e fila de revisão. Não existe medição que já justifique a troca.
O ADR-002 prefere fronteiras de módulo claras em API/worker e store inicialmente simples, em vez de serviços independentes. Serviços permitem escalar partes e equipes separadamente; cobram deploy, rede, contratos distribuídos e operação mais complexa. Um monólito pode sofrer contenção entre importação e extração. Gatilho de revisão: em carga representativa, medir p95 do recibo, fila, uso de recursos e falhas correlacionadas; separar serviço só quando isolamento de escala ou falha resolver gargalo comprovado melhor que worker separado ou ajuste de capacidade. Reversibilidade exige mensagens versionadas e contratos de módulo estáveis. Nenhum gráfico de carga foi observado.
O ADR-003 reserva ao backend tenant, auth, schema, transições, orçamento e efeitos; ao humano, aprovação. Um workflow fixo classificar → extrair → validar → revisar cobre o começo. Um agente com escolha dinâmica de ferramentas só faria sentido se uma tarefa variável demonstrar ganho em evals e houver limites de passos, tempo, permissões e custo. A alternativa de aprovação automática reduziria trabalho humano, mas elevaria risco justamente no ponto de consequência. Gatilho de revisão: comparar propostas com revisão cega e taxas de correção por categoria; jamais inferir integridade sistêmica de score de modelo. Rollback: interromper chamadas de modelo e manter itens pendentes. O artigo da Anthropic ajuda a nomear workflow e agente; não prescreve autonomia para RelayOps.
Cada ADR contém opções rejeitadas, custo, reversibilidade e condição de revisão. Documento de decisão vale se mudar uma escolha futura diante de evidência; sem esse gatilho, ele vira histórico decorativo.
1. Diagrama sem critério de decisão. Sintoma: caixas de API, fila e banco recebem setas, mas ninguém sabe qual problema exige fila ou quando desmembrar serviço. Causa: confundir representação com decisão. Resposta: anexar cenário ao componente. Aqui, fila responde a importação confirmada que não pode se perder; ainda precisa teste de ack/retry. Se o teste mostrar processamento síncrono suficiente em carga validada, a fila pode esperar. O operador se importa com recibo confiável e item visível, não com número de caixas.
2. IA escolhida antes dos requisitos. Sintoma: equipe compra modelo e só depois pergunta como tratar documento que ele não entende. Causa: tomar flexibilidade linguística por requisito. Resposta: executar baseline, rotular tipos não suportados, medir custo de revisão e erro por campo. IA entra como hipótese para reduzir trabalho mensurado. Também pode não entrar: se maioria do fluxo couber em regras com revisão rápida, custo de integração pode superar benefício.
3. Qualidade do modelo confundida com integridade do sistema. Sintoma: demos mostram valor e ID corretos enquanto tenant ou versão estão errados. Causa: avaliar resposta isolada e omitir fronteiras. Resposta: testes adversos de associação cruzada, transições ilegais, duplicata e falha após ack; revisão humana para conteúdo; schema e provenance separados de precisão. Um modelo ótimo ainda pode alimentar store que aceita chave errada. Uma API segura ainda pode mostrar valores errados que humanos precisam corrigir. Métricas de ambas as camadas permanecem distintas.
4. Arquitetura sem orçamento ou responsabilidade operacional. Sintoma: plano tem chamadas ilimitadas, sem owner para teto, incidentes ou retenção. Causa: custo e operação tratados como pós-escrito. Resposta: definir teto por tenant e por janela antes de chamada paga; estimar também tempo de revisão, armazenamento e investigação. Nomear quem ajusta o limite, quem recebe alerta, quem interrompe processamento e como reprocessar após falha. Sem esses donos, um desenho “escalável” só escala conta e fila de erros.
O brief mantém uma tabela de hipótese, teste discriminante, owner e risco. Ela estabelece ordem de execução. Primeiro, exercitar documento com tenant divergente e provar rejeição local. Depois, implementar autenticação e store e repetir o ataque com duas identidades reais. Em paralelo, construir lote sintético rotulado para comparar regras e revisão; só depois buscar documento consentido de piloto. Medir latência do recibo até item visível em uma janela definida. Injetar falha entre confirmação e persistência, reconciliar jobs. Simular teto sem cobrança real. Por fim, testar carga que diferencia modularidade interna de serviços.
O protocolo de avaliação precisa de duas folhas. Qualidade da tarefa: documentos elegíveis, campo correto contra rótulo adjudicado, tempo humano de correção, documento enviado para revisão. Integridade do sistema: zero acesso cruzado nos testes, duplicatas, jobs sem terminal, transições inválidas, custo por tenant. Um stub pode avaliar runner e contrato, nunca precisão de modelo real. Dados de fixture sintética ajudam a reproduzir bugs; não representam diversidade do mercado.
Se uma medida falhar, ela deve alterar uma decisão concreta. Alta taxa de não suporte pode reabrir ADR-001. p95 ruim sob worker saturado pode reabrir ADR-002. Correções frequentes e alto custo podem manter ADR-003 mais restritivo. Se amostra for pequena ou desbalanceada, não há conclusão: aumentar a amostra ou mudar o teste, sem preencher a lacuna com opinião.
No custo, separar tarifa de provider, compute, storage e minutos de operador. Preço de modelo é mutável; qualquer simulação futura precisará data, moeda, unidade de cobrança, taxa de cache e sensibilidade por volume. Sem piloto, “custo por documento” é cenário, não dado. A regra de teto pertence ao backend: se orçamento acabar, item permanece revisável por humano, sem tentativa automática de burlar limite.
Na segurança, usar só fixtures sintéticas neste capítulo. Em piloto futuro: obter consentimento explícito, reduzir PII coletada, redigir logs, decidir retenção e deleção, testar isolamento em consulta e cache, registrar acesso por finalidade. Não declaramos compliance. Se um documento contiver instruções para o modelo, elas são conteúdo não confiável, jamais autorização. O backend não deve aceitar tenant escolhido em texto ou chamada de ferramenta do modelo.
Na reversibilidade, manter baseline, versionar schema/proposta, gravar origem e separar side effects. Desligar IA precisa resultar em fila needs_review, não em perda de trabalho. Aprovação e envio externo são passos distintos; este capítulo não envia nada. Para voltar de deploy futuro, é preciso saber quais documentos foram processados por qual versão, quais foram aprovados e quais efeitos ocorreram. O código local ainda não implementa esse ledger.
Escreva um cenário para uma pessoa autenticada no tenant acme que envia documento com Tenant: other. Inclua estímulo, ambiente, resposta e medida. Critério: outra pessoa consegue transformar seu texto em teste que verifica rejeição e ausência de escrita para ambos os tenants.
Solução comentada: “Dada API autenticada como acme e store com duas organizações; quando importação declara other; API responde erro de contrato antes de enfileirar; contador de writes em acme e other permanece zero para este request.” Na CLI atual, o teste possível é só rejeição sem store: node examples/baseline.mjs examples/fixtures/invoice-valid.txt other usa a fixture com Tenant: acme e espera other como contexto, portanto falha. Para provar zero escrita, implemente e instrumente store em capítulo posterior. Não trate ausência de banco como teste de banco aprovado.
Adicione fixture sintética com Tenant: acme e Type: purchase_order, ou outro tipo desconhecido. Execute a CLI e confirme status: needs_review, fields: {} e issue que nomeia tipo. Critério: o processo não inventa campos de fatura e não aprova item automaticamente.
Solução comentada: examples/fixtures/purchase-order.txt serve de entrada existente. Rode o comando documentado no README. O ramo type !== 'invoice' devolve issue explícita. Isso é fallback de parser, não prova que um operador conseguirá resolver o documento sem interface e treinamento. Para estimar valor, rotule um lote de pedidos e meça tempo de revisão manual.
Defina um envelope de carga e um teste que poderia mostrar que ADR-002 está errado. Critério: declare volume, duração, p95 de importação, backlog, CPU/memória, falhas correlacionadas, limiar de decisão e alternativa mais barata a testar antes da separação.
Solução comentada: exemplo hipotético: “Em ensaio de uma hora com 20 imports/s de fixtures sintéticas e dois workers, se p95 do recibo exceder 500 ms por contenção de CPU da extração, apesar de pool separado, avaliar serviço de worker independente.” Valores são hipóteses didáticas, não throughput observado. Verifique se desacoplar processo/worker dentro do mesmo deploy e limitar concorrência resolvem. Serviços passam a ser escolha quando teste repetido, custo operacional e ownership tornam a separação melhor. Não use o número inventado como benchmark do RelayOps.
Tenant: organização cujo contexto determina acesso a dados. Provenance: origem rastreável de um campo, como linha e regra. ADR: registro de decisão com alternativas e gatilho para reabrir. SLI: indicador medido; SLO: valor alvo para um indicador. Idempotência: repetir operação sem duplicar efeito. Trust boundary: ponto em que dados cruzam níveis diferentes de confiança ou permissão.
O resultado deste capítulo é uma arquitetura que pode ser contrariada por testes. O próximo capítulo aprofunda identidade e isolamento: tenant e documento passam a existir em transação real, e o ataque sintético de associação cruzada deixa de ser apenas argumento em texto. A página da série organiza a sequência; o link do próximo capítulo é previsto, não prova de publicação. Até lá, a decisão mais valiosa continua disponível offline: uma extração pode ser útil sem receber poder de aprovação, acesso ou gasto.
Uma revisão de arquitetura honesta também precisa registrar o que faria esta proposta mudar. Se os documentos reais, recebidos com consentimento, tiverem formatos fora do parser, a alternativa sem IA continua útil como controle, mas seu alcance será medido por tipo e por campo. Se a fila projetada não reduzir tempo de resposta sob carga representativa, o desenho deve ser simplificado. Se o limite financeiro bloquear revisão necessária, o orçamento e o fluxo manual precisam ser renegociados com operações antes de ativar novas chamadas. Se o teste de isolamento em persistência falhar, nenhum resultado de extração justifica o piloto. O próximo ADR deve nascer dessa evidência, com dono e data de revisão, em vez de preservar componentes por apego ao diagrama.
Produtos gratuitos e pagos para transformar ideias em uma base que você consegue executar.
13 produtos disponíveisContinue explorando tópicos similares
Um diagrama de microsserviços aparece antes de qualquer medição operacional. O capítulo final da série AI-native Architect usa uma simulação de tempo virtual para testar a ordem de atendimento por…
Um deploy do RelayOps reduz erros HTTP e, na mesma semana, aumenta o número de extrações erradas aceitas como corretas. O capítulo 5 constrói dataset versionado, runners determinísticos, graders,…
Um documento pede, em texto puro, para o próprio agente exportar o arquivo do tenant e se autopromover. A defesa óbvia — instruir o modelo a recusar — roda na camada errada. O capítulo 7 constrói…
Checklist de 47 pontos para encontrar bugs, riscos de segurança e problemas de performance antes do lançamento.
Templates testados em produção, usados por desenvolvedores. Economize semanas de setup no seu próximo projeto.