智能体
dev.to ·
@Debashish Ghosal
我做了两个 agent 系统,它们各自证明了对方是错的
作者构建了两个 agent 系统:一是 PlannerCritic,采用草稿→批评→修订的有界循环,由另一个模型批评计划并迭代直至收敛或升级人工;二是让两个 LLM 就一个 pull request 进行辩论。作者称两者各自失败在对方设计要防的地方,这也是他信任它们的原因。他尝试让 critic 更对抗性,结果 critic 开始以“不够详尽”为由拦截计划,于是把严重性契约从 prompt 移到代码中的 frozenset 以防漂移。在 170 个目标、花费 0.49 美元的现场测试中,critic 的 label_flip_rate 为 1.0(相同输入下标签翻转)。
AI推荐理由 作者构建了两个 agent 系统:PlannerCritic(草稿→批评→修订的有界循环)和双 LLM 辩论 PR 的系统,并指出两者各自失败在对方设计要防的点上。文中给出具体实验数据:170 个目标、成本 0.49 美元,以及 critic 的 label_flip_rate 为 1.0(相同输入下标签翻转),并说明把严重性契约从 prompt 移到代码中的 frozenset 以避免漂移。这是有具体数字和工程教训的开发者实践,对 agent 可靠性设计有参考价值;但正文截断,结论的普适性需自行验证。
74
正文
I built one engine where an LLM reviews another LLM's plan. I built another where two LLMs debate a pull request.
Each one failed in the way the other was designed to prevent. That's the only reason I trust either of them.
If you're putting your safety in a prompt, both stories end the same way.
System One: The Critic I Couldn't Make Reliable — Or Needed To
PlannerCritic runs a draft → critique → revise loop: one model writes a plan, another critiques it, and a bounded loop revises until it converges or escalates to a human.
My first instinct was the obvious one: tell the critic to be adversarial. That's a prompt fix for what I thought was a behavior problem.
It backfired. The critic started blocking plans for being "not thorough enough," which is a useless verdict. I had to move the severity contract out of the prompt and into a frozenset in code, where it couldn't drift.
Here's what the field test showed on 170 goals for $0.49:
Critic label_flip_rate: 1.0 — on identical input, it changed its verdict every single trial.
Critic evidence_drift_rate: 1.0 — its justification moved too.
underclaim_approvals: 0 — it never knowingly let a seeded defect through.
family_migration_rate: 0.0.
True failures: 0.
A maximally non-deterministic critic was completely safe. Not because it was reliable — because the deterministic gates owned the under-claim direction, and the critic was never allowed to be the safety boundary. The numbers are in the v0.2.1 field test results.
System Two: The "Debate" That Was Actually a Replay
AdversarialDebate does the opposite: two isolated models review the same PR and either converge on a verdict or preserve their disagreement.
The failure here was subtler. I asked the second model to be independent in the prompt. It looked like it worked. Then I read the raw logs: the "debate" was a stored replay, echoing text the first model had already generated.
89% of the second opinions were theater.
I tore out the prompt-level independence and enforced it mechanically — isolated contexts, no shared conclusion, evidence required per claim. Theater went from 89% to 0% across 217 debates, and on 411 debates against 70 real public PRs the system matched human review claims 81% of the time. Details in the v0.2.2 field test report.
The Convergence
Look at the two fixes side by side and they're the same fix.
System
Structural problem
Prompt attempt
What actually fixed it
PlannerCritic
Unreliable severity contract
"Be adversarial"
Severity contract in code (frozenset) + deterministic gates
AdversarialDebate
Fake independence
"Be independent"
Mechanical isolation invariant
Both times, the default instinct was to solve a structural problem with a prompt. Both times, the prompt was the wrong layer. The model was never the safety boundary — the architecture was.
Why This Generalizes (Cautiously)
This is a sample size of two, and both systems are mine, so take the convergence as suggestive, not proven.
But it's suggestive in a useful direction: if you can't make an LLM reliable, stop trying to. Make it irrelevant to safety. Let the nondeterministic part be as wild as it wants, and put the non-negotiable decisions in deterministic code that no prompt can override.
The Honest Limitation
The architectures aren't complete. PlannerCritic catches structural plan defects but not subtle logic errors. AdversarialDebate still has an unexplained 11.3% miss rate in narrative domains, and I can't fully account for it.
Nor is "two systems converged" proof of a universal law. It's two data points from one engineer. What I can defend is the direction: the failures were structural, and so were the fixes.
Where does the safety boundary live in your agent — in the prompt or in the code? I've been wrong about that in both directions.
Repos and receipts: planner-critic-engine · adversarial-debate · PlannerCritic failure-mode register — all MIT, all public.