[アップデート] Amazon CloudWatch Omni が一般提供開始されました!

[アップデート] Amazon CloudWatch Omni が一般提供開始されました!

CloudWatch Omniが一般提供開始されました!作ったのAIエージェントの情報を一箇所で色々と見れるようになったので触ってみました!
2026.09.24

はじめに

こんにちは、AgentCoreが大好きなコンサルティング部の神野です。

2026年9月23日に、生成AIやエージェント向けのオブザーバビリティ機能として Amazon CloudWatch Omni が一般提供開始されました!

https://aws.amazon.com/jp/blogs/aws/introducing-amazon-cloudwatch-omni-ai-powered-observability-for-generative-ai-and-agentic-workloads/

新しいダッシュボードのようなものがあり、なんだか壮大な感じですね!
実際に触ってみてOmniを体感してみましょう!

これまでの CloudWatch と何が違うの?

公式ブログを読むと、「アプリ中心」「AIを活用」「オープンな標準」「コンソールの外で提供」といった言葉と、トレース、評価、データセット、Playground、オンライン評価……と機能がずらっと並んでいます。

正直これだけだとあんまり分からないしなんだかできること多そう・・・ぐらいですよね。
エージェントのトレースは以前から CloudWatch の GenAI Observability ダッシュボードで見られましたし、評価も AgentCore Evaluations でできていたのでなにが変わったんだろう??と率直に思いました。

https://dev.classmethod.jp/articles/amazon-bedrock-agentcore-observability-genai-observability/

今までとOmniを比較してみるとこのような違いをざっと理解して整理してみました。

これまではトレース・評価・期待値やプロンプトの比較を別々の場所で扱っていたが、Omniでは1つの画面で続けて扱える

これまでは、トレースやオンライン評価は CloudWatch コンソールで確認し、オンデマンドの評価は AgentCore CLI でトレースIDなどを指定して実行していました。テスト用の質問やプロンプトの比較も手元で別に用意していて、画面とターミナルを行き来する感じでした・・・

それが Omni では、気になったトレースをその場で評価し、データセットに残し、Playground でプロンプトを比べるところまで1つの画面で進められるとのことです。
なるほど・・・!確かに便利そうだ・・・!

Omni でなにができるのか、全体像も押さえておきましょう。CloudWatch に集まったログ・メトリクス・トレースを、アプリの監視、分析とダッシュボード、エージェントの可観測性の3つの機能群から見られ、どの画面からでも Ask Assistant に質問できます。

CloudWatchに集まったデータを、Omniのスペースでアプリ監視・分析とダッシュボード・エージェントの可観測性の3つの機能群から見られ、どの画面でもAsk Assistantに質問できる

なお、Omni を有効にしても GenAI Observability ダッシュボードやアラームなど、従来の CloudWatch の機能はそのまま使えます。既存の仕組みの上に新しい画面が備わったイメージです。

ホームに並ぶ18個の機能と、この記事で触っている節は次のとおりです。

機能 使い所 記事の節
Application map サービス同士の呼び出し関係を地図で見る エージェント以外の機能
Services サービスごとのリクエスト数・エラー率を見る エージェント以外の機能
Traces アプリも含めたトレースを横断して探す エージェント以外の機能
Explore logs ログを SQL か日本語の質問で集計する エージェント以外の機能
Explore metrics メトリクスをグラフにする エージェント以外の機能
Alerts しきい値を超えたら通知する オンライン評価
Investigations AWS DevOps Agent と原因を調べる エージェント以外の機能
Dashboards よく見るページを保存する エージェント以外の機能
Markdown ダッシュボードにメモや手順を置く エージェント以外の機能
Agent overview エージェント全体の利用状況をつかむ エージェント向けのダッシュボード
Evaluation dashboard 評価器ごとの点数を比べる エージェント向けのダッシュボード
Evaluators 評価器を選ぶ・自作する 評価を実行する
Online evaluations 新しい実行を自動で採点する オンライン評価
Agent traces 1回の実行の中身を調べる トレースで調べる
Agent sessions 会話単位で入出力・費用・評価を見る エージェント向けのダッシュボード
Agent topology モデルとツールの呼び出しの流れを見る エージェント向けのダッシュボード
Datasets 質問と期待する回答を残す データセット
Prompt playground プロンプトの書き方を比べる Prompt playground

いや、機能めっちゃ多くね・・!!って率直に思いました。

機能がとにかく多いので、最初は混乱しますね!そこで今回は、小さな経費精算エージェントを1つ作り、「おかしな回答を見つけて直す」流れに沿って、1つずつ丁寧に見ていきます。

今回の進め方

社内の経費精算ルールに答えるエージェントを AgentCore Runtime にデプロイし、実際に質問を送って Omni で調べます。エージェントは Strands Agents で作ったシンプルな構成で、規程を検索するツール(search_expense_policy)と出張手当を計算するツール(calculate_travel_allowance)を持たせています。

エージェントのトレースがOmniに届き、トレース・評価・データセット・Playground・オンライン評価の順に確かめ、直した結果をエージェントへ戻す流れ

Omni の機能は、次の順番で1つずつ触っていきます。

  • トレース
    • おかしな回答がどこで起きたかを調べる
  • 評価
    • 回答を点数と理由で確かめる
  • 比較
    • 直す前と後のトレースを並べる
  • データセット
    • 質問と期待する回答をテストケースとして残す
  • Prompt playground
    • プロンプトの書き方を比べる
  • オンライン評価
    • 直した後の実行を自動で採点する
  • エージェント以外の機能
    • Services、Traces、Explore、ダッシュボード、アラートを見る

分量も多いので興味あるところだけ見るなどでも構いません!

前提

検証環境は次のとおりです。

項目 内容
リージョン バージニア北部(us-east-1)
AgentCore CLI 0.27.1
Strands Agents 1.56.0
bedrock-agentcore 1.23.1
aws-opentelemetry-distro 0.20.0
Runtime Python 3.14(CodeZip)
モデル Claude Sonnet 5(us.anthropic.claude-sonnet-5)

CloudWatch Omni は、記事執筆時点でバージニア北部・オレゴン・アイルランドの3リージョンで提供されていて、東京リージョンではまだ使えません。悲しい・・・

Ask Assistant や評価などの AI を使う機能は、スペースと同じ地域(米国なら米国内のリージョン)でクロスリージョン推論されます。

AgentCore CLI は Node.js の CLI です。まだ入れていなければ、次のコマンドでインストールします。

AgentCore CLIのインストール
pnpm add -g @aws/agentcore
agentcore --version

ではエージェントをサクッと作って検証していきます!

エージェントを作ってデプロイする

プロジェクトを作る

AgentCore CLI でプロジェクトを作成します。

実行コマンド
agentcore create --name omnisupport --project-name omnisupport \
  --framework Strands --model-provider Bedrock --memory none \
  --language Python --build CodeZip
cd omnisupport

app/omnisupport/ にエージェントのコード、agentcore/ に設定と CDK のプロジェクトができます。テンプレートにはサンプルの MCP クライアントが入っていますが今回は使わないので、app/omnisupport/mcp_client/app/omnisupport/skills/ のフォルダを削除し、app/omnisupport/pyproject.toml の依存関係から mcp の行を消しておきます。

モデルを Sonnet 5 にする

テンプレートのモデルは Claude Sonnet 4.5 になっていたので、app/omnisupport/model/load.py で Sonnet 5 に変えます。

app/omnisupport/model/load.py
from strands.models.bedrock import BedrockModel

def load_model() -> BedrockModel:
    """Get Bedrock model client using IAM credentials."""
    return BedrockModel(model_id="us.anthropic.claude-sonnet-5")

エージェントのコードを書く

app/omnisupport/main.py を、経費精算エージェントに書き換えます。
規程は6つの条文をコードの中に持たせました。検索ツールは、条文ごとに決めたキーワードが検索語に含まれるかで判定する簡単な作りです。

app/omnisupport/main.py(最初の版)
app/omnisupport/main.py
from strands import Agent, tool
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from model.load import load_model

app = BedrockAgentCoreApp()

SYSTEM_PROMPT = """あなたは社内の経費精算アシスタントです。
経費のルールに関する質問には、必ずsearch_expense_policyで規程を検索してから回答してください。
出張の宿泊費上限や日当の金額を聞かれたら、calculate_travel_allowanceで計算してください。
規程に書かれていないことは推測せず、経理部に確認するよう案内してください。日本語で回答してください。"""

EXPENSE_POLICY = [
    {
        "id": "RULE-01",
        "title": "国内出張の宿泊費",
        "keywords": ["宿泊", "ホテル", "出張", "泊"],
        "body": "宿泊費は1泊あたりの上限額までを実費精算します。上限は東京23区・大阪市が12,000円、その他の地域が10,000円です。"
        "上限を超えた分は自己負担です。領収書の宛名は会社名にしてください。",
    },
    {
        "id": "RULE-02",
        "title": "出張日当",
        "keywords": ["日当", "出張", "手当"],
        "body": "片道100km以上の出張には日当を支給します。日当は1日あたり2,000円で、出発日と帰着日も1日として数えます。",
    },
    {
        "id": "RULE-03",
        "title": "タクシーの利用",
        "keywords": ["タクシー", "交通", "移動"],
        "body": "タクシーは、公共交通機関がない時間帯(23時〜5時)か、10kg以上の荷物を運ぶ場合に利用できます。"
        "申請時に利用理由を記入してください。",
    },
    {
        "id": "RULE-04",
        "title": "会食費",
        "keywords": ["会食", "飲食", "接待", "食事"],
        "body": "取引先との会食は1人あたり5,000円までです。参加者全員の氏名と会社名を申請に記入してください。社内だけの飲食は対象外です。",
    },
    {
        "id": "RULE-05",
        "title": "申請期限",
        "keywords": ["期限", "申請", "締め"],
        "body": "経費は利用した月の翌月5営業日までに申請してください。期限を過ぎた申請は上長の承認理由が必要です。",
    },
    {
        "id": "RULE-06",
        "title": "海外出張の日当と宿泊費",
        "keywords": ["国外", "外国"],
        "body": "海外出張の日当は1日あたり5,000円です。宿泊費は1泊20,000円までを実費精算します。国内出張の日当(RULE-02)は適用しません。",
    },
]

HOTEL_LIMITS = {"tokyo": 12000, "osaka": 12000, "other": 10000}
DAILY_ALLOWANCE = 2000

@tool
def search_expense_policy(query: str) -> list[dict]:
    """経費精算規程を検索し、関連する条文を最大3件返す。"""
    scored = []
    for rule in EXPENSE_POLICY:
        score = sum(1 for k in rule["keywords"] if k in query)
        if score:
            scored.append((score, rule))
    scored.sort(key=lambda x: -x[0])
    return [
        {"id": r["id"], "title": r["title"], "body": r["body"], "score": s}
        for s, r in scored[:3]
    ]

@tool
def calculate_travel_allowance(area: str, nights: int) -> dict:
    """国内出張の宿泊費上限と日当を計算する。areaはtokyo / osaka / otherのいずれか。"""
    hotel_limit = HOTEL_LIMITS.get(area.lower(), HOTEL_LIMITS["other"])
    days = nights + 1
    return {
        "hotel_limit_per_night": hotel_limit,
        "hotel_limit_total": hotel_limit * nights,
        "days": days,
        "daily_allowance_total": DAILY_ALLOWANCE * days,
    }

# セッションごとに会話履歴を分ける
agents: dict[str, Agent] = {}

def get_agent(session_id: str) -> Agent:
    if session_id not in agents:
        agents[session_id] = Agent(
            model=load_model(),
            system_prompt=SYSTEM_PROMPT,
            tools=[search_expense_policy, calculate_travel_allowance],
        )
    return agents[session_id]

@app.entrypoint
async def invoke(payload, context):
    agent = get_agent(getattr(context, "session_id", None) or "default")
    async for event in agent.stream_async(payload.get("prompt", "")):
        if "data" in event:
            yield event["data"]

if __name__ == "__main__":
    app.run()

トレースに入出力を残す設定を入れる

Omni でプロンプトやツールの入出力を読むために、Runtime に環境変数 AWS_GENAI_CONTENT_EXTRACTION_OPT_OUT=true を設定します。AgentCore CLI では agentcore/agentcore.jsonruntimesenvVars を追加します。

agentcore/agentcore.json(runtimesの抜粋)
{
  "name": "omnisupport",
  "build": "CodeZip",
  "entrypoint": "main.py",
  "codeLocation": "app/omnisupport/",
  "runtimeVersion": "PYTHON_3_14",
  "networkMode": "PUBLIC",
  "protocol": "HTTP",
  "envVars": [
    { "name": "AWS_GENAI_CONTENT_EXTRACTION_OPT_OUT", "value": "true" }
  ]
}

公式ドキュメントによると、AgentCore では Runtime が AGENT_OBSERVABILITY_ENABLED=true を自動で入れ、トレースの送信先も ADOT が設定してくれるので、ユーザーが追加で指定する環境変数はこれです。設定しないと、トレースのプロンプトや回答が空になるようです。業務データを扱う場合は、トレースを読める人にもその内容が見える点に注意しましょう。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/omni-send-ai-agent-telemetry.html

デプロイして質問を送る

デプロイします。数分で完了し、アカウントで Transaction Search が無効だった場合は、ここで有効化されます。

実行コマンド
agentcore deploy -y
実行結果(抜粋)
✓ Deployed to 'default' (stack: AgentCore-omnisupport-default)

Note: Transaction search enabled. It takes ~10 minutes for transaction search to be fully active and for traces from invocations to be indexed.

いくつか質問を送ります。--session-id を付けると同じ会話の続きとして送れるので、会食費の質問は2ターンに分けました。

実行コマンド
agentcore invoke "来週、大阪に2泊3日で出張します。宿泊費の上限と日当はいくらですか?あと、新大阪駅からホテルまでタクシーを使ってもいいですか?"
agentcore invoke --session-id expense-dinner-session-00000000001 "先月の取引先との会食費を精算したいです。ルールを教えてください。"
agentcore invoke --session-id expense-dinner-session-00000000001 "参加者は4人で、合計18,000円でした。全額精算できますか?"
agentcore invoke "社内の歓送迎会の費用は経費で落とせますか?"
agentcore invoke "来月シンガポールに3泊5日で出張します。日当はいくらもらえますか?"

このうち、シンガポール出張の回答が少し変な回答になります。

シンガポール出張の質問への回答(抜粋)
- 日当は**1日あたり2,000円**で、出発日・帰着日も1日として数えます。

今回のシンガポール出張は「3泊5日」とのことですので、規程の考え方(出発日・帰着日を含めて日数計算)に基づくと、5日間分で **2,000円 × 5日 = 10,000円** となる可能性があります。

規程には海外出張の日当を1日5,000円とする RULE-06 があるので、正しくは25,000円です。
国内出張の日当(RULE-02)で答えてしまっています。この回答を Omni で調べていきます。

Omni のスペースを作る

Omni を使うには、最初にドメインとスペースを作ります。ドメインはチームがサインインするURL(https://<ドメイン名>.cloudwatch-omni.global.app.aws)で、スペースはテレメトリを受け取る作業場所です。今回は単一アカウント向けの「アカウントレベルドメイン」で作ります。

  1. CloudWatch コンソールの左メニューの一番下にある「Omni」を開き、紹介ページの「始める」を押します。

    CloudWatchコンソールの左メニューからOmniを開き、始めるを押す

  2. ドメインタイプで「アカウントレベルドメイン」を選び、ドメイン名とスペース名を入れます。ドメイン名は小文字・数字・ハイフンの3〜63文字で、全体で一意である必要があります。

    アカウントレベルドメインを選び、ドメイン名とスペース名を入れる

  3. 「アクセス許可」の3つのロールは「デフォルトロールを作成」のままにします。スペースを管理するロール、テレメトリを連携するロール、オンライン評価を実行するロールが作られます。

    ロールはすべてデフォルトロールを作成のままでよい

  4. 「デフォルトのテレメトリ設定を確認」を開くと、スパンの取り込み(Transaction Search)とメトリクスの OTel エンリッチメントの設定があります。今回のアカウントでは、デプロイ時に Transaction Search が有効になっていました。確認したら右側の「スペースを起動」を押します。

    スパンの取り込み(Transaction Search)は、無効ならセットアップで有効になる

  5. ロールの作成、データ連携、ドメインURLの準備が順に進みます。途中で「AWS Config サービスにリンクされたレコーダー」も有効になりました。数分で完了します。

    ロールの作成やデータ連携が順に進み、数分でスペースができる

  6. 完了すると設定画面にスペースが表示されるので、「Omni でスペースを起動」を押します。

    完成したらOmniでスペースを起動を押す

  7. Omni のサインイン画面が別タブで開きます。「Sign in via AWS console」を選ぶと、サインイン中のコンソールのセッションでそのまま入れます。

    Sign in via AWS consoleで、コンソールのセッションのまま入る

  8. 初回はウェルカム画面が出るので、右上の×で閉じます。「Explore Omni with sample data」を選ぶと、サンプルデータ入りのスペースを別ウィンドウで試せます。

    初回はウェルカム画面が出る。右上の×で閉じる

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/omni-set-up-omni-for-a-single-account.html

今回はシングルアカウントで検証しますが、複数のアカウントで使う場合は、「組織レベルドメイン」を選びます。

Organizations の管理アカウントがドメインを1回作ると、各メンバーアカウントのスペースが自動でそのドメインにひも付き、サインインURLと Identity Center の設定を1つにまとめられます。複数アカウントのログやトレースを1つのスペースで見たい場合は、CloudWatch の設定で、スペースのあるアカウントへデータを集約可能です。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/omni-set-up-omni-for-your-organization.html

初回の有効化時には、既存の CloudWatch のログとトレースが最大7日分取り込まれます。スペースを作る前に送っていた質問も、ホームの時点でエージェント1件として集計されていました!

Omniのホーム。Agent tracesからトレースの一覧を開く

ホームには、アプリケーション監視、ログやメトリクスの分析、エージェントの観測がずらっと並びます。
ここから開いた画面は「キャンバス」というタブに追加されていき、トレースの詳細や比較、データセットなどがパネルとして積み重なっていく作りです。なかなかビジーな画面ですね・・・!

まずはトレースを見ていきましょうか!

シンガポール出張の回答をトレースで調べる

トレースの一覧を開く

ホームの「Agent observability」にある「Agent traces」を押すと、トレースの一覧が開きます。

表示される期間は初期値で過去30分です。見たい時間帯に絞るには、右上の期間を押して「Absolute」を選び、開始・終了の日付と時刻を入れて「Apply」を押します。

右上の期間からAbsoluteを選び、見たい時間帯を指定してApply

送った5件の質問について、入力と出力の冒頭、トークン数、所要時間が表示されました!

質問ごとのトレースが並ぶ。シンガポール出張の行をクリックする

トレースの中身を読む

シンガポール出張の行をクリックすると、トレースの詳細が右側に開きます。
モデル呼び出し、検索ツール、回答生成が時系列で表示されます。
モデル呼び出し、検索ツール、回答生成が時系列で並びます。

トレースの中身。検索ツールは1回だけ呼ばれ、回答は国内の2,000円だった

検索ツールのスパン(execute_tool search_expense_policy)をクリックすると、右側が Span view に切り替わります。下にスクロールすると、Tool info にモデルが渡した引数、Input/Output にツールの返り値が表示されます。

検索ツールのスパンを選ぶと、検索語と返り値を確認できる

検索語は「海外出張 日当 シンガポール」で、返ってきたのは国内の RULE-02 と RULE-01 でした。

RULE-06 のキーワードは「国外」「外国」で、「海外」では見つからなかったんですね。トレースから原因の場所を特定できました!

Ask Assistant に原因を聞いてみる

AI Assistantに原因分析をやってもらうことも可能です。
まさかAI搭載とは至れり尽くせりですね・・・

画面下の入力欄(Ask Assistant)に質問を入れて Enter を押します。

画面下の入力欄に質問を入れてEnterで送る

入力した質問
このトレースで、シンガポール出張の日当を国内の金額で答えた原因を調べてください。

1分ほどで、トレースの流れと原因が返ってきました。

Ask Assistantの回答。海外出張の日当ルールが見つからなかったことを原因に挙げた

アシスタントは「規程データベースに海外出張の日当ルールが登録されていない」ことを根本原因に挙げました。実際には RULE-06 は登録されていて、検索で漏れていたので半分正解なのですが、どこを直すべきかの当たりを付けるにはぼちぼちな回答ですね。困ったらとりあえず使ってみるぐらいの感覚でしょうか。

評価を実行する

次は、回答を評価器で採点してどれぐらい良い回答なのか確認してみます。

  1. トレース一覧の左上のチェックボックスで、5件をまとめて選びます。右上の「Evaluate」を押します。

    一覧のチェックボックスでトレースを選び、Evaluateを押す

  2. 評価器を選ぶ画面が開きます。AWSの組み込みが18種類、AutoEval が3種類、DeepEval が10種類、このアカウントで作っていたカスタムが2種類の合計33種類があり、一度に10個まで選べます。

    評価器は組み込み・AutoEval・DeepEval・カスタムの33種類から最大10個を選べる

    DeepEval と AutoEval は、LLM の回答を評価するオープンソースのライブラリです。たとえば DeepEval.TaskCompletion は、判定用のモデルが「利用者の目的を達成できたか」を0〜1で採点します。Omni では AgentCore Evaluations がこれらを動かすので、インストールやコードは不要です。外部のライブラリでもビルトインなんだーと少し驚きました。

  3. 今回は次の8個にチェックを入れて「Run」を押しました。DeepEval を選ぶと判定用モデルの権限に関する注意が出ますが、セットアップで作られたロールのままで採点できました。

    DeepEvalを選ぶと判定モデルの権限に関する注意が出る。選び終えたらRun

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/third-party-evaluators.html

評価器 調べること
Correctness(正確さ) 回答の内容が事実として正しいか
Faithfulness(根拠への忠実さ) 回答がツールの結果などの根拠に沿っているか
Helpfulness(有用性) 利用者にとって役に立つか
Conciseness(簡潔さ) 必要な情報を落とさず簡潔か
InstructionFollowing(指示への従い方) システムプロンプトの指示に従っているか
ToolSelectionAccuracy(ツールの選び方) 適切なツールを選んだか
ToolParameterAccuracy(引数の正しさ) ツールに渡した引数が正しいか
DeepEval.TaskCompletion(タスク達成) 利用者の目的を達成できたか

数十秒で採点が終わり、一覧の Evaluations 列に点数が付きます。ツールを呼び出さなかった会話の2ターン目では、ツール系の評価器がスキップされていました。

数十秒で採点が終わり、一覧のEvaluations列に点数が付く

シンガポール出張のトレースを開くと、右側の Evaluations に評価器ごとの点数が並びます。各行の「>」を押すと、採点の理由を読めます。

Correctnessなどは1.00、DeepEval.TaskCompletionは0.70

評価器 点数
Correctness(正確さ) 1.00
Faithfulness(根拠への忠実さ) 1.00
Helpfulness(有用性) 1.00
Conciseness(簡潔さ) 0.00
InstructionFollowing(指示への従い方) 1.00
ToolSelectionAccuracy(ツールの選び方) 1.00
ToolParameterAccuracy(引数の正しさ) 1.00
DeepEval.TaskCompletion(タスク達成) 0.70

金額を間違えた回答なのに、Correctness は1.00でした。評価器はトレースの中の情報を基準に採点するので、返ってきた RULE-02 にもとづく計算としては正しいと判定されています。

一方、DeepEval.TaskCompletion は0.70で、「国内と海外の区別がはっきりせず、確定した金額を答えられていない」という理由で、この問題を捉えていました。評価器によって見え方がかなり違うので、複数の観点を並べて読むのがよさそうです。Conciseness はほとんどの回答で0.00で、長い回答が減点されています。評価器によって判断が違うのは面白いですし、数字を盲信せず理由もちゃんと見ないとですね。

エージェントを直して、トレースを比較する

直し方を探す

トレースで分かった原因はツール側にあるので、プロンプトの変更を元に戻し、RULE-06 のキーワードに「海外」を足します。

app/omnisupport/main.py(RULE-06の差分)
     {
         "id": "RULE-06",
         "title": "海外出張の日当と宿泊費",
-        "keywords": ["国外", "外国"],
+        "keywords": ["海外", "国外", "外国"],

再デプロイして同じ質問を送ります。

実行コマンド
agentcore deploy -y
agentcore invoke "来月シンガポールに3泊5日で出張します。日当はいくらもらえますか?"
実行結果(抜粋)
【規程 RULE-06:海外出張の日当と宿泊費】
- 日当:1日あたり **5,000円**(国内出張の日当規程は適用されません)
- 宿泊費:1泊あたり **20,000円まで** 実費精算

今回のご出張は3泊5日とのことですので、
- 日当:5日 × 5,000円 = **25,000円**

RULE-06 にもとづいて25,000円と答えるようになりました!

修正前と修正後のトレースを並べる

トレースを並べて比べる Compare も試します。

  1. トレース一覧で修正後と修正前の2件にチェックを入れ、「Compare」を押します。一覧に修正後のトレースが出ていない場合は、期間の終了時刻を延ばすか、右上の更新ボタンを押します。

    比べたい2件にチェックを入れてCompareを押す

  2. キャンバスの下に「Compare traces」のパネルが追加されるので、スクロールして開きます。

    修正後(A)はRULE-06の5,000円、修正前(B)はRULE-02の2,000円で答えている

項目 修正後(A) 修正前(B)
スパン数 9 9
トークン数 2,472 2,567
所要時間 8.07秒 11.08秒
回答の根拠 RULE-06(5,000円) RULE-02(2,000円)

出力が根拠ごと変わったことが分かります。直した前後を同じ画面で見比べられますし、比較したい時に使えそうですね。

質問と期待する回答をデータセットに残す

同じ質問で何度もテストできるよう、データセットに残します。ここでは修正前のトレース4件(大阪出張、会食ルール、歓送迎会、シンガポール出張)を使いました。

トレースからデータセットを作る

  1. トレース一覧で4件にチェックを入れ、「Add to dataset」から「Create new dataset」を選びます。

    トレースを選んでAdd to datasetからCreate new dataset

  2. 選んだ4件が表示されるので、「Create new dataset」を押します。1つのトレースが1つの例(Example)になります。

    選んだ4件がそれぞれ例(Example)になる

  3. 右側に作成画面が開くので、名前と説明を入れます。今回は次のように入れました。

    項目 入力した値
    Name expense_eval_v2
    Description 経費精算アシスタントの回帰テスト用。実際の問い合わせと、規程に沿った期待回答。

    名前と説明を入れる。名前は後から変えられない

  4. 右下の「Create dataset (4 examples)」を押します。画面下に処理中の通知が出ている場合は、通知を閉じてからボタンを押します。

    右下のCreate dataset(4 examples)で作成する

期待する回答を直す

ここで注意が必要なのが、Expected Output(期待する回答)には元の実行の回答がそのまま入る点です。シンガポール出張の例には「2,000円×5日」という誤った回答が入っているので、このまま使うと誤りを正解として固定してしまうので修正しましょう。

  1. ホームの「Datasets」から一覧を開き、作ったデータセットの鉛筆アイコンを押します。

    ホームのDatasetsから一覧を開き、鉛筆アイコンで編集する

  2. Examples の一覧でシンガポール出張の行を押すと、例の中身が開きます。Expected Output に元の回答が入っていることを確認し、右下の「Edit」を押します。

    例を開くと、期待する回答に元の誤った回答がそのまま入っている

  3. Scenario Description(シナリオの説明)と Expected Output を書き直し、「Save changes」を押します。

    期待する回答を規程どおりに書き直し、Save changes

  4. 左上の「←」で一覧へ戻り、残りの3件も同じように書き直します。

4件には次の期待値を入れました。

4件に設定した期待値
質問 Expected Output(期待する回答)
来月シンガポールに3泊5日で出張します。日当はいくらもらえますか? 海外出張の日当は1日あたり5,000円です(RULE-06)。3泊5日なので、日当は5日分の25,000円です。国内出張の日当(RULE-02、1日2,000円)は適用しません。
社内の歓送迎会の費用は経費で落とせますか? 社内のメンバーだけで行う歓送迎会の費用は、経費精算の対象外です。規程RULE-04「会食費」に「社内だけの飲食は対象外」と定められています。取引先が参加する会食であれば、1人あたり5,000円まで精算できます。
来週、大阪に2泊3日で出張します。宿泊費の上限と日当はいくらですか?あと、新大阪駅からホテルまでタクシーを使ってもいいですか? 大阪市の宿泊費の上限は1泊12,000円、2泊で24,000円です(RULE-01)。日当は1日2,000円で3日分の6,000円です(RULE-02)。新大阪駅からホテルまでのタクシーは、23時〜5時の時間帯か10kg以上の荷物がある場合だけ利用でき、申請時に理由を記入します(RULE-03)。
先月の取引先との会食費を精算したいです。ルールを教えてください。 取引先との会食は1人あたり5,000円まで精算できます(RULE-04)。申請には参加者全員の氏名と会社名を記入してください。社内だけの飲食は対象外です。

編集画面には期待値のほかに、Expected Tools(期待するツール)や Rubrics(採点基準)などの欄もあります。

版を発行する

  1. データセットの詳細で、Examples の横が「DRAFT · Modified」(下書きに変更あり)になっていることを確認し、「Publish new version」を押します。ボタンが押せないときは、パネルを閉じて開き直すと押せるようになりました。

    4件を直したらPublish new versionを押す

  2. 確認ダイアログで「Publish」を押します。

    Publishで下書きの内容をVersion 1として固定する

  3. 「DRAFT · matches Version 1」と表示されれば完了です。

    発行後はDRAFT・matches Version 1と表示される

発行後も下書き(DRAFT)は編集でき、比較に使った版の内容は変わりません。運用中に「この回答はおかしい」と見つけた問い合わせを、そのまま次回評価するときのテストケースにできます。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/omni-agents-datasets.html

Prompt playground で回答の書き方を比べる

評価で Conciseness がほとんど0.00だったので、回答の書き方を比べます。

Web の Prompt playground で試せるのはあくまでプロンプトだけという点は注意です。選んだモデルへプロンプトを直接送る機能で、エージェントそのものを動かすわけではなく、ツールも呼び出されません(エージェントを丸ごと動かして試すのは IDE 拡張の機能です)。

なので、エージェントに入れる前に「この書き方で良くなりそうか」をサクッとプロンプトで当たりを付ける場所、と考えるのがよさそうです。

今回はツールを使わない代わりに、規程の全文をシステムプロンプトに入れて比べます。

Playground を開いてプロンプトを入れる

  1. データセットの詳細で、右上の「Open」の横の「▼」を押し、「Open in playground」を選びます。

    データセットのOpenメニューからOpen in playground

  2. キャンバスの下に Playground のパネルが追加されます。右上の拡大アイコンで広げると操作しやすいです。データセットの4件が読み込まれ、モデルは初期値で Claude Sonnet 5 でした。

    Playgroundにデータセットの4件が読み込まれる。ここにシステムプロンプトを入れる

  3. A の System prompt に、次のプロンプトを貼り付けます。User input は {{input}} のままにしておくと、データセットの質問が入ります。

A(基準)のシステムプロンプト
A(基準)のシステムプロンプト
あなたは社内の経費精算アシスタントです。次の経費精算規程を根拠に回答してください。規程に書かれていないことは推測せず、経理部に確認するよう案内してください。日本語で回答してください。

# 経費精算規程
RULE-01 国内出張の宿泊費:宿泊費は1泊あたりの上限額までを実費精算します。上限は東京23区・大阪市が12,000円、その他の地域が10,000円です。上限を超えた分は自己負担です。領収書の宛名は会社名にしてください。
RULE-02 出張日当:片道100km以上の出張には日当を支給します。日当は1日あたり2,000円で、出発日と帰着日も1日として数えます。
RULE-03 タクシーの利用:タクシーは、公共交通機関がない時間帯(23時〜5時)か、10kg以上の荷物を運ぶ場合に利用できます。申請時に利用理由を記入してください。
RULE-04 会食費:取引先との会食は1人あたり5,000円までです。参加者全員の氏名と会社名を申請に記入してください。社内だけの飲食は対象外です。
RULE-05 申請期限:経費は利用した月の翌月5営業日までに申請してください。期限を過ぎた申請は上長の承認理由が必要です。
RULE-06 海外出張の日当と宿泊費:海外出張の日当は1日あたり5,000円です。宿泊費は1泊20,000円までを実費精算します。国内出張の日当(RULE-02)は適用しません。

パラメーターと評価器を設定する

  1. モデル名の右のアイコンを押すと、Temperature、Max tokens、Top P、Top K を設定できます。Sonnet 5 は Temperature を指定すると実行に失敗するので、空欄のままにします。

    モデル名の右のアイコンでパラメーターを開き、Temperatureを空欄にする

  2. 「Evaluators」を押すと、初期値で Correctness・Helpfulness・InstructionFollowing の3つが選ばれています。Conciseness にチェックを入れて4つにします。

    Evaluatorsの一覧でConcisenessを追加して4つにする

B を作って実行する

  1. A の右上の複製アイコンを押すと、同じ設定の B が右に追加されます。A には「Baseline」のラベルが付きます。

    Aの右上の複製アイコンでBを作る

  2. B の System prompt の末尾に、回答の形式を追加します。

Bの末尾に追加した指示
# 回答の形式
結論を1文目に書き、根拠の条文番号(RULE-xx)を示してください。回答全体は200字以内とし、絵文字・見出し・表・挨拶は使わないでください。
  1. 「Run All + Eval Responses」を押します。4件×2案の回答生成と評価が進み、1分ほどで結果がそろいます。

    A(Baseline)とBが並ぶ。Bのシステムプロンプトに回答の形式を追加する

結果を読む

B に「Winner」が付きました、時間やトークン、評価など総合してつけられているんですかね。シンガポール出張の回答は、A が見出し付きで767トークン、B は「日当は1日5,000円で、5日分の合計25,000円が支給されます(RULE-06)。」から始まる200トークンです。

BにWinnerが付く。Bの回答は短く、RULE-06を根拠に答えている

一番下に4件の平均がまとまります。

項目(4件の平均) A:基準 B:回答形式を追加
応答時間 10.28秒 4.51秒
出力トークン 642 198
Correctness(正確さ) 1.00 1.00
Helpfulness(有用性) 1.00 0.87
InstructionFollowing(指示への従い方) 1.00 1.00
Conciseness(簡潔さ) 0.25 0.63

4件の平均。Bは応答時間56%短縮、簡潔さ+0.38、有用性-0.13

B は応答時間が56%短くなり、Conciseness も上がった一方、Helpfulness は下がりました。回答を読むと、会食ルールの質問で B は「社内だけの飲食は対象外」を省いていました。

会食ルールの回答では、Bが「社内だけの飲食は対象外」を省き、有用性が0.83に下がった

点数だけでは何が抜けたか分からないので、回答も読んで確かめる必要がありますね。

比較の後には「Suggested improvement for B」として改善案も表示されます。ただ、今回は差分が JSON のような断片になっていましたが、改善のヒントとして捉えるのも良いかもしれませんね。

Bへの改善案。今回は差分にJSONのような断片が混ざっていた

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/omni-prompt-playground.html

オンライン評価で新しい実行を自動で採点する

オンライン評価を作る

Playground の結果をエージェントに反映する前に、新しい実行を自動で採点するオンライン評価を設定しておきます。

  1. ホームの「Online evaluations」を押して一覧を開き、「Create online evaluation」を押します。

    ホームのOnline evaluationsから一覧を開き、Create online evaluation

  2. 名前(今回は expense_assistant_online)を入れ、Data source は「Define with an Agent」のまま、Choose agent でエージェントを選びます。Omni にデータを送っているエージェントが一覧に出るので、選択するとトレースの場所が自動で設定されます。

    名前を入れ、Define with an Agentでエージェントを選ぶ

  3. 評価器は、Helpfulness(有用性)、Conciseness(簡潔さ)、GoalSuccessRate(会話全体で目的を達成できたか)、DeepEval.TaskCompletion(タスク達成)の4つにしました。

    評価器を選ぶ。今回はHelpfulness・Conciseness・GoalSuccessRate・DeepEval.TaskCompletion

  4. サンプリング率(100%)とセッションのタイムアウト(15分)は初期値、実行ロールはセットアップで作られた AgentCoreEvaluationRole のまま「Create」を押します。

    サンプリング率と実行ロールを確認してCreate

セッションが15分アイドルになると採点され、点数と理由が CloudWatch Logs(/aws/bedrock-agentcore/evaluations/results/<評価名>)に書き込まれます。

回答の形式をエージェントに入れる

Playground の結果を踏まえて、エージェントのシステムプロンプトに回答の形式を指定します。B で抜けた条件を落とさないための指示も合わせて加えました。

app/omnisupport/main.py(SYSTEM_PROMPTの差分)
 規程に書かれていないことは推測せず、経理部に確認するよう案内してください。日本語で回答してください。
+回答は結論を1文目に書き、根拠の条文番号(RULE-xx)を示してください。対象外になる条件や申請時の注意など、結論に関わる条件は省かないでください。
+回答全体は300字以内とし、絵文字・見出し・表・挨拶は使わないでください。

再デプロイして、いくつか質問を送りました。

実行コマンド
agentcore deploy -y
agentcore invoke "来月シンガポールに3泊5日で出張します。日当はいくらもらえますか?"
agentcore invoke "社内の歓送迎会の費用は経費で落とせますか?"
agentcore invoke "チームの打ち上げの飲み代って落ちますか?"

回答は短くなりましたが、歓送迎会と打ち上げの質問に正しく答えられなくなっていました。

社内の歓送迎会の質問への回答
歓送迎会費用が経費として認められるかは規程内に該当条文が見つからず判断できません。社内規程の検索結果が0件のため、対象範囲・上限額・申請条件等の詳細は不明です。誤った判断を避けるため、経理部に直接ご確認のうえ申請してください。

回答形式を指定する前は、検索結果が0件でも言い換えて RULE-04 を参照できていましたが、短くまとめる指示を入れたことで再検索が省かれるようになったようです。

点数の低い回答をオンライン評価から探す

この間違いは、オンライン評価の結果にも出ました。点数の低い回答を見つけて、トレースで原因を確かめるまでの流れを順に追ってみます。

  1. ホームの「Online evaluations」を開き、作成した評価(expense_assistant_online)をクリックします。右に詳細が開くので、「Analyze」から「View results」を選びます。

    オンライン評価を開き、AnalyzeからView resultsを選ぶ

  2. 評価器ごとの点数がダッシュボードで表示されます。右上の期間を「Past 1 day」に広げると、18時ごろに GoalSuccessRate と DeepEval.TaskCompletion の点数が下がっているのが分かります。回答の形式を入れて再デプロイした時間帯です。下の表で、気になる評価器(今回は GoalSuccessRate)の行をクリックします。

    期間を1日に広げると、18時ごろに点数が下がっているのが分かる

  3. 評価器の詳細が開き、合格(Pass)42件・不合格(Fail)5件と、セッションごとの点数と理由が並びます。「Score」の列の見出しをクリックして並べ替えると、0.00の5件が上に来ます。

    Scoreの列で並べ替えると、0.00の5件が上に来る

  4. 18:08の行(社内の歓送迎会の質問)をクリックすると、評価の理由(Explanation)、入力、出力が表示されます。理由には「search_expense_policy ツールが空の結果([])を返した」と書かれていて、この時点で原因の目星が付きます。下の「Session」のリンクをクリックします。

    評価の理由に、検索ツールが空の結果を返したと書かれている

  5. セッションの入力・出力と評価の点数が表示されます。右上の「View Full Trace」をクリックすると、トレースが開きます。

    セッションの入出力と評価を確認し、View Full Traceでトレースへ進む

  6. トレースを見ると、検索ツール(execute_tool search_expense_policy)は1回しか呼ばれておらず、そのまま回答しています。

    トレースでは、検索ツールが1回だけ呼ばれてそのまま回答している

  7. 検索ツールのスパンをクリックすると、検索語(Parameters)と結果(Output)が見られます。「歓送迎会 懇親会 費用 経費」で検索して、結果は空でした。

    ツールのスパンを開くと、検索語に対して結果が空だったと分かる

検索語がどの条文のキーワードにも一致せず、空の結果のまま「判断できません」と答えていました。評価の理由とトレースから原因までたどることができました!が操作わからないと最初はつらいですね・・・なにを触ったらいいかの動線が私も最初困惑しました・・・

回答の形式を入れる前後の点数は次のとおりです。

質問 GoalSuccessRate Helpfulness DeepEval.TaskCompletion
社内の歓送迎会(形式を入れる前) 1.00 1.00 0.85
社内の歓送迎会(形式を入れた後) 0.00 0.67 0.30
チームの打ち上げ(形式を入れた後) 1.00 0.67 0.30

回答を短くする変更で、別の質問に正しく答えられなくなっていたことに、自動の採点で気づくシナリオを体験できました!

Ask Assistant で深掘りする

もう少し深掘りしたいときは、トレースを開いたまま画面下の入力欄から Ask Assistant に聞くこともできます。

入力した質問
このトレースでGoalSuccessRateが0.00になった原因を教えて。直し方も提案して

トレースを開いたまま、下の入力欄からAsk Assistantに質問する

Ask Assistantが原因の候補と改善策を返した

1分ほどで原因の候補と改善策が返ってきました。「0件のときに再検索しない」などの候補は当たっていて、改善策も次の節で入れた修正とほぼ同じでした。外れる候補もあるので、参考程度に見るのがよさそうです。

ツールを直して、もう一度確かめる

プロンプトに「0件なら言い換えて検索し直す」を足す方法も試しましたが、6回中2回は同じ間違いが残りました。そこで、0件のときに条文の見出し一覧を返し、関連しそうな条文名で検索し直せるようにしました。

app/omnisupport/main.py(search_expense_policyの差分)
     scored.sort(key=lambda x: -x[0])
+    if not scored:
+        # 一致しないときは条文の見出し一覧を返し、近い条文を選び直せるようにする
+        return [{"id": r["id"], "title": r["title"], "note": "キーワード不一致。関連しそうな条文名で検索し直してください"} for r in EXPENSE_POLICY]
     return [

再デプロイして歓送迎会と打ち上げの質問を3回ずつ送ると、6回とも「社内だけの飲食は対象外(RULE-04)」と答えました。トレースを開くと、検索ツールが2回呼ばれています。

ツールを直した後のトレース。検索ツールが2回呼ばれている

1回目の検索(「歓送迎会 懇親会 費用 経費」)は一致せず、見出し一覧が返りました。

1回目の検索は一致せず、条文の見出し一覧が返る

2回目は見出しにある「会食費」を使って検索し直し、RULE-04 を取得できています。

2回目は見出しの語で再検索し、RULE-04に届いた

15分ほど待ってオンライン評価の結果を見ると、6回とも GoalSuccessRate は1.00で、DeepEval.TaskCompletion も0.85〜1.00に戻っていました!

変更 GoalSuccessRate DeepEval.TaskCompletion Conciseness
プロンプトで再検索を指示 0.00が2回 0.30〜0.95 0.50
ツールで見出し一覧を返す 6回とも1.00 0.85〜1.00 0.00〜0.50

直したつもりの変更で本当に良くなったかを、同じ評価器の点数で確かめられましたね。

app/omnisupport/main.py(最終版の差分まとめ)

最初の版からの変更は、RULE-06 のキーワード、回答の形式、検索ツールの0件時の処理の3か所です。

app/omnisupport/main.py
@@ SYSTEM_PROMPT
 規程に書かれていないことは推測せず、経理部に確認するよう案内してください。日本語で回答してください。
+回答は結論を1文目に書き、根拠の条文番号(RULE-xx)を示してください。対象外になる条件や申請時の注意など、結論に関わる条件は省かないでください。
+回答全体は300字以内とし、絵文字・見出し・表・挨拶は使わないでください。
@@ RULE-06
-        "keywords": ["国外", "外国"],
+        "keywords": ["海外", "国外", "外国"],
@@ search_expense_policy
     scored.sort(key=lambda x: -x[0])
+    if not scored:
+        # 一致しないときは条文の見出し一覧を返し、近い条文を選び直せるようにする
+        return [{"id": r["id"], "title": r["title"], "note": "キーワード不一致。関連しそうな条文名で検索し直してください"} for r in EXPENSE_POLICY]

点数が下がったらアラートで知らせる

毎回ダッシュボードを見に行くのは大変なので、評価の点数が下がったときにアラートで知らせるようにしてみます。

  1. ホームの「Evaluation dashboard」を開き、グラフの「Evaluators by」の右にあるベルのアイコンをクリックします。アラートの作成画面が開き、しきい値は Warning が0.7以下、Critical が0.5以下で最初から入っています。

    Evaluation dashboardのベルから開くと、しきい値が入った状態でアラートの画面が開く

  2. 「Show the saved alert query」を開くと、実際に保存されるクエリ(評価期間ごとに評価器の平均点を出す形)が表示されます。内容を確認したら「I reviewed the saved query」にチェックを入れます。

    保存されるクエリは、評価期間ごとに点数を集計する形に書き換わる

  3. 「Alert name」に名前(今回は omnisupport-eval-score-low)を入れます。

  4. 通知先は「Notification rules」の「Add rule」で追加します。選べるのは Slack と SNS です。今回は通知先を設定せずに進めました。

    通知先はSlackかSNSを選べる

  5. 右上の「Run」でクエリを一度実行してから、右下の「Create alert」をクリックします。実行する前に押すと「Run your query first」と表示されて作成できません。

作成したアラートは「Alerts」の一覧に並びました!

作成したアラートがAlertsの一覧に並ぶ

この作り方だとしきい値は、評価全体の1つの値ではなく評価器ごとの平均点にかかります。保存されるクエリは評価期間内の点数を評価器ごとに平均して返すので、GoalSuccessRate でも Conciseness でも、どれか1つの平均が0.5以下になれば Critical になる想定です。
特定の評価器だけを見たい場合は、「Edit query」で評価器名の条件を足します。

また、保存されるクエリはスペース全体の評価結果を対象にしていて、エージェント名での絞り込みは入っていませんでした。同じスペースに複数のエージェントがある場合は、「Edit query」で条件を足しておきましょう。

Omni のアラートは CloudWatch アラームとは別の仕組みで、コンソールのアラーム一覧には表示されませんでした。

CloudWatchコンソールのアラーム一覧には表示されない

エージェント向けのダッシュボードを眺める

エージェント向けのダッシュボードも順番に見てみました。どれもホームの「Agent observability」から開けます。データが出ないときは、右上の期間を広げてください。

Agent overview で全体をつかむ

「Agent overview」では、エージェントのセッション数、トレース数、トークン数、エラー率などが表示されます。

Agent overviewで、セッション数・トレース数・トークン数・エラー率をまとめて見る

ざっと全体の傾向を掴む時に便利そうで、どれから調べるかを決める入口として使えそうです。

Evaluation dashboard で評価器ごとの点数を比べる

「Evaluation dashboard」では、オンライン評価やオンデマンド評価の結果を評価器ごとに集計できます。

平均(Avg)、前の期間との差(Delta)、ばらつき(Std dev)、件数(Count)を1つの表で見られます。

Evaluation dashboardで評価器ごとの平均点と件数を一覧する

今回の検証ではConciseness(簡潔さ)の平均が0.22と低く、前半で見た傾向が数字でも分かります。個々のトレースを開く前に「どの観点が足りていないか」を見る画面として良さそうです。

Agent sessions でセッションごとに見る

「Agent sessions」では、セッション(会話)単位で最初の入力、最後の出力、トークン数、所要時間、推定費用(Est. Cost)、評価結果が一覧になります。

Agent sessionsで、セッションごとの入出力・費用・評価を並べる

セッションを選んで「Evaluate」や「Add to dataset」もできます。複数ターンの会話を扱うエージェントでは、セッション単位で見るとやり取り全体でうまくいったかを追いやすいと思います。1セッションあたりの推定費用まで見れるのは嬉しいですね!
高額な料金はないかなどもチェックできそうです。

Agent topology で呼び出しの流れを見る

「Agent topology」は、エージェントの中でモデルとツールがどの順番で呼ばれたかを、トレース数とともにフロー図で表示する画面です。

Agent topologyで、エージェント・モデル・ツールの呼び出しの流れを見る

invoke_agent からモデルの呼び出しに進み、search_expense_policy が呼ばれ、一部は再度検索している様子が分かります。

右上の「Graph」に切り替えると、同じ流れをノードのグラフでも見られます。ノードごとにトレース数と平均の所要時間が付くので、どこで時間がかかっているかを見たいときはこちらが分かりやすいです。

Agent topologyをGraphに切り替えると、ノードごとのトレース数と平均時間が表示される

ノードをクリックすると、そのツールやモデルがどこから呼ばれ、次に何を呼んだか(Incoming・Outgoing)と、最近のトレースの一覧が表示されます。ここから個別のトレースにも進めます。

ノードをクリックすると、呼び出し元・呼び出し先と最近のトレースが表示される

トポロジーでエージェントの動きの全体感はつかめますが、多用するかな・・・?というのはあります。調査の入口としては、トレースや評価の一覧を見ることのほうが多そうです。

サンプルデータで試す

ウェルカム画面の「Explore Omni with sample data」から開けるデモ用スペースでは、複数のエージェントやサービスのデータが入った状態の画面も試せます。自分のエージェントを用意する前に、雰囲気をつかむのにちょうどいいですね。

サンプルデータ入りのデモ用スペース

Omni のエージェント以外の機能も触ってみる

Omni のホームには、エージェント向け以外に「Application performance monitoring」と「Analytics and dashboards」の機能も並んでいます。今回のエージェントのデータで、ひととおり触ってみました。

ホームにはアプリ監視と分析の機能も並んでいる

Services でエージェントをサービスとして見る

ホームの「Services」を開くと、スペースで見つかったサービスの一覧が表示されます。今回のエージェントも omnisupport_omnisupport.DEFAULT という1つのサービスとして並び、リクエスト数とエラー率が出ていました。

Servicesにエージェントもサービスとして並ぶ

「Application map」は、サービスやリソースの呼び出し関係を地図のように描く画面です。エージェント(58リクエスト)から Sonnet 5 への呼び出し(127回)が線でつながって表示されました。

期間を1日にすると、Application mapにエージェントとモデルの呼び出し関係が描かれる

エージェントがどのモデルをどれくらい呼んでいるかは、ここで一目で分かります。

ノードをクリックすると、そのエージェントの詳細パネルが開きます。トークン数やセッション数、リクエスト数・P99 レイテンシ・エラーに加えて、点数の低い評価器5つとトレースの一覧が表示されます。

Application mapのノードをクリックすると、エージェントの詳細パネルが開く

中身は Agent overview から開くエージェントの詳細とほぼ同じで、こちらも違うのは入口なのかなーという印象を受けました。

Traces でトレースを横断して見る

アプリも含めて、スペース全体のトレースを横断して探す画面です。

  1. ホームの「Traces」を開く
  2. 右上の期間をクリックし、「Past 1 day」を選んで「Apply」をクリックする(ここはみたい期間でOK)
  3. 画面右上の「Agents」に切り替える

初期表示の「Applications」はアプリケーション向けの表示で、今回は0件でした。「Agents」に切り替えると、エージェントのトレースが表示されます。ここから Compare や Evaluate、Add to dataset にも進めるので、前半の Agent traces と同じように分析に使えます。

Tracesの右上でAgentsに切り替えると、エージェントのトレースがトレース単位で並ぶ

Explore logs で日本語からクエリを作る

「Explore logs」は、Dataset に入ったログを SQL で検索する画面です。サンプルクエリも並んでいますが、今回は自然言語からクエリを作ってみました。

  1. ホームの「Explore logs」を開く
  2. クエリ欄の左にある星マークをクリックし、「Ask AI to generate a query」を選ぶ
  3. 下の入力欄に「In #Explore generate a query that shows」と入るので、続けて質問を入力して Enter キーを押す

Explore logsの星マークからAsk AI to generate a queryを選ぶ

入力した質問
ロググループごとのログ件数(多い順)

30秒ほどで、ロググループごとに件数を数えるクエリが作られて実行されました。期間も17:00〜20:00に自動で広げられていて、回答には「omnisupport の実行ログが1,444件で最多」とまとめられています。

日本語の質問からクエリが作られ、ロググループごとの件数が返った

クエリの書き方を覚えていなくても、日本語で聞けば集計できます。作られたクエリは画面に表示されるので、中身を確認してから使うのが安心です。

Explore metrics でメトリクスをグラフにする

「Explore metrics」では、CloudWatch のメトリクスを PromQL に近い書き方で検索できます。Bedrock のモデル呼び出し回数を見てみます。

  1. ホームの「Explore metrics」を開く
  2. 左の「Search metrics...」に Invocations と入力し、表示された「Invocations」をクリックする
  3. 右上の期間を「Past 4 hours」に変える(ここはみたい期間でOK)

前半の検証で質問を送った時間帯に、呼び出し回数の山ができているのが分かります。

Explore metricsでInvocationsを選ぶとグラフが出る

星マークから自然言語で聞くと合計回数は答えてくれましたが、グラフは描かれなかったので、グラフを見たいときは上の手順でメトリクスを選ぶほうが確実でした。

ダッシュボードとして保存する

Explore で作ったページは、そのままダッシュボードとして保存できます。

  1. 右上の「Save」をクリックする
  2. 「Dashboard name」に名前を入れる(今回は omnisupport-overview
  3. 「Save」をクリックする

SaveでページをダッシュボードとしてOmniに保存する

保存したダッシュボードはホームの「Dashboards」に一覧で表示され、次からはここから開けます。

Dashboardsに保存したダッシュボードが並ぶ

いつもみたいものを保存して置く感覚ですね。

ホームの「Markdown」は、ページに文章のパネルを置く機能です。開くとサンプルの文章が入ったパネルができ、右上の「Edit」で本文を書き換えられます。

Markdownパネルでダッシュボードにメモを置ける

ダッシュボードに「このグラフが何を示しているか」「アラートが鳴ったら誰に連絡するか」といったメモや手順を並べておくのに使う形みたいです。最初はマークダウンがなぜ・・??と思いました。

Explore からもアラートを作れる

Explore のクエリ欄の右上にあるベルのアイコンからも、そのクエリをもとにアラートを作れます。作り方は、前の「点数が下がったらアラートで知らせる」と同じです。

ベルのアイコンから、このクエリをもとにアラートを作る画面が開く

Investigations は DevOps Agent と連携して使う

「Investigations」を開くと、「AWS DevOps Agent is not connected」と表示されました。スペースの integrations で AWS DevOps Agent を接続すると、Omni から調査を始められるようになります。今回は接続していないので、画面の確認にとどめています。

InvestigationsはAWS DevOps Agentとの連携が必要

エージェント1つのデータでも、Services・Traces・Explore のそれぞれの切り口から同じ実行を見られました。アプリとエージェントを同じスペースに入れておけば、アプリ側のエラーとエージェントの回答を1か所で追えそうです。

料金

Omni の料金は、データの取り込み・保存・分析の従量課金で、スペースやダッシュボード、アラートそのものには固定料金がかかりません。バージニア北部の主な単価は次のとおりです。

項目 単価
スパンの取り込み 0.35〜0.15 USD/GB(段階制)
ログの取り込み 0.50 USD/GB
ログの保存(Standard) 0.030 USD/GB-月
ログ・トレースのクエリ 0.005 USD/GB(取り込み量の5倍までは無料)
ダッシュボード・アラート 料金に含まれる

https://aws.amazon.com/cloudwatch/omni/pricing/

なお、Ask Assistant 自体の料金は料金ページに書かれていませんでした。Assistant が実行したクエリの分が、上の表のクエリ料金としてかかる形なのかな?と思いつつ、このあたりはちょっと気になっています・・・

エージェントの評価は AgentCore Evaluations の料金、Prompt playground の生成は選んだモデルの Bedrock の料金です。

項目 単価
組み込み評価器 入力 0.0024 USD/1,000トークン、出力 0.012 USD/1,000トークン
カスタム評価器 1.50 USD/1,000評価(モデル料金は別)
AgentCore Runtime 0.1276 USD/vCPU時間、0.0169 USD/GB時間(実行中のみ)

https://aws.amazon.com/bedrock/agentcore/pricing/

スペースのセットアップで有効になる AWS Config のレコーダーにも料金がかかるので、気になる場合は確認しておきましょう。

まだ監視・評価の SaaS を入れておらず、エージェントのトレース・評価・アラートを1つの画面で見たいなら、選択肢になりそうです!(ここは実際に運用してみないとなにも言えないところですが・・・)

すでに別のツールや既存の機能で問題なく運用できているなら、急いで乗り換えなくてもよいかなとも思いました。まずはデモ用スペースやサンプルを触ってみて、考えるのがいいかなと思います!

後片付け

削除する場合の手順です。

AgentCore のエージェントは、プロジェクトのスキーマを空にしてからデプロイすると削除されます。

実行コマンド
agentcore remove all --force
agentcore deploy -y

オンライン評価は Omni の Online evaluations の一覧から、データセットは Datasets の一覧(ゴミ箱アイコン)から削除できます。スペースとドメインは、CloudWatch コンソールの Omni 設定画面にある「アクション」から削除します。

おわりに

CloudWatch Omni で、エージェントのトレース調査から評価、データセット、プロンプト比較、オンライン評価、アラートまで一通り触ってみました!盛りだくさんでしたね・・・!

慣れれば1つの画面で色々できるので便利そうだなと感じましたが、一方で機能がとにかく多いので、慣れるまでは少し迷いそうなので動線整備やまずはここみて!みたいなチュートリアルがあると嬉しいなと思いました。IDE 拡張や Experiments は今回試せなかったので、今度検証してみたいと思います!

まだまだ説明しきれていない機能もありますが、雰囲気はつかんでいただけたでしょうか!?ウェルカム画面からサンプルデータ入りのデモ用スペースも開けるので、興味があればぜひ触ってみてください!

本記事が少しでも参考になりましたら幸いです。最後までご覧いただきありがとうございました!

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事