Artefatos
Artefatos
O inventário do que precisa existir em disco, em banco e em rede para uma empresa rodar como Cognitive Enterprise. Não é lista de ferramentas — é lista de arquivos, tabelas e endpoints que alguém tem que criar e manter.
Os caminhos abaixo seguem uma organização de apadrinhamento — o mesmo caso que atravessa o treinamento. Em outra empresa mudam os nomes, não a estrutura.
01
Contexto raiz
O que todo agente lê antes de qualquer tarefa
Se um agente só pudesse ler três arquivos antes de trabalhar, seriam estes. É a camada mais barata de construir e a que mais muda o resultado.
- md
CLAUDE.mdO contexto que todo agente carrega antes de qualquer tarefa: o que a organização é, como se trabalha aqui, o que nunca se faz.
Declara que a organização atende crianças em vulnerabilidade, que dado de menor não sai da sede, e que o tom nunca é de pena.
▸Ver exemploOcultar exemplo
# Organização de apadrinhamento — contexto para agentes ## O que somos Conectamos padrinhos a crianças em comunidades atendidas. O produto não é a doação: é o vínculo. Ele se sustenta na correspondência anual entre criança e padrinho. ## Como se trabalha aqui - Toda afirmação sobre uma criança vem de um relatório de campo. Nunca de inferência. - Quando faltar dado, escale. Não complete. - Specs em `specs/`. Prompts em `agentes/`. Nada de instrução solta em conversa. ## O que nunca se faz - Publicar endereço, nome da escola ou sobrenome de criança. Sem exceção. - Enviar qualquer coisa a um padrinho sem passar pelo gate de `gates.yaml`. - Representar uma criança pela carência dela. Ver `tom-de-voz.md`. ## Onde olhar primeiro `ontologia.md` para saber o que as palavras significam · `politicas/` para as regras duras · `skills/` para o passo a passo de cada tarefa. - md
AGENTS.mdA mesma coisa em formato neutro, para agentes de outros fornecedores. Um arquivo, vários leitores.
Aponta para o CLAUDE.md em vez de duplicar conteúdo.
▸Ver exemploOcultar exemplo
# Agentes neste repositório Este arquivo existe para agentes que não leem `CLAUDE.md`. O conteúdo canônico é o `CLAUDE.md` — mantenha um só, referencie o outro. @CLAUDE.md ## Comandos - `python3 evals/rodar.py` — suíte de qualidade (obrigatória antes de qualquer merge) - `python3 build.py` — regera artefatos derivados ## Limites deste repositório Sem credencial de produção. Sem acesso a `dados/financeiro/`. Ações irreversíveis exigem aprovação humana registrada. - config
.claude/settings.jsonPermissões, hooks, modelo padrão e limites. O harness em formato de configuração, versionado.
Bloqueia escrita no cadastro, exige aprovação para envio, teto de 6 iterações.
▸Ver exemploOcultar exemplo
{ "permissions": { "allow": ["Read(./**)", "Bash(python3 evals/*)", "WebFetch(domain:docs.internos)"], "deny": ["Read(./dados/financeiro/**)", "Bash(curl:*)", "Write(./producao/**)"] }, "hooks": { "PreToolUse": [ { "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "python3 guardrails/sem_dados_sensiveis.py" }] } ] }, "env": { "MAX_ITERACOES": "6", "MODELO_PADRAO": "modelo-rapido" } } - md
identidade.mdMissão, princípios e o que a organização recusa fazer. É o System 5 do VSM em arquivo.
"Nunca representamos uma criança pela carência dela."
▸Ver exemploOcultar exemplo
# Identidade ## Missão Que cada criança apadrinhada tenha um adulto no mundo acompanhando o crescimento dela. ## Princípios 1. A criança é sujeito, não beneficiária. Ela aparece pelo que faz, não pelo que falta. 2. O padrinho merece a verdade. Carta bonita e imprecisa é pior que carta simples e exata. 3. Dado de menor de idade é responsabilidade, não ativo. ## O que recusamos - Usar imagem ou história de criança em campanha de captação sem consentimento vigente. - Prometer ao padrinho qualquer resultado sobre a vida da criança. - Automatizar qualquer etapa cujo erro a criança pague. - md
tom-de-voz.mdComo a organização escreve, com exemplos aprovados e reprovados lado a lado.
Três cartas exemplares e três reprovadas, cada uma com o motivo da reprovação.
▸Ver exemploOcultar exemplo
# Tom de voz na correspondência Escrevemos na voz da criança, em primeira pessoa, com vocabulário compatível com a idade. ## Aprovado > "Este ano entrei para o time de vôlei da escola. Ainda erro muito o saque, > mas a professora disse que eu melhorei bastante." Por quê: fato do relatório, voz da criança, progresso sem exagero. ## Reprovado > "Graças à sua generosidade, hoje eu tenho a oportunidade de estudar." Por quê: coloca o padrinho como salvador e a criança como carente. Fere o princípio 1 de `identidade.md`. ## Reprovado > "A Ana adora jogar futebol e sonha em ser jogadora profissional." Por quê: nada disso está no relatório. Invenção, mesmo que simpática, é erro grave. - md
memoria/*.mdO que os agentes aprenderam e vale para as próximas sessões. Um fato por arquivo.
"Irmãos só são mencionados se aparecerem no relatório do ano corrente."
▸Ver exemploOcultar exemplo
--- tema: correspondencia registrado_em: 2026-03-14 por: marina --- Irmãos só são mencionados na carta se aparecerem no relatório de campo **do ano corrente**. Motivo: em março de 2026 uma carta citou um irmão que havia saído do programa, e o padrinho perguntou por ele. Não temos como responder. Vale para: todas as tarefas de redação. Já está refletido em `skills/carta-apadrinhamento/SKILL.md`.
02
Fundação semântica
O que a empresa é, num formato que máquina lê
Esta é a camada que trava projeto em empresa tradicional. O conteúdo não é difícil, mas ninguém nunca escreveu.
- md
ontologia.mdO mapa das entidades do negócio e como se relacionam.
Estabelece que "criança apadrinhada", "criança atendida" e "criança de família atendida" são três entidades diferentes que o relatório chama igual.
▸Ver exemploOcultar exemplo
# Ontologia ## Criança Três entidades distintas que o relatório de campo chama pelo mesmo nome: | Entidade | Definição | Tem padrinho? | |---|---|---| | `crianca_apadrinhada` | Vinculada a um padrinho ativo | sim | | `crianca_atendida` | Participa dos programas, sem vínculo | não | | `crianca_familia` | Irmão de atendida, alcance indireto | não | Só `crianca_apadrinhada` gera correspondência. ## Padrinho Pessoa física com apadrinhamento ativo. **Todo padrinho é doador; nem todo doador é padrinho.** Doador sem vínculo nunca recebe carta. ## Apadrinhamento Relação entre `padrinho` e `crianca_apadrinhada`, com início, status e (às vezes) fim. É a entidade que morre quando o vínculo acaba — a criança continua existindo. ## Relatório de campo Registro anual feito pelo educador. **É a única fonte de fato sobre a criança.** Nada entra numa carta sem estar aqui. - md
glossario.mdTermos, sinônimos e — o mais importante — o que eles não significam.
Todo padrinho é doador; nem todo doador é padrinho.
▸Ver exemploOcultar exemplo
# Glossário **Padrinho** — pessoa com apadrinhamento ativo. *Não confundir com:* doador (contribui sem vínculo), mantenedor (pessoa jurídica). **Carta** — peça anual da criança para o padrinho. *Não confundir com:* comunicado (institucional), recibo (fiscal). **Desligamento** — fim do vínculo por mudança, idade ou decisão da família. *Não confundir com:* inadimplência (o padrinho parou de pagar; o vínculo segue 90 dias). **Educador de campo** — quem visita e escreve o relatório. *Não confundir com:* voluntário de sede (transcreve, não observa). - dados
schema.sqlA ontologia materializada em tabelas, com chaves, restrições e histórico.
crianca,padrinho,apadrinhamento,relatorio_campo,carta,envio.▸Ver exemploOcultar exemplo
create table crianca ( id uuid primary key, nome text not null, nascimento date not null, comunidade_id uuid not null references comunidade(id), tipo text not null check (tipo in ('apadrinhada','atendida','familia')), status text not null check (status in ('ativa','desligada')), desligada_em date ); create table apadrinhamento ( id uuid primary key, crianca_id uuid not null references crianca(id), padrinho_id uuid not null references padrinho(id), inicio date not null, fim date, unique (crianca_id, padrinho_id, inicio) ); create table relatorio_campo ( id uuid primary key, crianca_id uuid not null references crianca(id), ano int not null, educador_id uuid not null references educador(id), frequencia_escolar numeric(4,1), observacoes text, unique (crianca_id, ano) -- um relatório por criança por ano ); - md
politicas/*.mdUma regra de negócio por arquivo, estruturada: campo, motivo, exceção, responsável.
lgpd-menores.md— endereço, escola e sobrenome nunca saem da sede.▸Ver exemploOcultar exemplo
--- politica: lgpd-menores versao: 3 responsavel: juridico vigente_desde: 2025-08-01 --- # Dados de menor não saem da sede ## Regra Os campos abaixo **nunca** aparecem em conteúdo que sai da organização: | Campo | Onde vive | Motivo | |---|---|---| | `crianca.endereco` | cadastro | localização de menor | | `crianca.escola` | relatório | localização indireta | | `crianca.sobrenome` | cadastro | identificação | ## Exceção Uma só: intimação judicial, respondida pelo jurídico. Nunca por agente. ## Como isto é cumprido Não por prompt. Por código: `guardrails/sem_dados_sensiveis.py` recusa a saída. - md
catalogo-de-dados.mdOnde cada dado mora, quem é o dono e qual a classificação de sensibilidade.
Foto da criança: bucket privado, dona é a coordenação de programa, sensibilidade alta.
▸Ver exemploOcultar exemplo
# Catálogo de dados | Dado | Onde mora | Dono | Sensibilidade | Quem lê | |---|---|---|---|---| | Cadastro da criança | `postgres.crianca` | Coord. de programa | alta | agente redator (campos públicos) | | Foto anual | `s3://fotos/` (privado) | Coord. de programa | alta | ninguém automatizado | | Relatório de campo | `postgres.relatorio_campo` | Coord. de campo | média | agente redator | | Dados do padrinho | `postgres.padrinho` | Captação | alta | agente de envio | | Financeiro | `postgres.doacao` | Financeiro | alta | nenhum agente | | Cartas geradas | `postgres.carta` | Coord. de programa | média | agente verificador | Classificação **alta** implica: acesso nominal, registro em audit log, revisão trimestral. - config
eventos.yamlO vocabulário de eventos do negócio: o que acontece e o que cada coisa dispara.
relatorio.recebido,carta.gerada,carta.aprovada,carta.enviada.▸Ver exemploOcultar exemplo
eventos: relatorio.recebido: payload: { crianca_id: uuid, ano: int, origem: enum[app_campo, digitalizacao] } dispara: [tarefa.triar-relatorio] carta.gerada: payload: { carta_id: uuid, crianca_id: uuid, agente: string, versao_prompt: string } dispara: [tarefa.verificar-carta] carta.reprovada: payload: { carta_id: uuid, criterio: string, detalhe: string } dispara: [tarefa.reescrever-carta, gate.revisao-humana] carta.enviada: payload: { carta_id: uuid, enviada_em: timestamp, aprovada_por: string } dispara: [] # terminal e irreversível
03
Dados
Onde a verdade mora
Agente não inventa quando tem onde consultar. Cada linha aqui existe para responder a uma pergunta que o agente vai fazer.
- dados
Banco transacionalA verdade operacional, com histórico e não só o estado atual.
12 mil crianças, 8 mil padrinhos, 40 mil relatórios de campo acumulados.
▸Ver exemploOcultar exemplo
-- A pergunta que o agente faz antes de escrever qualquer carta. select c.id, c.nome, extract(year from age(c.nascimento)) as idade, r.frequencia_escolar, r.observacoes, a.inicio as apadrinhado_desde from crianca c join apadrinhamento a on a.crianca_id = c.id and a.fim is null join relatorio_campo r on r.crianca_id = c.id and r.ano = 2026 where c.id = $1 and c.status = 'ativa'; -- Sem linha de retorno, o agente NÃO escreve: ele escala. -- Criança desligada, relatório ausente e vínculo encerrado caem todos aqui. - dados
Índice vetorialO acervo pesquisável: documentos, políticas, histórico por entidade.
Os relatórios dos últimos três anos de cada criança, indexados para recuperação.
▸Ver exemploOcultar exemplo
# Indexação: um documento por relatório, com metadado que permite filtrar antes de buscar. colecao.upsert( id=f"relatorio:{r.crianca_id}:{r.ano}", texto=r.observacoes, metadados={"crianca_id": str(r.crianca_id), "ano": r.ano, "sensibilidade": "media", "tipo": "relatorio_campo"}, ) # Recuperação: SEMPRE filtrada por criança. Busca semântica solta, # num acervo de 40 mil relatórios, traz a criança errada com texto convincente. trechos = colecao.buscar( consulta="progresso escolar e atividades", filtro={"crianca_id": str(crianca_id), "ano": {"$gte": 2024}}, k=5, ) - dados
Object storageO que não cabe em banco: fotos, PDFs, digitalizações, áudios.
As fotos anuais de cada criança e os relatórios manuscritos escaneados.
▸Ver exemploOcultar exemplo
s3://apadrinhamento/ ├── fotos/ │ └── {crianca_id}/{ano}.jpg privado · url assinada · 15 min ├── relatorios-digitalizados/ │ └── {crianca_id}/{ano}.pdf privado · entrada de OCR └── cartas/ └── {carta_id}/ ├── rascunho.md versão do agente ├── evidencia.json claim → fonte, da auto verificação └── final.pdf gerado só após o gate Regra: nada aqui é público. Toda leitura passa por URL assinada e fica no audit log. - dados
golden/Os pares entrada / saída-esperada que servem de gabarito oficial.
200 cartas aprovadas com o relatório que as originou, sendo 30 casos difíceis escolhidos de propósito.
▸Ver exemploOcultar exemplo
golden/ ├── 001-padrao-simples/ │ ├── entrada.json relatório de campo completo, criança ativa │ ├── esperado.md carta aprovada pela coordenação em 2024 │ └── porque.md "caso base: se este falhar, tudo falhou" ├── 031-mudou-de-cidade/ │ ├── entrada.json relatório aponta comunidade diferente do cadastro │ ├── esperado.md carta que não menciona a mudança │ └── porque.md "o agente inventava despedida. Incidente #14, mar/2026" └── 047-relatorio-contraditorio/ ├── entrada.json frequência 95% e observação "faltou muito" ├── esperado.md ESCALAR — nenhuma carta é resposta correta aqui └── porque.md "aceitar contradição em silêncio é o pior modo de falha" 30 dos 200 casos são difíceis de propósito. São eles que dão valor ao conjunto. - dados
baseline/A medição do processo antes da automação, datada e assinada.
80 cartas manuais: 25 min cada, 3,2% de erro factual, 8% de retrabalho, 11 dias de fila.
▸Ver exemploOcultar exemplo
medido_em,amostra,metrica,valor,unidade,fonte 2026-01-20,80,tempo_por_carta,25.0,minutos,cronometragem em 4 turnos 2026-01-20,80,erro_factual,3.2,percentual,revisão cega por 2 coordenadoras 2026-01-20,80,retrabalho,8.0,percentual,cartas devolvidas pela revisão 2026-01-20,80,fila_alta_temporada,11.0,dias,fila média de novembro/2025 2026-01-20,80,custo_por_carta,9.30,BRL,horas × custo médio da hora - dados
Camada analíticaTabelas de leitura para painel e para o agente que analisa a própria operação.
Cartas por mês, custo por carta, taxa de escalada por idioma.
▸Ver exemploOcultar exemplo
create view v_cartas_mes as select date_trunc('month', c.criada_em) as mes, c.idioma, count(*) as cartas, avg(c.custo_brl) as custo_medio, sum(case when c.escalou then 1 else 0 end)::float / count(*) as taxa_escalada, avg(extract(epoch from (c.aprovada_em - c.criada_em))/3600) as horas_ate_aprovacao from carta c group by 1, 2; -- É desta view que sai o painel de custo e a comparação com o baseline. -- O agente que analisa a própria operação lê daqui, não da tabela crua.
04
Interfaces
Como o software da empresa é alcançado
Sistema sem interface programática não participa da operação agêntica. Aqui é onde a maioria das empresas descobre a própria dívida técnica.
- api
GET /criancas/{id}Leitura da ficha, devolvendo só o mínimo necessário para o perfil que pediu.
Devolve nome, idade e status no programa — nunca endereço nem escola.
▸Ver exemploOcultar exemplo
GET /criancas/9f3c…?perfil=redacao Authorization: Bearer <token do agente redator> 200 OK { "id": "9f3c…", "nome": "Ana", "idade": 11, "tipo": "apadrinhada", "status": "ativa", "apadrinhada_desde": "2023-03-01", "comunidade": "Vale Verde" } - api
GET /relatorios?crianca=&ano=O insumo da carta, filtrado por criança e período.
Traz frequência escolar, atividades e observações do educador de campo.
▸Ver exemploOcultar exemplo
GET /relatorios?crianca=9f3c…&ano=2026 200 OK { "crianca_id": "9f3c…", "ano": 2026, "educador": "e-221", "visitado_em": "2026-02-20", "frequencia_escolar": 94.0, "atividades": ["vôlei na escola", "oficina de leitura"], "observacoes": "Melhorou muito a leitura em voz alta. Entrou para o time de vôlei.", "completo": true } - api
POST /cartasCria a carta em rascunho. Nunca envia.
Separar criação de envio é o que torna possível existir gate humano entre as duas.
▸Ver exemploOcultar exemplo
POST /cartas { "crianca_id": "9f3c…", "ano": 2026, "idioma": "pt-BR", "agente": "redator@v12", "texto": "...", "evidencia": [...] } 201 Created { "id": "c-8812", "status": "rascunho", "criada_em": "2026-03-03T14:02:11Z" } - api
POST /cartas/{id}/enviarAção irreversível: exige gate, chave de idempotência e registro.
Rodar duas vezes por engano entrega uma carta, não duas.
▸Ver exemploOcultar exemplo
POST /cartas/c-8812/enviar Idempotency-Key: c-8812-envio-1 { "aprovada_por": "marina@org", "gate": "revisao-primeira-carta" } 200 OK { "id": "c-8812", "status": "enviada", "enviada_em": "2026-03-05T09:14:00Z" } # Repetir a mesma chave devolve 200 com o MESMO enviada_em. Nunca envia duas vezes. # Sem Idempotency-Key: 400. Sem aprovada_por: 403. - api
Servidor MCP do cadastroO sistema interno exposto por protocolo comum, para qualquer agente plugar.
Trocar o sistema de cadastro troca o servidor MCP; os agentes não mudam.
▸Ver exemploOcultar exemplo
{ "name": "cadastro-apadrinhamento", "version": "2.1.0", "tools": [ { "name": "buscar_crianca", "description": "Ficha da criança no perfil do agente que chamou.", "inputSchema": { "type": "object", "properties": { "crianca_id": { "type": "string" } }, "required": ["crianca_id"] } }, { "name": "relatorio_do_ano", "description": "Relatório de campo. Devolve completo:false se faltar campo.", "inputSchema": { "type": "object", "properties": { "crianca_id": {"type":"string"}, "ano": {"type":"integer"} }, "required": ["crianca_id","ano"] } } ] } - config
.mcp.jsonA lista de servidores MCP que os agentes deste repositório enxergam — inclusive o de documentação de bibliotecas.
Cadastro, doações e a documentação atualizada dos frameworks usados no código.
▸Ver exemploOcultar exemplo
{ "mcpServers": { "cadastro": { "command": "npx", "args": ["-y", "@org/mcp-cadastro"], "env": { "PERFIL": "redacao" } }, "doacoes": { "command": "npx", "args": ["-y", "@org/mcp-doacoes"] }, "docs-libs": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] } } } - api
POST /webhooks/relatorio-recebidoO campo avisa quando chega relatório novo.
O agente acorda por evento em vez de varrer o banco de hora em hora.
▸Ver exemploOcultar exemplo
POST /webhooks/relatorio-recebido X-Assinatura: sha256=8f21… <- verificada antes de qualquer processamento { "evento": "relatorio.recebido", "id_evento": "ev-77120", <- dedupe: reentrega não reprocessa "crianca_id": "9f3c…", "ano": 2026, "origem": "app_campo" } 202 Accepted
05
Procedimentos executáveis
Como o trabalho é feito
O manual descreve o trabalho; o artefato executa. Tudo aqui é lido por agente.
- md
skills/carta-apadrinhamento/SKILL.mdO procedimento completo de uma tarefa, carregado sob demanda.
Padrão da carta, estrutura, proibições e o que fazer quando falta dado no relatório.
▸Ver exemploOcultar exemplo
--- name: carta-apadrinhamento description: Escreve a carta anual da criança para o padrinho a partir do relatório de campo. --- # Carta de apadrinhamento ## Antes de começar 1. Busque o relatório do ano. Se `completo: false`, **escale** e pare. 2. Busque o resumo dos dois anos anteriores (para não repetir assunto). 3. Confira o status: criança desligada não recebe carta. ## Estrutura 1. Saudação com o nome do padrinho 2. Um parágrafo de escola 3. Um parágrafo de atividade ou conquista 4. Uma pergunta da criança para o padrinho 5. Despedida ## Restrições - 180 a 320 palavras · idioma do padrinho · voz da criança em primeira pessoa - Toda afirmação precisa de linha correspondente no relatório - Nunca: endereço, escola, sobrenome, promessa, agradecimento por caridade ## Ao terminar Rode `validar.py`. Se falhar, corrija e rode de novo. Duas falhas seguidas: escale. - dados
skills/carta-apadrinhamento/exemplos/Saídas exemplares aprovadas e reprovadas, com o motivo de cada reprovação.
Seis cartas: três que passariam, três que não, e por quê.
▸Ver exemploOcultar exemplo
exemplos/ ├── aprovado-01.md + motivo: fato → fonte em cada frase, voz natural ├── aprovado-02.md + motivo: criança com pouca informação; carta curta e honesta ├── aprovado-03.md + motivo: padrinho espanhol, idioma correto sem tradução literal ├── reprovado-01.md − motivo: "graças à sua generosidade" — padrinho como salvador ├── reprovado-02.md − motivo: inventou hobby que não está no relatório └── reprovado-03.md − motivo: citou o nome da escola (violação de LGPD) Os reprovados valem mais que os aprovados: eles delimitam a fronteira. - codigo
skills/carta-apadrinhamento/validar.pyO script que confere a saída antes de ela sair da skill.
Tamanho, idioma e varredura de dados proibidos.
▸Ver exemploOcultar exemplo
import re, sys, json PROIBIDO = [ (r"\bRua\b|\bAv\.|\bAvenida\b", "endereço"), (r"\bEscola\s+[A-ZÁ-Ú]", "nome de escola"), (r"gra[çc]as? [àa] sua", "padrinho como salvador"), ] def validar(texto: str, idioma: str) -> list[str]: erros = [] n = len(texto.split()) if not 180 <= n <= 320: erros.append(f"extensão: {n} palavras (esperado 180–320)") for padrao, nome in PROIBIDO: if re.search(padrao, texto, re.I): erros.append(f"conteúdo proibido: {nome}") if idioma == "es" and " você " in texto: erros.append("idioma: trechos em português numa carta em espanhol") return erros if __name__ == "__main__": d = json.load(sys.stdin) e = validar(d["texto"], d["idioma"]) print(json.dumps({"ok": not e, "erros": e}, ensure_ascii=False)) sys.exit(1 if e else 0) - md
specs/correspondencia.mdA especificação do processo: entrada, saída, critérios de aceite, o que escala.
É dela que derivam prompt, testes e documentação — não o contrário.
▸Ver exemploOcultar exemplo
# Spec — correspondência anual ## Outcome O padrinho renova o apadrinhamento porque sente que acompanha a vida de uma criança real. ## Tarefa `escrever-carta` — uma execução por criança apadrinhada ativa, por ano. ## Entrada `relatorio_campo` do ano (obrigatório, `completo: true`) · resumo dos 2 anos anteriores · idioma do padrinho · políticas vigentes. ## Saída Carta em markdown + `evidencia.json` com claim → fonte. ## Critérios de aceite | # | Critério | Como se mede | Exigência | |---|---|---|---| | 1 | Fidelidade factual | toda afirmação tem fonte | 100% | | 2 | LGPD | nenhum campo proibido | 100% | | 3 | Idioma | o do padrinho | 100% | | 4 | Extensão | 180–320 palavras | 100% | | 5 | Tom e dignidade | LLM-as-judge, rubrica | ≥ 4,0 | ## Escala para humano quando Relatório incompleto ou contraditório · criança desligada · menção a situação de risco · duas falhas seguidas na validação. - md
templates/carta.mdO esqueleto da saída, com os campos fixos e os livres explicitamente marcados.
Fato e LGPD são fixos; voz, ordem e ênfase são livres.
▸Ver exemploOcultar exemplo
{{! Campos FIXOS: validados em código. Campos LIVRES: variam a cada geração. }} Olá, {{padrinho.primeiro_nome}}! {{! FIXO — vem do cadastro }} {{escola}} {{! LIVRE — voz, ordem e ênfase do agente }} {{atividade_ou_conquista}} {{! LIVRE }} {{pergunta_ao_padrinho}} {{! LIVRE }} Com carinho, {{crianca.primeiro_nome}} {{! FIXO — nunca o sobrenome }} {{! Proibidos por guardrail, não por instrução: endereco, escola_nome, sobrenome }} - md
progresso.mdO estado de uma tarefa longa entre execuções: o que já foi feito, o que falta, onde parou.
A migração de 12 anos de correspondência avança 20 registros por iteração, sem perder o lugar.
▸Ver exemploOcultar exemplo
--- tarefa: migrar-correspondencia-historica iniciado: 2026-03-02 atualizado: 2026-03-19T14:22Z --- ## Onde parei Lote 34 de 61. Último registro convertido: `carta:2019:8841`. ## Feito - [x] 2014–2018 · 12.408 cartas · sem pendência - [x] 2019 · 2.100 de 3.980 cartas ## Falta - [ ] 2019 · 1.880 cartas restantes - [ ] 2020–2025 ## Aprendido no caminho - Cartas anteriores a 2016 não têm `crianca_id`; casar por nome + comunidade + ano. - 41 registros com data inválida foram para `duvidas.md`. Não invente data. ## Próximo passo Retomar em `carta:2019:8842`. - md
runbooks/carta-errada-enviada.mdO que fazer quando o erro já saiu. Passo a passo, com dono de cada etapa.
Quem avisa o padrinho, quem registra o incidente, quem transforma em caso no gabarito.
▸Ver exemploOcultar exemplo
# Runbook — carta errada enviada **Gatilho:** erro factual, de LGPD ou de tom identificado após o envio. **Dono:** DRI da correspondência (hoje: Marina). **Prazo do passo 1:** 4 horas. ## 1. Conter (0–4 h) - [ ] Suspender o lote: `./scripts/parar.sh correspondencia` - [ ] Levantar quantas cartas saíram com o mesmo defeito (query em `runbooks/consultas.sql`) ## 2. Comunicar (4–24 h) - [ ] Padrinho afetado: contato por pessoa, nunca por agente - [ ] Se houver LGPD envolvida: acionar o jurídico no mesmo dia ## 3. Registrar (até 48 h) - [ ] Abrir `incidentes/AAAA-MM-DD-descricao.md` com causa raiz - [ ] Criar o caso em `golden/` — **o incidente não fecha sem isto** - [ ] Adicionar critério na suíte se o eval não pegaria o defeito ## 4. Retomar - [ ] Suíte inteira verde, incluindo o caso novo - [ ] Religar com o nível de autonomia rebaixado por 2 semanas
06
Agentes e tarefas
Quem faz o quê
Um agente sem arquivo só existe na cabeça de quem o criou. Estes arquivos funcionam como o organograma da força de trabalho.
- config
tarefas.yamlO catálogo das unidades delegáveis: entrada, goal, ferramentas, custo esperado e dono.
escrever-carta,triar-relatorio,traduzir-carta,revisar-lote.▸Ver exemploOcultar exemplo
tarefas: escrever-carta: entrada: [relatorio_campo, resumo_historico, idioma_padrinho] goal: "Carta de 180 a 320 palavras, na voz da criança, com toda afirmação rastreável ao relatório do ano." tools: [buscar_crianca, relatorio_do_ano, criar_carta] escala_se: [relatorio_incompleto, contradicao, crianca_desligada, risco] custo_esperado_brl: 0.42 dono: marina triar-relatorio: entrada: [relatorio_campo] goal: "Classificar em completo / incompleto / contraditório." tools: [relatorio_do_ano] escala_se: [contradicao] custo_esperado_brl: 0.03 dono: marina - md
agentes/redator/agent.mdO harness de um agente: papel, tarefas que executa, ferramentas, limites e critério de escalada.
Redige a carta; não consulta dado financeiro; escala se o relatório for contraditório.
▸Ver exemploOcultar exemplo
--- nome: redator tarefas: [escrever-carta] modelo: modelo-capaz max_iteracoes: 6 --- # Agente redator ## Papel Transformar um relatório de campo em uma carta. Não decide nada além do texto. ## Ferramentas `buscar_crianca` · `relatorio_do_ano` · `criar_carta` (rascunho) **Não tem:** envio, escrita no cadastro, leitura de financeiro. ## Limites - 6 iterações. Estourou, escala. - Falhou duas vezes em `validar.py`, escala — não tenta uma terceira. ## Escalada Chama `gate.revisao-humana` com o motivo em uma frase e a evidência parcial anexada. - md
agentes/redator/prompt.mdO prompt de sistema, versionado como código e alterado junto com a suíte.
Cada mudança aqui dispara a suíte inteira de evals.
▸Ver exemploOcultar exemplo
Você escreve a carta anual de uma criança apadrinhada para o padrinho dela. REGRAS INVIOLÁVEIS 1. Toda afirmação sobre a criança vem do relatório de campo fornecido. Nada de inferência. 2. Se faltar informação, escreva uma carta mais curta. Nunca invente para preencher. 3. Nunca cite endereço, nome de escola ou sobrenome. 4. A criança é sujeito. Ela aparece pelo que faz — nunca pelo que falta. PROCESSO 1. Leia o relatório e liste os fatos disponíveis. 2. Escreva a carta usando apenas esses fatos. 3. Monte `evidencia.json`: cada frase da carta → a linha do relatório que a sustenta. 4. Sobrou frase sem fonte? Reescreva antes de entregar. # versão: v12 · alterado em 2026-03-14 · suíte rodada: sim (98,5%) - md
agentes/verificador/agent.mdO agente que confere o trabalho do outro contra a fonte.
Não escreve nada: devolve a tabela de afirmação → fonte → ok/falha.
▸Ver exemploOcultar exemplo
--- nome: verificador tarefas: [verificar-carta] modelo: modelo-rapido --- # Agente verificador ## Papel Conferir a carta contra a fonte. **Não escreve nem corrige** — só julga e devolve evidência. ## Saída obrigatória ```json { "aprovado": false, "claims": [ { "frase": "Entrei para o time de vôlei.", "fonte": "relatorio:2026:atividades", "ok": true }, { "frase": "Sonho em ser jogadora.", "fonte": null, "ok": false } ], "motivo": "1 afirmação sem fonte" } ``` ## Por que é um agente separado O mesmo turno que escreveu tende a aprovar o que escreveu. Contexto limpo é o ponto. - config
orquestracao.yamlQue tipo de tarefa vai para qual modelo, e quando escala direto para humano.
Relatório completo → modelo barato. Contraditório → modelo caro. Criança fora do programa → humano.
▸Ver exemploOcultar exemplo
rotas: - quando: { tarefa: triar-relatorio } modelo: modelo-rapido max_iteracoes: 2 - quando: { tarefa: escrever-carta, relatorio: completo } modelo: modelo-rapido - quando: { tarefa: escrever-carta, relatorio: [incompleto, contraditorio] } modelo: modelo-capaz - quando: { crianca_status: desligada } destino: humano motivo: "Não existe carta correta para criança fora do programa." padrao: { modelo: modelo-capaz } - md
agentes/README.mdO organograma dos agentes: quem chama quem, com que protocolo e em que ordem.
Extrator → redator → verificador, com o coordenador decidindo escalada.
▸Ver exemploOcultar exemplo
# Time de agentes — correspondência ``` relatorio.recebido │ ▼ [ triador ] ── incompleto ──▶ gate.revisao-humana │ completo ▼ [ redator ] ──▶ rascunho + evidencia.json │ ▼ [ verificador ] ── reprovado ──▶ volta ao redator (máx. 2×) │ aprovado ▼ gate.envio (humano, quando exigido por gates.yaml) │ ▼ carta.enviada ``` Protocolo: cada agente recebe e devolve JSON com esquema fixo. Nenhum agente chama outro diretamente — quem coordena é o orquestrador, por evento.
07
Qualidade
Como se sabe que está certo
Sem esta camada, nada do que vem antes pode subir de nível de autonomia, porque subir de nível exige evidência.
- dados
evals/casos/*.jsonOs casos de teste, um por arquivo, com o motivo de existirem registrado.
Criança que mudou de cidade; relatório contraditório; padrinho que escreve em espanhol.
▸Ver exemploOcultar exemplo
{ "id": "047-relatorio-contraditorio", "porque_existe": "Aceitar contradição em silêncio é o pior modo de falha do sistema.", "entrada": { "crianca_id": "9f3c…", "relatorio": { "ano": 2026, "frequencia_escolar": 95.0, "observacoes": "Faltou muito no segundo semestre por problema de transporte." }, "idioma": "pt-BR" }, "esperado": { "acao": "escalar", "motivo_contem": "contradi" }, "criterios": ["fidelidade", "lgpd", "idioma", "extensao", "tom"] } - md
evals/criterios.mdAs rubricas: o que é nota 1 e o que é nota 5, critério por critério.
Dignidade, fidelidade factual, tom, extensão e idioma.
▸Ver exemploOcultar exemplo
# Rubricas ## Tom e dignidade (1 a 5) — avaliado por LLM-as-judge **Nota 5** > "Este ano entrei para o time de vôlei. Ainda erro o saque, mas melhorei." Criança como sujeito. Progresso sem exagero. Nenhuma menção ao padrinho como provedor. **Nota 1** > "Graças a você, hoje eu posso sonhar. Sem sua ajuda eu não teria nada." Criança definida pela carência. Padrinho como salvador. Gratidão performática. **Penalize:** linguagem de pena · comparação que diminui a criança · foco no que falta · promessa que a organização não pode cumprir. ## Fidelidade factual (0 ou 1) — automático 1 se toda frase da carta tem entrada correspondente em `evidencia.json` com `ok: true`. - codigo
evals/rodar.pyUm comando que roda a suíte inteira e imprime o percentual por critério.
200 casos, 6 minutos, R$ 4 por execução.
▸Ver exemploOcultar exemplo
#!/usr/bin/env python3 """Roda a suíte inteira. Falhar aqui bloqueia o deploy.""" import json, pathlib, sys from criterios import fidelidade, lgpd, idioma, extensao, tom_por_juiz CRITERIOS = {"fidelidade": fidelidade, "lgpd": lgpd, "idioma": idioma, "extensao": extensao, "tom": tom_por_juiz} MINIMO = {"fidelidade": 1.0, "lgpd": 1.0, "idioma": 1.0, "extensao": 1.0, "tom": 0.80} def main() -> int: casos = [json.loads(p.read_text()) for p in pathlib.Path("evals/casos").glob("*.json")] placar, falhou = {}, False for nome, fn in CRITERIOS.items(): passou = sum(fn(c) for c in casos if nome in c["criterios"]) total = sum(1 for c in casos if nome in c["criterios"]) taxa = passou / total placar[nome] = taxa marca = "ok " if taxa >= MINIMO[nome] else "FALHA" if taxa < MINIMO[nome]: falhou = True print(f" {marca} {nome:14} {taxa:6.1%} (mínimo {MINIMO[nome]:.0%})") pathlib.Path("evals/resultados").mkdir(exist_ok=True) return 1 if falhou else 0 if __name__ == "__main__": sys.exit(main()) - dados
evals/resultados/O histórico por versão. É a comparação entre execuções que revela a regressão.
Percentual por critério, semana a semana, versionado junto com o prompt.
▸Ver exemploOcultar exemplo
data,versao_prompt,fidelidade,lgpd,idioma,extensao,tom,casos 2026-03-01,v10,0.985,1.000,1.000,1.000,0.86,200 2026-03-08,v11,0.990,1.000,1.000,1.000,0.87,200 2026-03-14,v12,0.990,1.000,1.000,1.000,0.71,200 - codigo
.github/workflows/evals.ymlO gate automático: falhar na suíte bloqueia o deploy.
Sem isto, a suíte é decoração.
▸Ver exemploOcultar exemplo
name: evals on: pull_request: paths: ["agentes/**", "skills/**", "politicas/**", "evals/**"] schedule: - cron: "0 6 * * 1" # segunda de manhã: pega mudança de modelo do fornecedor jobs: suite: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: python3 evals/rodar.py # sai != 0 se algum critério ficar abaixo - uses: actions/upload-artifact@v4 with: { name: resultado, path: evals/resultados/ } - md
analise/variedade.mdO inventário das exceções que o processo real produziu, confrontado com o que o gabarito cobre.
14 tipos de exceção observados no ano; 9 estão no golden dataset. Os 5 restantes são a exposição atual.
▸Ver exemploOcultar exemplo
# Variedade observada × variedade coberta — 2026-Q1 | # | Tipo de exceção | Vezes no ano | No gabarito? | |---|---|---|---| | 1 | Relatório incompleto | 210 | sim | | 2 | Criança mudou de comunidade | 88 | sim | | 3 | Padrinho em espanhol | 74 | sim | | 4 | Relatório contraditório | 31 | sim | | 5 | Criança desligada no meio do ano | 24 | sim | | 6 | Homônimas na mesma comunidade | 12 | sim | | 7 | Relatório digitalizado ilegível | 9 | sim | | 8 | Dois relatórios para o mesmo ano | 7 | sim | | 9 | Padrinho falecido | 5 | sim | | 10 | Criança com dois apadrinhamentos | 4 | **não** | | 11 | Menção a situação de risco | 3 | **não** | | 12 | Padrinho pede idioma diferente do cadastro | 3 | **não** | | 13 | Relatório de educador desligado | 2 | **não** | | 14 | Comunidade encerrada no meio do ano | 1 | **não** | **Cobertura: 9 de 14 tipos · 89% dos casos, 36% dos tipos.** Os 5 descobertos representam 13 casos por ano — pouco volume, alto risco. O tipo 11 (situação de risco) nunca pode ser automatizado: vira gate obrigatório, não caso de teste. Regra: toda exceção nova observada entra nesta tabela **no mesmo dia**, mesmo antes de virar caso no gabarito. A tabela é o mapa da exposição. - md
evals/calibracao.mdA conferência do juiz-modelo contra julgamento humano, datada.
30 casos avaliados por gente e pelo juiz, com o percentual de concordância.
▸Ver exemploOcultar exemplo
# Calibração do juiz — 2026-03-10 30 cartas avaliadas em `tom` por duas coordenadoras e pelo juiz-modelo, às cegas. | | Humano ≥4 | Humano <4 | |---|---|---| | **Juiz ≥4** | 17 | 2 | | **Juiz <4** | 1 | 10 | **Concordância: 90%** (27/30). Aceitável — mínimo interno é 85%. ## Os 3 desacordos - 2 casos: o juiz aprovou cartas que as coordenadoras acharam frias. Rubrica ajustada para penalizar ausência de voz da criança, não só presença de linguagem de pena. - 1 caso: humano reprovou por erro factual, que não é critério de tom. Descartado. Próxima calibração: junho/2026, ou antes se trocarmos de modelo.
08
Governança
O que não pode acontecer
Cada arquivo aqui responde à pergunta: se o agente errar da pior forma possível, até onde vai o estrago?
- config
permissoes.yamlA matriz agente × acesso, com o mínimo necessário e o resto revogado.
O redator lê relatório e cadastro básico; não lê dado financeiro nem tem credencial de envio.
▸Ver exemploOcultar exemplo
agentes: redator: ler: [crianca.publico, relatorio_campo, politicas, skills] escrever: [carta.rascunho] negado: [doacao, padrinho.contato, crianca.endereco, crianca.escola, s3://fotos] verificador: ler: [carta, relatorio_campo] escrever: [carta.parecer] negado: ["*"] expedidor: ler: [carta.aprovada, padrinho.contato] escrever: [envio] negado: [relatorio_campo, crianca.*] exige_gate: true # Revisão trimestral obrigatória. Acesso não usado por 90 dias é revogado. - codigo
guardrails/As regras críticas implementadas em código, fora do prompt.
sem_dados_sensiveis.pyrecusa qualquer saída que contenha endereço, escola ou sobrenome.▸Ver exemploOcultar exemplo
# guardrails/sem_dados_sensiveis.py # Roda como hook PreToolUse. Não é conselho ao modelo: é impedimento. import re, sys, json PADROES = { "endereco": r"\b(Rua|Av\.|Avenida|Travessa)\s+[A-ZÁ-Ú]", "escola": r"\b(Escola|Colégio|E\.M\.)\s+[A-ZÁ-Ú]", "cpf": r"\b\d{3}\.\d{3}\.\d{3}-\d{2}\b", "sobrenome": r"\b{nome}\s+[A-ZÁ-Ú][a-zá-ú]+", # formatado com o nome da criança } def bloquear(texto, contexto): for nome, p in PADROES.items(): if re.search(p.format(**contexto), texto): return f"bloqueado: {nome} — ver politicas/lgpd-menores.md" return None if __name__ == "__main__": ev = json.load(sys.stdin) motivo = bloquear(ev["conteudo"], ev["contexto"]) if motivo: print(json.dumps({"decision": "block", "reason": motivo})) sys.exit(2) # 2 = bloqueia a ferramenta e devolve o motivo ao agente - config
gates.yamlOnde um humano aprova, com dono nomeado e prazo de resposta.
Primeira carta de cada criança nova; qualquer carta reprovada uma vez pelo verificador.
▸Ver exemploOcultar exemplo
gates: revisao-primeira-carta: quando: { primeira_carta_da_crianca: true } aprovador: coordenacao-programa prazo_horas: 48 se_estourar: notificar_dri revisao-reprovada: quando: { verificador_reprovou: true } aprovador: coordenacao-programa prazo_horas: 24 envio-em-lote: quando: { tamanho_lote: ">200" } aprovador: marina prazo_horas: 8 # Renovação que passou limpa no verificador NÃO tem gate. O gate existe onde há risco, # não em todo lugar — senão vira carimbo e para de significar alguma coisa. - config
autonomia.yamlO nível de cada tarefa por segmento, com a evidência que sustenta e a data.
Carta em português: nível 4 desde 12/03. Em espanhol: nível 3, faltam 40 casos.
▸Ver exemploOcultar exemplo
tarefas: escrever-carta: pt-BR: nivel: 4 # age sozinho desde: 2026-03-12 evidencia: - "6 semanas acima do baseline em todos os 5 critérios" - "0 incidentes de LGPD" - "kill switch acionado em treino em 2026-02-28" es: nivel: 3 # age com aprovação falta: "40 casos em espanhol no golden dataset" revisar_em: 2026-06-01 escrever-carta-crianca-desligada: todos: nivel: 2 # só sugere motivo: "Não existe resposta correta automatizável." - dados
Audit logRegistro append-only de quem decidiu o quê, quando e com base em quê.
Gerada pelo agente v12 em 3/3, com base no relatório de 20/2, aprovada por Marina, enviada em 5/3.
▸Ver exemploOcultar exemplo
create table audit ( id bigserial primary key, em timestamptz not null default now(), ator text not null, -- 'agente:redator@v12' ou 'humano:marina@org' acao text not null, -- 'carta.gerada', 'carta.aprovada', 'carta.enviada' entidade text not null, -- 'carta:c-8812' base jsonb not null, -- com base em quê: fontes, versões, evidência resultado text not null ); revoke update, delete on audit from public; -- append-only, inclusive para admin - codigo
scripts/parar.shO comando de parada, mais o gatilho automático por limite de custo ou de erro.
Para sozinho se o custo médio por carta passar de R$ 1,50.
▸Ver exemploOcultar exemplo
#!/usr/bin/env bash # Parada manual. Testada em treino todo trimestre — botão nunca acionado é suposição. set -euo pipefail PROCESSO="${1:?uso: parar.sh <processo>}" echo "pausando fila de $PROCESSO..." redis-cli SET "pausado:$PROCESSO" 1 EX 86400 redis-cli SET "motivo:$PROCESSO" "parada manual por $(whoami) em $(date -Iseconds)" psql -c "insert into audit(ator,acao,entidade,base,resultado) values ('humano:$(whoami)','operacao.pausada','processo:$PROCESSO','{}','ok')" echo "pausado. Retomar: ./scripts/retomar.sh $PROCESSO"
09
Observabilidade
O que está acontecendo agora
Eval mede em laboratório; esta camada acompanha a produção. Sem ela, você descobre o problema pelo cliente.
- painel
Traces por execuçãoEntrada, saída, ferramentas chamadas, tokens, custo, latência e versão do prompt.
Foi o trace que mostrou relatórios digitalizados entrando inteiros no contexto.
▸Ver exemploOcultar exemplo
{ "trace_id": "tr-91ac", "tarefa": "escrever-carta", "crianca_id": "9f3c…", "agente": "redator@v12", "inicio": "2026-03-03T14:02:03Z", "duracao_ms": 38210, "passos": [ { "tipo": "tool", "nome": "relatorio_do_ano", "ms": 210, "tokens_saida": 480 }, { "tipo": "modelo", "nome": "modelo-rapido", "tokens_entrada": 5120, "tokens_saida": 610, "custo_brl": 0.31 }, { "tipo": "tool", "nome": "validar", "ms": 40, "resultado": "falhou:extensao" }, { "tipo": "modelo", "nome": "modelo-rapido", "tokens_entrada": 5900, "tokens_saida": 590, "custo_brl": 0.11 } ], "custo_total_brl": 0.42, "escalou": false } - painel
Painel de custoCusto por tarefa e por resultado, em série temporal.
Mostrou o salto de R$ 0,42 para R$ 1,10 por carta, três horas antes de alguém perceber.
▸Ver exemploOcultar exemplo
<svg viewBox="0 0 620 210" class="mock" role="img" aria-label="Painel de custo por carta"> <text class="mk-t" x="0" y="14">CUSTO POR CARTA · ÚLTIMAS 8 SEMANAS</text> <text class="mk-n" x="0" y="52">R$ 0,71</text> <text class="mk-s" x="112" y="52">por carta entregue · baseline humano R$ 9,30</text> <g class="mk-grade"> <line x1="0" y1="180" x2="620" y2="180"/><line x1="0" y1="140" x2="620" y2="140"/> <line x1="0" y1="100" x2="620" y2="100"/> </g> <polyline class="mk-linha" points="10,168 90,165 170,170 250,120 330,96 410,150 490,160 570,158"/> <circle class="mk-alerta" cx="330" cy="96" r="5"/> <text class="mk-s" x="300" y="84">pico: R$ 1,10</text> <g class="mk-eixo"><text x="10" y="198">jan</text><text x="250" y="198">fev</text> <text x="490" y="198">mar</text></g> </svg> - config
alertas.yamlOs três alertas que pegam quase tudo.
Custo médio 2× a semana anterior; taxa de escalada subindo; latência p95 estourando.
▸Ver exemploOcultar exemplo
alertas: - nome: custo-dobrou consulta: "avg(custo_brl) últimas 24h > 2 × avg(custo_brl) semana anterior" severidade: alta destino: [dri, canal-operacao] - nome: escalada-subindo consulta: "taxa_escalada últimas 4h > 1.5 × mediana dos últimos 30 dias" severidade: media destino: [dri] - nome: latencia-p95 consulta: "p95(duracao_ms) últimas 2h > 90000" severidade: baixa destino: [canal-operacao] # Três bastam. Alerta que dispara toda semana vira ruído e ninguém olha mais. - painel
Painel de qualidadePercentual por critério ao longo do tempo, por versão.
É onde a regressão silenciosa fica visível.
▸Ver exemploOcultar exemplo
<svg viewBox="0 0 620 210" class="mock" role="img" aria-label="Painel de qualidade por critério"> <text class="mk-t" x="0" y="14">% POR CRITÉRIO · POR VERSÃO DE PROMPT</text> <g class="mk-grade"><line x1="120" y1="30" x2="120" y2="185"/></g> <g class="mk-rot"> <text x="0" y="52">fidelidade</text><text x="0" y="82">lgpd</text> <text x="0" y="112">idioma</text><text x="0" y="142">extensão</text> <text x="0" y="172">tom</text> </g> <g class="mk-barra"> <rect x="120" y="42" width="485" height="12"/><rect x="120" y="72" width="490" height="12"/> <rect x="120" y="102" width="490" height="12"/><rect x="120" y="132" width="490" height="12"/> </g> <rect class="mk-barra-ruim" x="120" y="162" width="348" height="12"/> <text class="mk-s" x="478" y="172">0,71 → era 0,87</text> </svg> - dados
incidentes/Um arquivo por incidente, com causa raiz e o caso que ele virou no gabarito.
Nenhum incidente é considerado fechado sem o caso correspondente.
▸Ver exemploOcultar exemplo
--- incidente: 2026-03-21-nome-trocado severidade: alta detectado_por: padrinho dri: marina --- # Carta com o nome de outra criança ## O que aconteceu Duas crianças homônimas na mesma comunidade. O agente buscou por nome, não por id, e escreveu a carta da Ana S. com os dados da Ana R. ## Causa raiz `buscar_crianca` aceitava nome como parâmetro. Nunca deveria ter aceitado. ## O que ficou permanente - [x] `buscar_crianca` só aceita `crianca_id` — parâmetro `nome` removido - [x] Caso `052-homonimas` no golden dataset - [x] Critério novo na suíte: id da carta bate com id do relatório - [x] Nota em `ontologia.md` sobre homônimos na mesma comunidade O incidente só fecha com os quatro marcados. Três deles não corrigem esta carta — corrigem todas as próximas. - painel
Painel de fila e SLAQuanto tempo cada tarefa espera por aprovação humana.
Mostra quando o gate virou o gargalo do processo.
▸Ver exemploOcultar exemplo
<svg viewBox="0 0 620 190" class="mock" role="img" aria-label="Fila de aprovação humana"> <text class="mk-t" x="0" y="14">ESPERANDO APROVAÇÃO HUMANA</text> <text class="mk-n" x="0" y="52">34</text> <text class="mk-s" x="56" y="52">cartas na fila · prazo do gate: 48 h</text> <g class="mk-rot"> <text x="0" y="92">revisao-primeira-carta</text><text x="0" y="122">revisao-reprovada</text> <text x="0" y="152">envio-em-lote</text> </g> <g class="mk-barra"> <rect x="200" y="82" width="260" height="12"/><rect x="200" y="112" width="90" height="12"/> </g> <rect class="mk-barra-ruim" x="200" y="142" width="380" height="12"/> <g class="mk-s"><text x="470" y="92">21 · 12 h</text><text x="300" y="122">9 · 4 h</text> <text x="590" y="152">4 · 61 h</text></g> </svg>
10
Economia e responsabilidade
Quanto custa e quem responde
Aqui o projeto de tecnologia vira decisão de negócio: quanto custa e quem responde.
- dados
unit-economics.csvCusto por token, por tarefa e por resultado, comparado ao baseline humano.
R$ 0,42 em tokens, R$ 0,71 por carta entregue, contra R$ 9,30 do processo manual.
▸Ver exemploOcultar exemplo
etapa,unidade,valor,moeda,observacao tokens_entrada,por carta,0.29,BRL,média de 5.100 tokens tokens_saida,por carta,0.13,BRL,média de 600 tokens subtotal_modelo,por carta,0.42,BRL,custo direto de inferência retrabalho_agente,por carta,0.05,BRL,12% das cartas rodam 2× escalada_humana,por carta,0.24,BRL,8% × 25 min × custo/hora custo_por_resultado,por carta entregue,0.71,BRL,o número que decide baseline_humano,por carta entregue,9.30,BRL,medido em 2026-01-20 - config
dri.yamlQuem responde por cada processo agêntico. Pessoa com nome, não área.
Correspondência: Marina. Ela não revisa as 4.000; responde pelo sistema que as produz.
▸Ver exemploOcultar exemplo
processos: correspondencia: dri: marina@org substituto: joao@org responde_por: [qualidade, custo, incidentes, nivel de autonomia] nao_responde_por: [infraestrutura, contrato de modelo] revisa: { evals: semanal, selos_maturidade: trimestral, permissoes: trimestral } triagem-relatorios: dri: marina@org substituto: joao@org # Processo agêntico sem DRI não sobe de nível de autonomia. Regra sem exceção. - dados
span-of-control.csvQuantos processos cada pessoa supervisiona e com que instrumentos.
Marina: 6 processos, todos com eval, painel de custo e gates definidos.
▸Ver exemploOcultar exemplo
pessoa,processos,com_eval,com_painel,com_gate_definido,horas_semana_supervisao marina@org,6,6,6,6,7 joao@org,2,2,1,2,4 - md
maturidade.mdOnde a organização está em cada conceito, revisado por trimestre.
O mesmo selo que aparece nas fichas deste dicionário.
▸Ver exemploOcultar exemplo
# Maturidade — revisão de 2026-Q1 | Conceito | Selo | Evidência | Próximo passo | |---|---|---|---| | Golden dataset | 🟢 em produção | 200 casos, 30 difíceis | manter: todo incidente vira caso | | Evals | 🟢 em produção | suíte bloqueia deploy desde jan/26 | adicionar critério de repetição | | Auto verificação | 🟡 experimentando | roda em pt-BR, não em es | estender ao espanhol | | Baseline humano | 🟢 em produção | medido em 2026-01-20 | remedir em jan/27 | | Ontologia | 🟡 experimentando | 12 entidades escritas | faltam as de captação | | Monitoramento | 🟢 em produção | traces + 3 alertas | painel de qualidade por versão | | Span of control | 🔴 não usamos | — | medir antes de opinar | Revisado por: Marina · Próxima revisão: 2026-06-30 - md
roadmap-autonomia.mdO que falta para cada tarefa subir de nível, com data e responsável.
Espanhol precisa de 40 casos a mais no gabarito antes de ir para o nível 4.
▸Ver exemploOcultar exemplo
# Roadmap de autonomia | Tarefa / segmento | Hoje | Alvo | O que falta | Quando | Dono | |---|---|---|---|---|---| | escrever-carta · pt-BR | 4 | 4 | — | — | marina | | escrever-carta · es | 3 | 4 | 40 casos em espanhol no golden | jun/26 | marina | | triar-relatorio | 3 | 4 | 4 semanas de eval acima do baseline | mai/26 | joao | | carta · criança desligada | 2 | 2 | permanece em 2 por decisão | — | marina | ## Regra Nenhuma linha sobe sem: evidência anexada, data e DRI. "Está indo bem" não é evidência. - md
decisoes/ADR-*.mdAs decisões de arquitetura, datadas, com as alternativas que foram descartadas e por quê.
Por que MCP em vez de integração ponto a ponto com cada sistema.
▸Ver exemploOcultar exemplo
# ADR-007 — MCP em vez de integração ponto a ponto **Data:** 2026-02-10 · **Status:** aceita · **Decisor:** time de plataforma ## Contexto Quatro sistemas internos (cadastro, doações, e-mail, campo) e três agentes previstos. Ponto a ponto seriam 12 integrações, cada uma refeita a cada troca de agente. ## Decisão Um servidor MCP por sistema. Agentes falam MCP, nunca a API interna diretamente. ## Alternativas descartadas - **SDK interno compartilhado** — resolveria hoje, mas amarra os agentes à nossa linguagem. - **Integração direta** — mais rápida na primeira, insustentável na terceira. ## Consequências - (+) Trocar o sistema de cadastro troca 1 servidor, não 3 agentes. - (−) Uma camada a mais para operar e monitorar. - (−) Latência adicional de ~40 ms por chamada. Aceita. ## Quando revisitar Se ficarmos com um único agente por mais de um ano, esta decisão perde a justificativa.