今年早些时候,Andrej Karpathy(@karpathy)将一个 Agent 对准自己的训练代码,让它运行了两天。它跑了 700 次实验,保留了 20 次超过基准的结果,使模型训练速度提高了 11%。然后他说了一句很有意思的话:任何你能廉价评估的指标,都可以交给一队 Agent 来处理。
回复率就是一个能廉价评估的指标。此后我花了一些时间,研究将这个循环应用到对外联系场景会是什么样子。
我的构建方案:
Codex 读取上周的结果,修改对外联系系统运行时使用的评分文件和话术文件,运行一次测试,然后创建一个 pull request。它会将改动连同证据和评分一起提交到 playbook,然后等待人工批准。发送和合并操作被排除在循环之外。
这个第一循环我构建过几次:感知市场、给账号评分、根据信号撰写内容、检查消息、记录结果、从回复中学习。本文要讲的是第二循环——那个用来修改第一循环的循环。
这就是构建方案:将 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、不进行数据丰富、不接入投放系统。改进循环应该先在本地文件上证明自己,然后才能接近真正的对外发送系统。
第一步:先写规则
在编写评分文件、提示词文件之前,先写 AGENTS.md。这个文件能让 Agent 既有用又可控。
1# 自我改进对外联系规则23你根据结果改进对外联系系统。45硬性规则:6- 永远不要发送消息。7- 永远不要抓取或丰富真实用户数据。8- 永远不要自行合并。9- 只编辑本仓库中的文件。10- 一次只改动一个概念。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- pull request 摘要
规则的唯一用途:缩小工作范围。没有规则,Codex 就会试图通过扩大范围来帮忙。它会增加更多数据、触及更多文件、调用更多工具,或者自动化一个本应由人类控制的步骤。在这里,任务更小:读取结果,提议改动一个文件,证明改动有效,然后等待。
好的表现是什么样。 你可以在批准 PR 之前阅读规则,并确切知道 Codex 被允许做什么。
哪里会出问题。 规则变成了一份合规文档。如果 AGENTS.md 需要目录,那已经太大了。保持可操作性。
第二步:将判断逻辑移到配置中
大多数对外联系的判断逻辑存在于人的头脑中。然后团队购买软件,期望软件能改进它看不见的决策。
将判断逻辑移到一个文件中。
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 函数中。如果规则可见,团队就能审查它、讨论它、改进它,而无需将销售判断变成一次工程重构。
好的表现是什么样。 文件足够小,可以展开讨论。五个信号是一个不错的第一版。
哪里会出问题。 评分文件变成了杂物抽屉。二十个信号、六个阈值以及针对每个边缘情况的例外规则会导致改进器过拟合。从小处开始,让结果告诉你下一个调节旋钮应该放在哪里。
第三步:将结果作为记忆写入
最重要的文件是 memory/outcomes.jsonl。
每次接触一行,在结果已知时写入:
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 这类细节足以改变一个权重。
在构建改进器之前先构建验证器:
1构建 scripts/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 在下一次运行之前应该改变哪个信号、话术或短语。
好的表现是什么样。 一周后,一个陌生人可以读取该文件,并判断哪些信号产生了回复、哪些话术产生了不匹配的对话、以及市场忽略了哪些内部偏爱的选项。
哪里会出问题。 团队在周五凭记忆回填结果。胜利被保留,不匹配的原因变得模糊,系统从虚构中学习。在结果落地时立即写入该行。
第四步:构建评估关卡
在 Codex 编辑任何内容之前,它需要一个无法通过解释绕过的测试。
创建 evals/fixtures.yaml:
1cases:2 - account: Northwind Finance3 signals: [competitor_comparison, implementation_page_visit]4 expected: human_review5 note: "一个账号有两个强信号"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:
1构建 evals/score.py。23读取 config/scoring.yaml 和 evals/fixtures.yaml。45对每个案例:61. 对每个信号累加权重。72. 加上负面信号的惩罚。83. 对账号进行路由:9 - score >= thresholds.human_review => human_review10 - score >= thresholds.draft => draft11 - otherwise => ignore124. 将路由结果与期望结果比较。1314打印每个预测结果。15打印最终准确率,格式为 score=0.00 到 score=1.00。16仅在准确率为 1.00 时退出 0。
第一个关卡应该足够小以便理解,足够敏锐以捕捉真实的偏差。在我的第一次运行中,基准未能通过一个案例:
1Northwind Finance: predicted=human_review expected=human_review2Bluepeak Studio: predicted=ignore expected=ignore3KiteOps: predicted=ignore expected=draft4Atlas Recruiting: predicted=ignore expected=ignore5score=0.75
这很好。系统将实现意图置于草稿阈值以下,因此它忽略了一个测试用例认为应该发送消息的账号。最好在测试中捕捉到这一点,而不是在一个月后才发现丢失了大量账号。
好的表现是什么样。 一个命令给出一个数字,每个失败的案例都易于检查。
哪里会出问题。 测试用例只包含明显的成功案例。于是任何鲁莽的改动都能通过。在关卡中加入棘手的案例:弱意图、不匹配、无回复、过时信号,以及你希望系统当初跳过的账号。
第五步:让 Codex 提议一次评分改动
现在 Codex 可以编辑了。
创建 prompts/improve_scoring.md:
1你改进对外联系评分系统。23阅读:4- AGENTS.md5- config/scoring.yaml6- memory/outcomes.jsonl7- evals/fixtures.yaml89你的任务:101. 找出一条应该改变的评分规则。112. 理由必须引用 memory/outcomes.jsonl。123. 只修改 config/scoring.yaml。134. 运行 python3 evals/score.py。145. 如果评分提高,保留改动。156. 如果评分持平或下降,撤销你的编辑并停止。1617输出:18- 具体改动的行19- 导致该改动的结果行20- 改动前的评分21- 改动后的评分22- 该改动是否应该成为 PR2324不要编辑 prompts。25不要添加新信号。26不要触碰发送逻辑。
通过仓库封装运行:
1scripts/run_codex_step.sh improve_scoring
我的改进器第一个版本犯了一个有用的错误。它追逐了看起来最干净的回复信号。competitor_comparison 在微小的结果日志中拥有最高的回复率,因此改进器想要增加它的权重。评估结果保持在 0.75,因此改动被拒绝了。
这正是关卡存在的理由。一个较弱的系统会因为听起来合理而接受这个说法。而这个系统提出了一个更好的问题:改动是否修复了已知的遗漏?
第二次尝试找到了能起作用的最小改动:
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
这就是循环变得有用的时刻。它为了一个原因改变了一条规则,并通过对测试用例的证明验证了改动。

好的表现是什么样。 提议的 diff 枯燥且可追溯:改动了一行,附上了一条基于结果的理由,一个评估得到了改进。
哪里会出问题。 Codex 同时改变了三个权重和两个提示词。现在没人能说出哪个改动起了作用。保持规则严格:每个提案只针对一个概念。
第六步:分别改进提示词文件
评分只是系统的一半。消息模板也会退化。
上个月有效的行开始变得千篇一律。在一个细分领域中能获得回复的问题,在另一个领域中却无人理会。感觉犀利的措辞,到了市场上却遭到惩罚。将提示词改进视为独立的轨道,这样 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 - "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"
然后创建 prompts/improve_prompt.md:
1你改进一个对外联系话术。23阅读:4- AGENTS.md5- config/plays.yaml6- memory/outcomes.jsonl7- 所选话术的提示词文件89选择一个至少有 10 个结果的话术。1011找出:12- 在积极结果中出现的行或结构13- 在 no_reply 或 bad_fit 结果中出现的行或结构14- 任何应该被禁止的短语1516对该话术的提示词做一次小编辑。1718规则:19- 不要修改评分。20- 不要创建新的话术。21- 不要添加新的渠道。22- 引用结果行。23- 写出修改前后的指令。2425然后运行文案评估(如果有)。26如果没有文案评估,则将 PR 标记为 review_required。
有些改进可以自动评分。其他的仍然需要判断力。如果没有文案评估,Codex 可以提议提示词编辑,但它应该将 PR 标记为需要审查,而不是假装编辑已经得到验证。
好的表现是什么样。 Codex 说:“这个短语出现在七个 no_reply 结果中,所以我将其添加到了 banned_lines”,或者“积极回复引用了第一句中的实现细节,所以我收紧了话术要求。”
哪里会出问题。 改进器因为一条消息获得了回复就重写了整个语气。提示词编辑应该比你本能设想的更小。
第七步:以 pull request 形式发布改动
这是控制层。Codex 编辑文件,运行评估,编写 PR 摘要。人工审查并合并。

创建 prompts/pr_summary.md:
1为这次对外联系改进编写一个 pull request 摘要。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 应该看起来像是团队成员写的:
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.
这就是安全系统。Codex 做繁琐的工作。操作员坚持标准。
好的表现是什么样。 每周一个 PR,小的 diff,清晰的理由,通过的评估。
哪里会出问题。 有人因为审查感觉麻烦而允许 Codex 自行合并。那一分钟将系统从“改进”变成了“偏离”。
第八步:设定节奏
不要在每次回复后都运行。那样系统会过度拟合到某个突出的账号。
让一周过去,让结果积累,然后调优。

创建 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
前两次调优手动运行。阅读每个 diff。观察当样本量较小的时候 Codex 试图改变什么。一旦提案变得枯燥,就将其设置为定时任务。
好的表现是什么样。 每周一个 PR 出现,附带证据、diff 和评估结果。你可以合并、编辑或关闭它。
哪里会出问题。 任务运行了,但没人审查,PR 堆积如山。一个自我改进的系统仍然需要一个人为习惯:阅读 diff。
克隆即运行版本
仓库应该附带四个命令:
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 不是你自行组合的仓库,而是你直接使用的 Agent。它能检测市场动态,判断谁值得联系以及为什么现在联系,在邮件和 LinkedIn 上草拟对外消息供你审批,并持续从结果中改进。
这个仓库展示了大多数团队从未构建过的自我调优层:结果变成提议的规则改动;提议的规则改动通过一个关卡;人工合并决定什么变为实际运行。max 将相同的运行逻辑作为托管系统来运行。
如果你想要完整的仓库,可以告诉我,我会发给你。





