v2.2.1 の組み込み Guide スキルを使い始めて2週間ほど経った頃、私はひとつのコミットを危うくそのまま通しかけました。Guide には「テーブルは HTML の <table> で書く」と明記してあり、それまでの15コミットすべてが従っていたので、16本目もざっと眺めて承認しようとしたのです。実際にはそのコミットだけ Markdown のパイプ記法に戻っていました。
問題はエージェントが間違えたことではありません。遵守率が上がったことで、私が見るのをやめかけた ことです。Guide スキルは確かに効きます。けれども効くからこそ、残った数パーセントの違反が一番見えにくい場所に隠れます。助言レイヤと、確実に違反を止める決定論レイヤをどう噛み合わせるか。私が個人開発で複数のリポジトリを回す中で固めた設計を、順を追ってお見せします。
組み込み Guide スキルは確率的な遵守率の引き上げ
v2.2.1 で入った組み込みの Guide スキルは、リポジトリやプロジェクトに紐づく恒常的な指示をエージェントに持たせるための仕組みです。AGENTS.md に散らばっていた「このリポジトリではこう書く」というルールを、エージェントが毎セッション参照する前提の場所へ集約できます。
私の手元では、導入前後で体感がはっきり変わりました。Guide を置く前は、5〜6コミットに1回くらいの頻度で「規約から外れた出力」が混ざっていました。Guide を置いたあとは、その頻度がぐっと下がります。
ただし、ここで誤解してはいけない点があります。Guide スキルがやっているのは遵守率の引き上げ であって、保証ではありません。モデルの出力は確率的なので、同じ Guide を読んでいても、文脈が長くなったり似た指示が競合したりすると、ときどき外します。「ほぼ守る」と「必ず守る」の間には、運用上は大きな溝があります。
遵守率が上がるほど、残った違反は見えにくくなる
ここが今回の核心です。直感に反しますが、Guide スキルの遵守率が高いほど、レビューする側の注意力は落ちます。
人間のレビューは、違反を「ときどき見つける」状態だと緊張感が保たれます。ところが10本中9本以上がきれいに通ると、無意識に流し読みへ移行します。私が16本目を承認しかけたのは、まさにこの状態でした。Guide が効くほど、私自身が検出器として鈍化していたわけです。
この性質は、率で考えると整理できます。仮に1本あたりの違反確率が25%から5%へ下がったとします。違反は5分の1になりますが、人間が各コミットへ割く注意は、頻度が下がるほど比例以上に薄くなります。結果として「すり抜けた1本が本番に届く確率」は、必ずしも下がりません。 助言だけで運用を閉じてはいけない理由は、品質が悪いからではなく、品質が良くなったがゆえの油断にあります。
助言レイヤ(Guide)には「判断の前提」を書く
では Guide には何を書くべきでしょうか。私は「機械が後から検査できないこと」を中心に置いています。
なぜこのリポジトリが HTML テーブルを使うのか(描画系が GFM を解釈しないという背景)
コミットを小さく保つ理由(レビューを差し戻し可能な単位にしたい)
命名や語調の方針(読者に向けた敬体、誇張表現を避ける)
逆に、機械的に検査できる規約(テーブル記法、ファイルの対応関係、禁止語)は Guide に「書いてもよい」ものの、そこに頼り切らない 前提で置きます。Guide は方針の共有、検査は別レイヤ、という役割分担です。
# Repository Guide (抜粋)
## 表組み
- 表は必ず HTML の <table> で書く。Markdown のパイプ記法は描画が崩れる。
- 背景: このプロジェクトのレンダラは GFM テーブル拡張を読み込んでいない。
## コミット粒度
- 1コミット = 1つの意味のある変更。機械置換と意味の変わる変更を混ぜない。
- 理由: レビュアーが「ここだけ戻す」を選べる単位を保つため。
## 語調
- 読者向けの文章は敬体(です・ます)で統一する。
- 誇張語(最強・爆速・神)は使わない。
この Guide を読んだエージェントは、ほとんどの場合 HTML テーブルを書きます。「ほとんど」を「必ず」に変えるのが、次の決定論レイヤです。
決定論レイヤ:検査できる規約はコードで止める
機械的に判定できる規約は、文章で頼むのではなくコードで弾きます。ポイントは、ゲートが真偽だけを返す こと。曖昧さを持ち込まないことです。
以下は、Guide に書いた3つの規約のうち「機械検査できる2つ」を検証する最小のゲートです。エージェントが生成・編集した出力を受け取り、違反があれば終了コード1と違反内容を返します。
#!/usr/bin/env python3
"""guide_gate.py — Guide のうち機械検査可能な規約を決定論的に検証する。
exit 0 = 合格 / exit 1 = 違反(違反内容を stdout に出す)"""
import re
import sys
from pathlib import Path
# 規約1: Markdown パイプ表(コードフェンス外)を禁止し HTML <table> を強制
TABLE_SEP = re.compile( r " (?m) ^\s * \| ? [ : ] * - {2,} [ : ] * (?: \| [ : ] * - {2,} [ : ] * ) + \| ? \s * $ " )
# 規約2: 禁止語(誇張表現)
BANNED = [ "最強" , "爆速" , "神レベル" , "完全網羅" ]
def strip_code (text: str ) -> str :
text = re.sub( r "``` . *? ```" , "" , text, flags = re. DOTALL )
return re.sub( r "` [ ^ ` \n ] * `" , "" , text)
def check (path: Path):
body = strip_code(path.read_text( encoding = "utf-8" ))
issues = []
if TABLE_SEP .search(body):
issues.append( "markdown-table: パイプ記法の表を検出。<table> に変換すること" )
for w in BANNED :
if w in body:
issues.append( f "banned-word: 禁止語『 { w } 』を検出" )
return issues
def main ():
failed = False
for arg in sys.argv[ 1 :]:
issues = check(Path(arg))
if issues:
failed = True
print ( f "[NG] { arg } " )
for i in issues:
print ( f " - { i } " )
else :
print ( f "[OK] { arg } " )
sys.exit( 1 if failed else 0 )
if __name__ == "__main__" :
main()
コードフェンスの中の例示テーブルを誤検出しないよう、strip_code() で先にコードブロックを除去しているのが実装上の勘所です。最初に書いたときは、記事内のサンプルテーブルにゲートが反応して延々と差し戻しが続きました。これは「検査対象から例示を外す」という、検証ゲート共通の落とし穴です。
違反をエージェントへ差し戻す再実行ループ
ゲートが違反を返したとき、人間が直すのではなく、違反内容をそのままエージェントへ返して直させます 。Guide が方針、ゲートが事実判定、差し戻しが修正の駆動、という三者が噛み合うと、運用がほぼ無人で回ります。
#!/usr/bin/env bash
# regenerate_until_clean.sh — ゲートが通るまでエージェントに修正させる
set -euo pipefail
MAX_RETRY = 3
TARGET = " $1 " # 検証対象ファイル
for attempt in $( seq 1 " $MAX_RETRY " ); do
if python3 guide_gate.py " $TARGET " ; then
echo "✅ ゲート通過(試行 ${ attempt } 回目)"
exit 0
fi
echo "↩️ 違反を差し戻して再生成(${ attempt }/${ MAX_RETRY })"
# ゲートの出力をそのままエージェントへ渡し、当該ファイルだけ直させる
VIOLATIONS = "$( python3 guide_gate.py " $TARGET " || true )"
agy run --file " $TARGET " --instruction "次の違反のみ修正せよ。他は触るな:
${ VIOLATIONS }"
done
echo "🛑 ${ MAX_RETRY } 回で収束せず。人間のレビューへエスカレーション。"
exit 1
agy run は私の環境での呼び出し例なので、実際の起動方法は手元の構成に合わせてください。重要なのは引数の設計です。差し戻し時に「次の違反のみ修正せよ。他は触るな」と範囲を絞ること。これを書かないと、エージェントが違反箇所のついでに無関係な行まで書き換え、レビュー範囲が膨らみます。再実行の上限(ここでは3回)を超えたら人間へ上げるのも必須で、無限ループはトークンを静かに溶かします。
効果:助言だけと、助言+ゲートの比較
私が4つのリポジトリで2週間運用した範囲での比較です。母数は手作業の集計なので厳密な統計ではありませんが、傾向ははっきり出ました。
構成 規約違反の発生率 本番へのすり抜け 1件あたり差し戻し時間
Guide なし 約 4本に1本 月に複数回 手動修正で長い
Guide のみ(助言) 約 20本に1本 ゼロにならない 気づけば短い/見落とすと長い
Guide + 決定論ゲート 約 20本に1本(発生率は同じ) 0 (ゲートで全捕捉)自動差し戻しで約3分の1
注目してほしいのは、Guide とゲートを足しても違反の発生率そのものは変わらない 点です。ゲートは発生を減らす道具ではなく、発生したものをプロダクションへ届かせない道具です。本番運用に乗せる直前で確実に止められるかどうかが、放置運用の安心感を左右します。役割が違うので、どちらか一方では運用が閉じません。違反率を下げるのは Guide、すり抜けをゼロにするのはゲート、という分担を最初から意識すると設計が素直になります。私としては、検査できる規約はすべてゲート側へ寄せることを推奨します。Guide にも書いておく場合でも、合否判定の正本はあくまでコード側に置くのが安全です。
私の場合、この組み合わせにしてから、AdMob 連携まわりの設定ファイルのように「壊れると収益に直結するが見た目では気づきにくい」変更でも、ゲートが先に止めてくれる安心感が出ました。レビューの心理的な負荷が下がったのが、数値以上に効いた変化です。
次の一歩
具体的には、次の3手順から始めるのがお勧めです。
いま AGENTS.md に書いている規約を「人間が背景を理解すべき方針」と「機械が真偽判定できる規約」の2つに仕分けます。
前者は Guide スキルへ集約し、後者は10行ほどの決定論ゲートに落とします。
最初の1本は、自分が過去に一度でもすり抜けを許した規約を選び、差し戻しループに繋いで放置運用を試します。
この順で進めると、効果がすぐ体感できます。助言が効くほど検査が要る、という逆説を運用に組み込めるかどうかが、エージェントを長く放置運用できるかの分かれ目だと感じています。