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.

O repositório
Comece pela pasta. A estrutura importa porque o Codex só consegue melhorar o que consegue ler e editar.
1codex-self-improving-outbound/2 AGENTS.md3 README.md4 config/5 scoring.yaml6 plays.yaml7 prompts/8 improve_scoring.md9 improve_prompt.md10 pr_summary.md11 memory/12 outcomes.jsonl13 evals/14 fixtures.yaml15 score.py16 scripts/17 append_outcome.py18 run_codex_step.sh19 propose_improvement.py20 open_pr.sh21 weekly_tune.sh22 examples/23 outcomes.sample.jsonl24 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.
1# Self-Improving Outbound Rules23You improve an outbound system from outcomes.45Hard 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.1415Allowed edits:16- config/scoring.yaml17- config/plays.yaml18- prompts/*.md1920Required output:21- changed files22- reason for each change23- before score24- after score25- 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.
1signals:2 competitor_comparison:3 weight: 84 reason: "buyer is comparing alternatives"5 implementation_page_visit:6 weight: 67 reason: "buyer is checking whether this can be installed"8 job_repost:9 weight: 510 reason: "role is still open and urgent"11 funding_event:12 weight: 513 reason: "budget or mandate may have changed"14 generic_download:15 weight: 116 reason: "content interest, weak buying intent"1718thresholds:19 draft: 620 human_review: 102122negative_signals:23 student_research: -824 vendor_pitch: -625 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:
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:
1Build scripts/append_outcome.py.23It accepts:4- date5- account6- signal7- play8- score9- outcome: reply | meeting | no_reply | bad_fit | bounced10- reason1112It rejects:13- missing fields14- unknown outcomes15- empty reason16- dates in the future1718Append 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:
1cases:2 - account: Northwind Finance3 signals: [competitor_comparison, implementation_page_visit]4 expected: human_review5 note: "two strong signals on one account"67 - account: Bluepeak Studio8 signals: [generic_download]9 expected: ignore10 note: "content-only intent"1112 - account: KiteOps13 signals: [implementation_page_visit]14 expected: draft15 note: "implementation intent should clear draft threshold"1617 - account: Atlas Recruiting18 signals: [job_repost, student_research]19 expected: ignore20 note: "bad-fit marker cancels the signal"
Depois crie evals/score.py:
1Build evals/score.py.23Read config/scoring.yaml and evals/fixtures.yaml.45For each case:61. Sum weights for every signal.72. Add negative signal penalties.83. Route the account:9 - score >= thresholds.human_review => human_review10 - score >= thresholds.draft => draft11 - otherwise => ignore124. Compare route to expected.1314Print 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:
1Northwind Finance: predicted=human_review expected=human_review2Bluepeak Studio: predicted=ignore expected=ignore3KiteOps: predicted=ignore expected=draft4Atlas Recruiting: predicted=ignore expected=ignore5score=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:
1You improve the outbound scoring system.23Read:4- AGENTS.md5- config/scoring.yaml6- memory/outcomes.jsonl7- evals/fixtures.yaml89Your 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.1617Output:18- the exact line changed19- the outcome rows that caused it20- before score21- after score22- whether the change should become a PR2324Do not edit prompts.25Do not add new signals.26Do not touch delivery.
Execute através do wrapper do repositório:
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:
1- implementation_page_visit: 42+ implementation_page_visit: 6
A avaliação passou:
1Northwind Finance: predicted=human_review expected=human_review2Bluepeak Studio: predicted=ignore expected=ignore3KiteOps: predicted=draft expected=draft4Atlas Recruiting: predicted=ignore expected=ignore5score=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.

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:
1plays:2 migration_note:3 prompt_file: prompts/plays/migration_note.md4 use_when:5 - competitor_comparison6 banned_lines:7 - "thought this might be relevant"8 - "quick question"910 implementation_angle:11 prompt_file: prompts/plays/implementation_angle.md12 use_when:13 - implementation_page_visit14 banned_lines:15 - "checking out our solution"16 - "would love to chat"
Depois crie prompts/improve_prompt.md:
1You improve one outbound play.23Read:4- AGENTS.md5- config/plays.yaml6- memory/outcomes.jsonl7- the prompt file for the chosen play89Pick one play with at least 10 outcomes.1011Find:12- lines or structures that appear in positive outcomes13- lines or structures that appear in no_reply or bad_fit outcomes14- any phrase that should be banned1516Make one small edit to that play's prompt.1718Rules: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.2425Then 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.

Crie prompts/pr_summary.md:
1Write a pull request summary for this outbound improvement.23Include: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.1112Keep it short.13Do not claim the change is live.
Crie scripts/open_pr.sh:
1#!/usr/bin/env bash2set -euo pipefail34branch="codex/weekly-tune-$(date +%Y-%m-%d)"56git checkout -b "$branch"7git add config prompts evals memory8git commit -m "Codex weekly outbound tune"910body="$(cat outputs/pr-summary.md)"1112python3 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:
1Changed:2- Raised implementation_page_visit from 4 to 6.34Why:5- KiteOps had implementation-page intent and replied with implementation timing.6- The previous score routed this account to ignore.78Before:9- eval score 0.751011After:12- eval score 1.001314Reviewer 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.

Crie scripts/weekly_tune.sh:
1#!/usr/bin/env bash2set -euo pipefail34cd "$(dirname "$0")/.."56python3 evals/score.py || true7scripts/run_codex_step.sh improve_scoring8python3 evals/score.py9scripts/run_codex_step.sh pr_summary > outputs/pr-summary.md10scripts/open_pr.sh
Depois o cron:
10 8 * * MON cd ~/codex-self-improving-outbound && scripts/weekly_tune.sh
Se você usar GitHub Actions, mantenha a mesma estrutura:
1name: weekly-outbound-tune23on:4 schedule:5 - cron: "0 8 * * 1"6 workflow_dispatch:78jobs:9 tune:10 runs-on: ubuntu-latest11 steps:12 - uses: actions/checkout@v413 - uses: actions/setup-python@v514 with:15 python-version: "3.11"16 - run: pip install -r requirements.txt17 - run: python3 evals/score.py || true18 - 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:
1git clone <repo>2cd codex-self-improving-outbound3python3 -m venv .venv4source .venv/bin/activate5pip install -r requirements.txt6python3 evals/score.py7python3 scripts/propose_improvement.py
Primeira execução esperada:
1score=0.752changed config/scoring.yaml3implementation_page_visit: 4 -> 64score=1.005open 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ê.





