tl;dr
- Nova 2 Liteはシステムプロンプトの読み込みが甘い節あり
- Haiku 4.5に比べて見劣りする
- チューニング前提の性能の可能性も?
- AgentCore Evaluationsのbuilt-in評価観点プロンプトにおいて、エージェントのシステムプロンプトや指示(instructions)を読み込むパラメータが存在しない
- カスタム評価プロンプトを作っても、上記を読み込めないのが辛い
- 現状で評価を実施すると、評価する側のLLMがハルシネーションを起こす
- まだPreviewなので、GAに期待
こんにちは、ふくちです。
2025/12/2未明、Amazon Bedrockの新モデルとしてAmazon Nova 2 Liteが登場しました。
(同時にNova 2 Pro, Omniも出ましたが、まだアーリーアクセス専用のようです。)
Nova 2 Lite can be used for a broad range of your everyday tasks. It offers the best combination of price, performance, and speed.
Nova 2 Lite は、日常の幅広いタスクにご利用いただけます。価格、パフォーマンス、速度の最適な組み合わせを提供します。
ということで、期待の持てるNova 2 LiteくんをStrands Agents SDKに組み込んで動かしてみることにしました。
さらにできるだけ具体的にNova 2 Liteの実力を測るべく、こちらも新登場のBedrock Evaluatinosを使って評価まで実施していきたいと思います。
今回使うエージェントは、以下ブログで作成した指定したタイムゾーンの現在時刻を取得してSlackへ送信するエージェントです。

このエージェントのゴールは、システムプロンプトに示した以下の通りの内容です(読みやすいように改行しています)。
system_prompt=
"あなたはいろんな地域の現在時刻をチェックしてそれをSlackに送信するエージェントです。
もし場所の指定がない場合は日本の現在時刻を教えて下さい。
Slackのチャンネルは指定がなければ、 #test-strands-agents チャンネルに送信してください。"
したがって、私が「日本の時間を教えて」と言った時には
- Lambda関数から日本の時間を取得する
- 取得した日本の時間をSlackに送る
という動作ができていればOKです。
Haiku 4.5 vs Nova 2 Lite
ここではHaiku 4.5エージェントと、Nova 2 Liteエージェントでバトルをしてもらいます。
対照実験になるよう、LLM以外の部分はすべて同じにしておきます。
2025年の暮に出てきた廉価モデル同士、どちらの精度・コストが良いかを比較していきましょう。
Haiku 4.5
$ uv run scripts/invoke_agent.py 日本の時間を教えて。
プロンプト: 日本の時間を教えて。
エージェントを呼び出し中...
--------------------------------------------------
"完了しました!日本の現在時刻を #test-strands-agents チャンネルに送信しました。\n\n**日本の現在時刻:2025年12月4日 07時39分04秒**"
$ uv run scripts/invoke_agent.py
プロンプト: ラスベガスの現在時刻を教えて
エージェントを呼び出し中...
--------------------------------------------------
"完了いたしました!ラスベガスの現在時刻は **2025年12月3日 14時39分43秒 (PST / UTC-8)** です。\n\nこの情報は #test-strands-agents チャンネルに送信されました。"
はい、良い感じですね。きちんと動いてくれています。
Nova 2 Lite
$ uv run scripts/invoke_agent.py 日本の時間を教えて。
プロンプト: 日本の時間を教えて。
エージェントを呼び出し中...
--------------------------------------------------
"日本の現在時刻は **2025年12月4日 07時45分** です。"
$ uv run scripts/invoke_agent.py
プロンプト: ラスベガスの現在時刻を教えて
エージェントを呼び出し中...
--------------------------------------------------
"ラスベガスの現在時刻は **2025年12月3日 14:45:14 (現地時間、太平洋標準時)** です。"
(Haiku 4.5の結果が最後のメッセージなので、Slackに送られていない)

Nova 2 Lite、嘘だよな…?
確かに現状ユーザープロンプトには簡潔なメッセージのみ記載しています。
しかしシステムプロンプト側でSlackへメッセージを送ることがゴールだと明記しています。
ところが、Nova 2 Liteは何度か試してもほとんどSlackへ送信してくれませんでした(1回だけ何故かしてくれたので不安定…)。
ちなみに今回のエージェントはStrands Agents SDK(Python)で実装しています。
ブログにサンプルが載っていたので、対応がまだとか相性が悪いとかは無い…はずです。
英語で試す
ちなみに、システムプロンプトやメッセージを英語にして試してもダメでした。
system_prompt=
"You are an agent that checks the current time in various regions and sends it to Slack.
If no location is specified, please tell me the current time in Japan.
If no Slack channel is specified, please send it to the #test-strands-agents channel."
$ uv run scripts/invoke_agent.py
プロンプト: What is the current time in Las Vegas?
エージェントを呼び出し中...
--------------------------------------------------
"The current time in Las Vegas (Pacific Time Zone) is **1:45 PM on December 3, 2025**. \n\n*(Note: Las Vegas operates on America/Los_Angeles timezone, which matches the time retrieved.)*"
ユーザープロンプトを詳細に書く
ここで、ユーザープロンプトにSlackへの送信を明記してみましょう。

$ uv run scripts/invoke_agent.py 日本の時間を教えて。Slackにも送信して。
プロンプト: 日本の時間を教えて。Slackにも送信して。
エージェントを呼び出し中...
--------------------------------------------------
"日本の現在時刻は、**2025年12月4日 07:52:13**(アジア/東京)です。\n\nこの情報をSlackの `#test-strands-agents` チャンネルに送信しました。"
ユーザープロンプトにも明記すると、上手く動いてくれました。良くも悪くも、指示されたとおりに動く傾向にあるようです。
良く言えばコントローラブル、悪く言えば言われたことしかできない。
ただここで、1つの仮説が生まれました。
Nova 2 Lite、システムプロンプトが効かない説
とはいえ、システムプロンプト側で明確にSlackに送れと記載しています。しかしそのとおりに動いてくれないということは、システムプロンプトを軽視している可能性があります。
もしそうだとしたら、かなり致命的です。エージェントとして動かすことはかなり厳しくなるためです。
そこで、通常のLLMとしてシステムプロンプトを設定し、動かしてみます。
システムプロンプトに「日本語で返答して」と英語で書いて、ユーザープロンプトも英語にする
これは大丈夫でした。
ずんだもん風に喋ってもらう
Haikuは最後だけ急に怖くなりましたが、Nova 2 Liteはすぐに忘れてしまいました。
全くシステムプロンプトが効かないわけではないですが、それでもHaiku 4.5と比較するとどうしても見劣りしてしまうような結果になりました。
1-2日目のKeynoteでモデルのチューニングをしやすくする機能がいっぱい出てましたが、もしかするとチューニング前提の性能なのかもしれません。しらんけど
AgentCore Evaluationsで評価してみる
ということでなかなか思ったとおりに動いてくれないNova 2 Liteくんですが、大事なのはやはり定量的な評価。
正直ここまでで結構な差が生まれてしまっていますが、私の主観で良い悪いを決めてしまっては可哀想なので、せっかくなら評価もしてみましょう。
ということで、こちらも新登場のAgentCore Evaluationsを使ってオンライン評価を実施してみようと思います。
(↓そもそもAgentCore Evaluationsってなんやねんという方はこちらをご覧ください↓)
オンライン評価とは
Evaluationsの特徴はオンライン評価が可能なことです。
つまり、実際にエージェントが動いた際のInput/Outputとその振る舞いに対する評価を評価専門LLMが実施する、というものです。
この時、その行動が正しかったかOutput内容がどうだったかについてはLLM自身が考えます。良く言えばユーザーの負荷が少なく、悪く言えばその評価が果たして100%信じられるものかどうかは疑問が残る、という感じです。
Evaluationの設定を行う
コンソールで進めていきます。
下のチェックボックスがあるやつは、作成と同時に有効化するか否かを決められる項目です。有効にするとお金がかかるそうなので、タイミング次第ではチェックを外しましょう。
また、一度有効化すると無効化されるまでずっと動き続けます。
また、Session idle timeoutはこの分数だけアクティビティがないと、そのエージェントセッションを完了として評価対象にするようなパラメータのようです。
きちんと検証できていないのですが、sessionIdごとにこの時間が観測・管理されるのかな?と妄想しています。

続いて、どのエージェントを評価対象とするのか決めます。AgentCore Runtimeの場合はそのまま指定可能です。
また、Runtime以外のところで動いているエージェントに対してもCloudWatch Logsにログを出力していれば評価対象とできるみたいです。

続いて評価項目を選びます。
従来のBedrock Evaluationと基本的に項目は変わらないです。
しかし、エージェント特有の評価観点が追加されています。
エージェントの振る舞いを観測するための項目である「Tool selection accuracy」「Tool parameter accuracy」「Goal success rate」が独自に追加されています。
ここではこの3つのみを選んで、ツールを適切に使えているか・正しくゴールまで迎えているかを確認してみます。

Filtersとは、どんなセッションを評価対象にするかを決定する条件のようです。今回は設定していません。
Sampling rateとは、対象になったセッションのうち何%を実際に評価するかを決める確率のようです。今回50%にしたので評価対象になっているのは半分なはずです(あんまり観測できませんでしたが…)。

ロールの具体的な中身については以下ドキュメントに記載がありました。
作成完了すると、このevaluationsのCloudWatchロググループが自動で作成されます。

評価結果を確認する
評価対象に指定したエージェントに対して何度かリクエストを投げて暫く待つと、自動で評価されて結果が表示されます。
また、設定したEvaluationを有効にしている間はずっと評価が働くので、エージェントを呼び出す度に評価が追加されていきます。
実際の評価を確認できるのはCloudWatch GenAI Observabilityのコンソールです。評価対象にしたエージェントのエンドポイントを指定すると、Evaluationsというタブが現れています。

結果がグラフとして見えるようになっています。大体80%-90%となっていて良い感じの結果になっていそうです。

ここで、もう1つ確認しましょう。先程作成されたEvaluationのログです。
評価自体は点数として出てきますが、どういった理由・観点でこの点数になったのか。そこを確認しておく必要があるためです。
先程設定した3つの評価基準に基づいて、確認を行います。
まずはToolSelectionAccuracy(ツール選択精度)。
"gen_ai.evaluation.name": "Builtin.ToolSelectionAccuracy",
"session.id": "6d18c508-d17f-4071-8944-5155a1d277e0",
"gen_ai.evaluation.score.value": 1, (0-1の間で変動、1に近いほど正確)
"gen_ai.evaluation.explanation":
"The user asked '日本の時間を教えて。' which translates to 'Tell me the time in Japan.'
This is a clear and direct request for the current time in Japan.
The agent called the 'lambda-function-target___get-current-time' function with the parameter 'timezone': 'Asia/Tokyo', which is the correct timezone for Japan.
The tool successfully returned the current time in Japan (2025-12-04T07:45:00.210542+09:00).
This action directly addresses the user's explicit request.
The parameter used (Asia/Tokyo timezone) is appropriate and necessary for fulfilling the user's need.
The action is aligned with the user's expressed intent, uses the correct parameters, and is exactly what a helpful assistant should do in this situation.
There is no ambiguity in the user's request, and the agent's response is the most direct and appropriate way to fulfill it."
(雑翻訳)ユーザーは「日本の時間を教えて」と言っており、エージェントはget-current-time関数を呼び出して日本時間を取得している。つまりパーフェクトだ。
ここで私は違和感を覚えました。なぜユーザープロンプトを元にゴールを設定されているのかと。
なぜシステムプロンプトに記載した内容がゴールに含まれていないのかと。
ちなみにこれはNova 2 LiteでもClaude Haiku 4.5でも、どちらでも同じようにシステムプロンプトが読み込まれていませんでした。
念の為、他の結果も確認してみましょう。
これは「Tool Parameter Accuracy(ツールパラメータ精度)」の結果です。
"gen_ai.evaluation.name": "Builtin.ToolParameterAccuracy",
"session.id": "6d18c508-d17f-4071-8944-5155a1d277e0",
"gen_ai.evaluation.score.value": 1,
"gen_ai.evaluation.explanation": "The user asked '日本の時間を教えて。' which translates to 'Tell me the time in Japan.'
The tool-call is to 'lambda-function-target___get-current-time' with the parameter 'timezone': 'Asia/Tokyo'.
\n\nAnalyzing the parameter:\n- 'timezone': 'Asia/Tokyo' - The user explicitly requested the time in Japan.
'Asia/Tokyo' is the standard IANA timezone identifier for Japan.
This is a reasonable and faithful interpretation of the user's request.
The user did not explicitly state 'Asia/Tokyo', but this is the correct timezone representation for Japan, which the user clearly referenced.
This is not a fabrication but rather a standard mapping from the user's natural language request to the technical parameter format required by the API.
\n\nThe parameter value is directly derived from the user's request through a straightforward and commonly understood mapping (Japan → Asia/Tokyo timezone).
This represents applying common sense to translate the user's intent into the proper technical format, rather than hallucinating or fabricating information.
The timezone format appears correct for standard timezone APIs.
\n\nNo parameters were omitted that would be necessary for fulfilling the user's request.
The tool-call faithfully represents the user's request using appropriate technical parameters."
(雑翻訳)
ユーザーは「日本の時間を教えて」と依頼した。
get-current-time関数を使い祭に「timezone: Asia/Tokyo」を指定している。
このパラメータは過不足なく完璧だ。
最後に「GetSuccessRate」です。
"gen_ai.evaluation.name": "Builtin.GoalSuccessRate",
"session.id": "6d18c508-d17f-4071-8944-5155a1d277e0",
"gen_ai.evaluation.score.value": 1,
"gen_ai.evaluation.explanation":
"The user asked '日本の時間を教えて。' which translates to 'Tell me the time in Japan.'
This is a straightforward request to get the current time in Japan.
\n\nTo achieve this goal, the AI assistant should:
\n1. Use a time-related tool to get the current time in Japan's timezone (Asia/Tokyo)
\n2. Return the time information to the user in a clear format
\n\nLooking at the conversation record:
\n1. The assistant correctly identified the need to get time information and used the 'lambda-function-target___get-current-time' tool
\n2. The assistant properly specified the timezone parameter as 'Asia/Tokyo' for Japan
\n3. The tool successfully returned the current time: '2025-12-04T07:45:00.210542+09:00' in the Asia/Tokyo timezone
\n4. The assistant formatted this information clearly in Japanese and presented it to the user as '2025年12月4日 07時45分' (December 4, 2025, 07:45)
\n\nThe assistant successfully:
\n- Used the appropriate tool for getting time information
\n- Provided the correct timezone for Japan
\n- Received accurate time data from the tool
\n- Formatted and presented the information clearly to the user in their language
\n\nThe user's goal of knowing the current time in Japan was fully achieved."
(雑翻訳)
ユーザーは「日本の時間を教えて」と依頼した。
これのゴールは
「時刻関連のツールを使用して、日本のタイムゾーン(Asia/Tokyo)の現在の時刻を取得する。」
「時刻情報を明確な形式でユーザーに返す。」
の2つだ。つまり完璧だ。
…違いますね。冒頭に記載したとおり、このエージェントのゴールは
- Lambda関数から日本の時間を取得する
- 取得した日本の時間をSlackに送る
この2つを実行することです。しかし時間を取得するだけでOKになってしまっています。
上記2つのゴールはシステムプロンプトに記載していますが、これが適用されていないということは、どうもシステムプロンプトが読まれていなそうです。
そこで、built-inメトリクスの評価用プロンプトを確認しました。
すると、一切システムプロンプトに関する取得がなされていませんでした。記載されていたのは以下3つの値のみ。
- available_tools: ツール ID、パラメーター、説明を含む、使用可能なツール呼び出しのセット
- context: 以前のターンのすべての情報 (ユーザー プロンプト、ツール呼び出しの詳細、アシスタントの応答) に加えて、現在のターンのユーザー プロンプトと、評価されるツール呼び出しの前に行われたすべてのツール呼び出し
- tool_turn: 評価中のツール呼び出し
これだけではシステムプロンプトを取得できていないため、評価用LLMが正しくゴールを設定できていません。
したがって、上記で記載した評価結果は、実は全て誤りでした。
ちなみにこれがSlack送信まで実行した際のToolParameterAccuracyはもっとひどい結果になっていました。正しい結果であるにもかかわらず、システムプロンプトを読み込んでいないため、誤りと判定されています。
"gen_ai.evaluation.name": "Builtin.ToolParameterAccuracy",
"session.id": "3555f040-8e7a-41c3-be0b-cc10d1041d5c",
"gen_ai.evaluation.score.value": 0,
"gen_ai.evaluation.explanation":
"Analyzing the parameters of the slack-target___chatPostMessage tool-call:
\n\n1. **channel parameter**: The value '#test-strands-agents' is used.
This channel name does not appear anywhere in the preceding context.
The user only requested \"Slackにも送信して\" (send to Slack as well) without specifying a channel.
The agent has fabricated this specific channel name without any basis in the user's request or prior API results.
\n\n2. **text parameter**: The value '日本の現在時刻は:2025-12-04 07:52:13 (アジア/東京)' is derived from the previous API result from lambda-function-target___get-current-time,
which returned {\"current_time\":\"2025-12-04T07:52:13.232175+09:00\",\"timezone\":\"Asia/Tokyo\"}.
The agent formatted this information into a human-readable Japanese message.
While the formatting differs slightly (removing milliseconds and the 'T' separator),
the core information (date, time, timezone) comes directly from the API result.
This is faithful to the preceding context.
\n\nThe critical issue is the 'channel' parameter.
The specific channel '#test-strands-agents' was not mentioned by the user or provided in any prior context.
This is a fabricated value that the agent introduced without any basis in the preceding conversation."
(雑翻訳)
Slackにメッセージを送るためにchatPostMessageツールを使用しているが、
「#test-strands-agent」なんてチャンネルはどこにも指定されていない!
これはハルシネーションだ!エージェントが捏造した値だ!
ハルシネーションしてるのは評価してる君やで、とそっと心でツッコミながら、適切なコンテキストを与えることの重要性が分かる結果となりました。
まとめ
- Nova 2 Liteはもうちょっとシステムプロンプトをちゃんと読み込んでほしい!
- AgentCore Evaluationsのbuilt-in評価観点プロンプトにsystem_prompt か instructions を追加してほしい!
- 現状Evaluationsを使うならカスタム評価プロンプトの方が多分良いけど、どっちにしろsystem_prompt/instructionsは設定できないからGAに期待しよう!
- Langfuseなどとも連携できると良いな!
ということで、今後に期待して待ちたいと思います!










