Claude Managed Agents と Better Stack MCP Server で作るオンコール SRE アシスタント

Claude Managed Agents のパブリックベータと Better Stack MCP Server を組み合わせて、ant CLI だけでオンコール SRE アシスタントを組み立てた手順と手応え

ogawaApril 17, 2026

2026 年 4 月に Anthropic が Claude Managed Agents のパブリックベータを公開しました。エージェントの実行基盤(サンドボックス、状態管理、認証情報の取り回し、実行トレースなど)を Anthropic 側で丸ごと提供してくれるサービスです。

一方、Tagbangers では Better Stack(旧 Better Uptime)を使っています。当初は外形監視がメインでしたが、最近は Metrics から Tracing まで SRE に必要な機能が徐々に充実してきています。以前ブログでも紹介した 監視 IP を GitHub Actions で自動追従する仕組み も、この Better Stack まわりの運用を楽にするための取り組みでした。

その Better Stack も MCP Server を提供しています。AI アシスタントから Uptime の監視データやインシデント情報にそのままアクセスできるものです。

この 2 つを繋いで「オンコールアシスタントに直近のインシデントを調べてもらう」という SRE 文脈での最小構成を、ant CLI だけで組み上げてみました。なお Claude Console に GUI も用意されているので、同じことはブラウザからでも一通り行えます。

必要なもの

手順を再現するには、以下を事前に用意しておきます。

  • Claude API キーClaude Console で発行)
  • ant CLI
  • Better Stack のアカウント
  • Better Stack の API トークンを発行できる権限

Claude 側の料金は 3 軸あります。

  • トークン課金 — 標準の Claude API 料金と同じ
  • Managed Agents のランタイム課金$0.08 / session-hourrunning 状態の時間のみ
  • Web 検索の課金$10 / 1,000 検索web_search ツールを使った場合のみ

Better Stack 側は無料プランの範囲で検証できます。

全体像

今回組み立てる構成はこんな形です。

[あなたのシェル]
     ↓ ant CLI
[Claude Managed Agents API]
     ├── Agent(SRE Assistant)         ← agent.yaml で定義
     ├── Environment(SRE Assistant)     ← environment.yaml で定義
     ├── Vault(Better Stack の static_bearer credential)
     └── Session(上記を組み合わせた実行インスタンス)
              ↓ Authorization: Bearer <token> を Anthropic 側が注入
         [Better Stack MCP Server]
              ↓
         [Uptime 監視データ]

組み立てるリソースは 4 つです。

  • Agent — どう振る舞うか(モデル、システムプロンプト、使えるツール、接続する MCP サーバー)を宣言したもの
  • Environment — エージェントが動くコンテナのテンプレート(ネットワーク設定、パッケージ)
  • Vault / Credential — MCP サーバー用の認証情報を保管する場所
  • Session — 上記を組み合わせて作る実行インスタンス

Agent と Environment は宣言的に定義する再利用可能なリソース、Session は毎回作って使い捨てる実行インスタンス、という粒度の切り分けになっています。

Step 0: ant CLI をインストールする

macOS なら Homebrew で一発です。

brew install anthropics/tap/ant
xattr -d com.apple.quarantine "$(brew --prefix)/bin/ant"
 
ant --version

続いて API キーと Better Stack のトークンを環境変数にセットします。antANTHROPIC_API_KEY を自動で読みます。

export ANTHROPIC_API_KEY="sk-ant-..."
export BETTERSTACK_TOKEN="..."      # Step 1 で発行

Step 1: Better Stack で API トークンを発行する

Better Stack のダッシュボードから Settings → API tokens → Team-based tokens へ。

API トークンには Global tokens と Team-based tokens の 2 種類があり、Team-based tokens の方が権限スコープが狭いので今回はこちらを選びます。必要最小限の権限だけ与えるのがトークン運用の鉄則です。

Team-based tokens には Uptime API tokensTelemetry API tokens の 2 種類があります。今回は Uptime のモニター・インシデント API を使うので前者を発行し、環境変数 BETTERSTACK_TOKEN にセットしておきます。

Step 2: Vault と Credential を作る

Claude 側で認証情報を保管する Vault を作り、そこに Better Stack 用の static_bearer Credential を登録します。

VAULT_ID=$(ant beta:vaults create \
  --display-name "Better Stack" \
  --metadata '{service: betterstack}' \
  --transform id --format yaml)
 
echo "$VAULT_ID"   # vlt_01...

続いて Credential を追加します。こちらは YAML を stdin で流し込む形が読みやすいです。

ant beta:vaults:credentials create --vault-id "$VAULT_ID" <<EOF
display_name: Uptime API token
auth:
  type: static_bearer
  mcp_server_url: https://mcp.betterstack.com
  token: $BETTERSTACK_TOKEN
EOF

ポイントは 認証情報そのものは、ここ以降 API レスポンスに出てこない ことです。token / access_token / refresh_token / client_secret は write-only の扱いで、Credential を取得しても mcp_server_urldisplay_name しか返ってきません。エージェントのコンテナにもトークンは届かず、Anthropic 側のプロキシが MCP サーバーへのリクエストに Authorization: Bearer <token> を付与する形で使われます。プロンプトインジェクションで乗っ取られても、トークンを盗み出すことはできない設計です。

💡 Vault は static_bearer のほか mcp_oauth にも対応しています。 OAuth の場合は refresh_tokentoken_endpoint を Credential に入れておくと、アクセストークンのリフレッシュも Managed Agents が自動で処理してくれます。Slack や GitHub のような OAuth 前提の MCP サーバーと連携するときも、トークン更新処理を自前で書く必要はありません。

Step 3: Agent を定義する

Agent の定義は、再利用とバージョン管理の対象になるので YAML ファイルに切り出します。

# agent.yaml
name: SRE Assistant
description: Better Stack の監視データにアクセスできるオンコール SRE アシスタント
model: claude-sonnet-4-6
system: |
  あなたは Better Stack の監視データにアクセスできるオンコール SRE アシスタントです。
 
  主な役割:
  - 依頼に応じてインシデントを調査する
  - モニターの健全性と可用性を確認する
  - 調査結果をインシデントのコメントとして残す
  - 現在のオンコール担当者を特定する
 
  調査時の原則:
  1. 直近のインシデントをまず確認する
  2. 何らかのアクションを提案する前に、インシデントの詳細を読む
  3. 具体的なデータ(インシデント ID、タイムスタンプ、エラーメッセージ)を添えて簡潔に報告する
  4. 確信が持てない点は、推測せず「確信が持てない」と明言する
 
  接続されているツールを通じて、Better Stack の稼働監視およびインシデント管理機能にアクセスできます。
mcp_servers:
  - type: url
    name: betterstack
    url: https://mcp.betterstack.com
tools:
  - type: agent_toolset_20260401
  - type: mcp_toolset
    mcp_server_name: betterstack
    default_config:
      permission_policy:
        type: always_allow

作成コマンドはシンプルです。

AGENT_ID=$(ant beta:agents create --transform id --format yaml < agent.yaml)
 
echo "$AGENT_ID"   # agent_01...

ポイントは 2 つあります。

① MCP サーバーの宣言と利用は分かれている

mcp_servers は「このエージェントはどの MCP サーバーに接続するか」を宣言する場所で、tools は「エージェントが実際に呼び出せる能力」を並べる場所です。MCP サーバーを登録しただけでは使えず、tools 配列で mcp_toolset エントリを入れて初めて呼び出せるようになります。

💡 tools に指定できるのは 3 種類あります。

  • 組み込みツールセットagent_toolset_20260401) — bash、read、write、edit、grep、glob、web_search、web_fetch の 8 つ。Anthropic のコンテナが実行する。
  • MCP ツールmcp_toolset) — mcp_servers に登録した MCP サーバーが提供するツール。MCP サーバーが実行する。
  • カスタムツールcustom) — 自分のアプリケーションが実行する独自のツール。エージェントが呼び出すと、アプリケーション側が結果を返すまでセッションが待機する。人間の承認を挟む Human-in-the-loop 処理はこれで実装する。

今回は組み込みツールと MCP ツールの 2 種類だけを使っています。

② 認証情報はここには書かない

mcp_servers には URL だけを書き、認証情報は一切含めません。認証は Session 作成時に Vault で紐付けます。

💡 default_config.permission_policy.type: always_allow を明示的に入れています。 省略すると MCP ツールはデフォルトで always_ask ポリシーになり、ツール呼び出しのたびに承認待ちでセッションが idle になります。詳しくは後述の「MCP ツールはデフォルトで承認待ちになる」を参照してください。

💡 Managed Agents で使える MCP サーバーはリモート(URL 指定)のみです。 npx @modelcontextprotocol/server-xxx のようなローカル stdio MCP サーバーは使えません。MCP サーバーへの接続はエージェントを動かすハーネス側が行うため、Environment のコンテナ内で起動したプロセスにはハーネスから到達できないのが理由です。もしローカル stdio サーバーを使いたい場合は、Agent SDK の方を選ぶことになります。

Step 4: Environment を定義する

こちらも YAML で切り出します。

# environment.yaml
name: SRE Assistant
config:
  type: cloud
  networking:
    type: limited
    allowed_hosts: []
    allow_mcp_servers: true
    allow_package_managers: false
ENVIRONMENT_ID=$(ant beta:environments create --transform id --format yaml < environment.yaml)
 
echo "$ENVIRONMENT_ID"   # env_01...

networking の設定が肝です。limited は「allowed_hosts に書いた HTTPS ホスト以外は基本ブロック」という設定で、そこに allow_mcp_servers: true を加えると「Agent の mcp_servers に登録した URL だけは追加で通す」という挙動になります。今回のように MCP サーバーだけが必要なら allowed_hosts は空配列で十分です。

{type: unrestricted} で全部開けてしまうこともできますが、本番運用を見据えるなら limited + allow_mcp_servers の方が妥当です。

Step 5: Session を作る

Agent / Environment / Vault を組み合わせて実行インスタンスを作ります。

SESSION_ID=$(ant beta:sessions create \
  --agent "$AGENT_ID" \
  --environment-id "$ENVIRONMENT_ID" \
  --vault-id "$VAULT_ID" \
  --title "Better Stack インシデント調査 #1" \
  --transform id --format yaml)
 
echo "$SESSION_ID"   # session_01...

--vault-id を渡した瞬間、API は「Agent が繋ぎに行く MCP サーバー URL(https://mcp.betterstack.com)」と「Vault に登録された Credential の mcp_server_url」を突き合わせて、一致するものがあれば自動的にその Credential を使うようになります。Credential の認証情報は一切コマンドラインに出てきていないのに、これだけで認証が成立します。

Step 6: メッセージを送って動かす

Session にユーザーメッセージを送ると、エージェントが自動的に起動してツール呼び出しを始めます。別ターミナルで先にストリームを開いておきます。

# Terminal 1: イベントをストリームで受信
ant beta:sessions stream --session-id "$SESSION_ID"

続いて別ターミナルからユーザーメッセージを送信します。

# Terminal 2: ユーザーメッセージを送信
ant beta:sessions:events send \
  --session-id "$SESSION_ID" \
  --event '{
    type: user.message,
    content: [{
      type: text,
      text: "Better Stack で現在監視しているモニターの一覧を取得し、直近のインシデントがあれば最大 3 件を確認してください。各インシデントについて、ID、開始時刻、対象モニター、現在のステータスを簡潔にまとめて報告してください。"
    }]
  }'

Terminal 1 にイベントが順次流れてきます。session.status_idle が来たらエージェントが仕事を終えた合図です。

今回の実行結果は次の通りでした。

項目
所要時間31.8 秒
使用トークン48.3k input / 891 output
ツール呼び出し2 回(uptime_list_monitors_tooluptime_list_incidents_tool

エージェントは「承知しました。モニター一覧と直近インシデントを並行して取得します。」と応答したあと、実際に 2 つのツールを順番に呼び出し、結果を統合して日本語のレポートにまとめてくれました。

レポートには以下のような内容が含まれていました。

  • モニター一覧のサマリー(ステータスごとの件数)
  • 直近インシデント 3 件の詳細(ID、原因、タイムライン)
  • 指示にない情報への自発的な指摘 —「直近 3 件はすべて解決済みですが、現在別のモニターが Down 状態になっています」

システムプロンプトで「具体的なデータを添えて報告する」「確信が持てない点は明言する」と指示しただけで、ID やタイムスタンプを含む構造化されたレポートが返ってきます。

実際の出力形式(記事用の架空例。実在の監視状況とは関係ありません)

モニター一覧(全 12 件)

ステータス件数
Up(正常稼働中)10 件
Down(障害中)1 件
Paused(一時停止)1 件

現在 DOWN 中のモニター:

  • ID: 100001sample-api.example.com/health 最終確認: 2026-04-17 10:23:33 UTC

直近のインシデント(最大 3 件)

#インシデント ID対象モニター原因開始時刻 (UTC)ステータス
1200001sample-api.example.com/healthHTTP 502 Bad Gateway2026-04-12 17:03:23解決済み(約 2 分で復旧)
2200002CloudWatch: SampleCluster | AWS/ES | ClusterStatus.yellowAWS Elasticsearch クラスタが Yellow 状態2026-04-09 10:24:52解決済み(Ack 後、約 5 日で復旧)
3200003sample-service.example.comタイムアウト(レスポンスヘッダー未受信)2026-04-09 05:32:14解決済み(約 1 時間で復旧)

サマリー

  • 直近 3 件のインシデントはすべて解決済みです。大きな継続障害はありません。
  • 現在注意が必要なのは sample-api.example.com/health(ID: 100001) で、現時点でも Down 状態です。
  • AWS Elasticsearch の Yellow アラートは約 5 日間継続しており、やや長めの復旧でした。

イベントログから裏側を見る

ストリームは流れていくので、あとから追跡するには ant beta:sessions:events list が便利です。--transform でフィールドを絞り込めば、タイムラインを一望できます。

ant beta:sessions:events list \
  --session-id "$SESSION_ID" \
  --transform '{created_at, type, name, mcp_server_name, evaluated_permission}' \
  --format jsonl
{"created_at":"2026-04-17T...","type":"session.status_running"}
{"created_at":"2026-04-17T...","type":"user.message"}
{"created_at":"2026-04-17T...","type":"agent.thinking"}
{"created_at":"2026-04-17T...","type":"agent.message"}
{"created_at":"2026-04-17T...","type":"agent.mcp_tool_use","name":"uptime_list_monitors_tool","mcp_server_name":"betterstack","evaluated_permission":"allow"}
{"created_at":"2026-04-17T...","type":"agent.mcp_tool_result"}
{"created_at":"2026-04-17T...","type":"agent.mcp_tool_use","name":"uptime_list_incidents_tool","mcp_server_name":"betterstack","evaluated_permission":"allow"}
{"created_at":"2026-04-17T...","type":"agent.mcp_tool_result"}
{"created_at":"2026-04-17T...","type":"agent.message"}
{"created_at":"2026-04-17T...","type":"session.status_idle"}

各イベントに「どのツールを誰が実行しようとして、どのパーミッションポリシーで評価されたか」まで残ります。これがそのまま監査ログになるので、「なぜエージェントはこの判断をしたか」を後から追跡できます。ツール呼び出しの引数まで見たければ --transform '{type, name, arguments}' でもう 1 段深掘りできます。

MCP ツールはデフォルトで承認待ちになる

最初のセッションでは、ツール実行の直前でセッションが idle になって止まってしまいました。イベントログを見ると:

{
  "type": "agent.mcp_tool_use",
  "name": "uptime_list_incidents_tool",
  "mcp_server_name": "betterstack",
  "evaluated_permission": "ask"
}

evaluated_permission: "ask" となっており、エージェントがツールを呼び出そうとして ユーザーの承認を待っている状態 でした。

これは Managed Agents のデフォルト動作で、MCP ツールはデフォルトで always_ask ポリシー になっています。MCP サーバー側で新しいツールが追加されたとき、勝手に実行されないようにするための安全設計です。一方、Built-in tools のデフォルトは always_allow で、こちらは毎回承認を求めません。

always_ask のままでも、user.tool_confirmation イベントを返せばエージェントは処理を続行します。今回はフル自動で動かしたかったので、そもそも承認を求めない設定にしました。

信頼できる MCP サーバーに対しては、Agent 定義で明示的に always_allow に変えることができます。Step 3 の agent.yaml に含めていた以下の部分がそれです。

tools:
  - type: agent_toolset_20260401
  - type: mcp_toolset
    mcp_server_name: betterstack
    default_config:
      permission_policy:
        type: always_allow

2 回目以降のセッションは、この設定でスムーズに実行できるようになりました。

注目したいのは、承認待ちの間はセッションが idle なのでランタイム課金は発生しないという点です。Managed Agents のランタイム課金は running 状態の時間だけが対象なので、1 時間でも 1 日でも承認を待てます。Slack のボタンクリック待ちや、メール承認待ちといった長時間の人間介入(Human-in-the-loop)が、現実的なコスト感で実装できるのはこの仕組みのおかげです。

触ってみて感じたこと

実装の手間が劇的に少ない

エージェント自体のコードは 1 行も書いていません。Better Stack MCP Server があらかじめ API を MCP プロトコルに整形してくれているので、こちらがやったのは「この URL に繋いで」と宣言することだけです。

Vault で認証情報をコードから切り離せる安心感

トークンを Agent 定義や環境変数に書かなくていい、という設計はシンプルですが効果が大きいです。コンテナ内のエージェントがどんな指示を受けても、Vault に置いたトークンを読み出すことはできません。認証情報を「脳」と「手足」で分離する、という Managed Agents 全体の設計思想がここに現れています。

「待てる」エージェントの価値

承認待ちで idle になっている間、課金されないというのは実運用では効いてきます。本番の SRE ワークフローに組み込むなら、重要な操作ではどうしても人間判断を挟みたい場面があります。その時間をコストに換算しなくていいのは、設計の自由度を大きく広げてくれます。

ここから発展させるなら

今回は読み取り系のツール呼び出しだけで終えましたが、Better Stack MCP には書き込み系のツールも揃っています。

  • uptime_create_incident_comment_tool — インシデントに調査状況のコメントを追加
  • uptime_acknowledge_incident_tool — インシデントを acknowledge してエスカレーションを止める

これらを組み合わせると、「アラートが鳴ったら、エージェントが初動調査をして状況コメントを残し、人間がオンコールを引き受けるまでの数分をカバーする」という SRE アシスタントが作れそうです。

さらに発展させるなら、

  • カスタムツール で人間の承認を必須にする操作を設計する
  • Outcome を定義して、「インシデントが解決するまで自律的に調査と対応を反復する」ループを組む
  • Slack MCP を組み合わせて、調査結果を on-call チャンネルに投稿する

といった方向性があります。リサーチプレビューの機能も含めて、SRE 業務とエージェントの相性はかなり良いというのが、今回の検証での手応えです。

まとめ

今回の検証を通じて見えてきたのは、Claude Managed Agents が プログラミングもインフラ構築もほぼ不要でエージェントを組み立てられる プラットフォームになっているということでした。ant CLI と 2 枚の YAML だけで、MCP サーバー経由のツール連携まで含めた SRE アシスタントが動くところまで到達しています。

さまざまなサービスが MCP Server を続々と公開していることもあり、Agent と組み合わせられる道具の幅も一気に広がっています。ここまで手軽に動かせると、「次はあれも試したい」「これも組み合わせたい」と、やりたいことのイメージが膨らみますね。

そして、すべての構成が API 経由で宣言的に扱えるということは、自分のアプリケーションからエージェントを動的に生成する ような使い方にも道が開けるということでもあります。ユーザーごとに異なる Vault を持たせて、リクエストに応じて Session を作る、という SaaS 寄りの組み込みも現実的な選択肢になりそうです。

リサーチプレビューの機能も含めて、ここから何ができるようになっていくのか、とても楽しみです。しばらくプロトタイプを重ねながら、活用シーンを探っていこうと思います。