今年の初め、Andrej Karpathy(@karpathy)は、自身のトレーニングコードにエージェントを向け、2日間実行させました。700 件の実験を実行し、ベンチマークを上回った 20 件を残し、モデルのトレーニングを 11% 高速化しました。その後、彼は非常に興味深いことを言いました。安価に評価できる指標はすべて、エージェントスウォームに任せることができる、と。
返信率は、安価に評価できる指標の 1 つです。私はそれ以来、そのループをアウトバウンドに向けた場合がどのようになるかを考えてきました。
私の構築:
Codex は先週の成果を読み込み、アウトバウンドシステムが実行するスコアリングファイルとプレイファイルを編集し、テストを実行して、プルリクエストを開きます。証拠とスコアを添えてプレイブックへの変更を提案し、人間が承認するのを待ちます。送信とマージはループの外側にあります。
私は最初のループを何度か構築してきました。市場を感知し、アカウントをスコアリングし、シグナルから文章を作成し、メッセージをチェックし、結果をログに記録し、返信から学習する。この記事は、2 番目のループ、つまり最初のループを編集するループについてです。
それが構築です。GTM をバージョン管理されたコードとして、市場から改善していく。

リポジトリ
フォルダから始めます。Codex が読み取って編集できるものだけを改善できるため、構造は重要です。
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
リポジトリは意図的にシンプルにしています。config/scoring.yaml は、どのシグナルが重要かのルールを保持します。prompts/ は、メッセージを作成するプレイを保持します。memory/outcomes.jsonl は、市場が何をしたかを保持します。evals/score.py は、提案された変更が役立ったかどうかを判断するゲートです。AGENTS.md は、Codex が何かに触れる前に読み取るルールです。
最初のバージョンはオフラインで実行します。CRM も、エンリッチメントも、配送システムもありません。改善ループは、実際のアウトバウンドマシンの近くに行く前に、ローカルファイルで実証されるべきです。
ステップ 1. まずルールを書く
スコアリングファイルの前、プロンプトファイルの前に、AGENTS.md を書きます。これは、エージェントを有用に保ち、制限するファイルです。
1# 自己改善型アウトバウンドルール23あなたは、成果からアウトバウンドシステムを改善します。45厳格なルール:6- メッセージを送信してはいけません。7- 実際の人物をスクレイピングしたりエンリッチしたりしてはいけません。8- セルフマージしてはいけません。9- このリポジトリ内のファイルのみを編集してください。10- 一度に 1 つの概念だけを変更してください。11- すべての提案された変更について、memory/outcomes.jsonl からの成果を引用してください。12- 変更が PR になる前に、evals/score.py を改善してください。13- 評価が改善されない場合は、編集を元に戻して停止してください。1415許可される編集:16- config/scoring.yaml17- config/plays.yaml18- prompts/*.md1920必要な出力:21- 変更されたファイル22- 各変更の理由23- 変更前のスコア24- 変更後のスコア25- プルリクエストの概要
ルールの役割は 1 つだけです。作業範囲を狭めること。これがないと、Codex は範囲を広げて助けようとします。データを追加したり、より多くのファイルに触れたり、より多くのツールを呼び出したり、人間の制御下にあるべきステップを自動化したりします。ここでの仕事はもっと小さく、成果を読み取り、1 つのファイル変更を提案し、それが役立つことを証明し、待機することです。
うまくいっている状態。 PR を承認する前にルールを読めば、Codex が何を許可されていたかを正確に把握できます。
失敗するポイント。 ルールがコンプライアンス文書になることです。AGENTS.md に見出しの目次が必要になったら、それはすでに大きすぎます。運用可能な状態に保ってください。
ステップ 2. 判断を設定に移す
ほとんどのアウトバウンドの判断は、誰かの頭の中にあります。その後、チームはソフトウェアを購入し、ソフトウェアが自分たちの見えない判断を改善することを期待します。
判断をファイルに移します。
1signals:2 competitor_comparison:3 weight: 84 reason: "購入者が代替案を比較している"5 implementation_page_visit:6 weight: 67 reason: "購入者がこれをインストールできるか確認している"8 job_repost:9 weight: 510 reason: "ポジションがまだ空いており緊急性がある"11 funding_event:12 weight: 513 reason: "予算や権限が変更された可能性がある"14 generic_download:15 weight: 116 reason: "コンテンツへの関心、弱い購買意図"1718thresholds:19 draft: 620 human_review: 102122negative_signals:23 student_research: -824 vendor_pitch: -625 competitor: -10
このファイルは、目に見える仮説として始まります。一般的なダウンロードをゼロとカウントすべきなら、チームは正確な行を指摘して変更できます。実装ページの訪問が考えていたよりも強いシグナルであれば、Codex は差分を提案し、それを正当化する成果行を示すことができます。
このロジックを Python 関数に埋め込まないでください。ルールが見えていれば、チームはそれをレビューし、議論し、営業判断をエンジニアリングのリファクタリングに変えることなく改善できます。
うまくいっている状態。 ファイルは議論するのに十分小さく、5 つのシグナルが適切な最初のバージョンです。
失敗するポイント。 スコアリングファイルがガラクタ入れになることです。20 のシグナル、6 つのしきい値、そしてすべてのエッジケースに対する例外ルールは、改善器をオーバーフィットさせます。狭く始めて、成果が次のノブをどこに置くべきかを教えてくれるのを待ちます。
ステップ 3. 成果をメモリとして書き込む
最も重要なファイルは memory/outcomes.jsonl です。
タッチごとに 1 行、成果が判明したときに書き込みます:
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"}
reason フィールドが全てです。no_reply はほとんど何も教えてくれません。content-only intent は、次の実行にこのシグナルがドラフトに値しないかもしれないと伝えます。bad_fit は、理由が理由を説明している場合にのみ役立ちます。asked about implementation timeline は、重みを変える可能性のある種類の詳細です。
改善器を構築する前に、バリデーターを構築します:
1scripts/append_outcome.py を構築します。23受け入れ:4- date5- account6- signal7- play8- score9- outcome: reply | meeting | no_reply | bad_fit | bounced10- reason1112拒否:13- フィールド不足14- 未知の outcome15- 空の reason16- 未来の日付1718有効な行を memory/outcomes.jsonl に追加します。19追加した行を出力します。
ここから複利効果が始まります。ダッシュボードはキャンペーンが低迷していることを教えてくれます。クリーンな成果ログは、次の実行の前にどのシグナル、プレイ、フレーズを変更すべきかを Codex に伝えることができます。
うまくいっている状態。 1 週間後、部外者がファイルを読んで、どのシグナルが返信を生み出し、どのプレイがミスマッチの会話を生み出し、どの社内のお気に入りが市場に無視されたかを判断できます。
失敗するポイント。 チームが金曜日に記憶から成果をバックフィルすることです。成功は残り、ミスマッチの理由は曖昧になり、システムはフィクションから学習します。成果が着地した時に行を書き込んでください。
ステップ 4. 評価ゲートを構築する
Codex が何かを編集する前に、言い訳ができないテストが必要です。
evals/fixtures.yaml を作成します:
1cases:2 - account: Northwind Finance3 signals: [competitor_comparison, implementation_page_visit]4 expected: human_review5 note: "1 つのアカウントに対する 2 つの強いシグナル"67 - account: Bluepeak Studio8 signals: [generic_download]9 expected: ignore10 note: "コンテンツのみの意図"1112 - account: KiteOps13 signals: [implementation_page_visit]14 expected: draft15 note: "実装意図はドラフトしきい値を超えるはず"1617 - account: Atlas Recruiting18 signals: [job_repost, student_research]19 expected: ignore20 note: "ミスマッチマーカーがシグナルを打ち消す"
次に evals/score.py を作成します:
1evals/score.py を構築します。23config/scoring.yaml と evals/fixtures.yaml を読み込みます。45各ケースについて:61. すべてのシグナルの重みを合計します。72. ネガティブシグナルのペナルティを追加します。83. アカウントをルーティングします:9 - score >= thresholds.human_review => human_review10 - score >= thresholds.draft => draft11 - それ以外 => ignore124. ルートと expected を比較します。1314各予測を出力します。15最終的な精度を score=0.00 から score=1.00 で出力します。16精度が 1.00 の場合のみ Exit 0 で終了します。
最初のゲートは、理解できるほど小さく、実際のミスを捉えるほど鋭利であるべきです。私の最初の実行では、ベースラインは 1 つのケースで失敗しました:
1Northwind Finance: predicted=human_review expected=human_review2Bluepeak Studio: predicted=ignore expected=ignore3KiteOps: predicted=ignore expected=draft4Atlas Recruiting: predicted=ignore expected=ignore5score=0.75
それは良いことでした。システムは実装意図をドラフトしきい値以下と判断し、フィクスチャがメッセージに値するとしたアカウントを無視していました。1 ヶ月間アカウントを見逃した後よりも、テストでそれを発見する方がはるかに良いです。
うまくいっている状態。 1 つのコマンドが 1 つの数値を与え、失敗した各ケースは簡単に検査できます。
失敗するポイント。 フィクスチャが明らかな成功例のみを含んでいることです。そうすると、すべての無謀な変更が通過します。弱い意図、ミスマッチ、無返信、古いシグナル、そしてシステムがスキップすべきだったアカウントなど、醜いケースをゲートに含めてください。
ステップ 5. Codex に 1 つのスコアリング変更を提案させる
これで Codex が編集できるようになりました。
prompts/improve_scoring.md を作成します:
1あなたはアウトバウンドスコアリングシステムを改善します。23読み込み:4- AGENTS.md5- config/scoring.yaml6- memory/outcomes.jsonl7- evals/fixtures.yaml89あなたの仕事:101. 変更すべきスコアリングルールを 1 つ見つけてください。112. 理由は memory/outcomes.jsonl を引用しなければなりません。123. config/scoring.yaml のみを変更してください。134. python3 evals/score.py を実行してください。145. スコアが改善された場合、変更を保持してください。156. スコアが変わらないか低下した場合、変更を元に戻して停止してください。1617出力:18- 変更された正確な行19- それを引き起こした成果行20- 変更前のスコア21- 変更後のスコア22- 変更が PR になるべきかどうか2324プロンプトを編集しないでください。25新しいシグナルを追加しないでください。26配信に触れないでください。
リポジトリラッパーを通して実行します:
1scripts/run_codex_step.sh improve_scoring
私の改善器の最初のバージョンは、有益な間違いを犯しました。最もきれいな返信シグナルを追いかけました。competitor_comparison は小さな成果ログで最も強い返信率を持っていたため、改善器はその重みを増やそうとしました。評価は 0.75 のままであったため、変更は却下されました。
まさにそのためにゲートが存在するのです。弱いシステムなら、もっともらしく聞こえるというだけでその話を受け入れていたでしょう。これはより良い質問をしました。変更は既知のミスを修正したか?
2 回目の試行で、役立った最小の編集を見つけました:
1- implementation_page_visit: 42+ implementation_page_visit: 6
評価は合格しました:
1Northwind Finance: predicted=human_review expected=human_review2Bluepeak Studio: predicted=ignore expected=ignore3KiteOps: predicted=draft expected=draft4Atlas Recruiting: predicted=ignore expected=ignore5score=1.00
これがループが有用になる瞬間です。1 つのルールを、1 つの理由で変更し、フィクスチャに対して変更を証明しました。

うまくいっている状態。 提案された差分は退屈で追跡可能です。1 行変更、1 つの成果に基づく理由が付随、1 つの評価が改善。
失敗するポイント。 Codex が一度に 3 つの重みと 2 つのプロンプトを変更することです。そうなると、どの変更が役立ったのか誰にもわかりません。ルールを厳格に保ってください。提案ごとに 1 つの概念。
ステップ 6. プロンプトファイルを個別に改善する
スコアリングはシステムの半分に過ぎません。メッセージテンプレートも劣化します。
先月うまくいったフレーズが、陳腐に聞こえ始めます。あるセグメントで返信を獲得した質問が、別のセグメントでは無視されます。社内では鋭く感じられるフレーズが、市場によって罰せられます。プロンプトの改善を別のレーンとして扱い、Codex が同じ PR でスコアリングとコピーを混在させないようにします。
config/plays.yaml を作成します:
1plays:2 migration_note:3 prompt_file: prompts/plays/migration_note.md4 use_when:5 - competitor_comparison6 banned_lines:7 - "関連するかもしれないと思いました"8 - "簡単な質問"910 implementation_angle:11 prompt_file: prompts/plays/implementation_angle.md12 use_when:13 - implementation_page_visit14 banned_lines:15 - "私たちのソリューションをチェックしています"16 - "ぜひお話ししたいです"
次に prompts/improve_prompt.md を作成します:
1あなたは 1 つのアウトバウンドプレイを改善します。23読み込み:4- AGENTS.md5- config/plays.yaml6- memory/outcomes.jsonl7- 選択されたプレイのプロンプトファイル89少なくとも 10 件の成果がある 1 つのプレイを選んでください。1011見つける:12- ポジティブな成果に現れる行や構造13- no_reply または bad_fit の成果に現れる行や構造14- 禁止すべきフレーズ1516そのプレイのプロンプトに 1 つ小さな編集を加えてください。1718ルール:19- スコアリングを変更しないでください。20- 新しいプレイを作成しないでください。21- 新しいチャネルを追加しないでください。22- 成果行を引用してください。23- 変更前と変更後の指示を書いてください。2425その後、コピー評価が存在すれば実行してください。26コピー評価が存在しない場合は、PR を review_required として開いてください。
一部の改善は自動的にスコアリングできます。その他は依然としてセンスが必要です。コピー評価がない場合、Codex はプロンプト編集を提案できますが、編集が証明されたふりをするのではなく、レビュー用として PR にマークする必要があります。
うまくいっている状態。 Codex が「このフレーズは 7 件の無返信成果に現れたため、banned_lines に追加しました」または「肯定的な返信が実装の詳細を最初の文で引用していたため、それを必須にするようにプレイを調整しました」と言う。
失敗するポイント。 1 つのメッセージが返信を得たという理由だけで、改善器が全体のトーンを書き換えることです。プロンプトの編集は、あなたの本能よりも小さくあるべきです。
ステップ 7. 変更をプルリクエストとして出す
これが制御層です。Codex がファイルを編集し、評価を実行し、PR サマリーを書きます。人間がレビューしてマージします。

prompts/pr_summary.md を作成します:
1このアウトバウンド改善のプルリクエストサマリーを書いてください。23含める:41. 何が変わったか。52. なぜ変わったか、成果行を引用して。63. 変更前のスコア。74. 変更後のスコア。85. 変更されたファイル。96. リスク。107. 人間のレビュアーが確認すべきこと。1112簡潔にしてください。13変更がライブになったとは主張しないでください。
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"
PR はチームメイトが書いたように読めるべきです:
1変更:2- implementation_page_visit を 4 から 6 に引き上げました。34理由:5- KiteOps が実装ページの意図を持ち、実装のタイミングについて返信しました。6- 以前のスコアはこのアカウントを ignore にルーティングしていました。78変更前:9- eval score 0.751011変更後:12- eval score 1.001314レビュアー確認事項:15- 実装意図が十分に具体的であることを確認してください。16- 一般的なダウンロードは低く保ってください。17- 実際の営業判断と一致する場合のみマージしてください。
これが安全装置です。Codex は退屈な作業を行います。運用者が基準を維持します。
うまくいっている状態。 週に 1 件の PR、小さな差分、明確な理由、合格する評価。
失敗するポイント。 誰かがレビューを面倒に感じて、Codex にマージ権限を与えることです。その 1 分が、改善するシステムと漂流するシステムを分けます。
ステップ 8. リズムに乗せる
すべての返信の後にこれを実行しないでください。そうすると、システムが 1 つの声の大きいアカウントにオーバーフィットします。
週が経過し、成果が蓄積されるのを待ってから調整します。

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
次に cron:
10 8 * * MON cd ~/codex-self-improving-outbound && scripts/weekly_tune.sh
GitHub Actions を使用する場合も、同じ形状を維持します:
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
最初の 2 回の調整は手動で実行してください。すべての差分を読んでください。サンプルが少ないときに Codex が何を変更しようとするか観察してください。提案が退屈になったら、スケジュールに載せてください。
うまくいっている状態。 証拠、差分、評価結果とともに毎週 PR が現れます。マージ、編集、クローズのいずれかを行います。
失敗するポイント。 ジョブが実行され、誰もレビューせず、PR が積もることです。自己改善システムにも、1 つの人間の習慣が必要です。差分を読むこと。
クローンして実行するバージョン
リポジトリには、4 つのコマンドが同梱されているべきです:
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
期待される最初の実行:
1score=0.752changed config/scoring.yaml3implementation_page_visit: 4 -> 64score=1.005open PR for human review
オフラインデモはファイル契約を証明します。Codex の実行は編集ループを証明します。その後、サンプル成果を自分のものに置き換え、シグナル名を変更し、自分のプレイを追加し、システムが異なるルーティングをすべきだったアカウントを反映するフィクスチャを構築します。
配信を配線することから始めないでください。改善ループを証明することから始めてください。
フルバージョン: max
このリポジトリは手動層です。ファイル、公開シグナル、およびあなたの Codex プランから実行されます。すべてのルールが公開されているため、形状を教えてくれます。
yourmax.ai は、継ぎ目が隠された同じシステムです。
自分で配線するリポジトリではなく、max はあなたが直接使用するエージェントです。市場の動きを検出し、誰に、なぜ今連絡する価値があるかを判断し、あなたの承認のためにメールと LinkedIn 全体にアウトリーチをドラフトし、成果から改善を続けます。
リポジトリは、ほとんどのチームが決して構築しない自己調整層を示しています。成果は提案されたルール変更になり、提案されたルール変更はゲートを通り、人間のマージが何をライブにするかを決定します。max は同じ運用ロジックを採用し、管理されたシステムとして実行します。
完全なリポジトリをご希望の場合は、お知らせいただければお送りします。





