Raias 1 a 6 · arquitetura
Como sair de "um agente por documento" (157) para uma estrutura que sustenta os 157 tipos com 8 especialistas, tools reutilizáveis e skill do tipo como configuração. Ver também: as 20 skills · board da Raia 1 · guia de agentes agno · as 4 camadas de armazenamento.
A Raia 1 tem 157 tipos e 26.036 documentos reais, mas 68% do volume está em 20 tipos e 88% em 40. Um agente por tipo significaria 157 prompts, 157 conjuntos de tools e 157 baterias de teste para cobrir uma cauda de 12%.
A validação, olhando documento por documento, se repete em 8 famílias. O que muda entre tipos da mesma família não é o raciocínio, é a configuração: o que aceitar, quais campos extrair, o que cruzar, quando parar e chamar humano. Então: 8 agentes especialistas + 1 roteador, e o "agente do documento" que a reunião pediu existe como skill do tipo, versionado no banco e editável pelo time no Sandbox.
Uma linha por document_type. É o que o time edita no Sandbox e o que a I.A pré-popula a partir de documentos reais aprovados. O especialista lê a skill em tempo de execução.
-- tabela nova (nosso banco, sem sync com Airtable) document_type_agent_card ( document_type_id int primary key references document_types(id), family text not null, -- identidade | registro_civil | credencial | narrativa -- | merito | financeiro | terceiros | foto accepts jsonb not null, -- formatos e variantes aceitas extract_fields jsonb not null, -- campos a extrair (nome, validade, ano fiscal...) objective_checks jsonb not null, -- checagens que o agente pode concluir sozinho cross_checks jsonb not null, -- cruzamentos com o dossiê (tool sql) translation_rule text not null, -- never | if_not_english | always escalate_when jsonb not null, -- condição -> papel (LA | specialist | attorney) resend_message_pt text not null, -- texto ao cliente, COMP-05 (PT claro) tools_allowed text[] not null, -- whitelist do catálogo version int not null, updated_by uuid, updated_at timestamptz )
Por que tabela e não prompt solto: o prompt fica no agent_prompt_versions por família (governado no Sandbox, com diff e reverter); a skill é o dado do tipo. Trocar o texto de reenvio de um documento não deveria exigir deploy nem versionar prompt.
| Tool | O que faz | Usada pelas famílias |
|---|---|---|
doc.extract_fields | OCR + extração estruturada dos campos declarados na skill | todas |
doc.quality | legibilidade, páginas faltando, corte, borda, rotação, página em branco | todas |
case.sql_lookup | consulta o dossiê (nomes, datas, vínculos, forms já preenchidos) via espelho no backend | todas fato exato |
case.timeline_check | compara datas do documento com a linha do tempo do caso (lacunas, sobreposição) | 1, 3, 6 |
doc.expiry_check | validade do documento contra a data prevista do filing | 1, 6 |
translation.request | abre o fluxo de tradução com prazo próprio (10 dias) e marca o documento | 2, 3, 4, 6 |
aila.requirements | requisitos do tipo de caso e do critério (busca semântica na base AILA) | 4, 5, 7 |
criteria.coverage | quais critérios do caso já estão cobertos e por quais documentos | 5 nova |
issuer.credential_check | confere registro/credencial de quem emitiu o parecer | 7 |
app.request_resend | devolve ao cliente no app com o texto da skill e reabre prazo | todas |
human.escalate | roteia para LA/Specialist/Attorney com o achado pronto e o motivo | todas |
i94.fetch | puxa o I-94 do CBP quando o cliente não tem o arquivo | 1 nova |
Regra: tool nova só entra no catálogo, nunca dentro de um agente. O skill do tipo faz a whitelist. Isso mantém 12 tools para 157 tipos.
Segue o padrão do guia de agentes agno: FastAPI no apps/agno, auth Bearer AGNO_API_KEY, espelho no backend Node com requireIdentity, case_id como escopo.
POST /documents/review { "case_id": 123, "document_id": 456, "document_type_id": 78, "files": ["storage://..."], "mode": "auto" } // auto (chegou do app) | manual (time pediu) | dry_run (sandbox) 200 { "verdict": "ok" | "ressalva" | "rejeitado", "family": "registro_civil", "card_version": 3, "checks": [{ "id":"issuer_official", "pass":true }, { "id":"filiation_matches_claim", "pass":false, "evidence":"mãe: [NOME] no doc vs [NOME] no dossiê" }], "extracted": { "birth_date":"[DD/MM/AAAA]", "issuer":"..." }, "translation_required": true, "next_action": { "type":"escalate", "to":"specialist", "reason":"filiacao_divergente" }, "client_message_pt": "...", // só quando next_action = resend "sources": ["card:v3", "aila:8CFR204.5", "case:dossier"] }
Invariantes: o agente nunca grava status final de aprovação, ele propõe (ai_status/ai_output); quem muda o estado do documento é a ação humana ou a regra objetiva configurada; toda resposta carrega sources para aparecer no painel "Fontes do agente" da tela.
| Situação | Quem resolve | Por quê |
|---|---|---|
| Ilegível, página faltando, tipo errado, documento expirado | agente devolve ao cliente | checagem objetiva, verificável, sem juízo |
| Documento em outro idioma quando o tipo exige tradução | agente abre tradução | regra do tipo, prazo próprio |
| Divergência de nome, data ou filiação contra o dossiê | LA ou Specialist | pode ser erro de digitação ou problema real de vínculo |
| Suficiência de conjunto (bona fide marriage, perseguição) | Attorney | juízo de prova; o agente entrega o mapa do que existe e o buraco |
| Mérito EB (critério regulamentar atendido?) | sempre humano | o agente enquadra e cita a fonte; concluir é do advogado (COMP-06) |
| Overstay, antecedente, indício de fraude | Managing Attorney | red flag: escalonamento imediato, não é erro de documento |
Requisito bloqueante da reunião. O que ela precisa ter, na ordem em que dá valor:
administrative_notes/specialist_notes.dry_run: roda a skill contra os cenários de teste sem gravar nada no caso, com custo e latência por documento.agent_test_runs já existe como base).Critério de corte sugerido para ligar uma família em produção: falso aprovado = 0 no golden set, auto-resolução acima de 50% nos checks objetivos.
| Onda | Família | Volume | Por que nesta ordem |
|---|---|---|---|
| 1 | Identidade e status | 5.432 docs | maior volume, checagem mais objetiva, quase toda auto-resolvível: prova o padrão com risco baixo |
| 1 | Foto (câmera guiada no app) | 549 docs | não é agente, é produto; ganho imediato de 12% para perto de 90% de aproveitamento |
| 2 | Registro civil | 3.322 docs | estreia o fluxo de tradução automática e o cruzamento de filiação |
| 2 | Credencial acadêmica/profissional | 4.026 docs | reusa extração + tradução; entra a regra de credential evaluation (R4) |
| 3 | Narrativa e cartas | 4.071 docs | exige cuidado de PII e mapa de cobertura do conjunto |
| 3 | Financeiro e fiscal | 1.624 docs | extração numérica e consistência entre anos |
| 4 | Terceiros | 646 docs | o ganho real está na fila de cobrança, não na análise |
| 4 | Mérito EB | 2.683 docs | último: depende de AILA madura e nunca conclui sozinho |
| Raia | Volume | Papel do agente | Saída | Tool que só ela precisa |
|---|---|---|---|---|
| 1 · Cliente e terceiros | 157 tipos · 26.036 docs | Validador: recebe upload e julga forma | verdict + checks + campos extraídos | i94.fetch, doc.quality |
| 2 · Peças do escritório | 97 tipos · 7.963 docs | Redator: produz rascunho e revisa contra requisito | texto com origem por afirmação + lista de lacunas | draft.compose, text.anticlone, research.library |
| 3 · Formulários | 85 tipos · 7.826 docs | Preenchedor: monta o form do dossiê e roda os checks | form preenchido + campos sem origem marcados | form.fill, form.version_check |
| 5 · Governo | 17 tipos · 904 docs | Leitor de ofício: extrai prazo e cria a obrigação | prazo com dono + demanda nova (RFE) + aviso | deadline.create, demand.open |
| 6 · Record only | 16 tipos · 404 docs | Indexador: transforma em conhecimento consultável | resumo indexado na base do caso | reusa o pipeline de ingestão (RAG) |
Consequência para o teste: o golden set da Raia 1 é "documento julgado"; na Raia 2 é "peça aprovada pelo Attorney" (avalia-se rascunho, com nota humana); na Raia 3 é "form protocolado sem rejeição"; na Raia 5 é "prazo criado corretamente a partir do ofício". Critério de promoção muda junto: na Raia 5 o pecado capital não é falso aprovado, é prazo não criado.
Quatro níveis, com o nome que o time usa:
| Nível | O que é | Exemplos | Consequência técnica |
|---|---|---|---|
| Raia | quem entrega ou produz o documento | cliente · escritório · formulário · governo · registro | define o papel do agente (validar, redigir, preencher, ler ofício, indexar) |
| Família | o que o caso é | EB · Humanitários · Family · Court | organiza a navegação; é como o advogado pensa |
| Grupo de validação | como o documento se confere | identidade · registro civil · mérito · narrativa | define o agente: um especialista por grupo |
| Documento | o tipo em si | Passport · Birth certificate · I-140 | o skill do tipo (config), não um agente novo |
O grupo existe porque 51% do volume serve todos os tipos de caso. Se o agente fosse por família, teríamos quatro validadores de certidão divergindo com o tempo. Certidão é certidão em EB, Humanitários, Family ou Court.
Court entra como família porque existe caso que nasce judicial, com documentos que não existem em nenhuma outra: habeas corpus (petição, TRO, declarações, EAJA, réplica), apelação ao BIA e as motions de corte. Levantamento na base: 52 tipos e ~1.729 documentos.
| Onde o Court aparece | Tipos | Docs | O que é |
|---|---|---|---|
| Raia 2 · peças do escritório | 45 | 1.452 | HC, TRO, briefs, motions, proof of service |
| Raia 5 · governo | 2 | 130 | ordem do juiz, soltura (release on own recognizance) |
| Raia 1 · cliente | 2 | 105 | evidência para bond: vínculo com o país, origem dos recursos |
| Raia 3 · formulários | 3 | 42 | EOIR-26, EOIR-26A, EOIR-27, I-290B |
E o foro continua existindo como atributo do caso (forum: uscis · eoir · federal_court · consular, com histórico), porque um caso pode mudar de lugar sem mudar de família: o asilo afirmativo referido vira defensivo e segue sendo Humanitários. Os dois eixos convivem; não são a mesma pergunta.
⚠ Cuidado de nome: "Court" (família, o caso judicial) e "EOIR/Corte" (foro, onde tramita) são coisas diferentes e aparecem juntas nas telas. Nos boards isso está marcado explicitamente.
| Ponto levantado | Definição | Onde aparece |
|---|---|---|
| "Qual é o time dele? É um agente só?" | A primeira coisa na ficha do agente é a identidade: solo ou membro de time, com o ID e a versão em uso | aba Identidade & contrato no Studio |
| "Cada agente vai ter um ID, vai ser uma família... agente, documento, raia 1, família 1" | ID hierárquico (agent.legal.doc.raia1.registro_civil) e vínculo tipo de documento → agente gravado no banco, não decidido pelo LLM | bloco "atende estes documentos" |
| "O sistema roda, passa um arquivo que não validou. Como o Joel vai saber que é esse agente aqui para ele mexer?" | Caminho fechado nos dois sentidos: a tela do documento diz quem analisou e abre o agente; o agente lista de onde vieram as chamadas | painel "Quem analisou" na tela do documento + "de onde vêm as chamadas" |
| "O birth certificate poderia chamar o marriage certificate ou não?" | Não. Especialista nunca chama especialista. Outro arquivo vem por ferramenta com escopo por tipo; dependência entre documentos é coordenada por cadeia | bloco "precisa de outro documento?" + cadeia do diploma |
| "Vai ter uma lista de agentes comuns?" | Sim: biblioteca compartilhada (comparador de nomes/datas, leitor OCR, tradutor assistido) que qualquer família pode acionar | categoria Agentes comuns no catálogo e na árvore |
| "Qual o input e o output? Recebe mensagem, um arquivo, um conjunto?" | Contrato explícito por agente: entrada (1 documento · tipo · dados do caso) e saída (resultado + checagens + campos + encaminhamento), em formato fixo | bloco Entrada / Saída |
| "Pode ter memória ou não. Chat tem que ter memória. Tem perfis de agente" | Perfil declarado por agente e os recursos do AGNO ligados/desligados (ferramentas, conhecimento, saída estruturada, memória, histórico, raciocínio) com o motivo de cada um | bloco "recursos do AGNO neste agente" |
| "Primeiro a estrutura, depois o teste" | Teste derivado do contrato: casos reais no banco de teste, 10 a 40 execuções por agente variando o documento | aba Testes (próximo passo) |
document_type_agent_card) com prompt por família no agent_prompt_versions: ou você prefere prompt por tipo também versionado?