PR

なぜAIの「自律ループ」を捨てたのか?エージェントに不可逆な操作をさせない「直線パイプライン」と二層防御の現場設計

AI・自動化・開発
この記事の要約(TL;DR):
  • 課題: AIエージェントに「納得いくまで自分で修正させる」無制限な自律ループを組むと、反復によってコンテキストが肥大化し、重要な指示が埋もれたり、APIコストが予測しにくくなったりする問題が起こりやすくなります。
  • 解決策: 無制限なループを廃止し、「初稿 ➔ 冷徹査読 ➔ 最終清書」の「固定ステップの直線パイプライン」に切り替えることで、処理速度の向上とトークン消費の極小化を両立しました。
  • ハイブリッド運用: 思考や文章生成はLLM(Gemini 3.8 Flash等)に任せ、マークダウン記法やテーブル整形などの規律は「決定論的なPythonスクリプト(正規表現)」で一瞬で完結させます。
  • 安全設計: SNS発信やファイル破壊などの「取り消せない操作」には、AIによる下準備(安全圏)と人間による確認(承認ゲート)を分離する「二層防御(Two-Tier Guardrails)」を組み込むことが実運用の鉄則です。

1. はじめに:AIエージェントの「自律的な無限ループ」という罠

コーヒー豆の焙煎の合間に、自作のAIエージェントシステム(Ann)をMac上で動かしながら、ブログ執筆や日々の情報発信の自動化を進めています。

エージェント開発を始めた当初、多くのチュートリアルが推奨するように、私は以下のような「自律的なフィードバックループ」を組み込んでいました。

設計思想 処理の流れ 実際に発生した現場の課題
自律ループ型(以前) AIが初稿作成 ➔ AIが自己採点 ➔ 95点未満ならAIが自動で書き直す(合格するまでループ) APIクォータが数時間で枯渇し、ターンを重ねるほど文章が不自然に劣化しやすい。
直線パイプライン型(現在) 初稿作成 ➔ 冷徹査読 ➔ 最終清書の「固定ステップ(直線型)」で完結 処理時間が数秒に短縮され、トークン消費が予測可能になり、文章の破綻が大幅に減少する。

「AI自身に採点させ、基準に達するまで自分で修正させれば、寝ている間に完璧なアウトプットが出来上がるのではないか」という期待は、運用開始から数日で打ち砕かれました。

なぜ自律ループは破綻しやすいのか、そしてなぜ「直線型」に行き着いたのか、その理由から振り返ります。


2. なぜ「無制限な自律ループ」を廃止したのか?3つの失敗要因

実際にループを回し続けて痛感したのは、以下の3つの構造的な問題でした。

① 会話履歴の肥大化による「文脈腐敗(Context Rot)」

LLMは、1つのセッション内で対話ターンが増えると、過去の試行錯誤や不要な修正指示までコンテキスト内に残りやすくなります。その結果、初期の前提条件の重み付けが薄れ、本来守るべき大前提やトーン&マナーを外れたり、堂々巡りの修正を繰り返す傾向が見られました。

② APIクォータとコストの予測不能な急増

「合格点に達するまで繰り返す」という条件分岐は、1回のタスクで消費されるトークン数を予測不能にします。わずか1記事の下書きを生成するためにAPIのレートリミットや1日の利用枠(RPD)を激しく消費してしまい、他の作業がストップする本末転倒な事態が起きました。

③ 欠陥の自己強化

AI自身に「自分の書いた文章を批評させる」と、自分の論理の破綻や不自然な比喩を正当化してしまい、修正すればするほど文章が読みにくくなる現象が確認されました。

これらの経験から、私は「無制限の自律ループをシステムから廃止する」という決断を下しました。


3. 解決策:「直線パイプライン」と決定論的スクリプトのハイブリッド

036Factoryで現在採用しているのは、「初稿作成 ➔ 冷徹査読 ➔ 最終清書」という、後戻りしない固定ステップの「直線パイプライン」です。

自律性を無制限に開放するのではなく、タスクごとに「固定回数のステップ」で上限を区切ります。そしてここで極めて重要なのが、「すべてをLLMにやらせない」という役割分担です。

工程 担当エンジン 役割と遵守ルール
Step 1: 初稿作成 LLM(Gemini 3.8 Flash等) 素材と要点を元に、全体の骨格とストーリーを一気に書き出す(余計な推敲を挟まない)。
Step 2: 冷徹査読 LLM(特化監査プロンプト) 「〜である」という過度な断定を排除し、「〜しやすい」等の客観表現へ是正。論理の穴を指摘。
Step 3: 最終清書・整形 Pythonスクリプト(正規表現) マークダウン記法、太字のカッコ位置、テーブル構造の自動変換を一瞬・0トークンで機械的に適用。

なぜ整形を「コード(正規表現)」に任せるのか?

マークダウンの記法ブレ(例: WordPressエディタで崩れない太字記法やHTMLテーブル変換)の修正をLLMに指示すると、また新たな文脈が生まれ、別の箇所が勝手に書き換わるリスクがあります。

「思考や文章の生成はLLM(確率的処理)、形式の統一や構文チェックはPythonスクリプト(決定論的処理)」という二分法をとることで、トークン消費をゼロに抑え、高い再現性で確定ファイルが出力できるようになりました。


4. もう一つの防衛線:「取り消せない操作」に対する二層防御

直線パイプラインによって「生成」の安定性は確保できましたが、エージェントを自動化する上でさらに危険なのが「取り消せない操作(不可逆操作)」です。

不可逆操作の危険性

  • SNSへの即時ポスト(XやThreadsでの誤爆・重複投稿)
  • WordPress記事の本番公開・既存記事の破壊的上書き
  • データベースや重要な設定ファイルの削除

これらをAIに「全自動」で実行させると、万が一の誤認やバグが生じた際に致命的な事故に繋がります。

そこで構築したのが、「二層防御(Two-Tier Guardrails)」というアーキテクチャです。

二層防御の構造

【レイヤー1:AI全自動の安全圏(ドラフト領域)】
・データの収集、下書き生成、画像レンダリング、構文検証
・状態: draft / pending / dry-run
・保存先: ローカル一時領域、SQLiteキュー、Obsidian Drafts

          ▼ [境界線:Human-in-the-Loop(人間の承認ゲート)]

【レイヤー2:人間承認によるコミット(本番領域)】
・専用Webダッシュボード(localhost:8036)での目視確認
・CLI引数における「--apply」の明示指定
・人間が引き金を引いた場合のみ、本番API(SNS投稿・WP公開)へ送信

実装例:不可逆操作の影響を抑える「Safety Guard」モジュール

ツール群の安全性を担保するため、以下の2つの防衛線を1つの軽量Pythonモジュール(scripts/safety_guard.py)として標準装備しました。

  1. ファイル変更前の自動スナップショット退避(Safe Shadowing)
  2. デフォルトDry-Run & 実行確認ゲート(Confirmation Gate)
import sys
import shutil
from pathlib import Path
from datetime import datetime
from typing import Optional

BACKUP_DIR = Path("archive/backups")

def create_safe_backup(file_path: Path) -> Optional[Path]:
    """
    ファイルを上書き・変更する直前に、タイムスタンプ付きで自動退避する。
    (ファイル操作などの破壊的変更を、直前のスナップショットにより復旧可能にする)
    """
    p = Path(file_path)
    if not p.exists():
        return None
    BACKUP_DIR.mkdir(parents=True, exist_ok=True)
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_file = BACKUP_DIR / f"{p.stem}_{timestamp}{p.suffix}.bak"
    shutil.copy2(p, backup_file)
    print(f"💾 [Safety Guard] 安全バックアップ作成: {backup_file.name}")
    return backup_file

def confirm_action(action_name: str, target: str = "", force_flag: str = "--apply") -> bool:
    """
    不可逆操作を実行する直前のゲートキーパー。
    明示的なフラグがない限り、シミュレーション(Dry-Run)で安全に停止する。
    """
    if force_flag in sys.argv or "--force" in sys.argv:
        return True

    print(f"\n🛡️ [Safety Guard] 不可逆操作を検知: 【{action_name}】")
    if target:
        print(f"   対象: {target}")

    # 対話環境(TTY)であれば確認を促す
    if sys.stdin.isatty():
        resp = input(f"   実行する場合は '{force_flag}' を指定するか [y/N] を入力: ")
        return resp.strip().lower() in ["y", "yes"]

    # バッチ・自動実行時は安全側に倒して中断(Dry-Run)
    print(f"⚠️ [Safety Guard] 対話モード外です。実行には '{force_flag}' の明示付与が必要です。")
    return False

マルチエージェント間通信も「ファイル境界」で疎結合にする

036Factoryでは、全体統括を行う「Ann」とnote展開を担当する「Ren」という複数のエージェントが協調して動作しています。

ここでもエージェント同士を直接API(HTTPリクエスト等)で接続せず、muse_inbox/ というローカルディレクトリ(ファイル受渡箱)を介した非同期キュー方式をとっています。
一方のエージェントが直接APIで他方を呼び出さないため、障害や例外の影響範囲をファイル受け渡し単位に限定し、システム全体の疎結合と耐障害性(レジリエンス)を高めています。


5. まとめ:自律性の「上限」を設計することが、最も堅牢な自動化をつくる

AIエージェントの運用を続ける中で行き着いた結論は、「自律性を最大化するのではなく、タスクごとに自律性の上限を設計すること」こそが、最もコストが低く、持続可能なシステムを作るということです。

  1. 無制限な自律ループを廃止し、「直線パイプライン」にする(迷走ループの防止)
  2. フォーマット整形はLLMではなくPythonスクリプトに任せる(確率的処理と決定論的処理の分離)
  3. 下準備はAIに任せ、最後の本番送信は人間が承認する(二層防御・Human-in-the-Loop)
  4. 不可逆な操作にはデフォルトでDry-Runとファイル自動バックアップを義務付ける(事故防止)

コーヒーの焙煎でも、生豆の選別や温度管理などの下準備は徹底して行いますが、最終的に「煎り止め」のダンパーを引く瞬間は、焙煎士自身の目と鼻で判断します。

AIエージェントも全く同じで、AIが得意な「徹底した下準備」と、人間にしかできない「最終確認の引き金」を正しく切り分けることが、心地よい協業の第一歩だと感じています。

☕ 記事の執筆・開発の合間に「普通のコーヒー」を焼いています

036 Factoryの本業は、ご注文をいただいてから生豆を一粒ずつ手作業で選別(ハンドピック)して焙煎する、小さな自家焙煎珈琲工房です。

PC作業やAIとの対話で加熱した頭をふっとリセットする、雑味のない「毎日飲める普通のコーヒー」を少数精鋭で焼いています。この記事が少しでもお役に立ちましたら、ぜひ一度うちの工房を覗いてみてください。


タイトルとURLをコピーしました