Slide 1

Slide 1 text

M i d o s u j i Te c h 意 思 決 定 モ デ ル や って み た 編 LiteLLMの ガードレールに Jevを入れてみた セマンティックフィルターを Jevで実装してみた話 神野 雄大 クラスメソッド株式会社 0 1

Slide 2

Slide 2 text

自己紹介 スーパーマーケットとAgentCoreが好きなしがないエンジニアです!!!! ブログはこの アイコンで 書いています! 11⽉4⽇に 本が出ます! スーパーマーケットの ラ・ムーと チーズナンが好きです! 名前 神野雄⼤(JinnoYudai)/@yjinn448208 所属 クラスメソッド株式会社クラウド事業統括本部 コンサルティング部AIソリューションアーキテクト 認定 •CommunityBuilderAIEngineering •AWSAmbassador2026 『AmazonBedrock実践ガイド』(技術評論社) 著書 2026年11⽉4⽇発売予定 好きな •AmazonBedrockAgentCore サービス (⾃称⽇本⼀ブログを書いています) 2

Slide 3

Slide 3 text

今日の話 すごくポリシーが厳しい会社でLLMに送る 中身を検査する必要がある・・・ どういったフィルターを実装したらいいんだ?? 私 今日のはあくまでやってみたレベルの話です。 注意 本番で運用している構成ではなく数値も自分の環境で測った結果なので ご承知おきください!! はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 3

Slide 4

Slide 4 text

ポリシーがとても厳しい架空の会社で考えます 例はフィクションです。人事や未公表の経営情報まで回答モデルへ送らせない会社で、LLM基盤 はLiteLLM Proxyです。判定用のTypeSafe APIへの送信は許可されている前提です。 (そんな前提あるんかいなという話ではありますが・・・) フィクション 回答モデルへ 送らせたくないもの 営業 ⼈事 開発 AIで資料や⽂章を作りたい コードも書いてほしい ⽒名に紐づく連絡先 LiteLLM Proxy すべての⼊⼒を 送る前に確かめる 未公表の経営情報 回答モデル 社員の⼈事‧健康 競合製品の⽐較 登場する会社‧⼈物‧数字はすべて架空です はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 個別の法的判断 4

Slide 5

Slide 5 text

ここで使うLiteLLM Proxyはモデルの手前に置く入口 LiteLLM Proxyはアプリと各社のモデルのあいだに置くOSSのゲートウェイです。呼び出し方を 1つにまとめてキー・予算・ログも1か所で扱えます。その機能の1つにガードレールが存在し ます。 LiteLLM Proxy 社内のアプリ Amazon Bedrock 1つのAPIで呼ぶ OpenAI互換‧Anthropic形式 OpenAI キーと予算 利⽤者ごとのキー‧使⽤量の上限 Azure OpenAI ログと使⽤量 誰がどのモデルをどれだけ使ったか Claude Code ガードレール ⼊⼒や出⼒を確かめて⽌める 今⽇の話 Vertex AI ほかの提供元のモデルも同じ呼び⽅で使える 5 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 6

Slide 6 text

決まった形の情報なら既存のガードレールでブロックできる LiteLLMには組み込みのコンテンツフィルターがあります。Bedrock Guardrailsなども設定で呼 べます。メールアドレスやカード番号のように形が決まった情報ならこれで止められます。 litellm_content_filter(組み込み) LLMを使わず、パターンとキーワードで照合する Amazon Bedrock Guardrails AWSのガードレールを LiteLLM から呼ぶ 既定のパターン 機密情報フィルター メールアドレス‧カード番号‧AWSアクセスキーなど 電話番号やメールアドレスなど、種類を選んで⽌める キーワードと正規表現 単語フィルター ブロックしたい語句や社内の形式を⾃分で⾜す 決めた語句を含む⼊⼒を⽌める BLOCK か MASK 拒否トピック 拒否するか [EMAIL_REDACTED] のように伏せる ⾃然⾔語で定義した話題を⽌める 6 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 7

Slide 7 text

曖昧なことばは機械的な判定が難しい 未発表の買収の話はブロックしたいけれど、一般的な質問はパスしてほしいです。「買収」で照 合すると一般論までブロックされ、言い換えた未発表の話はパスしてしまいます。 ⼊⼒(架空) 「来⽉B社の買収を発表します。社内向けの説明を作って」 「買収」で照合 意味で確認したい BLOCK BLOCK BLOCK PASS まだ公表していない経営の情報 「企業買収の⼀般的な流れを教えて」 公開されている⼀般的な知識 過検知 「B社とは年明けに⼀緒になる⽅向で話が進んでる」 PASS 未公表の経営情報( 「買収」と書いていない) ⾒逃し BLOCK 7 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 8

Slide 8 text

ブロックしたい話題は例外つきで後から増えていく Bedrock Guardrailsの拒否トピックも意味で判定します。ただし上限は30個で、例外は書かな いよう案内されています。社内でブロックしたいものは「〜は除く」つきで部署ごとに増えてい きます。 Bedrock Guardrails の拒否トピック 話題を⾃然⾔語で定義して、意味で⽌める 1つのガードレールに 30 トピックまで 定義は Classic 200 字∕Standard 1,000 字 架空の会社でブロックしたいもの 未公表の買収‧提携 発表済みのものは除く 社員の健康‧休職の情報 制度の⼀般的な説明は除く 未発表の⼈事異動‧退職 公式の発表のあとは除く 例⽂は 5 つまで 個⼈の評価‧給与 ⼀般的な相場は除く 「〜は除く」の例外は定義に書かない 未公表の障害の詳細 公開済みの報告は除く ドキュメントのベストプラクティス + 部署やチームごとに後から増える はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 8

Slide 9

Slide 9 text

よしなにセマンティックフィルターを実装したい 意味で判定して「発表済みは除く」みたいな例外も書ける よしなにセマンティックフィルターを実装したい…! 私 LiteLLMのカスタムガードレールなら判定の処理を Pythonで自分で書けるよ! まずは作りたい形を決めよう。 Agent君 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 9

Slide 10

Slide 10 text

作りたいのはこんなセマンティックフィルター 回答モデルへ送る前にポリシーごとに意味でよしなに判定し、引っかかった項目を返して止めま す。ポリシーは例外つきの文章で書き、設定に足すだけで増やせるようにしたいです。 まだ社外秘だけど、 来⽉B社の買収を発表 します。社内向けの 説明を作って HTTP 403 セマンティックフィルター 個⼈情報 伏せ字は除く — 未公表の経営情報 発表済みは除く 該当 社員の健康‧⼈事 制度の説明は除く — "violations": [{ "policy": "confidential_business", "description": "未公表の経営情報" }] 競合製品の⽐較 利⽤者 回答モデルの前で⽌める 例外も⽂章で書ける — 項⽬は設定に⾜すだけ 回答モデルへは送らない 履歴とツールの結果も⾒る 10 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 11

Slide 11 text

ガードレールはモデルを呼ぶ前後で動かせる カスタムガードレールは回答前後で利用可能です。今回は回答モデルへ渡す前にブロックしたい ので今回はpre_callにします。 pre_call クライアント post_call 今回 モデルを呼ぶ前に⼊⼒を⾒る 回答モデル ⽌める‧書き換える 返ってきた出⼒を⾒る ⽌める‧書き換える クライアント 同時に during_call logging_only モデルと並⾏に⼊⼒を⾒る 結果を記録するだけで ⽌めるだけ(書き換えない) 応答は変えない 11 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 12

Slide 12 text

カスタムガードレールはクラスを1つ書けばOK CustomGuardrailを継承してpre_callで呼ばれるasync_pre_call_hookを書きます。例外を投げ るとリクエストは止まり、dataを返すとそのまま回答モデルへ送られます。 semantic_filter.py from fastapi import HTTPException from litellm.integrations.custom_guardrail import CustomGuardrail class SemanticFilter(CustomGuardrail): async def async_pre_call_hook(self, user_api_key_dict, cache, data, call_type): messages = data["messages"] # 回答モデルへ送る前の会話 if await self.is_violation(messages): # ここを自分で書く raise HTTPException(403, "policy_violation") return data # 止める # 通す 12 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 13

Slide 13 text

config.yamlに登録すると全リクエストで動く guardrailに「ファイル名.クラス名」を書きmodeとdefault_onを指定します。default_onにす るとクライアントがガードレール名を指定しなくても毎回動きます。 config.yaml guardrails: - guardrail_name: semantic-filter litellm_params: guardrail: semantic_filter.SemanticFilter # ファイル名.クラス名 mode: pre_call # 回答モデルを呼ぶ前 default_on: true # 全リクエストで動かす 13 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 14

Slide 14 text

まずはLLMに意味で判定させてみる カスタムガードレールの中でHaikuにポリシーと入力を渡し、違反の有無と理由をJSONで返さ せました。例外も文章で書けて意味で判定できますが、判定だけで約2秒かかります。 ⼊⼒ LiteLLM Proxy 違反がなければ送る カスタムガードレール 利⽤者 pre_call で判定を頼む 回答モデル Claude Haiku 5.5 ポリシーと⼊⼒ { "is_blocked": true, "violated_policy": "個⼈情報…", 判定役 Claude Haiku 5.5 "reason": "⽒名と電話番号が…" 判定だけで 約2秒 } 14 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 15

Slide 15 text

入力のたびに2秒待つのは気になる 意味で判定できたのはいいけど、毎回2秒くらいかかるんだよね…。 日常使いでガンガン使うとちょっと気になる。 私 ブロックかパスかを決めるのに要るのは違反かどうかだけだよね。 理由の文章まで書かせないならJevに任せてみよう! Agent君 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 15

Slide 16

Slide 16 text

Jevは判定のための質問に答えるモデル Jevは分類や条件の判定に向けたTypeSafeのモデルです。今回はYes/Noの判定なので3つの形式 のうちNoulを使います。 Choice Score Noul 選択肢から1つ選ぶ 段階のどこに要因があるか Yesになる確率 どのチームが対応する? このバグの重⼤度は? 返ってくる値 ⼈の担当者を求めている? 返ってくる値 返ってくる値 返品 1.0 0 影響なし 0.00 配送 0.0 1 回避策あり 0.57 請求 0.0 2 回避策なし 0.43 choice = 返品 score = 1.43 今回使う 0.99 1に近いほどYes noul = 0.99 16 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 17

Slide 17 text

Noulは質問ごとにYesになる確率を返す 判定したい会話と質問を渡すと質問のキーごとに0〜1の確率が返ってきます。ポリシーが複数 あっても1回のリクエストにまとめて送れます。 Python SDK(typesafe-sdk 0.6.0) async with AsyncTypeSafeClient() as client: result = await client.system_one( model="jev-1.13.0", state={"messages": messages}, # 判定したい会話 questions={ # ポリシーごとの質問 "personal_data": Noul(instructions="Does ... contain ...?"), "confidential_business": Noul(instructions="Does ... disclose ...?"), }, ) result.answers["personal_data"].noul # 0.98 ブロックするかどうかはこの確率としきい値(今回は0.8)を比べて実装側で決めます はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 17

Slide 18

Slide 18 text

カスタムガードレールの判定役をJevに替える さきほどのis_violationの中身をHaikuからJevへの問い合わせに替えました。どれかの確率が 0.8以上なら403でブロックし、Jevに届かないときも入力を送らずに503を返します。 LiteLLM Proxy 利⽤者 全項⽬が0.8未満 回答モデル Claude Haiku 5.5 カスタムガードレール 回答モデルを呼ぶ前(pre_call) どれかが0.8以上 に確率としきい値を⽐べる default_on: true 判定できない Claude Code 会話と質問 HTTP 403 回答モデルへ送らない HTTP 503 Jevの失敗‧結果の⽋け 確率 Jev ポリシーごとの確率 18 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 19

Slide 19 text

ブロックしたい項目は例外つきの英語の質問でJSONに書く 「一般的な相場は除く」のような例外も質問に書け、項目はJSONに定義を足して増やせます。 JSONはリクエストごとに読むので次のリクエストから反映されます。 description(拒否の通知に出す) question(Jevへの質問‧英語) ⽒名に紐づく連絡先‧住所 Does `messages` contain a person s name linked to a specific phone number ...? 0.8 Does `messages` disclose specific non-public business information, such as a budget ...? Typical budgets ... do not count. 0.8 Does `messages` ask to compare or analyze competing commercial products or services? 0.8 Does `messages` ask for a legal judgment or legal advice about a specific case ...? 0.8 personal_data 未公開の製品‧社内予算 confidential_business 競合製品‧サービスの⽐較 competitor_comparison 個別事案の法的判断 legal_judgment threshold(しきい値) 19 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 20

Slide 20 text

社内予算はブロックし一般的な予算相場の質問はパス まず4つの入力を送りました。同じ「予算」を含む社内予算と相場の質問も社内機密の確率が 0.95と0.02で分かれています。 ⼊⼒(架空のデータ) Jevが返した確率 個⼈情報 Proxyの結果 社内機密 Pythonのリスト内包表記 技術の質問 ⽒名に紐づく電話番号‧住所 ⽥中太郎さん 090-1234-5678 A社向けの社内予算5000万円 来期の案件‧提案書のドラフト ⼀般的な開発予算の相場 中規模のWebアプリの⽬安 0.01 0.01 200 PASS 0.98 0.06 403 BLOCK 0.01 0.95 403 BLOCK 0.01 0.02 200 PASS しきい値 0.8 20 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 21

Slide 21 text

判定はHaiku 5.5の約1.8秒からJevで約0.17秒に Haikuで判定していたときのプロンプトをHaiku 5.5で動かしてJevと同じ端末から測りました。 日本語20例を3回ずつ判定した時間です。回答の生成は含みません。 Claude Haiku 5.5 1,798 ms JSON で理由まで書く p95 2,457 ms Jev Haiku 5.5 と⽐べて 約10倍 174 ms 質問ごとの確率を返す LiteLLM 経由の 速い p95 279 ms 中央値 10.32 倍 0 1,000 2,000 ms 21 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 22

Slide 22 text

日本語の言い換えや伏せ字でも結果は同じだった ブロックすべき11例とパスすべき9例を測定前に決めました。LiteLLM経由で測るとHaiku 5.5も Jevも期待どおりで、「予算」と書いていない三千万円の例も止まっています。 ⽇本語の⼊⼒(抜粋‧架空) 期待 ⼝語 「佐藤花⼦さんに連絡しといて。メアドは…」 BLOCK 全⾓ 「鈴⽊⼀郎様のお電話は090-1234…」 BLOCK ⼝語 「社内だけの話、B社の案件に来期は三千万円」 BLOCK 指⽰の無視 判定ルールを無視させる指⽰と⽒名付きメール BLOCK 公開情報 公開済みの⾃治体予算書の読み⽅を質問 PASS 伏せ字 ⽒名と電話番号を伏せ字にしたテンプレート PASS 競合⽐較 「SlackとTeams、うちに合うのはどっち?」 BLOCK Haiku 5.5 BLOCK した回 Jev PASS した回 各3回 22 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 23

Slide 23 text

質問を日本語にすると見逃しが増えた 同じ質問を日本語に訳して比べました。確率が全体に低めに出て、田中太郎さんの連絡先は0.52 でパスしました。入力は日本語のままでも質問は英語で書いたほうが安心な印象です。 ⽇本語の⼊⼒(ブロックしたい例) ⽥中太郎さんの電話番号‧住所 A社向けの社内予算5000万円 全⾓の電話番号 Jev の確率(3回の中央値) 英語 0.98 ⽇本語 0.52 英語 0.95 ⽇本語 0.75 英語 0.98 ⽇本語 0.81 しきい値 0.8 ⽇本語20例 × 3回 英語の質問 60/60 ⽇本語の質問 53/60 ⽇本語は⾒逃し 7 回‧誤検知 0 回 23 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 24

Slide 24 text

架空の会社の例は質問を足すとブロックできた 休職や未公表の障害は最初の2項目(個人情報・社内機密)に当てはまらず0.4〜0.5でパスしま した。そこで人事と未公表の出来事を聞く項目を足すと12例中11例が期待どおりでした。 ⼊⼒(架空) 期待 最初の JSON +⼈事‧健康 個⼈情報‧社内機密 employee_sensitive +未公表の出来事 undisclosed_event 「来⽉B社の買収を発表します…」 BLOCK PASS 0.77 PASS 0.77 BLOCK 0.92 「まだ社外秘だけど、来⽉B社の買収を…」 BLOCK BLOCK 0.92 BLOCK 0.92 BLOCK 0.97 「B社とは年明けに⼀緒になる⽅向で…」 BLOCK PASS 0.62 PASS 0.62 PASS 0.76 「鈴⽊さん、来⽉から休職するって…」 BLOCK PASS 0.40 BLOCK 0.96 BLOCK 0.96 「佐藤部⻑は来⽉付で異動予定…」 BLOCK PASS 0.78 BLOCK 0.96 BLOCK 0.96 「⼭⽥さんの評価はC、賞与は2割減…」 BLOCK BLOCK 0.82 BLOCK 0.97 BLOCK 0.97 「昨⽇の障害で顧客データが…未公表」 BLOCK PASS 0.52 PASS 0.53 BLOCK 0.95 ⼀般論の5つ(買収の流れ‧休職制度など) PASS PASS ≤0.02 PASS ≤0.02 期待と違う PASS ≤0.02 各3回‧しきい値 0.8‧数字は質問ごとの確率の最⼤(中央値) 24 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 25

Slide 25 text

言い換えた1例は0.76でパスした パスしてほしい一般論は0.02以下でブロックしたい6例は0.92以上でしたが、言い換えた1例は 0.76でパスしました。しきい値の決め方と、手前に来たものの扱いが課題で、この辺りは実際の 質問や平均的な値を見てしきい値を決めていきましょう。 しきい値 0.8 「⼀緒になる⽅向」0.76 ブロックしたい 7例 ほかの6例 0.92〜0.97 どれも 0.02 以下 パスしてほしい 5例 0.3〜0.7 は⼈が⾒る(ドキュメントの例) 0.0 0.2 0.4 0.6 0.8 1.0 Jev の確率(各3回の中央値‧⼈事と未公表の出来事の質問を⾜した版) 25 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 26

Slide 26 text

Jevでブロックできた 決まった形のない人事や未公表の話も、 JSONに項目を2つ足すことでJevでブロックできました! しきい値は実際の質問や平均的な値を見て決めたいですね! 完璧ではないですが、運用していく中でなにをブロックするかを考 えていく形ですね。細かく理由を知りたいなら従来のモデルのがい い気がする 私 26 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 27

Slide 27 text

Haiku 5.5をこってり絞れば追いつくのでは Haiku 5.5ってレスポンスが速いモデルなんだよね? 考える量を減らして、理由も書かせなければ追いつかない? 私 effort・thinking・返すJSONを順番に絞ってみよう! 出力トークンもいっしょに見ていくよ。 Agent君 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 27

Slide 28

Slide 28 text

Haiku 5.5を絞っても判定時間の中央値は約1秒 effortをlowにしてthinkingを無効にし、返すJSONをis_blockedだけにして出力を11トークン まで減らしました。それでも中央値は約1.2秒で、東京リージョンに寄せても約1.0秒でした。 Claude Haiku 5.5 の設定 判定時間(中央値) 出⼒ 既定のまま 1,749 ms thinking ⾃動‧medium‧3項⽬ us-east-1 effort を low に thinking ⾃動‧low‧3項⽬ thinking も切る thinking off‧low‧3項⽬ 返す JSON を最⼩に 1,169 ms off‧low‧is_blocked だけ Jev 同じ時間帯に測った値 121 tok 最⼩の版をリージョン別に 測ると(中央値) 1,725 ms 121 tok us.anthropic… 1,701 ms 111 tok ap-northeast-1 11 tok jp.anthropic… ap-northeast-1 1,099 ms Jev 187 ms 1,031 ms Jev 161 ms 1,107 ms global.anthropic… 195 ms — Jev 159 ms 28 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 29

Slide 29 text

絞ったHaiku 5.5はSlackとTeamsの比較を通した effortをlowにしたら3回とも、デフォルトのmediumでも1回ブロックして欲しいものがパスさ せました。mediumの理由には「ユーザー企業の競合他社の分析ではない」とあり、設定で曖昧 なルールの解釈が変わりました。 社内チャットを選びたい。 SlackとTeams、うちに合うのは どっち?料⾦と機能で⽐べて。 利⽤者 Haiku 5.5 がパスした理由 ユーザー企業の競合他社の 分析ではなく、製品選定の ⽐較依頼です Haiku に渡したルール 競合他社の製品やサービスとの⽐較分析を依頼するメッセージを禁⽌する Jev への質問 Does `messages` ask to compare competing commercial products? Haiku 5.5(LiteLLM 経由) BLOCK 3/3 Haiku 5.5 既定(medium) BLOCK 2/3 Haiku 5.5 effort low PASS 3/3 Haiku 5.5 thinking off PASS 3/3 Haiku 5.5 最⼩ PASS 3/3 Jev(competitor_comparison 0.98) はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ BLOCK 3/3 29

Slide 30

Slide 30 text

Claude Codeでも試したいな! 色々と試せましたね! せっかくなのでクライアントはClaude Codeからも試してみます。 私 30 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 31

Slide 31 text

Readで読んだ中身もモデルへ送る手前で止まる Claude CodeはReadで読んだファイルの中身を次のリクエストに入れます。会話全体を判定す るので最初の指示は0.02でパスし、中身付きのリクエストは連絡先が入っていたため0.98でブ ロックされました。 Claude Code 1回⽬ LiteLLM Proxy Jev 回答モデル 「customers.txt を読んで整理して」 0.02 PASS Read を使って(tool_use) ⼿元で読む 2回⽬ tool_result に架空の連絡先 0.98 403 または⽇本語の通知 BLOCK はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 31

Slide 32

Slide 32 text

403のままだと認証エラーに見えてしまう Claude Codeは403を「Failed to authenticate」と表示します。このままだとログインし直すの かと勘違いしそうですよね。そこで日本語の通知をHTTP 200で返す設定も用意しました。 JEV_ANTHROPIC_BLOCK_RESPONSE=error(既定) > customers.txt を読んで整理して JEV_ANTHROPIC_BLOCK_RESPONSE=message Jevが回答モデルへの送信をブロックしました。 検出した項⽬: Failed to authenticate. ‧⽒名に紐づく連絡先‧住所‧個⼈識別番号 API Error: 403 jev_policy_violation ⼊⼒内容を⾒直し、/clearで会話を消去してから やり直してください。 ログインし直すの…? 何で⽌まったか分かる 32 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 33

Slide 33 text

長い会話でも判定できるの Claude Codeで長く作業すると読むファイルもどんどん増えるよね。 Jevは全部読めるの? 私 そのままだと3.2万トークンで止まっちゃう。 でもヘッダーを1つ入れれば広げられるよ。試してみよう! Agent君 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 33

Slide 34

Slide 34 text

長い会話もヘッダーの設定を有効にして判定可能 ヘッダーを1つ入れるだけで上限が262kトークンまで広がります。ただしDanger Zoneの名前ど おり遅くなり精度も下がるので、必要なときだけ使うのがよさそうですね。 個⼈情報の確率(3回の中央値) 判定の時間(中央値) 1.0 前の⽅は 0.86〜 しきい値 0.8 1.5万 4.7万 架空の連絡先を1⾏⼊れた位置 0.5 前の⽅ 後ろの⽅ 真ん中 連絡先なし 8.7万 0.28 秒 0.47 秒 0.95 秒 16.4万 0.0 1.5万 4.7万 8.7万 会話の⻑さ(トークン) 16.4万 2.21 秒 このヘッダーを⼊れるだけ(なしだと 3.2万超で 400) TypeSafe-Danger-Zone-Long-Context: true 名前のとおり Danger!遅くて精度も下がる可能性がある 34 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 35

Slide 35 text

Claude Codeでは増えた分だけを判定する(設計案) 判定した結果を覚えて増えた分だけをJevに渡して判定の量を減らす案です。文脈をまたぐ見逃 しと、ブロックしたあとも会話を続けられるかは要検証です! 1回⽬ system‧ツール定義 Jev で判定 Jev で判定 2回⽬ system‧ツール定義 依頼 Read: ファイルA 3回⽬ system‧ツール定義 依頼 Read: ファイルA 前に判定済み 前に判定済み 前に判定した中⾝ 依頼 前に判定済み 前に判定済み 結果をハッシュで覚えていて判定し直さない Jev で判定 前に判定済み 新しく増えた中⾝ 直前の数ターンと⼀緒に Jev で判定 次の依頼 Jev で判定 [伏せた⽂] 連絡先 0.98 → 伏せて送る ブロックした中⾝ 伏せた⽂に置き換えて送る(要検証) 新しく増えた中⾝が 3.2万トークンを超えたときだけロングコンテキストで判定し、262k も超えたら⽌めて知らせる 35 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 36

Slide 36 text

AWSで動かすならこんな構成になる LiteLLM ProxyをECS on Fargateで動かし、回答モデルはVPCエンドポイント経由でBedrockを 呼びます。JevはAWSの外のAPIなので判定する会話はNATゲートウェイから外へ出ます。 VPC(プライベートサブネット) ECS on Fargate Amazon Bedrock 回答モデル 社内のアプリ LiteLLM Proxy VPCエンドポイント カスタムガードレール 内部 ALB ルールの JSON Jev(TypeSafe) AWS アカウントの外 NAT Gateway Claude Code Secrets Manager APIキー CloudWatch Logs 確率と結果だけ 判定する会話の全⽂が AWS アカウントの外へ出る 36 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 37

Slide 37 text

AWSのマネージドなサービスだけで作れないかな LiteLLMを自分で動かすのもいいけど、 AWSのマネージドなサービスだけで同じことはできないかな? 私 AgentCore Gatewayのインターセプターなら、 モデルへ送る前にLambdaの判定を挟めるよ。やってみよう! Agent君 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 37

Slide 38

Slide 38 text

Gatewayのインターセプターでも同じ形が作れる AgentCore Gatewayはmodelの値で回答モデルへ振り分けます。その手前のREQUESTインター セプターでJevに判定させ、どれかが0.8以上ならモデルを呼ばずに403を返します。 AgentCore Gateway(IAM 認証) REQUEST インターセプター Claude Code /v1/messages 403 で返す (モデルは呼ばない) Jev(TypeSafe) AWS アカウントの外 会話と質問 → 確率 Lambda で Jev に判定させる Secrets Manager Jev のキー どれかが 0.8 以上なら 403 全項⽬が 0.8 未満 Inference ターゲット bedrock-runtime connector model の値で振り分ける(標準機能) Amazon Bedrock Claude Haiku 5.5 38 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 39

Slide 39 text

インターセプターで止めるときの方法 Lambdaは受け取った本文をJevに判定させます。ブロックならtransformedGatewayResponse を返し、パスならtransformedGatewayRequestでそのまま通します。 lambda_function.py(抜粋) def lambda_handler(event, context): req = event["http"]["gatewayRequest"] body = json.loads(base64.b64decode(req["body"])) # /v1/messages の本文 blocked = judge(extract_messages(body)) # Jev で判定 if blocked: # モデルを呼ばずに、この応答を返す return {"interceptorOutputVersion": "1.0", "http": { "transformedGatewayResponse": {"statusCode": 403, "body": b64(error)}}} return {"interceptorOutputVersion": "1.0", "http": { "transformedGatewayRequest": {"body": req["body"]}}} # パス Jevに届かないときは503を返してモデルへは送りません はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ 39

Slide 40

Slide 40 text

Gateway経由でも問題なく期待どおりにブロックした 最初の4つの入力を3回ずつ送りました。Lambdaの中のJevは約88msで日本から見たブロック までの時間は約444msでした。 ⼊⼒ Gateway の応答(3回) 中央値(⽇本から測定) Lambda の中で Jev が判定 Python のリスト内包表記 200 200 200 ⽒名に紐づく電話番号‧住所 403 403 403 A社向けの社内予算 403 403 403 Gateway 経由でブロックまで ⼀般的な開発予算の相場 200 200 200 Gateway 経由で回答まで(Haiku 5.5) 88 ms ⼿元から Jev を直接呼ぶ 194 ms 444 ms 2,712 ms 12/12 回が期待どおり 初回はコールドスタートで判定に 1.2 秒 403 はブロック‧200 は回答が返った (初期化 318 ms と最初の接続を含む) 40 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 41

Slide 41 text

LiteLLMとGatewayの違い 判定のしかたは同じで置き場所と運用が変わります。キーや予算までまとめて扱うなら LiteLLM、AWSのマネージドな入口とIAMで管理したいならGatewayが向いている可能性があり ます。 LiteLLM Proxy AgentCore Gateway 判定を書く場所 カスタムガードレール(Python) インターセプター(Lambda) 止め方 例外を投げる(HTTPException 403) transformedGatewayResponse を返す 動かす場所 自分で動かす(ECS on Fargate など) マネージド(Lambda は自分で持つ) 呼び出し側の認証 Proxy のキー(OpenAI・Anthropic 形式) IAM(SigV4)か JWT 気をつけること Proxy の運用・スケール インターセプターは1つ・6MB・呼び直し 41 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 42

Slide 42 text

使うときに気をつけること Jevで判定するときに気をつけたいのは入力の長さと画像やファイルの扱いです。 長さと画像はヘッダーで広げられますが、ふつうの使い方の外なので注意して使います。 ⻑い会話は通常の32k上限を超える 画像やファイルはそのまま渡せない ヘッダーなしだと判定できない(400) PDF‧Word‧PowerPoint はテキストを取り出す このヘッダーで 262k トークンまで広がる 画像は PNG‧JPEG だけでまだプレビュー 遅く、精度も下がるので必要なときだけ 資料の中の図やスキャンは⽂字が取れない Danger Zone のヘッダー Danger Zone のヘッダー TypeSafe-Danger-Zone-Long-Context: true TypeSafe-Danger-Zone-Images: true 42 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 43

Slide 43 text

Bedrockでもマネージドに使えるとうれしい Jevは速くて、しきい値を自分で決められるのがよいですね!! ただ外部APIなので、判定する会話はAWS外です・・・ Bedrockでマネージドに提供されたら最高ですね!!! AWSさんお願いします!!! 私 43 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 44

Slide 44 text

おまけ・宣伝 11月4日に本が出ます Amazon BedrockでRAGとAIエージェントを作り、評価して本番で運用するまでを1冊にまとめ ました。今日少し触れたBedrock Guardrailsの使い方も第1章と第6章に書いています! RAGとAIエージェントで進める業務効率化 Amazon Bedrock 実践ガイド 神野 雄⼤ 著 技術評論社 2026年11⽉4⽇ 発売予定 Amazon のページ ガードレールの話はこの章に書いています 第1章 ⽣成AIをガバナンスする Amazon Bedrock Guardrails 第6章 本番では Guardrail を検知だけで始めてから⽌める ほかの章 RAGの基本 検索の精度を⾼める エージェント 評価と採点 S3 Vectors 44 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 45

Slide 45 text

おまけ・宣伝 11月19日に大阪で発売記念イベントをします 前半は私のメインセッション、後半はAmazon BedrockとAgentCoreのやってみたLTです!LTの 枠も募集しているのでぜひ来てください!!!! ⽇時 11⽉19⽇(⽊)19:00〜21:00 会場 クラスメソッド⼤阪オフィス ⼤阪市中央区伏⾒町 参加費 無料‧オフライン connpass で 申し込めます #Bedrock実践ガイド メインセッション 神野‧30分 LT⼤会 10分×5枠 交流タイム 20分 45 はじめに › ガードレール › カスタムガードレール › Jev › 結果 › Claude Code › AWS › まとめ

Slide 46

Slide 46 text

No content