Claude Managed Agents と Better Stack MCP Server で作るオンコール SRE アシスタント
Claude Managed Agents のパブリックベータと Better Stack MCP Server を組み合わせて、ant CLI だけでオンコール SRE アシスタントを組み立てた手順と手応え
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 で発行)
antCLI- Better Stack のアカウント
- Better Stack の API トークンを発行できる権限
Claude 側の料金は 3 軸あります。
- トークン課金 — 標準の Claude API 料金と同じ
- Managed Agents のランタイム課金 —
$0.08 / session-hour、running状態の時間のみ - 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 のトークンを環境変数にセットします。ant は ANTHROPIC_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 tokens と Telemetry 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_url と display_name しか返ってきません。エージェントのコンテナにもトークンは届かず、Anthropic 側のプロキシが MCP サーバーへのリクエストに Authorization: Bearer <token> を付与する形で使われます。プロンプトインジェクションで乗っ取られても、トークンを盗み出すことはできない設計です。
💡 Vault は
static_bearerのほかmcp_oauthにも対応しています。 OAuth の場合はrefresh_tokenとtoken_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: falseENVIRONMENT_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_tool → uptime_list_incidents_tool) |
エージェントは「承知しました。モニター一覧と直近インシデントを並行して取得します。」と応答したあと、実際に 2 つのツールを順番に呼び出し、結果を統合して日本語のレポートにまとめてくれました。
レポートには以下のような内容が含まれていました。
- モニター一覧のサマリー(ステータスごとの件数)
- 直近インシデント 3 件の詳細(ID、原因、タイムライン)
- 指示にない情報への自発的な指摘 —「直近 3 件はすべて解決済みですが、現在別のモニターが Down 状態になっています」
システムプロンプトで「具体的なデータを添えて報告する」「確信が持てない点は明言する」と指示しただけで、ID やタイムスタンプを含む構造化されたレポートが返ってきます。
実際の出力形式(記事用の架空例。実在の監視状況とは関係ありません)
モニター一覧(全 12 件)
| ステータス | 件数 |
|---|---|
| Up(正常稼働中) | 10 件 |
| Down(障害中) | 1 件 |
| Paused(一時停止) | 1 件 |
現在 DOWN 中のモニター:
- ID: 100001 —
sample-api.example.com/health最終確認: 2026-04-17 10:23:33 UTC
直近のインシデント(最大 3 件)
| # | インシデント ID | 対象モニター | 原因 | 開始時刻 (UTC) | ステータス |
|---|---|---|---|---|---|
| 1 | 200001 | sample-api.example.com/health | HTTP 502 Bad Gateway | 2026-04-12 17:03:23 | 解決済み(約 2 分で復旧) |
| 2 | 200002 | CloudWatch: SampleCluster | AWS/ES | ClusterStatus.yellow | AWS Elasticsearch クラスタが Yellow 状態 | 2026-04-09 10:24:52 | 解決済み(Ack 後、約 5 日で復旧) |
| 3 | 200003 | sample-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_allow2 回目以降のセッションは、この設定でスムーズに実行できるようになりました。
注目したいのは、承認待ちの間はセッションが 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 寄りの組み込みも現実的な選択肢になりそうです。
リサーチプレビューの機能も含めて、ここから何ができるようになっていくのか、とても楽しみです。しばらくプロトタイプを重ねながら、活用シーンを探っていこうと思います。