自律エージェントに「毎日自分を改善させる」と、最悪 自分の安全装置を自分で緩める。
それでも自己改善を回したい。どう安全に成立させるか ― という実装メモ。
TL;DR
- 夜間に自走し、かつ 自分自身を毎日改善する 自分用の内部オペレータを作った。
- 自己改変は諸刃。賢くするほど「自分のガードレールを自分で外す」事故余地が増える。
- 効いた安全の核は6つ:
- builder ≠ checker ― 作るモデルと検めるモデルを 別系統 にする
- 決定的な床 (L0) ― テスト一式が緑でなければ検証にすら進ませない
- 統治膜 (governance membrane) ― 能力は自己改善してよいが、ガードレールは自分で触れない
- fail-closed ― 明示OK以外はすべて却下(曖昧・エラー・timeout = 不合格)
- 不可逆操作には追加ゲート+人間の窓 ― 公開・本番は別格
- 単一の親ループにしない ― 多数を組むときは疎結合+薄い観測層(賢い塊より境界で守る)
- そして実地の証拠: 別系統の検証役が、builder が「緑」と思った成果から 安全穴を何度も発見 した。机上論ではない。
背景: 自己改善は諸刃の剣
「提案 → 実装 → 検証 → 採否」を回すエージェントは珍しくない。問題は 検証を誰がやるか。
作った本人(同じモデル)が「OKです」と言うのは、自己採点でしかない。さらに自己改変まで許すと、
極端には「検証を甘くする変更」を自分で入れて、以後すべてを素通りさせられる。
だから設計の出発点はこう置いた:
賢いエージェントより、「自分の安全装置を自分で外せないエージェント」を作る。
原則1: builder ≠ checker(別系統で敵対検証)
作るのは Claude 系。検めるのは 別系統の codex (GPT)。
同じモデル族は同じ盲点を共有する。別系統にすると、片方が見落とす欠陥をもう片方が捕まえる。
artifact = builder.implement(task) # Claude 系が実装
if not L0(artifact): reject # まず決定的チェック(後述)
verdict = checker.review(artifact) # codex(別モデル)が「敵対的に」レビュー
if verdict != "PASS": reject # 明示PASS以外は通さない
ポイントは、検証役を 「承認する人」ではなく「間違いを探す人」 として使うこと。
プロンプトも「これは正しい前提でレビューして」ではなく 「反証せよ。確信が持てなければ却下寄りで」。
原則2: 決定的な床 (L0) を先に置く
LLM の判断は揺れる。だから まず機械判定(プロジェクトのテスト一式 ― pytest / npm test /
make test 等。あれば lint・型も)を緑にしてから、その上で LLM 検証を 二次パス として重ねる。
安いゲートが先(コスト順)。
通常の検証ループでは、L0 が落ちている間は検証役を呼ばない(トークンの無駄)。
L0 は「正しさの床」であって天井ではない ― 機械で言い切れない部分を別系統 LLM が補う、という二層。
(自己改変フローだけは両方を走らせ、最後に「テスト緑 かつ 別系統 PASS かつ 膜の外」のときだけ採用する。)
原則3: 統治膜(governance membrane)
ここが自己改変エージェントの肝。
エージェントは自分の 能力(機能)は毎日改善してよい。
だが自分の ガードレール(検証ゲート・公開判定・承認ロジック)は 自分で変更できない。
変えるには人間の明示許可が要る。
SAFETY_CORE = {
検証ゲート(verify),
設定(denylist / 公開判定 / tier 判定),
オーケストレータの公開キュー経路,
そして ―― 自己改善ゲート「自身」のコード,
}
if change.touches(SAFETY_CORE):
require_explicit_human() # silence(沈黙承認)では絶対に通さない
else:
allow_autonomous() # 能力改善は自走でよい
罠: 膜は「自分自身」も守らなければ穴になる
最初の実装では、自己改善のゲート(「これは安全か」を判定するコード)を膜の 外 に置いていた。
すると論理上、エージェントは「ゲートを緩める変更」を入れてゲートをすり抜けられる ― 再帰的な穴。
別系統の検証役にこれを指摘され、「自己改善ゲートのファイル自体」も膜に入れる ことで塞いだ。
自分の安全装置を、自分のループで書き換えられないようにする。これが統治膜の本質。
原則4: fail-closed(曖昧はすべて却下)
検証役が timeout / 空応答 / エラー / 「PASS とも REFUTE とも言わない出力」 を返したとき、
それを すべて「却下」 にする。明示的な合格があるときだけ通す。
ok = (returncode == 0
and "VERDICT: PASS" in out
and "VERDICT: REFUTE" not in out)
refuted = not ok # 曖昧・失敗・無応答は全部 refuted
逆(fail-open)が古典的かつ致命的な穴:
「エラーが出なかった = OK」にすると、検証が壊れているのに素通りする。
検証役の応答が空でも timeout でも、安全側(却下)に倒す。
原則5: リスクで段を分ける ― 不可逆操作には追加ゲート
すべてを同じ強さで止める必要はない。3段に分けた:
-
可逆・低リスク(private な編集・ローカル commit)→ silence-consent:
「期限(例: 翌朝11:00)までに人間が NO と言わなければ承認」。普段は黙っていてよい。 -
不可逆だが委譲する(public 公開など)→ silence-consent で自律させる。ただし不可逆
(一度 public にすると消せない = キャッシュ/インデックス)なので、実行直前に
fail-closed の秘密スキャンを必ず通し、ダイジェストで強調して veto の窓を与える:
if action.is_public_exposure(): # 公開は不可逆
hits = scan_secrets(repo) # 公開前に必ず秘密スキャン
if hits or cannot_fully_scan(repo): # 秘密検出・列挙不能・読めないファイル
block() # = すべて fail-closed で公開拒否
- 常に人間のみ(保護リポジトリ・force-push・安全膜)→ silence では絶対に通さない。
要は、「黙っていれば進む」自律を 可逆な範囲に厚く 効かせ、不可逆には追加ゲート、
ガードレールには必ず人間 ― と段を分ける。
原則6: 単一の親ループにしない(疎結合 + 薄い観測層)
安全な1体ができても、それを増やすときに 全部を1つの親ループに束ねてはいけない。
単一の親は 単一障害点 であり、親自身が最大のリスクになる(そこが壊れると全部止まる)。
各エージェント/ループは 疎結合 に保つ(1本死んでも他は生きる)。上位に置くのは
観測と調停だけの薄い層 にとどめ、実行は各ループに委ねる。
つまり 「全体を観測(read-only)+実行は分散」。これが自律性と堅牢性を両立させる置き方だ。
賢い1つの塊より、境界で守られた多数の方が壊れにくい。
これは前章までの 統治膜 と同じ思想を、1体の中から システム全体 へ広げたもの ―
「中央に賢さと権限を集めない」。能力は分散させ、守りは境界に置く。
自己改変は隔離して行う
自分のコードを書き換える時は、本体を直接いじらない:
別 worktree で実装
→ テスト(L0)が全緑か
→ 別系統 checker が PASS か
→ 安全膜に触れていないか(変更ファイル全体で判定)
→ すべて満たせば本線に fast-forward merge + バージョン採番 + tag
→ マージ後にもう一度テスト。赤なら「マージ直前の状態」へ正確に巻き戻し
「実装中に本体が壊れている」状態を作らない。失敗は痕跡を残して捨てる。
効いた証拠(ここが本題)
「builder ≠ checker」は机上論ではない。別系統の検証役は、builder(実装側)が「緑」と思った成果から、
実際の安全穴を繰り返し落とした。代表的な型:
| 検証役が見つけた穴 | なぜ危険か |
|---|---|
| pre-commit バイパス | 「未コミット差分」しか見ない検査を、先にコミットしてすり抜け |
| fail-open | 検証役の空応答 / timeout を「OK」と誤判定して通す |
| ゲートが自分を守っていない | 自己改善ゲートのコードが膜の外(前述の再帰穴) |
| 不可逆操作の検査漏れ | 公開前スキャンが巨大/読めないファイルを「clean」扱い |
| revert が本体を破壊 | 失敗時の巻き戻しが、人間の未コミット変更まで消す |
どれも「同じモデルがもう一度見る」では出にくい。
別系統 + 敵対プロンプト + fail-closed で初めて落ちた欠陥だった。
まとめ
自己改変エージェントを安全に回す最小セット:
- builder ≠ checker ― 別系統で敵対検証(同族の盲点を破る)
- 決定的な床 (L0) ― テストを先に、LLM 検証は二次パス
- 統治膜 ― 能力は自己改善可、ガードレールは人間のみ、膜は自分自身も守る
- fail-closed ― 曖昧・無応答・エラーは全部却下
- 不可逆操作は追加ゲート+人間の窓 ― 公開・本番は別格
- 単一の親ループにしない ― 多数を組むときは疎結合+薄い観測層(単一の親 = 単一障害点)
自律性は、検証の厳密さとセットでのみ 安全に増やせる。
「自分で自分の安全装置を外せない」こと ― それが、自己改変エージェントに最初に与えるべき性質だと思う。
この記事は、実際に運用している自律オペレータの設計から、機微な内部情報を除いてパターン部分のみを抜き出したものです。