Projeto 04 · segment-brief

Proposta que
passa no linter.

A pergunta sobre que segmento trabalhar leva cerca de uma semana em quase toda operação de CRM. A parte repetitiva desse trabalho é consulta e comparação, e é essa parte que o agente executa. O critério de aceite fica em código: a jornada proposta precisa passar no lifecycle-lint.

Seções desta página

4 ferramentas, liberadas pelo roteador conforme a intenção
2 rodadas de correção, por decisão de custo
13 casos de eval, dez de roteamento e três de sessão
17 testes automatizados em CI

Como esses números são contados: quatro ferramentas é o que tools.py declara, run_sql, cohort_size, rfm e propose_journey, e o roteador decide quais delas o modelo enxerga em cada execução. Duas rodadas é o teto em agent.py. Treze casos é a contagem em evals/cases.yaml, separada em dois blocos porque eles medem coisas diferentes. Os dezessete testes rodam em CI com o provedor roteirizado, sem chave de API e sem custo.

01

Narrativa

01
Problema

Alguém extrai dado, alguém cruza com receita, alguém escreve um documento, alguém contesta o recorte. Uma semana depois existe um briefing de segmento cuja qualidade ninguém consegue avaliar sem refazer o caminho inteiro.

02
Decisão

Roteador determinístico na entrada, agente no meio, validador na saída. O roteador classifica a pergunta em exploração, diagnóstico ou proposta por marcadores lexicais, e define quais ferramentas o modelo enxerga naquela execução. Uma pergunta exploratória não emite jornada por acidente de formulação.

03
Execução

O agente consulta o DuckDB em modo leitura com teto de 50 linhas, mede coortes contra um piso de amostra, calcula quintis de RFM e fecha com uma jornada no formato canônico. O YAML sai do modelo e entra no lifecycle-lint. Quando reprova, os achados voltam ao agente como resultado de ferramenta.

04
Aprendizado

A primeira proposta roteirizada passava com aviso, o que deixava o loop de correção sem demonstração. O validador do agente ficou mais rígido que o linter: quatro regras classificadas como aviso lá reprovam aqui. O linter audita régua escrita por gente, onde um aviso abre conversa com quem escreveu. A proposta do agente é automática, e refazer custa uma rodada.

02

Três intenções, três escopos

A mesma base, o mesmo agente, três perguntas. O que muda entre elas é o conjunto de ferramentas que o modelo enxerga, e quem decide isso é o roteador, em código. A saída fica em português, que é o idioma da operação para a qual a ferramenta foi escrita.

Execuções do agente

$ segment-brief ask "Que segmento a gente deveria estar trabalhando para reter melhor? Proponha uma jornada."
intenção: proposta · ferramentas: run_sql, cohort_size, rfm, propose_journey
→ run_sql({"query": "WITH d7 AS (SELECT u.user_id, u.canal_aquisicao, ..."})
50 linhas · afiliados × mensal × aulas na 1a semana
→ cohort_size({"where": "canal='afiliados' AND plano='mensal'"})
n = 3.412 · acima do piso de amostra (500)
→ rfm({"segment": "afiliados_mensal"})
quintis: recência alta · frequência baixa · valor médio
→ propose_journey({"id": "ativacao_afiliados_mensal", ...}) rodada 1/2
⇒ validador: reprovado (2 erro(s), 0 aviso(s))
ERRO L007 Canal intrusivo sem janela de silêncio
ERRO L009 Métrica de sucesso ausente ou de vaidade
→ propose_journey({"id": "ativacao_afiliados_mensal", ...}) rodada 2/2
⇒ validador: aprovado (0 erro(s), 0 aviso(s))
briefing · afiliados × mensal × d7 < 2 aulas · churn 44% contra 28%
jornada: ativacao_afiliados_mensal · holdout 0.1 · success: retencao_d30
exit code 0jornada aprovada

Repare no que não aparece na segunda e na terceira aba: propose_journey nem chega a ser oferecida ao modelo. O escopo de permissão é auditável justamente porque essa decisão fica fora dele.

Um agente que também roteia e valida a si mesmo devolve resultado sem critério de aceite verificável.

03

Código, modelo, código

Roteamento e validação ficam fora do modelo por decisão de projeto. Percorra as seis etapas para ver a reprovação do validador voltando ao agente como resultado de ferramenta.

etapa 1/6
segment-brief Pergunta em linguagem natural entra no roteador em código, que libera ferramentas para o agente; o validador em código reprova a primeira proposta e devolve os achados ao agente, que corrige e entrega o briefing com exit code 0. pergunta em linguagem natural router.py · código marcadores lexicais: exploracao | diagnostico | proposta agent.py · loop de uso de ferramentas run_sql · DuckDB, 50 linhas cohort_size · piso rfm · quintis propose_journey · YAML canônico validator.py · código lifecycle-lint rígido e piso de amostra · máximo 2 rodadas reprovação volta como resultado de ferramenta briefing + YAML aprovado · exit code 0

A pergunta em linguagem natural entra no pipeline. Nada foi decidido ainda.

O escopo de permissão precisa ser auditável, e o critério de aceite precisa ser o mesmo em toda execução. O agente ocupa a etapa intermediária, que é onde a tarefa é aberta o suficiente para justificar um modelo.

O limite de duas rodadas é decisão de custo. Um agente que não converge com os achados do linter em mãos raramente converge em dez tentativas, e cada rodada extra é token gasto sobre a mesma dúvida.

O roteador usa marcadores lexicais e erra em formulação ambígua. Classificar com modelo tornaria o escopo de permissão dependente de uma saída não determinística, e a troca não compensa: o custo do erro atual é uma ferramenta a menos na execução, e a pergunta pode ser reformulada.

04

A coorte plantada

O eval só é verificável porque a resposta certa está plantada em posição conhecida. Alunos vindos de afiliados no plano mensal que assistem menos de duas aulas na primeira semana churnam bem acima dos demais, e é esse recorte que o agente precisa encontrar sozinho.

44%
28%
31%
22%
afiliados · mensal
d7 menor que 2 aulas
demais
mensais
pago
geral
orgânico
geral

churn em 90 dias · escala 0 a 50% · base sintética com seed fixa versionada

Base sintética de edtech, gerada por script versionado com seed fixa: 20 mil alunos, 18 meses de eventos, sazonalidade de matrícula em janeiro, março e agosto. A coorte de risco em posição conhecida é o que torna o eval verificável, porque existe uma resposta certa contra a qual comparar.

Dado sintético é requisito aqui, declarado no README. Base real de empregador não entra em repositório público.

05

O validador é mais rígido que o linter

Quatro regras que o lifecycle-lint classifica como aviso reprovam aqui, mais o piso de amostra, que é exclusivo do validador. A diferença não é de rigor por rigor: muda quem recebe o achado.

Regra lifecycle-lint (régua humana) validator.py (proposta automática)
L005 · Segmento sem decaimento temporalavisoreprova
L007 · Canal intrusivo sem janela de silêncioavisoreprova
L008 · Jornada ativa sem grupo de controleavisoreprova
L009 · Métrica de sucesso ausente ou de vaidadeavisoreprova
Piso de amostra da coortenão existereprova

rodada 1/2 · propose_journey

Jornada ativacao_afiliados_mensal com canal intrusivo sem janela declarada e taxa_abertura como métrica de sucesso.

✕ reprovado · 2 erros

L007 L009 Os achados voltam ao agente como resultado de ferramenta.

rodada 2/2 · propose_journey

Janela de silêncio declarada, e a métrica troca abertura por retencao_d30.

✓ aprovado · 0 erros

Briefing entregue com holdout de 0.1. Se a hipótese está certa, o teste dirá, e é para isso que o holdout entra.

O linter audita régua escrita por gente, onde um aviso abre conversa com quem a escreveu. A proposta do agente é automática, e refazer custa uma rodada. Com esse custo, o padrão sobe.

06

Os dez casos de roteamento

Bloco determinístico, sem modelo e sem custo, que roda em CI a cada push. Verifica a classificação da pergunta e o conjunto de ferramentas liberado. O caso 9 é de fronteira: carrega marcadores de duas intenções.

# Pergunta Intenção Ferramentas liberadas
1"Que dados temos na base?"exploracaorun_sql
2"Quais eventos existem?"exploracaorun_sql
3"Quantos alunos ativos por plano?"exploracaorun_sql
4"Compare o churn por canal de aquisição"diagnosticorun_sql, rfm
5"Diagnostique por que mensais evadem"diagnosticorun_sql, rfm
6"Qual o tamanho da coorte de afiliados?"diagnosticorun_sql, cohort_size
7"Mostre o RFM dos inativos"diagnosticorun_sql, rfm
8"Proponha uma régua para afiliados mensais"propostaas 4 ferramentas
9"Compare churn por canal e proponha jornada para o pior" fronteirapropostaas 4 ferramentas
10"Que segmento trabalhar para reter melhor?"propostaas 4 ferramentas

Por que o caso de fronteira importa: uma pergunta que mistura diagnóstico e proposta precisa resolver para o escopo mais amplo, senão o agente perderia a ferramenta de que precisa no meio da execução. A regra é explícita e testada, em vez de emergir do comportamento do modelo.

07

Dois blocos de avaliação

Roteamento · 10 casos
Sem modelo

Determinístico. Verifica a classificação da pergunta e o conjunto de ferramentas liberado, incluindo um caso de fronteira com marcadores de duas intenções.

Sessões · 3 casos
Encanamento ou modelo

Com o provedor roteirizado mede ferramentas, validador e loop de correção, e roda em CI sem custo. Com a API mede o modelo, e o número obtido vale para aquela execução.

runs/proposta_afiliados.json
# o registro do que o agente fez, e não do que ele diz que fez
{
  "rota": "proposta",
  "ferramentas_liberadas": ["run_sql", "cohort_size", "rfm", "propose_journey"],
  "chamadas": [
    {"tool": "run_sql", "linhas": 50},
    {"tool": "cohort_size", "result": {"n": 3412, "piso": 500, "ok": true}},
    {"tool": "propose_journey", "rodada": 1, "veredito": "reprovado", "achados": ["L007", "L009"]},
    {"tool": "propose_journey", "rodada": 2, "veredito": "aprovado"}
  ],
  "tokens": 4213, "tempo_s": 9.8
}

Um placar que soma os dois blocos não informa nada sobre nenhum deles, então o relatório os separa e imprime o rótulo do que está sendo medido. A transcrição de cada execução fica em runs/, com rota, chamadas, vereditos, tokens e tempo.

08

A suíte

Três repositórios sobre a mesma tese: jornada de cliente é artefato versionável. Se ela pode ser declarada em arquivo, ela pode ser lida, auditada e revisada em pull request, com histórico e revisão por pares. Hoje ela vive dentro da interface da ferramenta de automação, onde não existe diff entre versões nem registro de por que aquele delay é de 48 horas.

A saída de um é a entrada do outro, o que torna objetivo o critério de aceite do agente: a jornada proposta precisa passar no linter.

01 · Auditar

Lê as jornadas declaradas em YAML e acusa o defeito antes da publicação, inclusive o que só existe entre duas réguas.

02 · Propor
segment-brief

Lê os eventos de produto e devolve o briefing de segmento com a jornada proposta, já validada pelo linter.

Esta página
03 · Ler

Guarda os prompts de leitura versionados, com asserções verificáveis e placar que mede regressão em CI.

09

Stack

Ver o repositório