NTT DATA TECH
📊

AgentCore RuntimeとLangfuseで高度なAI Observabilityを実現

に公開

Amazon Web Services(AWS)が提供する新しいAIエージェントプラットフォームAmazon Bedrock AgentCoreにおいて、AgentCore Observabilityの代わりにLangfuseを利用するノウハウをここでは提供します。
色々ブログなどを読んで試していて、情報が古かったりしてうまくいかなかったので、2025年10月時点での最新情報として記載したいと思います。

なお、AWSのBedrock AgentCoreの公式サンプルであるStrands Agent with Langfuse Observability on Amazon Bedrock AgentCore Runtimeの情報を参考にしました。これ以外の情報は仕様が日々変更しているせいか正しくないものが多かったのでご注意ください。

想定読者

  • LangfuseでAgentCore Runtime上のエージェントを監視したい人
  • AgentCore Runtimeを既に触って動かせる人
  • Observability/OpenTelemetryの基礎を理解している人(手順実行だけなら理解していなくても実行可能)

なぜLangfuseを使うのか?

AgentCoreには標準で「AgentCore Observability」と呼ばれるObservabilityの仕組みが提供されています。

AgentCore Observabilityの画面

これだけでも、エージェント内部のスパンやツール呼び出しを可視化でき便利です。しかし、この機能は実質的にCloudWatchのログやトレース機能を利用して表示しており、AI Observability専用ツールと比較すると、UIの見やすさや、トークン数・コストといったAI固有のメトリクス分析の面で物足りなさを感じる場合があります。

ここで、Langfuseを利用すると、下記の図のように入力と出力が並んで表示され、また、関数呼び出しとそれが何処に対応づいているのか、一目でわかるようになります。

Langfuseの画面

ここでは、Langfuseを利用してAIエージェントをモニタリングする方法をご紹介します

AgentCore Observabilityの仕組み

Langfuse対応を行う前に、AgentCore Observabilityの仕組みを理解しておくとスムーズです。
(このセクションはLangfuseのセットアップに必須ではありません。すぐに手順を知りたい方は次の章へスキップしてください)

AgentCore Observabilityは、特別な設定をしなくても、自動的にトレーシング情報を取得できます。これは、エージェント起動時に ADOT (AWS Distro for OpenTelemetry) を利用して、自動計装するよう(自動計装:auto-instrumentation)になっているためです。

AgentCore Runtimeは、エージェントのソースコードからコンテナをビルドしデプロイしますが、その際、作業フォルダにDockerfileが生成されます。このDockerfileを見てみましょう。

まず、下記のようにADOTをインストールしている記述が見つかります。

RUN uv pip install aws-opentelemetry-distro>=0.10.1

また、最後の行にコンテナ起動時にopentelemetry-instrumentでPythonのコードを自動計装するようになっています。

CMD ["opentelemetry-instrument", "python", "-m", "agentcore-sample"]

この仕組みにより、利用者はコードに何も書かなくてもCloudWatchにOTELでメトリクス情報が送信されるようになっています。

Langfuseの利用

上記を踏まえて、Langfuseを利用するには、ADOTの自動計装を無効化してLangfuseを利用します。

エージェント実装のポイント

Strandsを利用してテレメトリを取得するには、StrandsTelemetryをコードの最初でセットアップします。

エージェントのコード(の先頭)

from strands.telemetry import StrandsTelemetry
telemetry = StrandsTelemetry().setup_otlp_exporter()

これにより、Strandsで記述されたエージェントのメトリクスが送信されるようになります。
また、requirements.txtには、strandsのotelコンポーネントをインストールするように追加します。

requirements.txt

strands-agents[otel]

エージェントのデプロイ

AgentCore Runtimeにエージェントをデプロイするには、次の2つのステップが必要になります。

  1. AgentCore Runtimeの設定ファイルの作成(configure)
  2. AgentCore Runtimeのデプロイ(launch)

1. 設定ファイルの作成

from bedrock_agentcore_starter_toolkit import Runtime
from boto3.session import Session
boto_session = Session()
region = boto_session.region_name

agentcore_runtime = Runtime()
agent_name = "strands_langfuse_observability"
response = agentcore_runtime.configure(
    entrypoint="strands_claude.py",
    auto_create_execution_role=True,
    auto_create_ecr=True,
    requirements_file="requirements.txt",
    region=region,
    agent_name=agent_name,
    disable_otel=True, ## ★ここがポイントAgentCore標準のOTELを無効にする
)
response

上記、

disable_otel=True

を設定することにより、生成されるDockerfileのエージェント実行の部分が、下記のように変化し、自動計装が無効になります。

-    CMD ["opentelemetry-instrument", "python", "-m", "agentcore-sample"]
+    CMD ["python", "-m", "agentcore-sample"]

2.デプロイ

import base64

# Langfuse configuration
otel_endpoint = "http://<Langfuseのホスト名>:<ポート>/api/public/otel"
langfuse_public_key = "<Langfuseのパブリックキー>"
langfuse_secret_key = "<Langfuseのシークレットキー>"
# 認証トークンの作成
langfuse_auth_token = base64.b64encode(f"{langfuse_public_key}:{langfuse_secret_key}".encode()).decode()
otel_auth_header = f"Authorization=Basic {langfuse_auth_token}"

launch_result = agentcore_runtime.launch(
    env_vars={
        "BEDROCK_MODEL_ID": "us.anthropic.claude-3-7-sonnet-20250219-v1:0", 
        "OTEL_EXPORTER_OTLP_ENDPOINT": otel_endpoint,
        "OTEL_EXPORTER_OTLP_HEADERS": otel_auth_header,
        "DISABLE_ADOT_OBSERVABILITY": "true",
    }
)
launch_result

デプロイ時には、下記の3つの環境変数を渡すのがポイントです。

a. OTEL_EXPORTER_OTLP_ENDPOINT
b. OTEL_EXPORTER_OTLP_HEADERS
c. DISABLE_ADOT_OBSERVABILITY

a. OTEL_EXPORTER_OTLP_ENDPOINT

Langfuseは、OTELプロトコルでテレメトリを受け取りますが、そのエンドポイントです。下記のURLになります。/api/public/otelが必要なので注意してください。

b. OTEL_EXPORTER_OTLP_HEADERS

認証ヘッダを設定します。上記のコードを見ればわかりますが、下記の手順で作成します。

  1. <Langfuseのパブリックキー>:<Langfuseのシークレットキー>と 「コロン」で繋げた文字列を作成
  2. 作成した文字列をbase64でエンコード
  3. "Authorization=Basic <base64でエンコードした文字列>" を指定(Basicの後のスペースに注意)

最終的に下記のような文字列になります

Authorization=Basic x847Hce....Xj==

c. DISABLE_ADOT_OBSERVABILITY

disableにして、ADOT固有のメトリクス送信を無効化します。

動作確認

適当にエージェントにメッセージを送るなどしてどうさせれば、下記のようにLangfuseでメトリクスが取得されます。

【参考】agentcoreコマンドでの利用

AgentCore SDKを利用してLangfuseに対応する方法を紹介したが、agentcoreコマンドでエージェントをデプロイする方法についても補足しておく。

agentcore configure

agentcore configure

コマンドを通常通り実行する。 .bedrock_agentcore.yamlが作成されるので、下記のobservability/enabledをtrueからfalseに変更し、ADOTを無効化する。

.bedrock_agentcore.yaml

      protocol_configuration:
        server_protocol: HTTP
      observability:
-       enabled: true
+       enabled: false
    bedrock_agentcore:
      agent_id: null
      ...

agentcore launch

下記のコードを実行し、OTELの認証ヘッダーを作成する。

create-auth-header.py

import base64
langfuse_public_key = "<Langfuseのパブリックキー>"
langfuse_secret_key = "<Langfuseのシークレットキー>"
# 認証トークンの作成
langfuse_auth_token = base64.b64encode(f"{langfuse_public_key}:{langfuse_secret_key}".encode()).decode()
otel_auth_header = f"Authorization=Basic {langfuse_auth_token}"
print(otel_auth_header)

認証ヘッダを取得する。

$ python create-auth-header.py
Authorization=Basic cGstb...5MQ==

エージェントを起動する際に、--envオプションでLangfuseの利用に必要な環境変数を設定する

$ agentcore launch \
 --env "OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic cGst...5MQ==" \
 --env OTEL_EXPORTER_OTLP_ENDPOINT=http(s)://<Langfuseのホスト名>:<ポート>/api/public/otel \
 --env DISABLE_ADOT_OBSERVABILITY=true

まとめ

LangfuseをAgentCoreと組み合わせることにより、より高度な可視化ができるようになります。AgentCoreはAIエージェントの開発・運用に便利なプラットフォームですが、このように他のツールと組み合わせることにより、より高度な開発・運用を実現できます。

弊社では、継続してこのようなノウハウを共有していきたいと思います。

NTT DATA TECH
NTT DATA TECH
設定によりコメント欄が無効化されています