Como construir um sistema de outbound com autoaprendizado no Codex

@nifinet
INGLÊShá 2 dias · 19 de jul. de 2026
227K
358
22
13
1.7K

TL;DR

Nicolas Finet detalha uma estrutura técnica para a construção de um sistema de vendas outbound com autoaprendizado. O sistema utiliza agentes de IA para analisar taxas de resposta e propor melhorias nas mensagens via pull requests.

No início deste ano, Andrej Karpathy (@karpathy) apontou um agente para seu próprio código de treinamento e o deixou rodar por dois dias. Ele executou 700 experimentos, manteve os 20 que superaram o benchmark e fez o modelo treinar 11% mais rápido. Depois ele disse algo bastante interessante: qualquer métrica que você possa avaliar de forma barata pode ser entregue a um enxame de agentes.

Taxa de resposta é uma métrica que você pode avaliar de forma barata. Passei algum tempo desde então descobrindo como esse loop se parece quando apontado para ações de prospecção (outbound).

Minha construção:

O Codex lê os resultados da semana passada, edita os arquivos de pontuação e de abordagens (plays) que o sistema de prospecção utiliza, executa um teste e abre um pull request. Ele propõe uma alteração no manual (playbook) com as evidências e a pontuação anexadas, e então aguarda a aprovação humana. Envio e mesclagem ficam fora do loop.

Construí o primeiro loop algumas vezes: sentir o mercado, pontuar a conta, escrever a partir do sinal, verificar a mensagem, registrar o resultado, aprender com a resposta. Este artigo é sobre o segundo loop, aquele que edita o primeiro.

Essa é a construção: GTM (go-to-market) como código versionado que melhora a partir do mercado.

Nicolas Finet - inline image

O repositório

Comece pela pasta. A estrutura importa porque o Codex só consegue melhorar o que consegue ler e editar.

text
1codex-self-improving-outbound/
2 AGENTS.md
3 README.md
4 config/
5 scoring.yaml
6 plays.yaml
7 prompts/
8 improve_scoring.md
9 improve_prompt.md
10 pr_summary.md
11 memory/
12 outcomes.jsonl
13 evals/
14 fixtures.yaml
15 score.py
16 scripts/
17 append_outcome.py
18 run_codex_step.sh
19 propose_improvement.py
20 open_pr.sh
21 weekly_tune.sh
22 examples/
23 outcomes.sample.jsonl
24 weekly-pr.md

O repositório é propositalmente simples. O config/scoring.yaml contém as regras que decidem quais sinais importam. O prompts/ contém as abordagens que escrevem as mensagens. O memory/outcomes.jsonl armazena o que o mercado fez. O evals/score.py é o portal que determina se uma mudança proposta ajudou. O AGENTS.md é a lei que o Codex lê antes de tocar em qualquer coisa.

Execute a primeira versão offline. Sem CRM, sem enriquecimento, sem sistema de entrega. O loop de melhoria deve se provar em arquivos locais antes de chegar perto de uma máquina real de prospecção.

Passo 1. Escreva a lei primeiro

Antes do arquivo de pontuação, antes dos arquivos de prompt, escreva o AGENTS.md. Este é o arquivo que mantém o agente útil e contido.

markdown
1# Self-Improving Outbound Rules
2
3You improve an outbound system from outcomes.
4
5Hard rules:
6- Never send messages.
7- Never scrape or enrich real people.
8- Never self-merge.
9- Edit only files in this repo.
10- Change one concept at a time.
11- Cite outcomes from memory/outcomes.jsonl for every proposed change.
12- Improve evals/score.py before a change can become a PR.
13- If the eval does not improve, revert your edit and stop.
14
15Allowed edits:
16- config/scoring.yaml
17- config/plays.yaml
18- prompts/*.md
19
20Required output:
21- changed files
22- reason for each change
23- before score
24- after score
25- pull request summary

A lei tem um único trabalho: restringir o trabalho. Sem ela, o Codex tentará ajudar expandindo o escopo. Ele adicionará mais dados, tocará em mais arquivos, chamará mais ferramentas ou automatizará uma etapa que deveria permanecer sob controle humano. Aqui o trabalho é menor: ler resultados, propor uma alteração em um arquivo, provar que ajudou e depois esperar.

Como é quando funciona bem. Você pode ler a lei antes de aprovar um PR e saber exatamente o que o Codex tinha permissão para fazer.

Onde quebra. A lei vira um documento de conformidade. Se o AGENTS.md precisar de um sumário, já está grande demais. Mantenha-o operacional.

Passo 2. Mova o julgamento para a configuração

A maior parte do julgamento de prospecção vive na cabeça de alguém. Então o time compra um software e espera que ele melhore uma decisão que não consegue enxergar.

Mova o julgamento para um arquivo.

yaml
1signals:
2 competitor_comparison:
3 weight: 8
4 reason: "buyer is comparing alternatives"
5 implementation_page_visit:
6 weight: 6
7 reason: "buyer is checking whether this can be installed"
8 job_repost:
9 weight: 5
10 reason: "role is still open and urgent"
11 funding_event:
12 weight: 5
13 reason: "budget or mandate may have changed"
14 generic_download:
15 weight: 1
16 reason: "content interest, weak buying intent"
17
18thresholds:
19 draft: 6
20 human_review: 10
21
22negative_signals:
23 student_research: -8
24 vendor_pitch: -6
25 competitor: -10

Este arquivo começa como uma hipótese visível. Se um download genérico não deve contar nada, o time pode apontar para a linha exata e alterá-la. Se uma visita à página de implementação for um sinal mais forte do que você pensava, o Codex pode propor o diff e mostrar as linhas de resultado que o justificam.

Não enterre essa lógica em uma função Python. Se a regra estiver visível, o time pode revisá-la, contestá-la e melhorá-la sem transformar um julgamento de vendas em uma refatoração de engenharia.

Como é quando funciona bem. O arquivo é pequeno o suficiente para ser contestado. Cinco sinais é uma boa primeira versão.

Onde quebra. O arquivo de pontuação vira uma gaveta de bagunça. Vinte sinais, seis limites e regras de exceção para cada caso extremo farão o melhorador se ajustar demais. Comece enxuto e deixe os resultados te dizerem onde o próximo botão deve ficar.

Passo 3. Escreva os resultados como memória

O arquivo mais importante é o memory/outcomes.jsonl.

Uma linha por contato, escrita quando o resultado é conhecido:

javascript
1{"date":"2026-07-01","account":"Northwind Finance","signal":"competitor_comparison","play":"migration_note","score":8,"outcome":"reply","reason":"asked for migration notes"}
2{"date":"2026-07-01","account":"Bluepeak Studio","signal":"generic_download","play":"resource_followup","score":1,"outcome":"no_reply","reason":"content-only intent"}
3{"date":"2026-07-02","account":"KiteOps","signal":"implementation_page_visit","play":"implementation_angle","score":6,"outcome":"reply","reason":"asked about implementation timeline"}
4{"date":"2026-07-02","account":"Atlas Recruiting","signal":"job_repost","play":"hiring_angle","score":5,"outcome":"bad_fit","reason":"student research request"}

O campo reason é o ponto principal. no_reply não te diz quase nada. content-only intent diz à próxima execução que esse sinal talvez não mereça um rascunho. bad_fit só é útil quando o motivo explica o porquê. asked about implementation timeline é o tipo de detalhe que pode mudar um peso.

Construa o validador antes de construir o melhorador:

text
1Build scripts/append_outcome.py.
2
3It accepts:
4- date
5- account
6- signal
7- play
8- score
9- outcome: reply | meeting | no_reply | bad_fit | bounced
10- reason
11
12It rejects:
13- missing fields
14- unknown outcomes
15- empty reason
16- dates in the future
17
18Append valid rows to memory/outcomes.jsonl.
19Print the appended row.

É aqui que a acumulação começa. Um dashboard pode te dizer que uma campanha caiu. Um registro de resultado limpo pode dizer ao Codex qual sinal, abordagem ou frase deve mudar antes da próxima execução.

Como é quando funciona bem. Depois de uma semana, um estranho pode ler o arquivo e dizer quais sinais geraram respostas, quais abordagens geraram conversas de mau ajuste (bad-fit) e qual preferência interna o mercado ignorou.

Onde quebra. O time preenche resultados na sexta-feira de memória. Os acertos sobrevivem, os motivos de mau ajuste ficam borrados e o sistema aprende com ficção. Escreva a linha quando o resultado chegar.

Passo 4. Construa o portal de avaliação (eval gate)

Antes que o Codex edite qualquer coisa, ele precisa de um teste que não possa explicar de forma conveniente.

Crie evals/fixtures.yaml:

yaml
1cases:
2 - account: Northwind Finance
3 signals: [competitor_comparison, implementation_page_visit]
4 expected: human_review
5 note: "two strong signals on one account"
6
7 - account: Bluepeak Studio
8 signals: [generic_download]
9 expected: ignore
10 note: "content-only intent"
11
12 - account: KiteOps
13 signals: [implementation_page_visit]
14 expected: draft
15 note: "implementation intent should clear draft threshold"
16
17 - account: Atlas Recruiting
18 signals: [job_repost, student_research]
19 expected: ignore
20 note: "bad-fit marker cancels the signal"

Depois crie evals/score.py:

text
1Build evals/score.py.
2
3Read config/scoring.yaml and evals/fixtures.yaml.
4
5For each case:
61. Sum weights for every signal.
72. Add negative signal penalties.
83. Route the account:
9 - score >= thresholds.human_review => human_review
10 - score >= thresholds.draft => draft
11 - otherwise => ignore
124. Compare route to expected.
13
14Print each prediction.
15Print final accuracy as score=0.00 to score=1.00.
16Exit 0 only when accuracy is 1.00.

O primeiro portal deve ser pequeno o suficiente para entender e afiado o suficiente para pegar um erro real. Na minha primeira execução, a linha de base falhou em um caso:

text
1Northwind Finance: predicted=human_review expected=human_review
2Bluepeak Studio: predicted=ignore expected=ignore
3KiteOps: predicted=ignore expected=draft
4Atlas Recruiting: predicted=ignore expected=ignore
5score=0.75

Isso foi bom. O sistema tinha a intenção de implementação abaixo do limite de rascunho, então ignorou uma conta que a fixture dizia merecer uma mensagem. Melhor pegar isso num teste do que depois de um mês de contas perdidas.

Como é quando funciona bem. Um comando dá um número, e todo caso de falha é fácil de inspecionar.

Onde quebra. A fixture só inclui vitórias óbvias. Então toda mudança imprudente passa. Coloque casos feios no portal: intenção fraca, mau ajuste, sem resposta, sinais desatualizados e as contas que você gostaria que o sistema tivesse pulado.

Passo 5. Deixe o Codex propor uma mudança de pontuação

Agora o Codex pode editar.

Crie prompts/improve_scoring.md:

markdown
1You improve the outbound scoring system.
2
3Read:
4- AGENTS.md
5- config/scoring.yaml
6- memory/outcomes.jsonl
7- evals/fixtures.yaml
8
9Your job:
101. Find one scoring rule that should change.
112. The reason must cite memory/outcomes.jsonl.
123. Change only config/scoring.yaml.
134. Run python3 evals/score.py.
145. If the score improves, keep the change.
156. If the score stays flat or drops, revert your change and stop.
16
17Output:
18- the exact line changed
19- the outcome rows that caused it
20- before score
21- after score
22- whether the change should become a PR
23
24Do not edit prompts.
25Do not add new signals.
26Do not touch delivery.

Execute através do wrapper do repositório:

bash
1scripts/run_codex_step.sh improve_scoring

A primeira versão do meu melhorador cometeu um erro útil. Ela perseguiu o sinal de resposta mais limpo. competitor_comparison tinha a maior taxa de resposta no pequeno registro de resultados, então o melhorador queria aumentar esse peso. A avaliação permaneceu em 0,75, então a mudança foi rejeitada.

É exatamente para isso que o portal existe. Um sistema mais fraco teria aceitado a história porque parecia razoável. Este fez uma pergunta melhor: a mudança corrigiu o erro conhecido?

A segunda passada encontrou a menor edição que ajudou:

text
1- implementation_page_visit: 4
2+ implementation_page_visit: 6

A avaliação passou:

text
1Northwind Finance: predicted=human_review expected=human_review
2Bluepeak Studio: predicted=ignore expected=ignore
3KiteOps: predicted=draft expected=draft
4Atlas Recruiting: predicted=ignore expected=ignore
5score=1.00

Esse é o momento em que o loop se torna útil. Mudou uma regra, por um motivo, e provou a mudança contra uma fixture.

Nicolas Finet - inline image

Como é quando funciona bem. O diff proposto é chato e rastreável: uma linha alterada, um motivo embasado em resultado anexado, uma avaliação melhorada.

Onde quebra. O Codex muda três pesos e dois prompts de uma vez. Agora ninguém consegue dizer qual mudança ajudou. Mantenha a lei estrita: um conceito por proposta.

Passo 6. Melhore os arquivos de prompt separadamente

Pontuação é apenas metade do sistema. Os modelos de mensagem também se desgastam.

Uma linha que funcionava no mês passado começa a soar familiar. Uma pergunta que gera respostas em um segmento é ignorada em outro. Uma frase que parece afiada internamente é punida pelo mercado. Trate a melhoria de prompts como uma pista separada para que o Codex não misture pontuação e texto no mesmo PR.

Crie config/plays.yaml:

yaml
1plays:
2 migration_note:
3 prompt_file: prompts/plays/migration_note.md
4 use_when:
5 - competitor_comparison
6 banned_lines:
7 - "thought this might be relevant"
8 - "quick question"
9
10 implementation_angle:
11 prompt_file: prompts/plays/implementation_angle.md
12 use_when:
13 - implementation_page_visit
14 banned_lines:
15 - "checking out our solution"
16 - "would love to chat"

Depois crie prompts/improve_prompt.md:

markdown
1You improve one outbound play.
2
3Read:
4- AGENTS.md
5- config/plays.yaml
6- memory/outcomes.jsonl
7- the prompt file for the chosen play
8
9Pick one play with at least 10 outcomes.
10
11Find:
12- lines or structures that appear in positive outcomes
13- lines or structures that appear in no_reply or bad_fit outcomes
14- any phrase that should be banned
15
16Make one small edit to that play's prompt.
17
18Rules:
19- Do not change scoring.
20- Do not create a new play.
21- Do not add a new channel.
22- Cite outcome rows.
23- Write the before and after instruction.
24
25Then run the copy eval if present.
26If no copy eval exists, open the PR as review_required.

Algumas melhorias podem ser pontuadas automaticamente. Outras ainda precisam de bom gosto. Se não houver avaliação de cópia, o Codex pode propor a edição do prompt, mas deve marcar o PR para revisão em vez de fingir que a edição está comprovada.

Como é quando funciona bem. O Codex diz: "Esta frase apareceu em sete resultados de 'sem resposta', então a adicionei às linhas proibidas", ou "respostas positivas citaram o detalhe de implementação na primeira frase, então apertei a abordagem para exigir isso."

Onde quebra. O melhorador reescreve a voz inteira porque uma mensagem recebeu uma resposta. Edições de prompt devem ser menores que seu instinto.

Passo 7. Envie mudanças como pull requests

Esta é a camada de controle. O Codex edita arquivos, executa a avaliação e escreve o resumo do PR. Um humano revisa e mescla.

Nicolas Finet - inline image

Crie prompts/pr_summary.md:

markdown
1Write a pull request summary for this outbound improvement.
2
3Include:
41. What changed.
52. Why it changed, citing outcome rows.
63. Before score.
74. After score.
85. Files changed.
96. Risk.
107. What the human reviewer should check.
11
12Keep it short.
13Do not claim the change is live.

Crie scripts/open_pr.sh:

bash
1#!/usr/bin/env bash
2set -euo pipefail
3
4branch="codex/weekly-tune-$(date +%Y-%m-%d)"
5
6git checkout -b "$branch"
7git add config prompts evals memory
8git commit -m "Codex weekly outbound tune"
9
10body="$(cat outputs/pr-summary.md)"
11
12python3 scripts/create_pr.py \
13 "$branch" \
14 "Codex weekly outbound tune" \
15 "$body"

O PR deve parecer que foi escrito por um colega de equipe:

text
1Changed:
2- Raised implementation_page_visit from 4 to 6.
3
4Why:
5- KiteOps had implementation-page intent and replied with implementation timing.
6- The previous score routed this account to ignore.
7
8Before:
9- eval score 0.75
10
11After:
12- eval score 1.00
13
14Reviewer check:
15- Make sure implementation intent is specific enough.
16- Keep generic downloads low.
17- Merge only if this matches actual sales judgment.

Esse é o sistema de segurança. O Codex faz o trabalho tedioso. O operador mantém o padrão.

Como é quando funciona bem. Um PR por semana, diff pequeno, motivo claro, avaliação aprovada.

Onde quebra. Alguém dá permissão ao Codex para mesclar porque a revisão parece um atrito. Esse minuto separa um sistema que melhora de um sistema que deriva.

Passo 8. Coloque em uma cadência

Não execute isso após cada resposta. É assim que um sistema se ajusta demais a uma conta barulhenta.

Deixe a semana acontecer, deixe os resultados se acumularem, depois ajuste.

Nicolas Finet - inline image

Crie scripts/weekly_tune.sh:

bash
1#!/usr/bin/env bash
2set -euo pipefail
3
4cd "$(dirname "$0")/.."
5
6python3 evals/score.py || true
7scripts/run_codex_step.sh improve_scoring
8python3 evals/score.py
9scripts/run_codex_step.sh pr_summary > outputs/pr-summary.md
10scripts/open_pr.sh

Depois o cron:

bash
10 8 * * MON cd ~/codex-self-improving-outbound && scripts/weekly_tune.sh

Se você usar GitHub Actions, mantenha a mesma estrutura:

yaml
1name: weekly-outbound-tune
2
3on:
4 schedule:
5 - cron: "0 8 * * 1"
6 workflow_dispatch:
7
8jobs:
9 tune:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v4
13 - uses: actions/setup-python@v5
14 with:
15 python-version: "3.11"
16 - run: pip install -r requirements.txt
17 - run: python3 evals/score.py || true
18 - run: scripts/weekly_tune.sh

Execute os dois primeiros ajustes manualmente. Leia cada diff. Observe o que o Codex tenta mudar quando a amostra é pequena. Quando as propostas ficarem monótonas, coloque em um cronograma.

Como é quando funciona bem. Um PR semanal aparece com as evidências, o diff e o resultado da avaliação. Você mescla, edita ou fecha.

Onde quebra. O job roda, ninguém revisa e os PRs se acumulam. Um sistema auto-melhorável ainda tem um hábito humano: ler o diff.

A versão clone e execute

O repositório deve vir com quatro comandos:

bash
1git clone <repo>
2cd codex-self-improving-outbound
3python3 -m venv .venv
4source .venv/bin/activate
5pip install -r requirements.txt
6python3 evals/score.py
7python3 scripts/propose_improvement.py

Primeira execução esperada:

text
1score=0.75
2changed config/scoring.yaml
3implementation_page_visit: 4 -> 6
4score=1.00
5open PR for human review

A demo offline prova os contratos de arquivo. A execução do Codex prova o loop de edição. Depois disso, substitua os resultados de amostra pelos seus, renomeie os sinais, adicione suas abordagens e construa uma fixture que reflita as contas que você gostaria que o sistema tivesse roteado de forma diferente.

Não comece conectando a entrega. Comece provando o loop de melhoria.

A versão completa: max

Este repositório é a camada manual. Ele roda a partir de arquivos, sinais públicos e seu plano do Codex. Ele ensina a estrutura porque cada regra está exposta.

O yourmax.ai é o mesmo sistema com as costuras ocultas.

Em vez de um repositório que você mesmo monta, o max é o agente que você usa diretamente. Ele detecta movimentação no mercado, decide quem vale a pena contatar e por que agora, redige a abordagem por e-mail e LinkedIn para sua aprovação e continua melhorando a partir dos resultados.

O repositório mostra a camada de autoajuste que a maioria dos times nunca constrói: resultados se tornam mudanças de regras propostas, mudanças de regras propostas passam por um portal, e a mesclagem humana decide o que entra em produção. O max pega essa mesma lógica operacional e a executa como um sistema gerenciado.

Se você quiser o repositório completo, pode me avisar que eu envio para você.

Recriar no YouMind

Turn one viral article into a full content workflow

Collect the source, decode the pattern, create assets, draft the story, and distribute from one AI workspace.

Explore YouMind
Para criadores

Transforme seu Markdown em um artigo 𝕏 impecável

Quando você publica seus próprios textos longos, formatar imagens, tabelas e blocos de código para o 𝕏 é uma dor de cabeça. O YouMind transforma um rascunho completo em Markdown em um artigo 𝕏 impecável e pronto para publicar.

Experimente Markdown para 𝕏

Mais padrões para decifrar

Artigos virais recentes

Explorar mais artigos virais