6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AgentCore Observability をAgentCore外のエージェントから利用する

Last updated at Posted at 2025-12-26

はじめに

AIエージェントをAgentCore以外でもECSや軽ければAppRunnerなどで作ることもあるのですが、
そうした際のデバッグのためにエージェント内で何が起きているか、ツールをどう呼んでいるかを確認したい場合が結構あります。

AgentCore Runtime以外と組み合わせることでと親和性が高く、大体使っていたのですが、
AgentCore外のエージェントでもAgentCore Observabilityを利用することができると知り、
どのような設定で利用できるのかを実際に実装しつつ、試してみました。


前提条件

  • Python 3.10以上
  • AWSアカウントと認証情報の設定(aws configure
  • CloudWatch Transaction Searchの有効化(初回のみ、下記参照)

初回セットアップ: CloudWatch Transaction Searchの有効化

AgentCore Observabilityのトレースを表示するには、CloudWatch Transaction Searchを有効にする必要があります。これはアカウントごとに一度だけ実行します。

CloudWatchコンソールから有効化する方法

  1. CloudWatchコンソールを開く
  2. 左側ナビゲーションの Setup > Settings を選択
  3. Account を選択し、X-Ray traces タブを開く
  4. Transaction Search セクションで View settings を選択
  5. Edit を選択
  6. Enable Transaction Search を選択
  7. For X-Ray users を選択し、インデックスするトレースの割合を入力(1%は無料)
  8. Save を選択

有効化後、スパンが検索可能になるまで約10分かかります。

CloudWatch Transaction Search Settings

AWS CLIから有効化する方法

ステップ1: リソースベースポリシーの設定

X-RayがCloudWatch Logsにトレースを送信できるようにポリシーを設定します。

aws logs put-resource-policy \
  --policy-name AWSXRayToCloudWatchLogs \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "xray.amazonaws.com"
        },
        "Action": [
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ],
        "Resource": [
          "arn:aws:logs:*:*:log-group:aws/spans*",
          "arn:aws:logs:*:*:log-group:/aws/application-signals/data*"
        ]
      }
    ]
  }'

ステップ2: Transaction Searchの有効化

スパン取り込み先をCloudWatch Logsに設定します。

aws xray update-trace-segment-destination --destination CloudWatchLogs

ステップ3: 設定の確認

aws xray get-trace-segment-destination

成功すると以下のレスポンスが返ります:

{
  "Destination": "CloudWatchLogs",
  "Status": "ACTIVE"
}

有効化後、スパンが検索可能になるまで約10分かかります。

CloudWatch Transaction Search Settings


1. 必要な設定やインストール、起動方法

1.1 依存関係

以下のパッケージをインストールします。

pip install aws-opentelemetry-distro bedrock-agentcore

または pyproject.toml / requirements.txt に追加:

dependencies = [
    "aws-opentelemetry-distro",
    "bedrock-agentcore",
]

Strands Agentsを使用する場合

Strands Agentsフレームワークを使用する場合は、OTEL対応版をインストールしてください:

pip install 'strands-agents[otel]'

1.2 CloudWatchロググループの作成

環境変数を設定する前に、CloudWatchにロググループとログストリームを作成します。

AWS CLIで作成する場合

# ロググループを作成
aws logs create-log-group --log-group-name /aws/agentcore/your-agent-name

# ログストリームを作成
aws logs create-log-stream \
  --log-group-name /aws/agentcore/your-agent-name \
  --log-stream-name your-agent-name

CloudWatchコンソールから作成する場合

  1. CloudWatchコンソールを開く
  2. 左側ナビゲーションの Logs > Log groups を選択
  3. Create log group を選択
  4. ロググループ名を入力(例: /aws/agentcore/your-agent-name
  5. 作成したロググループを開き、Create log stream でログストリームを作成

1.3 環境変数

以下の環境変数を設定します。

環境変数 説明
AGENT_OBSERVABILITY_ENABLED true Observabilityの有効化
OTEL_PYTHON_DISTRO aws_distro AWS OpenTelemetryディストリビューション
OTEL_PYTHON_CONFIGURATOR aws_configurator AWSコンフィギュレーター
OTEL_EXPORTER_OTLP_PROTOCOL http/protobuf OTLPプロトコル設定
OTEL_EXPORTER_OTLP_LOGS_HEADERS 下記参照 CloudWatch連携ヘッダー
OTEL_RESOURCE_ATTRIBUTES service.name=your-agent-name サービス識別情報(GenAI Observabilityダッシュボードでの識別名)
AWS_DEFAULT_REGION us-east-1 AWSリージョン

OTEL_EXPORTER_OTLP_LOGS_HEADERS の設定例

x-aws-log-group=/aws/agentcore/your-agent-name,x-aws-log-stream=your-agent-name,x-aws-metric-namespace=bedrock-agentcore

your-agent-name は1.2で作成したロググループ名・ログストリーム名に合わせてください。

1.4 起動方法

opentelemetry-instrument でアプリケーションをラップして起動します。

opentelemetry-instrument uvicorn agent.main:app --host 0.0.0.0 --port 8080

Dockerfileの例:

CMD ["opentelemetry-instrument", "uvicorn", "agent.main:app", "--host", "0.0.0.0", "--port", "8080"]

1.5 必要なIAMポリシー

実行ロール(タスクロール、インスタンスロール等)に以下の権限を付与します。

マネージドポリシー

  • CloudWatchAgentServerPolicy
  • AWSXRayDaemonWriteAccess

カスタムポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
      ],
      "Resource": "arn:aws:logs:*:*:log-group:/aws/agentcore/your-agent-name:*"
    }
  ]
}

適用先

サービス ロール
App Runner インスタンスロール
ECS/Fargate タスクロール

2. セッション使用について

AgentCore Observabilityでは、OpenTelemetry Baggageを使用してセッションIDを設定できます。これにより、同一セッション内のトレースをグルーピングできます。

Session View

実装例

from fastapi import FastAPI
from opentelemetry import baggage, context  # (1)
import uuid

app = FastAPI()

@app.post("/invoke")
async def invoke_agent(request: InvokeRequest):
    # セッションIDの取得または生成
    session_id = request.session_id or str(uuid.uuid4())  # (2)

    # OpenTelemetry Baggageにsession.idを設定
    ctx = baggage.set_baggage("session.id", session_id)  # (3)

    # コンテキストをアタッチしてエージェントを実行
    token = context.attach(ctx)  # (4)
    try:
        result = await agent.invoke_async(request.prompt)
    finally:
        context.detach(token)  # (5)

    return {"response": result, "session_id": session_id}

コード解説

番号 コード 説明
(1) from opentelemetry import baggage, context baggage: トレース間でメタデータを伝播させる機能。context: OpenTelemetryのコンテキスト管理機能
(2) session_id = request.session_id or str(uuid.uuid4()) リクエストにセッションIDがあれば使用し、なければ新規生成。同じセッションIDを持つリクエストはCloudWatch上でグルーピングされる
(3) baggage.set_baggage("session.id", session_id) session.id キーでセッションIDを設定。このキー名はAgentCore Observabilityが認識する予約キー
(4) token = context.attach(ctx) コンテキストをアタッチし、トークンを取得。アタッチ後に実行されるすべてのスパンにセッションIDが自動的に伝播される
(5) context.detach(token) 処理完了後、トークンを使用してコンテキストをデタッチ。try/finallyで囲むことで例外発生時も確実にデタッチされる

3. カスタムスパンの利用について

OpenTelemetryのトレーサーを使用して、カスタムスパンを作成できます。これにより、独自の処理をトレースに記録できます。

Custom Span Detail

実装例: Web検索ツール

from opentelemetry import trace

# サービス名とバージョンを指定してトレーサーを取得
tracer = trace.get_tracer("web_search", "1.0.0")  # (1)

def web_search(query: str, max_results: int = 5) -> str:
    """Web検索を実行し、結果をトレースに記録"""

    with tracer.start_as_current_span("custom span web search tool") as span:  # (2)
        try:
            # 検索パラメータを属性として記録
            span.set_attribute("search.query", query)  # (3)
            span.set_attribute("search.max_results", max_results)
            span.set_attribute("tool.name", "web_search")
            span.set_attribute("search.provider", "duckduckgo")

            # イベントで処理開始を記録
            span.add_event("search_started", {"query": query})  # (4)

            # 検索を実行
            results = perform_search(query, max_results)

            # 結果数を記録
            span.set_attribute("search.results_count", len(results))

            # 個別の結果属性を追加(上位3件のみ)
            for i, result in enumerate(results[:3], 1):  # (5)
                span.set_attribute(f"search.result.{i}.title", result.get('title', '')[:100])
                span.set_attribute(f"search.result.{i}.url", result.get('href', ''))

            # イベントで処理完了を記録
            span.add_event("search_completed", {
                "status": "success",
                "results_count": len(results)
            })

            return format_results(results)

        except Exception as e:
            # エラーを記録
            span.set_attribute("search.error", str(e))
            span.record_exception(e)  # (6)
            span.add_event("search_failed", {"error": str(e)})
            raise

コード解説

番号 コード 説明
(1) trace.get_tracer("web_search", "1.0.0") サービス名とバージョンを指定してトレーサーを取得。トレースの整理・フィルタリングに有用
(2) start_as_current_span("custom span web search tool") スパンを開始。この名前はCloudWatchのトレースビューでスパンの識別子として表示される
(3) span.set_attribute("search.query", query) スパンに属性(キー/値ペア)を追加。CloudWatchで検索・フィルタリングに使用できる
(4) span.add_event("search_started", {...}) スパン内の特定時点にイベントを記録。処理のマイルストーンや状態変化を追跡できる
(5) span.set_attribute(f"search.result.{i}.title", ...) 動的なキー名で個別の結果を記録。データ量を抑えるため上位3件に限定
(6) span.record_exception(e) 例外情報(スタックトレース含む)をスパンに記録。エラーのデバッグに有用

まとめ

よいAIエージェントを作成するためには内部挙動を理解することが必要で、そのためにAgentcore Observabilityは強力なツールとなります。
それをAgentcore Runtime以外と組み合わせることで、Runtime以外でもAIエージェントの改善に活かしてもらえればと思います。
(Backend Serverとエージェント処理を1コンテナで構成したいという需要はまだあると思うので。。。)

参考リンク

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?