ANTIGRAVITY LABEN
記事一覧/Agents & Manager
Agents & Manager/2026-07-25上級

何本作ったかを指標にするのをやめた — 生成エージェントに「棄権」という結果を持たせる設計

バックグラウンドで走る生成エージェントの合否を『作った数』で測ると、品質ゲートは静かに緩んでいきます。ACCEPT / ABSTAIN / REJECT の三値と、棄権を成功として数えるSLO設計を、実運用のコードと実測とともに整理します。

Antigravity341エージェント設計15SLOバックグラウンド実行品質ゲート6

プレミアム記事

夜の 2 時過ぎ、スケジュール実行の完了通知が届きました。中身は「今回の生成物: 0 本」。当時の私はこれを失敗として扱っていて、翌朝いちばんに原因を調べ始めるのが習慣でした。

けれど、その 0 本はエラーではありませんでした。候補は生成されていて、品質ゲートがそのすべてを弾いていた。つまりゲートは正しく仕事をしていたのです。にもかかわらず、私の運用は「0 本=異常」という前提のまま組まれていました。

この記事は、その前提を反転させた記録です。バックグラウンドで走る生成エージェント — Antigravity 2.0 のスケジュールタスクやマネージドエージェントで、記事・アセット・レポートのような成果物を自律生成する構成 — において、「何本作ったか」を成功指標に据えると何が壊れるのか。そして合否に「棄権(abstain)」という第三の結果を持たせると、運用がどう変わるのかを、実際に動かしているコードとともに書きます。

スループットを指標にすると、ゲートは必ず緩む

生成エージェントを組むとき、最初に置きたくなる指標は「1 実行あたりの生成数」です。ダッシュボードに並べやすく、増減が一目でわかる。

ここに罠があります。生成数を成功指標にした瞬間、0 本の実行は「失敗」になります。失敗が続けばアラートが鳴り、運用者は無意識に手を打ちます。打てる手はふたつ。入力(題材・文脈)を良くするか、ゲートを緩めるか。前者は時間がかかり、後者は一行の変更で済む。

締切と疲労のなかで、人は安いほうを選びます。しきい値を少し下げる。「今回だけ」と例外を通す。こうしてゲートは、誰の悪意もないまま、少しずつ緩んでいきます。

私が個人開発で運用している生成パイプラインでも、まさにこれが起きました。生成数を追っていた時期は、平均すると毎晩何かしらが出ていた。けれど出ていたものの一部は、構文チェックは通るのに読者に何も残さない、薄い成果物でした。数は増え、価値は薄まる。指標は健康を示していたのに、システムは痩せていたのです。

対処は、指標の設計そのものを変えることでした。目指すべきは「純増か、さもなくば無」です。システムの平均品質を必ず引き上げる成果物だけを通し、そうでなければ何も出さない。凡庸な 1 本はマイナスであり、0 本はゼロ。ゼロはマイナスより上、という順序をコードに刻みます。

合否を三値にする — ACCEPT / ABSTAIN / REJECT

出発点は、ゲートの返り値を二値(通す/落とす)から三値に変えることです。

判定意味実行への寄与
ACCEPT純増と判断できる。公開してよい成果物を1つ確定
ABSTAIN悪くはないが純増とは言い切れない。今回は見送る成果物ゼロ。ただし失敗ではない
REJECT要件違反・破損・重複。通してはいけない成果物ゼロ。再生成の対象

二値ゲートの世界には ABSTAIN がありません。だから「悪くはないが、あえて出すほどではない」という最も多い状態が、ACCEPT 側に押し込まれてしまう。三値化の要点は、この中間帯に居場所を与えることです。

from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
 
 
class Verdict(str, Enum):
    ACCEPT = "accept"
    ABSTAIN = "abstain"
    REJECT = "reject"
 
 
@dataclass
class GateResult:
    verdict: Verdict
    reasons: list[str] = field(default_factory=list)
    signals: dict[str, float] = field(default_factory=dict)
 
 
class AcceptanceGate:
    """生成候補を三値で評価する。REJECT は要件違反、ABSTAIN は純増未満。"""
 
    def __init__(self, *, min_utility_signals: int = 3, novelty_floor: float = 0.35):
        self.min_utility_signals = min_utility_signals
        self.novelty_floor = novelty_floor
 
    def evaluate(self, candidate: "Candidate") -> GateResult:
        reasons: list[str] = []
 
        # --- 1) ハード要件: 1つでも欠けたら REJECT(純増以前の問題) ---
        if candidate.has_broken_frontmatter():
            reasons.append("frontmatter破損(YAMLがmap化して500になる)")
        if candidate.duplicates_existing(threshold=0.90):
            reasons.append("既存成果物と酷似(重複公開は純増でなく希釈)")
        if candidate.violates_policy():
            reasons.append("ポリシー違反(禁止語・要件外の逸脱)")
        if reasons:
            return GateResult(Verdict.REJECT, reasons)
 
        # --- 2) 純増の判定: 満たせないなら ABSTAIN(落とすのではなく見送る) ---
        utility = candidate.count_utility_signals()  # 動くコード/実測値/構造化手順...
        novelty = candidate.novelty_score()          # 既存コーパスとの差分
        signals = {"utility": float(utility), "novelty": novelty}
 
        if utility < self.min_utility_signals:
            reasons.append(f"実用性シグナル不足 {utility}/{self.min_utility_signals}")
        if novelty < self.novelty_floor:
            reasons.append(f"新規性が下限未満 {novelty:.2f} < {self.novelty_floor}")
 
        if reasons:
            return GateResult(Verdict.ABSTAIN, reasons, signals)
        return GateResult(Verdict.ACCEPT, ["純増と判断"], signals)

ここで意図的にやっていないことがあります。ABSTAIN の候補を「あと一歩だから」と自動で ACCEPT へ引き上げる処理です。near-miss の自動昇格は、緩みを再びコードの内側に呼び込むだけでした。中間帯は中間帯として、素直に見送る。これが後で効いてきます。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
合否を三値化するゲートの実装。ACCEPT / ABSTAIN / REJECT を理由つきで返し、near-miss の自動昇格を封じる
「作った数」から実行の成否を切り離す分類器と、棄権率を先行指標として読むメトリクス設計
グラウンディング欠落時に fail-closed で棄権する入力鮮度チェック。夜間の無人実行で沈黙して壊れない
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

Agents & Manager2026-07-16
AGENTS.md を厚くするほどルールが守られなくなった — 遵守率を計測して指示を削るまで
AGENTS.md に書いたルールが守られない。衝突でも読み込み失敗でもなく、単に無視されていました。ルールを検証可能な述語に分解し、遵守率を継続計測して指示を削るまでの運用記録です。
Agents & Manager2026-07-14
AGENTS.md を一行直したら挙動が崩れた — 指示そのものを回帰テストする仕組み
エージェントに渡す指示(AGENTS.md やスキル文)を直すたびに、別のタスクが静かに壊れます。コードでなく指示を被験体にした回帰ハーネスを、固定タスク集と決定的アサーションで実装し、無人運用に組み込むまでを示します。
Agents & Manager2026-07-10
エージェントが書いたファイルが .gitignore に飲まれる — commit 前に気づくための検出ゲート
エージェントが生成したファイルが .gitignore に一致していると、差分レビューでは正常に見えるのに commit には含まれません。ignored な生成物を push 前に検出するゲートスクリプトと、その運用調整をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →