Amazon Bedrock Guardrails のコード生成ワークフロー活用術
AWS は、コード生成ワークフローにおける Amazon Bedrock Guardrails の実装において、スループット制約やコスト増を防ぐための具体的な構成ベストプラクティスを提示し、安全かつ効率的な AI コーディング環境の構築指針を定めた。
AIニュース価値スコアβ
技術分析AI関連度、新規性、日本での有用性など6軸を公開検証中です。現在、掲載順には使用していません。
- AI関連度
- 75
- 情報源の信頼性
- 100
- 新規性
- 50
- 検索具体性
- 75
- 重複の少なさ
- 100
- 日本での有用性
- 25
AI コーディングエージェントの運用におけるセキュリティとパフォーマンス最適化という具体的な課題に対し、実装事例(15 人の開発者でのスロットリング問題)と解決策を提示しており、技術分析として価値が高い。ただし、これは AWS の公式ブログによるベストプラクティスの紹介であり、世界初の発見や独自調査ではないため新規性は中程度。また、日本固有の規制や企業事例が含まれていないため、日本の文脈での関連性は低い。
キーポイント
コード生成ワークフロー特有の課題
ストリーミング応答による大量データ出力やアジェンティックループ、並行セッションが、不適切な設定によりスロットリングエラーやコスト増、レイテンシ悪化を引き起こすリスクを指摘している。
Guardrails の具体的な保護機能
プロンプト攻撃(ジャイブーク・注入)の防止、機密情報(PII)のフィルタリング、有害なコードパターンの検出など、コード生成に特化した safeguards を紹介している。
最適化された構成とキャパシティプランニング
スロットリングを回避し、コストを抑えつつ堅牢な安全性を確保するための Guardrails 設定のベストプラクティスと、効果的なキャパシティプランニングの指針を提供している。
変更前のキャッシュによる重複検証の回避
ファイルの内容ハッシュを記録し、未変更のファイルに対する再評価をスキップすることで、リソースとコストを節約します。
大規模コードのチャンク処理による完全なスキャン
1,000文字ごとにファイルを分割して順次評価を行うことで、ガードレールの制限を超えた長文のコードも漏れなく検証できます。
ストリーミング間隔の最適化によるコスト削減
リアルタイム評価が必要な場合、デフォルトの50文字から1,000文字へストリーミング間隔を引き上げることで、API呼び出し回数を最大20倍削減できます。
ApplyGuardrail APIによる非同期・分離型評価
基盤モデルの呼び出しとは独立してテキストを評価できるため、プロンプトインジェクション対策として入力のみを事前に検証し、推論自体はガードレールなしで実行する構成が可能です。
重要な引用
As organizations adopt generative AI workflows with code at scale using these assistants, it is important that unsafe code patterns are detected and blocked whenever required.
Applying Amazon Bedrock Guardrails to workflows with these characteristics without proper configuration could potentially lead to constraints such as throttling errors, increased costs, and less than optimal latency.
With these best practices, you can build an efficient blueprint helping you with effective capacity planning with robust safety coverage.
"Analogous to running security scanners in a Git pre-commit hook."
"Cache: don't re-validate unchanged files"
Increasing the guardrail interval from the default 50 characters to 1,000 characters can reduce your API call volume by 20x.
影響分析・編集コメントを表示
影響分析
この記事は、大規模なコード生成 AI の導入が進む中で、セキュリティとパフォーマンスの両立という実務上の課題に対する具体的な解決策を示した点で重要です。開発者が Guardrails を単なる機能としてではなく、システム設計の一部として最適化して適用する必要性を強調しており、企業レベルでの安全な AI 活用を加速させる実践的な指針となります。
編集コメント
コード生成 AI の普及に伴い、セキュリティ対策がパフォーマンスのボトルネックになるケースが増える中、AWS が具体的な最適化手法を提示したのは非常にタイムリーです。実務レベルでの運用コストと安全性のバランスを取るための重要な指針となるでしょう。
本稿は、Amazon Bedrock Guardrails のベストプラクティスに関するシリーズの続編です。前回の記事はこちらをご覧ください。
AI を活用したコーディングアシスタントやコード生成ワークフロー(Claude Code、Kiro、OpenAI Codex など)が、開発者のソフトウェア作成方法を劇的に変えています。これらのツールはストリーミングレスポンスを通じてリアルタイムにコードを生成するため、長時間のセッションでは数千文字規模の出力が発生することも珍しくありません。組織がこうしたアシスタントを活用して大規模な生成 AI ワークフローを導入する際、必要に応じて不安全なコードパターンを検知しブロックすることが不可欠です。
Amazon Bedrock Guardrails は、コンテンツモデレーション用のフィルターや、ジールブレイク(脱獄)やプロンプトインジェクション、プロンプトリークを防ぐための対策、個人を特定できる情報(PII)の隠蔽・ブロックを行う機密情報フィルターなどを通じて、不安全なコードや望ましくないコードコンテンツを検知・フィルタリングします。
しかし、コーディングワークフローやエージェントループには、長いストリーミング出力、並行する開発者セッション、反復的なコンテキスト評価など、特有のスループット特性が存在します。これらの特性を持つワークフローに Amazon Bedrock Guardrails を適切に設定せずに適用すると、スロットリングエラーの発生、コスト増大、レイテンシの最適化不足といった制約が生じる可能性があります。本稿では、コーディングアシスタントを備えたコード生成ワークフロー向けに Amazon Bedrock Guardrails をどのように設定すればこれらの制約を克服できるかを解説します。これらのベストプラクティスを実践することで、堅牢な安全性カバレッジを保ちつつ、効率的なキャパシティプランニングが可能となる設計図を作成できます。
コード生成ワークフローにおけるガードレールの重要性
Amazon Bedrock Guardrails は、ユーザー入力とモデルのレスポンスから有害・望ましくないコンテンツを検出・フィルタリングする包括的な保護機能を提供し、安全な生成 AI アプリケーションの構築を支援します。これらの保護機能は多様なアプリケーションで設定・実装が可能ですが、以下のような有害なコードパターンを保護するために特化したガードレールも用意されています:
- プロンプト攻撃の検出 – モデルを操作して悪意のあるコードを生成させたり、指示を回避したりする試みをブロックします。
- 機密情報のフィルタリング – ユーザー入力やモデルからの回答に含まれる個人情報(PII)、カスタム正規表現、ハードコードされた AWS アクセスキー、データベース接続文字列、秘密鍵などを、生成されたコードに現れる前に検出してブロックまたはマスクできます。
- コンテンツモデレーション – ユーザーのプロンプトやモデルの回答から有害なコンテンツを検出しフィルタリングします。組織の利用許容ポリシーに違反するコンテンツも対象となります。
- 禁止トピックのブロック – 認証メカニズムを回避するコードの生成や、不正アクセスパターンの支援など、禁止された活動に関連する会話をブロックするための基準となるカスタムトピックを定義できます。
これらの保護機能は、AI が生成したコードを実システムで利用する際に不可欠です。
シナリオ:善きガードレールが暴走する瞬間
ある顧客のシステムチームは、Amazon Bedrock 上で Claude Code を 15 人の開発者に展開しました。設定したガードレールには、プロンプト攻撃(インジェクション)を検知して防ぐ機能、機密情報のフィルタリングで漏洩した認証情報を隠す・ブロックする機能、そして不安全なコードパターンをブロックするコンテンツフィルタの 3 つが用意されていました。
パイロット運用では 2 人の開発者で完璧に動作し、成功をおさめました。しかし、15 人全員が同時にコーディングセッションを開始したとたん、数分もたたないうちにチームからエラー報告が殺到します。「ThrottlingException(スロージョニング例外)」という Amazon Bedrock のモデル推論からの応答が表示され、コード補完が途中で止まってしまうのです。開発者の不満は高まり、Slack チャンネルは通知で埋め尽くされました。
何が起きたのか?
各開発者のセッションでは、関数あたり平均 5,000 文字のコードが生成されます。デフォルトのストリーミング設定では、Amazon Bedrock は 50 文字ごとにガードレールを評価するため、1 回の関数処理で 100 回の API 呼び出しが発生します。これが 15 人の同時セッションに拡大すると、1 秒間に 1,500 回の評価リクエストがシステムから発生することになります。
さらに深刻なのは、3 つのガードレールが同時に有効になっているため、各評価でテキストユニットを 1 ではなく 3 消費してしまう点です。これによりスループット(処理能力)の消費量が 3 倍に膨れ上がってしまいました。
ボトルネックの根本原因は利用枠の不足ではなく、アーキテクチャの不整合でした。彼らは短い会話に応用されたパターンを、大量処理が求められるコード生成パイプラインに無理やり適用してしまったのです。
本稿では、この課題を解決するためのアーキテクチャパターンを紹介します。
テキストユニット:ガードレールの通貨
アーキテクチャの詳細に入る前に、まずガードレール利用量がどのように計算されるかを理解しておく必要があります。これがその後のあらゆる最適化の鍵となるからです。
テキストユニットとは、1,000 文字を単位としたものです。例えば、1,000 文字のテキストに対して ApplyGuardrail API を呼び出し、3 つのセーフガード(保護機能)で評価を行うと、利用量は 3 テキストユニットとして計上されます。
重要なのは、この利用量が乗算的に計算される点です。利用量はコンテンツの長さだけでなく、有効なセーフガードの数にも比例して増加します。
コード生成ワークフローでは、関数ごとに数千文字に及ぶ冗長な出力が発生するのが一般的です。そのため、この乗算的な関係性は容量計画において極めて重要な要素となります。コンテンツフィルタ、拒否トピック、機密情報フィルタなどを設定したガードレールの場合、各セーフガードやフィルタが処理するテキストユニットの数に基づいて利用量が課金されます。
注意: コンテンツフィルタは、ハート、侮辱、性的表現、暴力、不正行為、プロンプト攻撃のいずれのカテゴリを有効にしても、1,000 文字あたり 1 テキストユニットとして課金されます。例えば、6 つすべてのカテゴリを有効にした場合でも、6 ユニットではなく 1 ユニットとしてカウントされます。乗算関係は、単一のポリシータイプ内のカテゴリ間ではなく、コンテンツフィルタ、拒否トピック、機密情報フィルタといった異なるポリシータイプの間に適用されます。
チャレンジ:コード生成ワークフローがスロットリングを引き起こす可能性
従来の対話型 AI ワークフローでは、ユーザーからの短い個別のプロンプトとモデルの応答が行われます。一方、コード生成ワークフローは、ガードレールのアーキテクチャに直接影響を与える点で異なります。
以下の表は、なぜコード生成ワークフローが特に要求が厳しいかを示しています。
| 特徴 | 対話型 AI | コード生成 |
|---|---|---|
| 出力長さ | 100〜500 文字 | 5,000〜50,000+ 文字 |
| セッション継続時間 | 単一または数回のやり取り | 長時間にわたる多段階のセッション |
| 同時利用者数 | 通常は非同期 | チームでの並行コーディング |
| コンテキストの再利用 | 最小限 | システムプロンプト、ツール定義、過去のコードを毎回再送信 |
| 中間出力 | 最小限 | 広範な思考連鎖(Chain-of-Thought)推論 |
これらの違いにより、従来のガードレール設計では対応が難しく、スロットリングやパフォーマンスの低下を招くリスクが高まります。
これらの違いから、ストリーミング出力の各チャンクを生成するたびにガードレールが評価を行うインラインスキャン方式では、実際の安全性向上に対する価値に見合わないほどの大量の評価が発生することがわかります。
ベストプラクティス:コード生成ワークフローにおけるアーキテクチャパターン
これらの課題に対処するため、コード生成ワークフローでガードレールを効率的に活用するためのアーキテクチャパターンをいくつか推奨します。各パターンは、評価頻度の削減や高リスクなコンテンツのみを選択的にスキャンするなど、問題の特定の側面に対応しています。ワークロードの特徴やセキュリティ要件に応じて、これらのパターンを単独で適用したり、組み合わせて使用したりできます。
アーキテクチャパターン 1:コミットフックモデル
インラインスキャンの仕組み:デフォルトのアプローチ
guardrailConfig を用いて Converse API や InvokeModel API でモデル呼び出しに直接ガードレールを紐付ける場合、これは「インラインスキャン」と呼ばれる手法になります。このモードでは、Amazon Bedrock Guardrails がトークン生成中にリアルタイムで継続的に、入力プロンプト全体とストリーミング出力の両方をアクティブなセキュリティ対策に対して評価します。従来の対話型 AI においては、このアプローチは非常に有効です。なぜなら、プロンプトが短く、回答も簡潔であるため、評価によるオーバーヘッドは無視できるほど小さいからです。
しかし、コード生成ワークフローにおいては、インラインスキャンは非効率なオーバーヘッドとなります。セキュリティ体制を本質的に改善しないまま、コストが増加し、クォータが浪費されるだけです。
コーディングアシスタントは単に短い回答を出力するわけではありません。推論やコメント、反復的な改良を交えながら、数千文字規模のコードをストリーミングで生成します。インライン評価を有効にした場合、この出力のすべての断片が、設定されたすべてのガードレールに対してスキャンされます。これには、最終評価以降変更されていない静的なシステムプロンプトや、以前に生成されたコンテキストも含まれます。
その結果、重複した作業が発生します。同じボイラープレート指令、ツール定義、過去の会話履歴がターンごとに再評価され、セキュリティ上の価値を追加することなく、テキストユニットのみを消費してしまいます。
核心的なベストプラクティスは、継続的なインラインスキャンから、戦略的なチェックポイントにおける選択的検証へとシフトすることです。これは Git ワークフローの「pre-commit hook(コミットフック)」に例えることができます。ストリーミングされるすべてのトークンをスキャンするのではなく、リスクプロファイルが変化する明確な境界点でコンテンツを検証します。
なぜ「pre-commit hook」の考え方が有効なのか
ソフトウェア開発者は、入力した行ごとにリンターやフォーマッター、セキュリティスキャナーを実行しません。彼らはコミット時に検証を行います。中間的な編集内容や削除された行、未完成の関数すべてを検証するのではなく、*重要な瞬間*に*完成した結果*を検証するのです。
Git ワークフローにおける pre-commit hook は、リポジトリへのコミットを試みた瞬間という明確な境界点で自動的に実行されるスクリプトです。これは変更内容が共有コードベースに組み込まれる直前の最後の関門と言えます。
このチェックポイントでは、保存されようとしている最終的な成果物に対して、すべての検証とテストを一括して実行します。
このパターンが機能する理由は、二つの競合する要件を適切にバランスさせているからです。一つは徹底性で、コミットされるすべての変更が完全に検証されます。もう一つは効率性で、コードが「進行中のドラフト」から「保存される成果物」へと移行し、リスクプロファイルが変化した時だけ検証が行われます。
Amazon Bedrock Guardrails への適用
核心的なベストプラクティスは、この原則を Amazon Bedrock Guardrails にも適用することです。継続的なインラインスキャンから、戦略的なチェックポイントにおける選択的検証へとシフトします。
コード生成パイプラインには、自然なコミットポイントが存在すると考えましょう。つまり、コンテンツの信頼レベルが移行する瞬間です。
- ユーザー入力を受信 – 信頼できないソースからシステムへコンテンツが入力される段階(ここで検証が必要)
- 最終的なコード成果物の組み立て完了 – モデルからの完全なレスポンスが提示または保存の準備ができている段階(ここで検証が必要)
- コードのファイル書き出しまたはリポジトリへのコミット – AI 生成コンテンツが永続化され、実行可能な状態になる直前(ここで検証が必要)
これらのチェックポイントの間、モデルが推論を行ったり中間トークンを生成したり、思考プロセスの説明を出力している間は、その内容は一時的なものです。まだ信頼境界を越えていません。この段階で継続的にスキャンしてもコストとクォータを浪費するだけで、セキュリティ態勢の向上には実質的に寄与しません。

重要な原則: ユーザーが提供した入力をモデルに渡す前に「ApplyGuardrail API」を用いて評価し、コミットする前に集約された最終的なコード成果物を検証します。すべての中間推論トークンを逐一チェックする必要はありません。
実装:ファイル操作前のコミット検証
最もリスクの高いチェックポイントである、AI 生成のコードがファイルに書き込まれたりリポジトリへコミットされたりする直前には、包括的なガードレール評価を実行してください。これは以下のように直接適用される「コミットフック」のパターンです。
import hashlib
from pathlib import Pathclass CodeCommitGuardrail:
"""
AI が生成したコード変更が保存される前に、すべてを検証します。
Git の pre-commit フックでセキュリティスキャナを実行するのと同じような役割です。
以下のような場合に使用してください:
- コーディングアシスタントがディスクにコードを書き込むとき
- AI が生成した変更をコミット対象としてステージングするとき
- 生成されたコードをデプロイしようとする直前
"""
def __init__(self, client, guardrail_id, guardrail_version):
self.client = client
self.guardrail_id = guardrail_id
self.guardrail_version = guardrail_version
self.validated_hashes = {} # キャッシュ:変更のないファイルは再検証しない
def validate_file_changes(self, staged_files: dict) -> dict:
"""
コミット前に、ステージングされたすべての AI 生成コードの変更を評価します。
Args:
staged_files: 変更された全ファイルの {ファイルパス:ファイル内容} を格納した辞書
Returns:
'safe'(boolean)と発見された違反事項を含む辞書
"""
violations = []
skipped = []
for file_path, content in staged_files.items():
# 前回検証以降変更されていないファイルはスキップする
content_hash = hashlib.sha256(content.encode()).hexdigest()
if self.validated_hashes.get(file_path) == content_hash:
skipped.append(file_path)
continue
# 1,000 文字ごとに区切ったチャンクで評価を行う
file_violations = self._evaluate_file(file_path, content)
ファイルに違反が見つかった場合、そのリストを統合します。見つからなければ、成功した検証結果をキャッシュに保存し、ファイルパスとコンテンツのハッシュ値を関連付けます。
最終的に返されるデータには、安全かどうか(違反がゼロか)、具体的な違反内容、評価対象となったファイル数、そしてキャッシュによりスキップされたファイル数が含まれます。
次に、個々のファイルを評価する関数の処理です。この関数は、ガードレールに照らして単一のファイル内容をチェックします。まず、コンテンツの先頭から 1000 バイトずつ区切りながらループを回し、各チャンクに対してクライアント経由でガードレールを適用します。
もし応答の結果が「GUARDRAIL_INTERVENED(ガードレールによる介入)」であれば、ファイルパスや位置情報、違反の詳細、そして該当するコードスニペットなどを記録した違反オブジェクトを追加していきます。すべてのチャンクを確認し終えた後、収集された違反リストを返却します。
コーディングアシスタントのファイル書き込み操作との統合例
def write_ai_generated_code(file_path: str, content: str, guardrail: CodeCommitGuardrail):
"""
保存前にコンテンツを検証する、ファイル書き込み用のラッパー関数。
"""
result = guardrail.validate_file_changes({file_path: content})
if not result['safe']:
print(f"Guardrail が {file_path} への書き込みをブロックしました")
for v in result['violations']:
print(f" オフセット {v['offset']} で違反検出:{v['assessments']}")
return False
# セーフなので書き込みを実行
Path(file_path).write_text(content)
print(f"{file_path} が検証され、正常に書き込まれました")
return True
アーキテクチャパターン 2:ストリーミング間隔を 1,000 文字に引き上げる
インタラクティブなコーディングセッションなど、違反を検知した瞬間に生成を即座に停止させる必要があるリアルタイム評価が必要な場合、ストリーミング間隔の最適化が重要です。デフォルトの 50 文字からガードレールの間隔を 1,000 文字に引き上げることで、API 呼び出し量を最大 20 倍削減できます。以下の設定例をご参照ください:
Guardrails を適用したコード生成ワークフローにおけるベストプラクティス(続き 14/15)
InvokeModelWithResponseStream で Guardrails を使用する際の注意点
response = bedrock_runtime.invoke_model_with_response_stream(
modelId='anthropic.claude-sonnet-4-20250514',
body=json.dumps(request_body),
guardrailIdentifier='your-guardrail-id',
guardrailVersion='1',
# 重要な設定:ストリーミング間隔を拡大
streamingConfigurations={
'guardrailStreamingInterval': 1000 # デフォルトは 50!
}
)
影響: 5,000 文字の関数であれば、評価回数は 100 回から 5 回に削減されます。また、50,000 文字のファイルでも、評価回数は 1,000 回から 50 回へと劇的に減少します。
アーキテクチャパターン 3:選択的な評価には独立した ApplyGuardrail API を活用する
スタンドアロンの ApplyGuardrail API を利用すれば、基盤モデルの種類に関係なく Amazon Bedrock Guardrails を適用できます。これにより、基盤モデルを呼び出すことなくテキストの評価を行うことが可能になります。
パターン:ガードなし推論における入力のみによる検証
主な懸念事項がプロンプトインジェクションの防止や悪意ある入力のブロックである場合、モデルに到達する前に動的なユーザーコンテンツのみを検証すれば十分です。この場合は、インライン Guardrails を使用せずにモデルを呼び出します。
import boto3
import json
bedrock_runtime = boto3.client('bedrock-runtime')必ず JSON 形式で返してください。translation フィールドのみ。他のフィールドは一切追加しないこと — 余計なフィールドを書こうとして本文がトークン上限で打ち切られる事故を防ぐため:
{"translation": "リライト全文"}
def process_coding_request(user_input: str, system_prompt: str, conversation_history: list):
"""
ガードレールでユーザー入力を検証し、インラインスキャンなしでモデルを呼び出します。
システムプロンプトと会話履歴は、各ターンごとに再評価されません。
"""
# ステップ 1: 新しい動的なユーザー入力のみを評価する
原文を表示
*This post continues our series on best practices with Amazon Bedrock Guardrails. For the previous post, see Build safe generative AI applications like a pro: best practices with Amazon Bedrock Guardrails.*
AI-powered coding assistants and code generation workflows, such as Claude Code, Kiro, and OpenAI Codex, are transforming how developers write software. These tools generate code in real time through streaming responses, often producing thousands of characters across extended sessions. As organizations adopt generative AI workflows with code at scale using these assistants, it is important that unsafe code patterns are detected and blocked whenever required. Amazon Bedrock Guardrails helps detect and filter unsafe and undesired code content with safeguards such as content filters for content moderation, prompt attack prevention with jailbreaks, prompt injection, and prompt leakage, sensitive information filters to redact and block personally identifiable information (PII), and more.
However, coding workflows along with agentic loops have unique throughput characteristics including long streaming outputs, concurrent developer sessions, and repetitive context evaluation. Applying Amazon Bedrock Guardrails to workflows with these characteristics without proper configuration could potentially lead to constraints such as throttling errors, increased costs, and less than optimal latency. In this post, we explain how Amazon Bedrock Guardrails can be configured for code generation workflows with coding assistants to overcome these constraints. With these best practices, you can build an efficient blueprint helping you with effective capacity planning with robust safety coverage.
Why guardrails are important for code generation workflows
Amazon Bedrock Guardrails offers comprehensive safeguards that detect and filter harmful and undesirable content from both user inputs and model responses, to help build safe generative AI applications. While these safeguards can be configured and implemented across a variety of applications, there are specific safeguards that can be used to protect harmful code patterns such as:
- Detect prompt attacks – block attempts to manipulate the model into generating malicious code or bypassing instructions.
- Filter sensitive information – can help block or mask sensitive information such as personally identifiable information (PII), custom regex in user inputs and model responses, catch hardcoded AWS access keys, database connection strings, or private keys before they appear in generated code.
- Content moderation – detect and filter harmful content in user prompts and model responses, including content that violates your organization’s acceptable use policies.
- Block denied topics – define custom topics that are used as a basis for blocking conversations related to prohibited activities, such as generating code to bypass authentication mechanisms or assisting with unauthorized access patterns.
These safeguards are essential when AI-generated code is used in production systems.
A scenario: When good guardrails go sideways
A customer system team has just rolled out Claude Code on Amazon Bedrock to 15 developers. They’ve configured a guardrail with three safeguards: prompt attack detection to help prevent injection, a sensitive information filter to redact or block leaked credentials, and a content filter to block unsafe code patterns. Everything worked perfectly during the pilot with two developers. After a successful pilot, all 15 developers start their coding sessions simultaneously. Within minutes, their team starts reporting errors: ThrottlingException responses from Amazon Bedrock model inference. Code completions stall mid-stream. Developers are frustrated, and their Slack channel lights up.
What happened? Each developer’s session generates roughly 5,000 characters of code per function on average. With the default streaming configuration, Amazon Bedrock evaluates guardrails for every 50 characters, triggering 100 API calls per function, per developer. Multiply across 15 concurrent sessions, and the system generates 1,500 evaluation requests per second. Worse, because they have 3 safeguards active, each evaluation consumes 3 text units instead of 1, tripling throughput consumption.
The root cause wasn’t insufficient quota. It was an architectural mismatch. They applied a pattern designed for short conversational exchanges to a high-throughput code generation pipeline. This post provides architectural patterns to solve this problem.
Text units: The guardrails currency
Before diving into architecture, it’s important to understand how guardrail consumption is calculated, because it’s the key to every optimization that follows.
A text unit is defined as 1,000 characters in the text. An ApplyGuardrail API call with 1,000 characters of text evaluated against 3 safeguards generates 3 text units of consumption.
Critically, consumption is multiplicative. It scales with both content length and the number of active safeguards.
For code generation workflows where outputs are typically verbose (thousands of characters per function), this multiplicative relationship is a critical factor in capacity planning. A guardrail configured with content filters, denied topics, and sensitive information filters is metered based on the number of text units processed by each safeguard or filter.
Note: Content filters are charged as a single text unit per 1,000 characters regardless of how many categories (Hate, Insults, Sexual, Violence, Misconduct, Prompt Attack) are enabled within the filter. For example, if you enable all six content filter categories, it still counts as one text unit, not six. The multiplicative relationship applies across distinct policy types (content filters, denied topics, sensitive information filters), not across categories within a single policy type.
The challenge: Code generation workflows could trigger throttling
Traditional conversational AI workflows involve short, discrete user prompts and model responses. Code generation workflows differ in ways that directly impact guardrail architecture:
The following table shows why code generation workflows are uniquely demanding:
Characteristic
Conversational AI
Code Generation
Output length
100-500 characters
5,000-50,000+ characters
Session duration
Single turn or few turns
Extended multi-turn sessions
Concurrent users
Typically, asynchronous
Teams coding simultaneously
Context reuse
Minimal
System prompts, tool definitions, and prior code resent every turn
Intermediate output
Minimal
Extensive chain-of-thought reasoning
These differences mean that an inline scanning approach, where guardrails evaluate every chunk of streamed output as it’s generated, creates a volume of evaluations that’s disproportionate to the actual safety value delivered.
Best Practices: Architecture Patterns for Code Generation Workflows
To address these challenges, we recommend a set of architecture patterns that optimize guardrail usage for code generation workflows. Each pattern targets a specific aspect of the problem — from reducing evaluation frequency to selectively scanning only high-risk content. You can apply these patterns individually or combine them based on your workload characteristics and safety requirements.
Architecture pattern 1: The pre-commit hook model
Understanding inline scanning: the default approach
When you attach guardrails directly to model invocation using guardrailConfig with the Converse or InvokeModel APIs, you’re using what’s known as *inline scanning*. In this mode, Amazon Bedrock Guardrails automatically evaluates both the full input prompt and the streaming output against active safeguards continuously, in real time, as tokens are generated. For traditional conversational AI, this approach works well: prompts are short, responses are concise, and the evaluation overhead is negligible.
But for code generation workflows, inline scanning becomes inefficient overhead. It adds cost and consumes quota without meaningfully improving your security posture. A coding assistant doesn’t produce only a brief response. It streams thousands of characters of code, interspersed with reasoning, comments, and iterative refinements. With inline evaluation active, every chunk of that output is scanned against every configured safeguard, including the static system prompt and previously generated context that hasn’t changed since the last evaluation. The result is redundant work: the same boilerplate instructions, tool definitions, and prior conversation history are re-evaluated turn after turn, consuming text units without adding safety value.
The core best practice is to shift from continuous inline scanning to selective validation at strategic checkpoints, analogous to a pre-commit hook in a Git workflow. Rather than scanning every token as it streams, validate content at well-defined boundaries where the risk profile changes.
Why “pre-commit hook” thinking works
Software developers don’t run linters, formatters, and security scanners after every line they type. They validate at commit time. They don’t validate every intermediate edit, every deleted line, or every half-written function, but validate the *finished result* at the *moment it matters*.
In a Git workflow, a pre-commit hook is a script that runs automatically at a specific, well-defined boundary: the moment you attempt to commit code to your repository. It’s the last gate before your changes become part of the shared code base. At this checkpoint, you run your validations and tests all at once, against the final artifact that’s about to be persisted.
This pattern works because it balances two competing needs: thoroughness (every committed change is fully validated) and efficiency (validation only happens when the risk profile changes, as code moves from “draft in progress” to “artifact being persisted”).
Applying the pattern to Amazon Bedrock Guardrails
The core best practice is to apply this same principle to Amazon Bedrock Guardrails: shift from continuous inline scanning to selective validation at strategic checkpoints.
Think of your code generation pipeline as having natural commit points, moments where content transitions from one trust level to another:
- User input received – Content enters your system from an untrusted source (validate here).
- Final code artifact assembled – The model’s complete response is ready to be presented or saved (validate here).
- Code written to file or committed to repository – AI-generated content is about to become persistent and potentially executable (validate here).
Between these checkpoints, while the model is reasoning, generating intermediate tokens, or producing chain-of-thought explanations, the content is ephemeral. It hasn’t crossed a trust boundary. Scanning it continuously adds cost and consumes quota without meaningfully improving your security posture.

Key principle: Use the decoupled ApplyGuardrail API to evaluate user-supplied inputs before they reach the model, and validate aggregated final code artifacts before they are committed, not every intermediate reasoning token.
Implementation: pre-commit validation for file operations
For the highest-risk checkpoint, when AI-generated code is about to be written to a file or committed to a repository, perform comprehensive guardrail evaluation. This is the pre-commit hook pattern applied directly:
import hashlib
from pathlib import Path
class CodeCommitGuardrail:
"""
Validates all AI-generated code changes before they are persisted.
Analogous to running security scanners in a Git pre-commit hook.
Use this when:
- A coding assistant writes code to disk
- AI-generated changes are staged for commit
- Generated code is about to be deployed
"""
def __init__(self, client, guardrail_id, guardrail_version):
self.client = client
self.guardrail_id = guardrail_id
self.guardrail_version = guardrail_version
self.validated_hashes = {} # Cache: don't re-validate unchanged files
def validate_file_changes(self, staged_files: dict) -> dict:
"""
Evaluate all staged AI-generated code changes before commit.
Args:
staged_files: Dict of {file_path: file_content} for all changed files
Returns:
Dict with 'safe' boolean and any violations found
"""
violations = []
skipped = []
for file_path, content in staged_files.items():
# Skip files that haven't changed since last validation
content_hash = hashlib.sha256(content.encode()).hexdigest()
if self.validated_hashes.get(file_path) == content_hash:
skipped.append(file_path)
continue
# Evaluate in 1,000-char aligned chunks
file_violations = self._evaluate_file(file_path, content)
if file_violations:
violations.extend(file_violations)
else:
# Cache successful validation
self.validated_hashes[file_path] = content_hash
return {
'safe': len(violations) == 0,
'violations': violations,
'files_evaluated': len(staged_files) - len(skipped),
'files_skipped_cached': len(skipped)
}
def _evaluate_file(self, file_path: str, content: str) -> list:
"""Evaluate a single file's content against guardrails."""
violations = []
for offset in range(0, len(content), 1000):
chunk = content[offset:offset + 1000]
response = self.client.apply_guardrail(
guardrailIdentifier=self.guardrail_id,
guardrailVersion=self.guardrail_version,
source='OUTPUT',
content=[{'text': {'text': chunk}}]
)
if response['action'] == 'GUARDRAIL_INTERVENED':
violations.append({
'file': file_path,
'offset': offset,
'length': len(chunk),
'assessments': response['assessments'],
'snippet': chunk[:200] + '...' if len(chunk) > 200 else chunk
})
return violations
# Example: Integration with a coding assistant's file-write operation
def write_ai_generated_code(file_path: str, content: str, guardrail: CodeCommitGuardrail):
"""
Wrapper for file writes that validates content before persisting.
"""
result = guardrail.validate_file_changes({file_path: content})
if not result['safe']:
print(f"Guardrail blocked write to {file_path}")
for v in result['violations']:
print(f" Violation at offset {v['offset']}: {v['assessments']}")
return False
# Safe to write
Path(file_path).write_text(content)
print(f"{file_path} validated and written successfully")
return TrueArchitecture pattern 2: Increase the streaming interval to 1,000 characters
When you do need real-time streaming evaluation, for example interactive coding sessions where you want to halt generation immediately upon detecting a violation, optimize the streaming interval. Increasing the guardrail interval from the default 50 characters to 1,000 characters can reduce your API call volume by 20x. See the following configuration:
# When using InvokeModelWithResponseStream with guardrails
response = bedrock_runtime.invoke_model_with_response_stream(
modelId='anthropic.claude-sonnet-4-20250514',
body=json.dumps(request_body),
guardrailIdentifier='your-guardrail-id',
guardrailVersion='1',
# Key configuration: increase streaming interval
streamingConfigurations={
'guardrailStreamingInterval': 1000 # Default is 50!
}
)Impact: A 5,000-character function goes from 100 evaluations to 5. A 50,000-character file goes from 1,000 evaluations to 50.
Architecture pattern 3: Use the decoupled ApplyGuardrail API for selective evaluation
With the standalone ApplyGuardrail API, you can use Amazon Bedrock Guardrails irrespective of the foundation model. You can evaluate text without invoking the foundation model.
Pattern: Input-only validation with unguarded inference
When your primary concern is preventing prompt injection and blocking malicious inputs, validate only the dynamic user content before it reaches the model. In that case, invoke the model without inline guardrails:
import boto3
import json
bedrock_runtime = boto3.client('bedrock-runtime')
def process_coding_request(user_input: str, system_prompt: str, conversation_history: list):
"""
Validate user input with guardrails, then invoke model without inline scanning.
The system prompt and conversation history are NOT re-evaluated every turn.
"""
Step 1: Evaluate ONLY the new dynamic user input
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み