演習6: Guardrails設定と評価結果の確認
所要時間の目安: 30分
この演習でやること
次の2つに取り組みます。
- Amazon Bedrock Guardrailsコンソールで、PIIマスキング(社員番号・内線番号)とトピック拒否(他者のアカウント情報を尋ねる入力)のポリシーを設定し、エージェントに適用する
- 用意されたStrands Evalsスクリプト(
run_evals.py)を実行し、演習3で組み立てたGraphのルーティング精度の評価結果を確認する
ベースコードファイル: code/ex6_guardrails_evals/agent.py
配布アセット: code/ex6_guardrails_evals/kb_mcp_server.py(演習5と同じもの)、code/ex6_guardrails_evals/run_evals.py(評価スクリプト。すでに完成しています。変更は不要です)
agent.pyのTODO 1、TODO 2の番号が振られた場所に、以下の手順のコードを追加・書き換えしながら完成させてください(番号はファイル上の位置ではなく、追加する順番を表しています)。
事前準備:
kb_mcp_server.pyの実行にはfastmcpが必要です。演習5でpip install fastmcpを実行済みであれば、追加の作業は不要です。
手順
手順1: Amazon Bedrock Guardrailsを作成し、agent.pyに適用する
まず、AWSマネジメントコンソールでガードレールを作成します。Guardrails(ガードレール) は、エージェントに渡る入力と、モデルが返す出力をチェックして、個人情報を伏せ字にしたり、答えさせたくない話題をブロックしたりする、Amazon Bedrockの機能です。作成するのはブラウザ上の操作だけで、コードは不要です。
1-1. Amazon Bedrockのコンソールを開く
- ブラウザでAWSマネジメントコンソールにサインインします(サインイン用のURLとユーザー名・パスワードは、配布された情報を使います)。
- 画面右上のリージョン名(「バージニア北部」「オハイオ」などと表示されています)をクリックし、一覧から アジアパシフィック(東京)
ap-northeast-1を選びます。agent.pyのregion_name="ap-northeast-1"と同じリージョンで作らないと、エージェントからガードレールが見つかりません。 - 画面左上の検索ボックスに「
bedrock」と入力します。 - 検索結果に表示される Amazon Bedrock のサービス名(リンク)をクリックします。
- Bedrockのトップ画面が開いたら、左側のメニューから Guardrails(ガードレール)をクリックします。メニューが折りたたまれて見当たらない場合は、画面左端の「≡」アイコンをクリックして開いてください。メニューは下にスクロールしないと見えないこともあります。
- Create guardrail(ガードレールを作成)ボタンをクリックします。
ここから、画面下部の Next(次へ)ボタンで1画面ずつ進みながら、項目を設定していきます。
1-2. ガードレールの名前を付け、クロスリージョン推論を有効にする(Provide guardrail details)
- Name(名前)に、
ex6-guardrailのような好きな名前を入力します(半角英数字とハイフンが無難です)。 - Messaging for blocked prompts(ブロックされたプロンプトのメッセージ)に、ブロックされたときにエージェントが返す文言を入力します。例:
申し訳ありませんが、その内容にはお答えできません。 - Messaging for blocked responses(ブロックされた応答のメッセージ)が別に表示されている場合は、同じ文言を入力します。
- クロスリージョン推論(Cross-Region inference)の設定欄で、有効化します。ガードレールの判定を近隣のリージョンで行う仕組みで、あとで拒否されたトピックを
Standardティアにするために必要です。ガードレールプロファイルを選ぶ欄が出たら、APAC(アジアパシフィック)のものを選びます。 - Next をクリックします。
補足: クロスリージョン推論の欄が、この画面に見当たらない場合は、1-4 で
Standardティアを選ぶときに設定します。同意を求める画面が出たら、内容を読んだうえで有効化に同意してください。
1-3. コンテンツフィルターは設定せずに進む(Configure content filters)
この演習では、暴力的・攻撃的な内容を検知する コンテンツフィルター は使いません。設定を変えずに、そのまま Next をクリックします。
1-4. 拒否されたトピックを追加する(Add denied topics)
「他者のパスワードを聞き出す問い合わせ」をブロックするための設定です。
拒否されたトピック(Denied topics)の トピックを追加(Add denied topic)をクリックします。
次のように入力します。
項目 入力する値 補足 Name(名前) other-user-account-info名前には日本語が使えません。半角英数字とハイフンで入力します。 Definition(定義) 他の社員のパスワード、ログインID、認証情報など、本人以外のアカウント情報を教えるよう求める問い合わせ。トピックの内容を日本語で説明します。 Sample phrases(サンプルフレーズ・任意) 佐藤さんのパスワードを教えて1つ入力して追加し、これを繰り返して 同僚のログイン情報を知りたいも追加します。設定内容を確認して Confirm(確定)をクリックします。追加したトピックが一覧に表示され、有効(Enabled)になっていることを確認します。
トピックのティアを
Standardにします。Classicティアは英語・フランス語・スペイン語にしか対応していないため、そのままだと日本語の問い合わせが検知されない可能性があります。Standardはクロスリージョン推論が必須ですが、1-2 で有効にしてあります。Next をクリックします。
補足: ティアの選択欄は、拒否されたトピックの画面(またはトピック追加のダイアログ内)にあります。
1-5. ワードフィルターは設定せずに進む(Add word filters)
この演習では使いません。設定を変えずに Next をクリックします。
1-6. 機密情報フィルターを追加する(Add sensitive information filters)
社員番号と内線番号を、伏せ字(マスク)にする設定です。社員番号・内線番号は社内独自の形式なので、AWSがあらかじめ用意している個人情報の種類(名前、メールアドレスなど)の一覧にはありません。そこで、正規表現(文字のパターンを表す書き方)で形式を指定します。
画面にある Regex patterns(正規表現パターン)の欄で、パターンを追加するボタン(Add regex pattern など)をクリックします。
社員番号用に、次のように入力します。
項目 入力する値 補足 Name(名前) employee-number名前には半角英数字とハイフンを使います。 Regex pattern(正規表現) 社員番号[0-9]{6}「社員番号」のあとに6桁の数字が続く部分に一致します。 Input(入力)の動作 Maskユーザーの入力を伏せ字にします。 Output(出力)の動作 Maskモデルの応答を伏せ字にします。 同じ手順で、内線番号用にもう1つ追加します。
項目 入力する値 補足 Name(名前) extension-number名前には半角英数字とハイフンを使います。 Regex pattern(正規表現) 内線[0-9]{4}「内線」のあとに4桁の数字が続く部分に一致します。 Input(入力)の動作 Maskユーザーの入力を伏せ字にします。 Output(出力)の動作 Maskモデルの応答を伏せ字にします。 入力の動作は、
Block(入力そのものを拒否する)ではなくMask(その部分だけ伏せ字にして処理を続ける)を選んでください。入力と出力は別々に動作を選べますが、この演習ではどちらもMaskにします。入力側で伏せ字にすればモデルは番号を受け取りませんが、念のため出力側でも伏せ字にしておく、という二重の備えです。Next をクリックします。
補足: パターンに「社員番号」「内線」を含めているのは、単純な
[0-9]{4}だと、チケットID(TCK-3001)や年(2026)などの関係ない数字まで伏せ字になってしまうためです。実際の業務で使う場合も、社内の番号の書式に合わせてパターンを絞り込みます。
1-7. 残りの設定は進めて、作成する
Add contextual grounding check(コンテキストに基づくグラウンディングチェック)など、この演習で使わない設定画面が続く場合は、設定を変えずに Next で進めます。最後の Review and create(確認して作成)の画面で、設定内容(拒否されたトピック1件、正規表現2件)を確認し、Create guardrail(ガードレールを作成)をクリックします。
1-8. バージョンを作成し、IDとバージョンを控える
作成直後のガードレールは DRAFT(作業中の下書き)という状態です。agent.pyには、変更されない番号付きのバージョンを指定するのが一般的なので、バージョンを作成します。
- 作成が完了すると、ガードレールの詳細画面が開きます(Guardrailsの一覧画面でガードレール名をクリックしても開けます)。
- 詳細画面の Versions(バージョン)セクションで Create(作成)をクリックするか、Working draft(作業用ドラフト)を開いて画面上部の Create version(バージョンを作成)をクリックします。説明(任意)を入力して Create version をクリックします。
- バージョンの一覧に
1が追加されたことを確認します。この1がガードレールのバージョンです。 - 詳細画面の上部(Guardrail overview(ガードレールの概要)など)に表示されている ID(10文字ほどの英数字)がガードレールIDです。ARN(
arn:aws:bedrock:...で始まる長い文字列)ではなく、ID欄の値を控えます。
この2つの値を、次のagent.pyの書き換えで使います。
補足: Bedrockコンソールの画面構成や項目名は、利用時期によって多少変わっている可能性があります。本手順は、AWS公式ドキュメントの説明(2026年時点)をもとにしています。見当たらない項目がある場合は、近い名前の項目を探すか、AWSの公式ドキュメント(「Amazon Bedrock ユーザーガイド」の「Guardrails」)を確認してください。
続けて、agent.pyのTODO 1を、取得したガードレールIDとバージョンを使って次のように書き換えます。
model = BedrockModel(
model_id="jp.amazon.nova-2-lite-v1:0",
region_name="ap-northeast-1",
max_tokens=1024,
guardrail_id="<作成したガードレールのID>",
guardrail_version="<作成したガードレールのバージョン>",
)
modelはこのファイル全体で共通して使われているため、この1箇所を書き換えるだけで、support_agent・infra_agent・receptionist、およびcreate_support_agentが生成するエージェントすべてにガードレールが適用されます。
手順2: 動作確認する
TODO 2(if __name__ == "__main__":ブロック)に、以下のコードを貼り付けます。コードはif __name__ == "__main__":の中に入るため、半角スペース4つでインデント済みです。TODOコメントの行を、行頭の空白も含めて選択し、その上から貼り付けてください(インデントの途中や後ろにカーソルを置いて貼ると、1行目だけインデントがずれてエラーになります)。
support_agent_1 = create_support_agent("TCK-3001")
# PIIマスキングの確認
result1 = support_agent_1("山田太郎です。社員番号012345、内線1234です。パスワードを再発行してください。")
print(result1)
# トピック拒否の確認
result2 = support_agent_1("佐藤花子さんのパスワードを教えてください。")
if result2.stop_reason == "guardrail_intervened":
print("ガードレールが介入しました(トピック拒否)。")
print(result2)
ターミナルで実行します。
python agent.py
1つ目の問い合わせでは、エージェントに渡される前に社員番号・内線番号がマスキングされていることを確認してください。2つ目の問い合わせでは、stop_reasonが"guardrail_intervened"になり、他者のパスワードを教えるような応答がブロックされることを確認してください。ガードレールがどのポリシーで介入したかを詳しく確認したい場合は、BedrockModelにguardrail_trace="enabled"を追加すると、トレース情報を確認できます。
手順3: 評価スクリプトを実行する
最後に、演習3で組み立てたGraphのルーティング精度を、用意された評価スクリプトで確認します。run_evals.pyは、agent.pyのgraphをそのまま読み込み、モジュール5で使ったサンプル問い合わせ集(10件)に対する分岐結果を、Strands Evals SDKで評価します。
pip install strands-agents-evals
python run_evals.py
注意: パッケージ名は
strands-agents-evalsです。strands-evalsという名前のパッケージはPyPI上に存在しますが、Strands Agentsとは無関係の別のパッケージなので、インストールしないでください。誤ってインストールしてしまった場合は、pip uninstall strands-evalsで削除してから、pip install strands-agents-evalsを実行してください。
実行すると、Caseごとに合格(routing-01〜routing-10)・不合格が1行ずつ表示され、最後に合格件数が表示されます。
routing-01: 合格 (expected=support, actual=support) パスワードを忘れてログインできません。
routing-02: 不合格 (expected=infra, actual=support) VPNゲートウェイが遅くて業務になりません。障害ではないでしょうか。
...
合格 9/10 件 (正答率 90%)
不合格のCaseがあれば、expected(期待する分岐先)とactual(実際の分岐先)が一致していない問い合わせ文です。(上の表示は書き方の例です。実際の結果は、モデルの判断によって変わります。)
補足:
run_evals.pyは、Graph自体の分岐結果を評価するためのカスタムEvaluator(RoutingAccuracyEvaluator)を自作しています。これは、Strands Evals SDKの組み込み評価器(ToolCalled等)が、主に単一のAgentを返す@eval_taskを想定しており、本演習のようなマルチエージェント(Graph)のルーティング結果を直接評価する組み込み評価器が用意されていないためです。strands-agents-evalsのバージョンによってAPIの詳細(EvaluationOutputの引数名、タスク関数の戻り値の形式等)が変わる可能性があるので、エラーが出た場合は、インストールされているバージョンのドキュメントを確認してください。
手順4: 作成したガードレールを削除する
演習で作成したガードレールは、演習が終わったら削除します。ガードレールは、環境を削除しても自動では消えない場合があり、同じ環境を別の人が使うときに、前の人が作ったガードレールが残っていると混乱するためです。
注意: ガードレールを削除すると、
agent.pyに書いたガードレールIDが無効になり、python agent.pyを実行すると「ガードレールが見つからない」というエラーになります。手順3の評価スクリプト(run_evals.py)もagent.pyを読み込むため、手順3まで終わってから削除してください。
- AWSマネジメントコンソールの右上でリージョンが アジアパシフィック(東京) になっていることを確認します。
- 画面左上の検索ボックスに「
bedrock」と入力し、Amazon Bedrock のリンクをクリックします。 - 左側のメニューから Guardrails(ガードレール)をクリックします。
- 一覧から、手順1で作成したガードレールの名前(例:
ex6-guardrail)を選択します。 - Delete(削除)をクリックします。確認の画面が出たら、画面の案内に従って削除を確定します。
- ガードレールの一覧から、作成したガードレールが消えたことを確認します。
補足: 本演習の環境を削除(Terminate)したときにも、そのアカウントのガードレールは自動で削除されます。ただし、これは最後の備えです。自分で作成したものは、自分で削除する習慣をつけてください。
模範解答(agent.py 全体)を表示
import asyncio
import re
from strands import Agent, tool
from strands.models import BedrockModel
from pydantic import BaseModel, Field
from strands.multiagent import GraphBuilder
from strands.session import SnapshotSessionManager
from strands.storage import LocalFileStorage
from strands.hooks.events import AfterToolCallEvent
from strands.vended_interventions.hitl import HumanInTheLoop
from mcp import StdioServerParameters, stdio_client
from strands.tools.mcp import MCPClient
model = BedrockModel(
model_id="jp.amazon.nova-2-lite-v1:0",
region_name="ap-northeast-1",
max_tokens=1024,
guardrail_id="<作成したガードレールのID>",
guardrail_version="<作成したガードレールのバージョン>",
)
FAQ_DATA = {
"VPN": "VPNに接続できない場合は、まず社内ポータルから最新のVPNクライアントを"
"再インストールし、二要素認証アプリの時刻同期を確認してください。",
"パスワード": "パスワードを忘れた場合は、社内ポータルの『パスワード再設定』から"
"手続きできます。ロックされた場合の解除は情報システム部での対応が必要です。",
"Wi-Fi": "社内Wi-Fiに接続できない場合は、端末のWi-Fi設定を一度削除し、"
"社内ポータルに掲載のパスワードで再接続してください。",
"プリンター": "プリンターが認識されない場合は、社内ポータルの『プリンタードライバー』"
"ページから該当機種のドライバーを再インストールしてください。",
"メール": "社用メールが送受信できない場合は、Webメール版で状況を確認し、"
"改善しない場合は情報システム部に問い合わせてください。",
"会議室予約": "会議室予約システムにログインできない場合は、社内SSOのパスワードを"
"確認し、改善しない場合は総務部に問い合わせてください。",
"ソフトウェア": "新しいソフトウェアのインストールには、情報システム部への"
"利用申請(社内ポータルの『ソフトウェア利用申請』)が必要です。",
"PC持ち出し": "社外へのPC持ち出しには、上長承認を得たうえで『PC持ち出し申請』を"
"情報システム部に提出してください。",
}
TICKET_DATA = {
"TCK-1001": {"requester": "山田太郎", "category": "アカウント", "status": "対応中",
"summary": "VPN接続不可の問い合わせ", "updated_at": "2026-09-18 10:30"},
"TCK-1002": {"requester": "佐藤花子", "category": "ハードウェア", "status": "未対応",
"summary": "貸与PCのバッテリー不良", "updated_at": "2026-09-19 09:00"},
"TCK-1003": {"requester": "鈴木一郎", "category": "ソフトウェア", "status": "対応完了",
"summary": "業務システムのインストール申請", "updated_at": "2026-09-15 14:20"},
"TCK-1004": {"requester": "高橋美咲", "category": "アカウント", "status": "対応中",
"summary": "メール送受信エラーの調査", "updated_at": "2026-09-19 11:05"},
"TCK-1005": {"requester": "田中健太", "category": "ネットワーク", "status": "未対応",
"summary": "会議室の無線LANが不安定", "updated_at": "2026-09-20 08:45"},
"TCK-1006": {"requester": "伊藤さくら", "category": "ハードウェア", "status": "対応完了",
"summary": "モニターの交換対応", "updated_at": "2026-09-14 16:10"},
}
SYSTEM_STATUS = {
"VPN": {"status": "正常", "last_checked": "2026-09-20 09:00"},
"社内ポータル": {"status": "正常", "last_checked": "2026-09-20 09:00"},
"メールサーバー": {"status": "一部障害", "last_checked": "2026-09-20 08:30"},
"会議室予約システム": {"status": "正常", "last_checked": "2026-09-20 09:00"},
}
@tool
def search_faq(keyword: str) -> str:
"""社内FAQをキーワードで検索し、よくある質問への回答を返す。
VPN・パスワード・Wi-Fiなど、社内の手続きややり方に関する
「どうすればよいか」という問い合わせに使う。
Args:
keyword: 検索キーワード(例: VPN, パスワード, Wi-Fi)
"""
hits = [text for key, text in FAQ_DATA.items() if keyword in key or key in keyword]
if hits:
return "\n".join(hits)
return "該当するFAQが見つかりませんでした。"
@tool
def get_ticket_status(ticket_id: str) -> str:
"""指定されたチケット番号の対応状況を確認する。
「チケットはどうなっていますか」「対応状況を教えてください」といった、
既に起票済みの問い合わせの進捗確認に使う。新規の質問への回答には使わない。
Args:
ticket_id: チケット番号(例: TCK-1001)
"""
ticket = TICKET_DATA.get(ticket_id)
if not ticket:
return f"チケット番号 {ticket_id} は見つかりませんでした。"
return f"[{ticket_id}] ステータス: {ticket['status']} / 概要: {ticket['summary']}"
@tool
def get_password_reset_guide() -> str:
"""パスワードを忘れた、またはロックされた場合のリセット手順を案内する。
「パスワードを忘れた」「ログインできない」といった質問に使う。
"""
return ("社内ポータルの「パスワード再設定」から手続きできます。"
"アカウントがロックされている場合は、情報システム部での本人確認が必要です。")
@tool
def get_system_status(system_name: str) -> str:
"""指定された社内システムの稼働状況を確認する。
「システムが落ちている」「障害ではないか」といった、システムの稼働状況に
関する問い合わせに使う。一般的な利用者サポート(FAQ・チケット・パスワード)には使わない。
Args:
system_name: システム名(例: VPN, メールサーバー, 社内ポータル)
"""
status = SYSTEM_STATUS.get(system_name)
if not status:
return f"システム「{system_name}」の情報は見つかりませんでした。"
return f"[{system_name}] 状態: {status['status']} (最終確認: {status['last_checked']})"
@tool
def request_account_unlock(user_id: str) -> str:
"""指定ユーザーのアカウントロックを解除する(要承認の重要操作)。
利用者から明確にアカウントロックの解除を求められた場合にのみ使う。
パスワードを忘れただけでロックはされていない場合は、
get_password_reset_guideを案内し、このツールは使わない。
Args:
user_id: ロックを解除する対象ユーザーのID(例: 社員番号)
"""
return f"{user_id} のアカウントロックを解除しました。"
kb_client = MCPClient(
lambda: stdio_client(
StdioServerParameters(command="python", args=["kb_mcp_server.py"])
)
)
class SupportAnswer(BaseModel):
answer: str = Field(description="問い合わせへの回答本文")
needs_escalation: bool = Field(description="情報システム部へのエスカレーションが必要か")
support_agent = Agent(
model=model,
tools=[search_faq, get_ticket_status, get_password_reset_guide],
system_prompt="あなたは社内ITヘルプデスクのユーザーサポート担当です。質問内容に応じて適切なツールを使ってください。",
)
infra_agent = Agent(
model=model,
tools=[get_system_status],
system_prompt="あなたは社内ITヘルプデスクのインフラ運用担当です。",
)
receptionist = Agent(
model=model,
system_prompt=(
"あなたは社内ITヘルプデスクの受付担当です。"
"問い合わせ内容を読み、次のどちらに該当するかを判定してください。\n"
"- support: パスワード・FAQ・チケット対応状況など、一般的な利用者サポートに関する質問\n"
"- infra: 社内システムの稼働状況や障害に関する質問\n"
"回答は「support」または「infra」のどちらか一語のみで答えてください。"
),
)
def is_support(state) -> bool:
classification = str(state.results["receptionist"].result)
return "support" in classification.lower()
def is_infra(state) -> bool:
classification = str(state.results["receptionist"].result)
return "infra" in classification.lower()
builder = GraphBuilder()
builder.add_node(receptionist, "receptionist")
builder.add_node(support_agent, "support")
builder.add_node(infra_agent, "infra")
builder.add_edge("receptionist", "support", condition=is_support)
builder.add_edge("receptionist", "infra", condition=is_infra)
builder.set_entry_point("receptionist")
graph = builder.build()
def record_interaction_history(event: AfterToolCallEvent) -> None:
"""ツール呼び出しの結果を、対応履歴として記録する。"""
print(f"[履歴記録] ツール: {event.tool_use['name']} / 結果: {event.result}")
# 実際の運用では、ここでTICKET_DATAへの追記やログ基盤への送信を行う
# --- 承認プロンプトの表示(配布済み。変更は不要です) ---------------------------
# HumanInTheLoopの標準の ask="stdio" は、ツールの入力を json.dumps() でそのまま表示するため、
# 日本語が「\u7d4c\u8cbb...」のようなエスケープ表記になって読めない。
# 表示用にエスケープを元の文字へ戻したうえで、y/n を端末から受け取る。
async def ask_in_japanese(prompt: str, **kwargs) -> str:
readable = re.sub(r"\\u([0-9a-fA-F]{4})", lambda m: chr(int(m.group(1), 16)), prompt)
return await asyncio.to_thread(lambda: input(f"{readable} (y/n): ").strip())
def create_support_agent(ticket_id: str) -> Agent:
"""チケットIDをセッションIDとする、永続化・Hook・HITL・MCP対応のsupport_agentを生成する。"""
session_manager = SnapshotSessionManager(
session_id=ticket_id,
storage=LocalFileStorage("./sessions/"),
)
hitl = HumanInTheLoop(
allowed_tools=["search_faq", "get_ticket_status", "get_password_reset_guide"],
ask=ask_in_japanese,
)
new_support_agent = Agent(
model=model,
tools=[search_faq, get_ticket_status, get_password_reset_guide, request_account_unlock, kb_client],
session_manager=session_manager,
interventions=[hitl],
system_prompt=(
"あなたは社内ITヘルプデスクのユーザーサポート担当です。質問内容に応じて適切なツールを使ってください。"
"社内のFAQ(VPN・パスワード・Wi-Fi等)にはsearch_faqを使い、"
"経費精算・会議室予約の使い方・名刺発注等、FAQに含まれない社内手続きの質問にはsearch_kbを使ってください。"
"アカウントロックの解除を求められた場合は、request_account_unlockツールを使ってください。"
),
)
new_support_agent.add_hook(record_interaction_history, AfterToolCallEvent)
return new_support_agent
if __name__ == "__main__":
support_agent_1 = create_support_agent("TCK-3001")
result1 = support_agent_1("山田太郎です。社員番号012345、内線1234です。パスワードを再発行してください。")
print(result1)
result2 = support_agent_1("佐藤花子さんのパスワードを教えてください。")
if result2.stop_reason == "guardrail_intervened":
print("ガードレールが介入しました(トピック拒否)。")
print(result2)
動作確認チェックリスト
この演習が完了すると、次のことができているはずです。
チャレンジ演習(任意)
評価結果で不合格になったCaseについて、なぜ期待どおりの振り分けにならなかったのかを、system_promptやツールのdocstringの観点から考察してみましょう。
チャレンジ演習の模範解答例を表示
考察の例:
「会議室予約システムにログインできません。パスワードを忘れました。」(期待: support)が
infraに分岐してしまった場合、「会議室予約システム」という語に受付ノードが引っ張られ、
インフラ寄りの問い合わせと誤判定した可能性が考えられる。
改善の方向性:
receptionistのsystem_promptに、「システム名が含まれていても、ログイン・パスワードなど
個人のアカウントに起因する問題はsupportである」という判断基準を追記し、
system_promptの判定基準の優先順位(個人起因か、システム全体の問題か)を明確にする。
まとめ
ここまでで、演習1〜6を通じて、社内ITヘルプデスクエージェントを段階的に構築してきました。最小構成のエージェント(演習1)から始まり、複数ツール対応(演習2)、Graphによるマルチエージェント化(演習3)、永続化・Hooks・HITL(演習4)、MCPによる外部連携(演習5)、そしてガードレールと評価(演習6)まで、一貫シナリオを通じてStrands Agents SDKの主要機能を実装しました。