0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントに「組織のルール」を渡すインフラを設計する

0
Posted at

Gemini_Generated_Image_jwx9gqjwx9gqjwx9.png

TL;DR

「組織固有のルールをAIエージェントにどう渡すか」を解決するRule Repositoryを提唱します。ルールをプロンプトに書く方式はスケールしません。RAG だと監査できません。ルールエンジンは非エンジニアによる保守が難しいでしょう。Rule Repository はこの課題に対し、自然言語ルール + ハイブリッド評価 + MCP/API ネイティブ統合というアプローチで取り組みます。本記事では、課題の構造と、Agentic システムを設計する際のアーキテクチャ判断を解説します。

レポジトリ:https://github.com/shibuiwilliam/rule-repository
ドキュメント:https://shibuiwilliam.github.io/rule-repository/


使い方

git clone https://github.com/shibuiwilliam/rule-repository.git
cd rule-repository
cp .env.example .env  # GEMINI_API_KEY を設定
docker compose up --build

http://localhost:3000 でUI、http://localhost:8000/docs でAPI、MCP は stdio で接続可能です。

image.png

image.png

image.png


Part 1: 課題定義 — エージェント時代の「ルール問題」

エージェントは汎用知で動いている

image.png

2026年5月現在、AIエージェントはコードを書き、メールを送り、経費を処理し、契約書をドラフトします。しかし、これらのエージェントが参照しているのは学習済みの一般知識であり、組織固有のルールではありません。もちろんプロンプトで情報やルールを入力することはできますが、エージェント活用のたびに人間が情報やルールを提供するのは手間でしょう。

どんな会社には以下のようなルールがあるはずです:

  • 「残業は月45時間まで。36協定届出済みの場合のみ例外」
  • 「30%以上の値引きにはVP承認が必要」
  • 「NDA契約には反社会的勢力排除条項を必須とする」
  • 「公開APIのエンドポイントにはrate limitを設定すること」

これらはConfluenceの奥、就業規則PDF、Slackのピン留め、CLAUDE.mdに散在しています。エージェントがこれらを構造的に参照する仕組みが必要といえます。

エージェント活用の「インフラ課題」としてのルール整備

image.png

個別のエージェントに個別のルールをプロンプトで教えることはできます。しかし組織スケールでは3つの理由で破綻します。

1. ルールは変わる。プロンプトは追従しない。

法改正、社内規程改定、例外条件の追加等々 —— ルールは絶えず変化します。10個のエージェントが同じルールを参照している場合、ルール変更時に10箇所を更新する運用は破綻します。Single Source of Truth が必要です。

2. 判定の監査ができない。

「なぜこのエージェントはこの経費を承認したのか?」に答えられません。LLMの推論過程は再現不能です。LLMリクエストを記録してトレースするツール(LangSmith、LangFuse等)はありますが、これは汎用的なLLMオブザーバビリティで、特定のルール管理と適用に適しているわけではありません。規制産業(金融、医療、人事)ではこれは致命的です。

3. ドメインを跨げない。

新規取引先との契約には、法務(反社条項)、財務(与信)、コンプライアンス(FCPA)、営業(支払条件)等、複数ドメインのルールが同時に適用されます。各部門が独立にルールを管理している限り、横断的な判定は人間の頭の中でしか行えません。

これは「ガバナンス」ではなく「インフラ」の問題です

ガバナンスと言うと「ルールを守りましょう」という組織論になりがちですが、ここでの課題は純粋に技術的なものと捉えます。

エージェントの実行パスに、組織ルールを低レイテンシで注入し、判定結果を構造化してレスポンスし、全判定を監査可能に記録するシステムをどう設計するか?

これが Rule Repository が解こうとしている問題です。


Part 2: エージェント時代にルール基盤が生む価値

image.png

価値1: ルール変更の伝播コストが O(1) になります

ルールリポジトリを更新すれば、全エージェントが次の呼び出しから新ルールを参照します。プロンプトの10箇所を更新する必要はありません。

価値2: 判定の説明責任を果たせます

「なぜこのエージェントはこの経費を承認したか?」→ 監査ログに「Rule #R-042 に基づき、金額が閾値以下であったため ALLOW」と記録されています。

価値3: 人間の修正がルールとして蓄積されます

エージェントの判定を人間が修正したとき、その差分パターンが新ルール候補として提案されます(Correction Flywheel)。組織知が自動的に形式化されていきます。

価値4: ドメイン横断の判定が可能になります

新規取引の契約を投入すると、法務・財務・コンプライアンス・営業の全ルールが一度に評価されます。部門の壁を超えた判定が API 一発で得られます。

価値5: 「エージェントを信頼してよいか」の判断材料が得られます

判定精度の推移、NEEDS_CONFIRMATION の発生率、人間による修正率——これらのメトリクスから、エージェントにどこまで自律性を与えるかをデータで判断できます。

Part 3: 既存アプローチの評価と比較

Agentic システムを設計する際、「ルールをどう扱うか」には複数のアプローチがあります。それぞれを比較検討します。

アプローチ1: プロンプト直書き

System: あなたはHRエージェントです。以下のルールに従ってください:
- 残業は月45時間まで
- 深夜勤務は管理職以外禁止
- 有給は年5日以上取得必須
...(200行続く)

課題:

プロンプトに注入する場合、コンテキストウィンドウを圧迫し、本来のタスクの精度が下がる可能性があるでしょう。また、判定の再現性がありません(プロンプトのバージョン管理が必要になります)。そしてドメイン横断が不可能です(全ドメインのルールを全エージェントに入れるのは非現実的です)。

アプローチ2: RAG(ルール文書を検索して渡す)

relevant_rules = vector_search(query=user_input, collection="rules")
response = llm.generate(context=relevant_rules, query=user_input)

課題:

毎回検索するため判定の一貫性が保証されません(embedding の近傍が変わりえます)。数値比較を LLM にやらせることにもなります(「52 > 45 か?」は計算であって推論ではありません)。また「どのルールに基づいて判定したか」を確定できず(検索結果は確率的です)、監査時に「同じ入力を入れたら同じルールが選ばれるか」を保証できません。

アプローチ3: ルールエンジン(OPA / Drools / DMN)

allow {
    input.overtime_hours <= 45
}
allow {
    input.has_36_agreement == true
}

課題:

ルールの所有者(法務、人事、財務)がフォーマル言語を書けません。また自然言語のニュアンス(「合理的な範囲」「原則として」)を表現できず、ルールのフォーマル言語への翻訳・メンテナンスのコストが高すぎます(ルール1件あたり数時間のエンジニア工数)。さらに LLM との統合が設計に含まれていないため、判定に解釈が必要なルールを扱えません。

アプローチ4: Rule Repository(本プロジェクト)

設計方針:

ルールは自然言語で保持し、ルール所有者が直接管理できるようにします。ただし構造メタデータ(modality, severity, scope, kind)を付与し、検索・フィルタ・ディスパッチに活用します。評価は2層構成で、計算で解けるものは決定論的に処理し、解釈が必要なものだけ LLM に委ねます。全判定は改竄不能な監査ログに記録し、エージェントは MCP / SDK / API 経由で呼び出すためプロンプトへの注入は不要です。


Part 4: アーキテクチャ判断 — Agentic システム設計の教訓

ここからは、Rule Repository の設計で行った判断とその根拠を解説します。Agentic なソフトウェアシステムを作るソフトウェアエンジニアの皆様に参考になれば幸いです。

Gemini_Generated_Image_shrws2shrws2shrw.png

Gemini_Generated_Image_vnkznsvnkznsvnkz.png

AD-1: 「判定のディスパッチ」をルールの種類で行う

最初は全ルールを LLM に渡していました。しかし計測すると、全体の約40%は数値比較やテーブル参照で確定する判定でした。

判断: ルールに kind フィールドを持たせ、種類に応じて評価レイヤーを切り替えます。

COMPUTATIONAL  → asteval(サンドボックス数式評価)
DEFINITIONAL   → lookup table 参照
PROCEDURAL     → state machine check
NORMATIVE      → LLM(規範解釈)
PRINCIPLE      → LLM(原則レベル推論)

効果:

  • COMPUTATIONAL ルールは p50 = 20ms で判定完了します(LLM は 1000ms以上)
  • コスト: 決定論的判定は $0 です(LLM は $0.002/判定)
  • 一貫性: 決定論的判定は 100% 再現可能です

教訓: Agentic システムでは「LLM に投げる前にルールベースで解決できないか」を常に問うべきです。LLM は最後の手段であるべきです。

AD-2: LLM の temperature を変えない

Gemini 3 の公式ドキュメントに「temperature を下げると推論品質が劣化しループに入る」と記載があります。実際に 0.2 にしたところ判定がおかしくなりました。

判断: temperature は常にデフォルト(1.0)とします。決定的な答えが欲しければ、LLM ではなく決定論的レイヤーを使います。

教訓: LLM の挙動を「パラメータで制御しよう」とするのは fragile です。アーキテクチャレベルで「LLM に何を聞き、何を聞かないか」を設計する方が堅牢です。

AD-3: 監査ログはハッシュチェーンにする

「なぜ DENY したか」を後から説明できないシステムでは「ルール管理」として不十分でしょう。

判断: 監査ログは append-only テーブルとします。各行が前行のハッシュを含むチェーン構造です。UPDATE/DELETE は PostgreSQL トリガーで物理的に拒否します。

CREATE TABLE audit_log (
    id BIGSERIAL PRIMARY KEY,
    prev_hash TEXT NOT NULL,
    payload JSONB NOT NULL,
    hash TEXT GENERATED ALWAYS AS (sha256(prev_hash || payload::text)) STORED
);

効果: 改竄すると chain が壊れて即座に検出できます。証跡として利用可能です。

教訓: Agentic システムでは「エージェントがなぜその行動をしたか」の説明責任が必ず問われます。監査を後付けするのは設計が10倍難しくなります。最初から組み込みましょう。

AD-4: PostgreSQL を Single Source of Truth にする

データ層としてストレージ、PostgreSQL、Elasticsearch(検索)、 Neo4j(関係グラフ)を使いますが、いずれも PostgreSQL を主として、他は派生ビューです。

判断: 矛盾が生じたら PostgreSQL が勝ち、他を再構築します。reconcile スクリプトで Neo4j を再生成し、reindex で Elasticsearch を再生成します。

教訓: 複数データストアを使うシステムでは「どれが真実か」を明示することが重要です。そうしないとデバッグ不能なデータ不整合に陥ります。「Derived view は壊れうる。Source of Truth は壊さない」が原則です。

AD-5: ルールを削除しない

ルールは effective_period.valid_until で退役させ、物理削除しません。

理由: 過去の判定を遡及的に説明する必要があるためです。「2025年3月時点ではこのルールが有効で、この判定が返された」を再現できなければなりません。

教訓: ルール/ポリシー系のシステムで DELETE を許可すると、過去判定の再現性が失われます。Soft delete ではなく「有効期間の終了」として扱うのが適切です。

AD-6: LLM レスポンスは必ず structured output にする

response = client.generate_content(
    contents=prompt,
    config=GenerateContentConfig(
        response_mime_type="application/json",
        response_json_schema=VerdictSchema,
    ),
)

free-form テキストから正規表現で verdict を抜くのは fragile すぎます。

教訓: LLM を「API として使う」なら、レスポンスは常に structured output で制約すべきです。パース失敗のハンドリングを書く時間より、スキーマを定義する時間の方が短いのです。

AD-7: ドメイン固有ロジックを Domain Pack で隔離する

法務固有のロジック(日本法の条/項/号パース)や人事固有のロジック(36協定例外)等をコアエンジンに入れると、各層の関心が混濁し、保守が困難になります。

判断: Domain Pack は独立パッケージとし、共通インターフェース(_core)にのみ依存させます。サーバー内部モジュールを import しません。

packages/domain-packs/
├── _core/          # manifest schema, base prompts
├── legal/          # 法務固有(プロンプト、アナライザー、テンプレート)
├── hr/             # 人事固有
├── finance/        # 財務固有
└── engineering/    # エンジニアリング固有

効果: 新ドメインの追加がサーバー本体のコード変更なしに可能です。各ドメインの専門家が自分の Pack だけをメンテナンスできます。

教訓: Agentic システムが複数ドメインを扱う場合、ドメイン知識をプラグイン化する設計は必須です。コアが全ドメインを知っている設計はすぐに破綻します。

AD-8: MCP をファーストクラスの統合パスにする

REST API は人間(フロントエンド)向けです。エージェント向けには MCP (Model Context Protocol) を設計時から組み込みます。

理由: MCP 対応エージェント(Claude Code, Cursor 等)が増えています。REST API を MCP にラップする後付け統合より、最初から MCP を設計に含める方がエージェント体験が良くなります。

# エージェントからの利用(MCP 経由)
verdict = await mcp_client.call_tool("evaluate_subject", {
    "kind": "business_event",
    "data": {"event_type": "overtime", "hours": 52},
    "scope": {"domain": "hr"}
})

教訓: 「エージェントが使うエージェントのためのシステム」を設計するなら、エージェントの統合プロトコルを最初から意識すべきです。後付けは「できる」けれども「使いやすい」にはなりません。


まとめ

AIエージェントを組織に導入するとき、多くのチームは「エージェントの賢さ」に注力することが多いでしょう。エージェントアーキテクチャ、プロンプトチューニング、ツール選択、評価ベンチマーク等々。しかし反面のボトルネックとして、エージェントが参照して制御に組み込むべきルールにアクセスできないことが常にあります。

Rule Repository は、この課題に対するひとつの解法を提示することを目的とします。

  1. ルールは自然言語で保持し、構造メタデータで検索可能にする
  2. 評価は「ルールベース → LLM」の2段構成にし、LLM を最後の手段にする
  3. 全判定を改竄不能に記録し、説明可能とする
  4. ドメイン知識はプラグインで隔離し、コアを薄く保つ
  5. エージェント統合(MCP)を後付けではなく設計時から組み込む

これらの原則が、Rule Repository に限らず、Agentic なシステムを設計するエンジニアに参考になると幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?