Skip to content

TypeScript Agent Guardrails

TypeScript AgentにAmazon Bedrock Guardrailをアタッチします。ガードレールは、エージェントがモデルに送信するメッセージとモデルの回答に対してAmazon Bedrockが適用する一連のルールです。ガードレールがない場合、ユーザーはエージェントにあらゆるトピックについて質問でき、モデルは回答の中でメールアドレスなどの個人データを繰り返すことができます。

ジェネレーターは、ルールを保持するポリシーファイル、エージェントのモデルにガードレールを適用するコード、およびAWSアカウントにガードレールを作成するインフラストラクチャを追加します。

  • agent.tsの隣にあるguardrail.jsonがルールを保持します:エージェントが拒否する必要があるトピックと、隠すかブロックする必要がある個人データ(PII、個人を特定できる情報)のタイプです。
  • CDKコンストラクトまたはTerraformモジュールは、合成または計画時にguardrail.jsonを読み取ります。ガードレールとその番号付きバージョンを作成します。ガードレールバージョンは、ルールの読み取り専用スナップショットです。
  • インフラストラクチャは、ガードレールのIDとバージョン番号をruntime configに書き込みます。runtime configは、インフラストラクチャがデプロイされたリソースの詳細を保存するAWS AppConfigアプリケーションです。エントリはagentcore.guardrails.<AgentClass>で、エージェントのクラスにちなんで名付けられます。例えばagentcore.guardrails.MyAgentです。ガードされた各エージェントには独自のエントリがあります。
  • guardrail.tsは、new Agent({...})呼び出しが使用するBedrockモデルを構築します。各モデル呼び出しの前に、モデルはruntime configからエージェントのエントリを読み取り、そのガードレールを適用します。

ts#agentジェネレーターで作成されたエージェントを含む既存のTypeScriptプロジェクトが必要です。

このジェネレーターを実行@aws/nx-plugin:ts#agent#guardrails

pnpm nx g @aws/nx-plugin:ts#agent#guardrails
コマンドを組み立てる2

必須

ジェネレーターオプション2 オプション
project必須string

TypeScript Agentを含むプロジェクト

agentstring

保護するAgentコンポーネントの名前。プロジェクトに複数のTypeScript Agentが含まれている場合は必須です。

ジェネレーターは、エージェントの隣に以下のファイルを追加します。ここで<agent>はエージェントコンポーネントの名前です(デフォルトではagent):

  • Directory<your-project>/src/<agent>/
    • agent.ts model: getGuardrailedModel()で作成されたエージェント
    • guardrail.json ガードレールが適用するルール
    • guardrail.ts ガードレールが適用されたBedrockモデルを構築

また、選択したiacプロバイダーのインフラストラクチャも追加します。ここで<agent-name>はエージェントのコンストラクトまたはモジュールのケバブケース名です:

  • Directorypackages/common/constructs/src/app/guardrails/<agent-name>/
    • <agent-name>-guardrail.ts ガードレールとそのバージョンを含むCDKコンストラクト

ジェネレーターは次のようにagent.tsを編集します:

import { getGuardrailedModel } from './guardrail.js';
import { Agent, tool } from '@strands-agents/sdk';
export const getAgent = async () => {
const agent = new Agent({
model: getGuardrailedModel(),
systemPrompt: `You are a mathematical wizard.

同じエージェントでジェネレーターを再度実行してもファイルは変更されず、guardrail.jsonへの編集は保持されます。

エージェントがinfra: noneで生成された場合、ジェネレーターはエージェントファイルのみを追加し、警告を出力します。その後、自分でガードレールを作成し、そのIDとバージョンをagentcore.guardrails.<AgentClass>のruntime configに{ guardrailId, guardrailVersion }として書き込みます。

すでにモデルを設定しているエージェント

Section titled “すでにモデルを設定しているエージェント”

new Agent({...})呼び出しがすでにmodelを設定している場合、ジェネレーターはagent.tsを変更しません。ファイル名と追加する行を出力します。独自のモデルオプションを保持するには、guardrail.tsのGuardrailedBedrockModelクラスでモデルを作成します。これはBedrockModelと同じオプションを受け取ります。例:

agent.ts
import { GuardrailedBedrockModel } from './guardrail.js';
const agent = new Agent({
model: new GuardrailedBedrockModel({ modelId: 'my-model-id' }),
// ...
});

ガードレールがチェックする内容

Section titled “ガードレールがチェックする内容”

ガードレールは、すべてのモデル呼び出しで2つのことをチェックします:

  • ユーザーの最新メッセージを含む、エージェントがモデルに送信する会話
  • エージェントがユーザーにストリーミングする前のモデルの回答

ガードレールがユーザーのメッセージをブロックすると、ユーザーはblockedInputMessagingテキストを受け取り、モデルは呼び出されません。Strandsは、エージェントの会話履歴内のブロックされたメッセージを[User input redacted.]に置き換えます。回答をブロックすると、ユーザーはblockedOutputsMessagingテキストを受け取ります。ANONYMIZEルールが一致すると、回答には値の代わりに{EMAIL}などのプレースホルダーが含まれます。

ガードレールは、ツール定義、モデルがツールに渡す引数、またはツールが返す結果をチェックしません。たとえば、ツールがデータベースから顧客のメールアドレスを返す場合、ガードレールはそれをモデルから隠しません。TypeScript Agentガイドの「Securing your Agent」で説明されているように、ツールの結果を信頼できないものとして扱ってください。

提供されるポリシーは、生成された数学エージェントの例です。投資アドバイスを拒否し、3種類の個人データを隠すかブロックします:

guardrail.json
{
"blockedInputMessaging": "Sorry, I can't help with that request.",
"blockedOutputsMessaging": "Sorry, I can't share that answer.",
"deniedTopics": [
{
"name": "Investment advice",
"definition": "Recommendations about which specific stocks, funds or other investments to buy or sell.",
"examples": ["Which stocks should I buy this year?"]
}
],
"piiEntities": [
{ "type": "EMAIL", "action": "ANONYMIZE" },
{ "type": "PHONE", "action": "ANONYMIZE" },
{ "type": "US_SOCIAL_SECURITY_NUMBER", "action": "BLOCK" }
]
}

フィールドは次のとおりです:

  • blockedInputMessaging:ガードレールがメッセージをブロックしたときにユーザーが受け取る返信。最大500文字。
  • blockedOutputsMessaging:ガードレールがモデルの回答をブロックしたときにユーザーが受け取る返信。最大500文字。
  • deniedTopics:エージェントが拒否する必要があるトピック。各トピックには、name(最大100文字の英字、数字、スペース、および文字-_!?.)、トピックを説明する最大1000文字のdefinition、およびオプションで各最大100文字のexamplesがあります。
  • piiEntities:アクションを実行する個人データのタイプ。typeは、EMAIL、PHONE、US_SOCIAL_SECURITY_NUMBERなどの機密情報タイプです。actionは、値をプレースホルダーに置き換えるANONYMIZE、またはメッセージまたは回答全体をブロックするBLOCKです。

トピック自体を説明するdefinitionを書いてください。たとえば、「Recommendations about which specific stocks to buy」は「Do not give investment advice」よりもうまく機能します。

バージョンが番号付けされている理由

Section titled “バージョンが番号付けされている理由”

guardrail.jsonを変更してデプロイするたびに、インフラストラクチャは新しい番号付きガードレールバージョンを作成し、runtime configに書き込みます。バージョンの説明にはguardrail.jsonのSHA-256ハッシュが保持されるため、ファイルへの変更は説明を変更し、新しいバージョンが古いバージョンを置き換えます。CDKコンストラクトでは、ハッシュは渡すガードレールプロパティもカバーします。

実行中のエージェントは再起動する必要がありません。runtime configから読み取った内容を5秒間キャッシュするため、AppConfigデプロイメントから5秒以内に新しいバージョンを使用します。古いバージョンはAppConfigデプロイメント後に削除されます:CloudFormationはクリーンアップステップで削除し、Terraformはガードレールをエージェントに配線するで示されているように、ガードレールモジュールをそのモジュールのdepends_onに追加すると、デプロイメントモジュールの後に削除します。

エージェントはDRAFTバージョンを使用しません。DRAFTは常に最新のルールを保持するため、AWSコンソールで行われた編集は、デプロイメントなしで実行中のエージェントに到達します。guardrail.tsは、runtime config内のバージョンがバージョン番号でない場合にエラーをスローします。

ガードレールをエージェントに配線する

Section titled “ガードレールをエージェントに配線する”

ジェネレーターは、ts#agentジェネレーターがエージェントのデプロイをユーザーに任せるのと同じように、スタックまたはルートTerraformモジュールを変更しません。完了すると、エージェントの名前が入力された以下のコードを出力します。これを追加して、ガードレールを作成し、そのruntime configエントリを書き込み、エージェントがガードレールを適用できるようにします:

packages/infra/src/stacks/application-stack.ts
import { MyAgent, MyAgentGuardrail } from '@my-scope/common-constructs';
const agent = new MyAgent(this, 'MyAgent');
new MyAgentGuardrail(this, 'MyAgentGuardrail', { agent });

コンストラクトは、ガードレールのIDとバージョンをagentcore.guardrails.MyAgentのruntime configに書き込み、agentにガードレールを適用する権限を付与します。エージェントコンストラクトは、すでにエージェントがruntime configを読み取ることを許可しています。

コンストラクトは以下を公開します:

  • guardrail(CfnGuardrail)およびversion(CfnGuardrailVersion)
  • guardrailId、guardrailArn、guardrailVersion
  • grantApply(grantee)、別のプリンシパルにガードレールに対してbedrock:ApplyGuardrailを付与します

また、GuardrailIdおよびGuardrailVersionスタック出力も追加します。そのpropsはagentと任意のCfnGuardrailプロパティです。CfnGuardrailプロパティはguardrail.jsonよりも優先されます。たとえば、コンテンツフィルターを追加します:

new MyAgentGuardrail(this, 'MyAgentGuardrail', {
agent,
contentPolicyConfig: {
filtersConfig: [
{ type: 'HATE', inputStrength: 'HIGH', outputStrength: 'HIGH' },
],
},
});

配線を忘れると、runtime configにエージェントのエントリがありません。モデルはBedrockを呼び出す前にエラーをスローするため、エージェントはガードレールなしでは実行されません。MyAgentの場合、エラーは次のとおりです:

No guardrail for this agent in runtime config at agentcore.guardrails.MyAgent. Add the MyAgentGuardrail construct (CDK) or the guardrails/my-agent module (Terraform) to your infrastructure.

エージェントはすべてのプロトコル(http、a2a、ag-ui)で起動し、各リクエストはこのエラーで失敗します。

<agent>-devターゲットはLOCAL_DEV=trueを設定します。LOCAL_DEVがtrueでRUNTIME_CONFIG_APP_ID環境変数が設定されていない場合、guardrail.tsはruntime configを読み取りません。一度警告を出力し、エージェントはガードレールなしで実行されます:

Terminal window
pnpm nx agent-dev your-project

ルールをローカルでテストするには、最初にガードレールをデプロイします。次に、RuntimeConfigApplicationIdスタック出力(CDK)またはmodule.runtime_config_appconfig.application_id(Terraform)から、デプロイされたruntime configアプリケーションのIDにRUNTIME_CONFIG_APP_IDを設定します。シェルには、AppConfigを読み取り、ガードレールを適用できるAWS認証情報も必要です:

Terminal window
RUNTIME_CONFIG_APP_ID=<application-id> pnpm nx agent-dev your-project

エージェントは自分のエントリのみを読み取るため、複数のガードされたエージェントが同じアプリケーションに対してローカルで実行できます。エージェントがruntime configを読み取れない場合、またはエントリが欠落している場合は、一度警告を出力し、ガードレールなしで実行されます。

<agent>-serveターゲットはLOCAL_DEVを設定しないため、RUNTIME_CONFIG_APP_IDとデプロイされたエントリが必要です。そうでない場合、各リクエストは上記のように失敗します。<agent>-chatターゲットは実行中のエージェントに接続し、runtime config自体は必要ありません。

Amazon Bedrockは、入力と回答の両方でテキストを評価する各ガードレールポリシーに対して課金します。Amazon Bedrock pricingを参照してください。

各モデル呼び出しも長くなります。これは、ガードレールがエージェントがユーザーにストリーミングする前に回答をチェックするためです。

  • このジェネレーターは、ts#agentで作成されたエージェントをサポートします。AgentCore Harnessはサポートしていません。
  • guardrail.jsonは、拒否されたトピックとPIIエンティティのみを保持します。コンテンツフィルターやワードフィルターなどの他のポリシーは、コンストラクトのprops(CDK)を使用するか、モジュールを編集(Terraform)して追加します。
  • ガードレールは、ガードレールがチェックする内容で説明されているように、ツールの結果をチェックしません。