ユニファ開発者ブログ

ユニファ株式会社プロダクトデベロップメント本部メンバーによるブログです。

AWS DevOps Agent を触ってみた

はじめに

こんにちは、SRE の松田です。

普段の業務では主に AWS の運用を行っています。 「AI エージェントが運用を助けてくれる」という話題は最近よく見かけますが、実際のところ今の自分の業務に組み込めるのかどうか気になっていました。
実際に触って動かして、確かめるのが一番早いと思っています。
本記事では、AWS が 2026 年 3 月に GA した AWS DevOps Agent を、検証してみた結果をまとめます。「使ってみた」で終わらせないために検証を3つの段階に分けました。

  1. 基本動作の確認
    • 単純なボトルネックに対して、どのような調査ステップを踏むのか
  2. Custom Skills による拡張
    • 自分で書いた SKILL.md で、エージェントの調査手順を変えられるのか
  3. 複雑な状況下での診断精度
    • 複数のシグナルが混在する現実的な状況での応答品質

「何を扱えて、何を扱えないのか」を自分の手で探ることが目的です。
先にお伝えしておくと、この記事では「導入するべき/するべきでない」という結論は出しません。
やってみて得られた結果と、次に試してみたいことを記載していきます。


AWS DevOps Agent とは

まず簡単に押さえておきます。

  • 2026 年 3 月 31 日に GA しました。AWS・マルチクラウド・オンプレを対象に、インシデント調査・RCA(Root Cause Analysis・障害の根本原因を突き止める分析のことです)・運用改善提案・SRE タスク(自然言語)を担うエージェントです
  • production operations(調査・予防・SRE タスク)が GA しています
  • 料金は、エージェントがアクティブに動いている時間に対する従量課金です($0.0083/agent-second ≒ $29.88/agent-hour)。アイドル時には課金されません

参考:

仕組みのうえでの特徴を挙げると、次のようになります。

  • Agent Space
    • エージェントの動作単位であり、セキュリティ境界でもあります。複数の AWS アカウント・ツール連携・ユーザーアクセスを内包します
  • トポロジー
    • 接続された AWS アカウントを解析して、アプリケーションのリソース構成と関係性を自動でマッピングしてくれます
  • Skills
    • エージェントの調査手順を、構造化した Markdown(SKILL.md)で記述・拡張できる仕組みです。AWS が自動生成する「Learned Skills」と、ユーザーが書く「Custom Skills」があります
  • Agent Journal
    • エージェントが「何を考え、どう動いたか」を時系列でつづった、読み取り専用のログです。人間が後から読める形で残るのが特徴で、本記事では主にこの Journal を見ながら検証を進めました(以下、単に Journal とも書きます)
  • CloudTrail 連携
    • エージェントが叩いた AWS API は、すべて CloudTrail に記録されます。ただし「エージェントが何を考えたか」という推論の可視性という点では、Agent Journal の方が読みやすいです。今回の検証では Journal を主軸に置きました

統合先としては、CloudWatch / Datadog / Dynatrace / New Relic / Splunk / Grafana / GitHub / GitLab / Azure DevOps / ServiceNow / PagerDuty / Slack / Microsoft Teams に対応し、
MCP(Model Context Protocol)/ ACP / A2A といったプロトコルで、リモートからも呼び出せます。

参考:


検証の全体像

意図的にボトルネックを仕込んだ最小構成を、CloudFormation で構築しました。

DynamoDB をプロビジョンドモード・1 RCU に絞り、並列リクエストですぐ枯渇する状態にしてあります。
RCU(Read Capacity Unit)は DynamoDB の読み取り処理能力の単位で、ざっくり「1 RCU ≒ 毎秒1回の読み取り」くらいの意味です。
1 RCU は、実運用ではまず使わないほど低い設定にしています。負荷をかけると Lambda は ProvisionedThroughputExceededException(プロビジョニングしたスループットを超えたというエラー)を返し、CloudWatch アラームが発火します。

この構成を採用した理由は3つあります。

  1. Free Tier の範囲にほぼ収まること
  2. 根本原因が Lambda 本体ではなく、依存先の DynamoDB にあること(エラーの出ている箇所から、その原因までエージェントが辿れるかを確かめたかったため)
  3. 短時間で確実に再現できること

観察方法

エージェントの調査が走っている間、Operator App(調査や対応を行う、運用者向けの Web コンソール)の Agent Journal をリアルタイムで観察しました。
Journal には、エージェントの思考ステップ・参照した Skill・下した判断が、時刻付きで記録されていきます。何をどの順で考えたのかを、人間に読める形で追跡できます。


【段階1】素のエージェントが障害をどう調べるか

セットアップ: Agent Space と IAM ロール

DevOps Agent を使い始めるには、まず Agent Space を作成します。
作成画面で名前を付け(今回は devops-agent-lab)、エージェントの応答言語に Japanese (Japan) を指定します。

この作成画面の中で、最初に判断が必要になるのが IAM ロールです。DevOps Agent では、2種類のロールを用意します。

ロール 用途 アタッチした許可ポリシー
Agent Space ロール(devops-agent-lab-agent-space-role) エージェントが AWS API を叩くための実行ロール ReadOnlyAccess
Operator App ロール(devops-agent-lab-webapp-role) Operator App(運用者向け Web コンソール)へのアクセス用 AIDevOpsOperatorAppAccessPolicy + ReadOnlyAccess

Agent Space の作成画面では、このうちプライマリアカウントロール(エージェント用)とウェブアプリ用ロールを、それぞれ「既存のロールを割り当て」で指定します。
今回は、先に作っておいた2つのロールを割り当てました。

Agent Space ロールの信頼ポリシーは、以下の通りです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "aidevops.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "<アカウントID>"
        }
      }
    }
  ]
}

Operator App ロールの信頼ポリシーは、以下の通りです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "aidevops.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ],
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "<アカウントID>"
        }
      }
    }
  ]
}

信頼ポリシーで sts:AssumeRole に加えて sts:TagSession も許可しているのには理由があります。Operator App ロールにアタッチする AIDevOpsOperatorAppAccessPolicy は、aws:PrincipalTag/AgentSpaceId でアクセスをスコープする作りになっています。Operator App はセッションに AgentSpaceId のタグを付与し、そのタグで操作対象の Agent Space を絞り込むため、タグを付与するための sts:TagSession が要る、というわけです。

つまり、オペレーター画面から調査を指示する(内部的には aidevops:CreateBacklogTask を呼ぶ)には、次の2つが両方そろっている必要があります。

  1. Operator App ロールに AIDevOpsOperatorAppAccessPolicy がアタッチされていること
  2. 信頼ポリシーに sts:TagSession があり、セッションに AgentSpaceId タグが付くこと

どちらかが欠けると aws:PrincipalTag/AgentSpaceId 条件が満たされず、操作系 API は「どの identity-based policy も許可していない」として弾かれます。実際、セットアップ当初に ReadOnlyAccess だけで進めたときも、検証のために sts:TagSession を外したときも、同じ aidevops:CreateBacklogTask の denied が出ました。どちらの場合も、オペレーター画面自体は開けるのに、調査を指示しようとした時点で弾かれます。

User: arn:aws:sts::<アカウントID>:assumed-role/devops-agent-lab-webapp-role/<セッションID> is not authorized to perform: aidevops:CreateBacklogTask on resource: arn:aws:aidevops:ap-northeast-1:<アカウントID>:agentspace/<Agent Space ID> because no identity-based policy allows the aidevops:CreateBacklogTask action

またConditionaws:SourceAccount で、自分のアカウント以外からこのロールが assume されるのを防いでいます。
公式手順では、さらに aws:SourceArn(agentspace の ARN)でも絞る例が示されているので、より厳密にしたい場合はそちらも足すとよいです。

そして、許可ポリシーは、両ロールとも ReadOnlyAccess をベースにしました。
ReadOnlyAccess は範囲の広いポリシーですが、エージェントが実際に使える権限は Permission Guardrail(エージェントがロールを assume する際に AWS 側が自動でセッションポリシーを被せ、実効権限を絞り込む仕組み)によって、読み取り系の調査権限に制限されます。そのため、これでも問題なく動きます。

なお公式手順では、より最小権限に寄せた専用マネージドポリシー AIDevOpsAgentAccessPolicy を使う例が示されています。

参考:

ちなみに、サービスリンクロール AWSServiceRoleForAIDevOps(Agent Space を最初に作成したときに自動作成されます)自体の権限は、意外と限定的で、マネージドポリシー AWSServiceRoleForAIDevOpsPolicy の中身は次のとおりです。

  • cloudwatch:PutMetricData: 使用量メトリクスの送信(AWS/AIDevOps ネームスペース限定)
  • vpc-lattice:CreateResourceGateway ほか :プライベート接続用(AWSAIDevOpsManaged タグ限定).
  • ec2:DescribeVpcs など :VPC ネットワーク情報の読み取り(これだけ条件なし)
  • iam:CreateServiceLinkedRole: VPC Lattice 用 SLR の作成

参考: DevOps Agent IAM permissions

トポロジーの自動マッピング

まず興味深かったのは、AWS アカウント内のリソースの把握が自動で進んでいく様子でした。
Agent Space を作成した直後は、マッピングされた関係が 0 件です。

ところが数分後に開き直すと、トポロジーマッピングが完了し、関係の数が 73 件に増えていました。
私が何かを登録したわけではなく、接続した AWS アカウントを自動で解析して、リソースと依存関係を学習してくれたみたいです。

実際にマッピングされた構成は、Operator App の Topology View で次のように表示されます。

注目したいのは、リソース名がそのまま表示されるのではなく役割ベースの名前に自動で変換されている点です。

トポロジー上の名前 実際のリソース
External Users クライアント(curl / ab)
API Gateway devops-agent-experiment-api
User Request Handler Lambda(devops-agent-experiment-get-user)
User Data Store DynamoDB(devops-agent-experiment-users)
Lambda Error Alarm CloudWatch Alarm
Lambda Logs CloudWatch Logs

「User Request Handler」「User Data Store」という命名は、エージェントがコードや設定を読んで推論した結果です。
リソース名ではなく役割として表現されているため、初めてこの画面を見るメンバーでもアーキテクチャの意図が伝わりやすくなっています。

このトポロジー生成は、裏側で Learned Skill「understanding-agent-space」が効いています。
Agent Space 内のリソースを自動解析し、 コンポーネント間の依存関係を、構造化された知識として保存する仕組みです。

実際に調査 Journal の冒頭を見ると、毎回必ず、このスキルが最初に読み込まれていました。

スキルを読み込み: /aidevops/skills/user/understanding-agent-space/SKILL.md
ファイルを読み込み: /aidevops/skills/user/understanding-agent-space/references/components/devops-agent-experiment-api.md

エージェントは、まず「自分が何を監視しているか」を把握してから調査に入る設計になっています。
この Learned Skill があるおかげで、アラームが発火したときに、そのアラームはどの Lambda に紐づいていて、その Lambda はどの DynamoDB テーブルを使っているのか、を最初のステップで即座に把握できます。

参考: Learned Skills(understanding-agent-space と Topology の関係)

障害を起こすと、5分28秒で根本原因にたどり着いた

まず、並列リクエストで負荷をかけて CloudWatch アラームを発火させます。そのうえで、調査を Operator App(オペレーター画面)から手動で起動しました。
手順はシンプルで、オペレーター画面を開き、「インシデントレスポンス」からメッセージを入力して送るだけです。

今回は「devops-agent-experiment-lambda-errors アラームが発火しています。今すぐ調査してください」と投げました。

すると 5分28秒後に、RCA が出力されました。その間、Journal には以下のステップが刻まれていました。

経過時間 何をしたか
+9s Learned Skill を読み込み。このアラームは Lambda devops-agent-experiment-get-user のエラーを監視していると把握
+29s CloudWatch アラームを確認。134エラー/528呼び出し(25%)、閾値3件を大幅に超過
+1m2s 4つのサブエージェントを並列起動(Lambda ログ・Lambda メトリクス・DynamoDB メトリクス・インフラ変更)
+1m48s CloudWatch Logs から ProvisionedThroughputExceededException を特定
+1m48s Lambda 自体のスロットリング・タイムアウト・同時実行制限はすべて正常 → Lambda は被害者で、犯人は依存先(DynamoDB)
+1m58s DynamoDB: 550件の ReadThrottleEvents、725 RCU 消費(プロビジョニング 1 RCU の 725 倍)
+2m15s 根本原因を確定
+5m28s Investigation completed

ここで注目したいのが、+1m2s の並列調査です。
「Lambda のエラーを見たら Lambda を調べる → 次に DynamoDB を調べる」という直列の思考ではなく、最初から4方向を同時に走らせて、結果を統合しています。これが5分という速さの理由だと思いました。

4方向の調査結果がそろうと、エージェントは「Lambda 自体は正常で、原因は依存先の DynamoDB」と切り分けました。
Lambda 側はスロットリング0件・タイムアウトなし・同時実行も上限に届かず、として除外し、DynamoDB のスループット超過を原因と確定しています。

そして、最終的に出力された RCA は次の通りでした。

DynamoDB テーブル devops-agent-experiment-users は 1 RCU でプロビジョニングされているが、実際の負荷は 05:06 に 725 RCU を消費していた(725倍の超過)。
DynamoDB はバーストキャパシティ(最大300秒分)を提供するが、継続的な超過には対応できず、バーストキャパシティが枯渇した。
550 件の ReadThrottleEvents が発生。Lambda 関数は ConsistentRead=True を使用しているため RCU 消費が 2 倍になっており、問題をさらに悪化させている。
キャパシティをオンデマンドモードに変更するか、実負荷に合わせて増やすことで解決する。

エージェントは約2分で、Lambda 自体は正常で、原因は依存先の DynamoDB にあると切り分けました。
エラーが出ているコンポーネントそのものではなく、その依存先まで見にいけるかどうかが、初動調査の速さを決めるのだと実感しました。

エージェントが「分からない」と申告 (調査ギャップ)

段階1で最も印象的だったのは、調査の途中でエージェントが、自ら調査のギャップを申告したことでした。

「コードリポジトリへのアクセスがないため、Lambda 関数のデプロイのコード差分を確認できない」

直近 (04:54:46) のデプロイで ConsistentRead 設定が変わったのかどうかを確かめたかったものの、CloudTrail ではコードの中身までは追えないため検証できない。
そう判断して Journal に「ここは検証できていない」と明記したうえで、その範囲で言える結論だけを RCA に残していました。

これは、RCA の信頼性を考えるうえで重要な観点だと感じました。LLM ベースのエージェントで怖いのは、確認できていないことを、さも確認したかのように断定してしまう挙動です。
今回観測したのはその逆で、確認できないことを確認できないと申告し、推論の前提として明示していました。
出力された RCA を人間がレビューするときに、エージェントがどこを根拠にして、どこを未確認のまま残したのかが Journal から追えるのは、運用に載せるうえで安心できる材料になります。

このギャップは、後で出てくる MCP サーバーでコードの差分を見せれば、埋められそうです。
エージェントが「足りない」と言った部分を、後からツールで補える。ここも良い作りだと思いました。


【段階2】Custom Skills でエージェントの調査手順を変える

Skills の仕組み

AWS DevOps Agent の Skills は、Markdown(SKILL.md)で、エージェントの調査手順や知識を構造化して与える仕組みです。Custom Skills と Learned Skills の2種類があります。

  • Custom Skills
    • ユーザーが書いて投入するスキルです。
      • SKILL.md + references/ + assets/ のディレクトリ構造で、frontmatter の description が発火条件を制御します。
      • description は100〜1,024文字が目安で、曖昧だとエージェントがスキルをスキップしてしまいます。
  • Learned Skills
    • エージェントが Agent Space のデータから自動生成するスキルです。現時点で4つ提供されています。
      • understanding-agent-space(Agent Space の構造理解。トポロジー表示の基盤)
      • understanding-code-dependencies(サービス間・パッケージ依存の把握)
      • understanding-pipeline-topology(パイプライン構成の把握)
      • tool-use-best-practices(過去の調査からツール利用パターンを抽出。30回の調査ごとに自動更新)

仕様としては、Agent Skills というオープンスタンダードをベースにしています(全てではなく一部に対応)。
スキルに入れられるのは MarkdownPDF画像データといった文書だけで、実行されるスクリプトは今のところ入れられないようです(zip でアップロードする場合は 6MB・100ファイルまで)。 SKILL.md は管理画面で直接書けるほか、GitHub リポジトリから読み込んで Git で管理することもできます。

もう一つ便利なのが、スキルに「どのフェーズで使うか」を指定できる点です。
DevOps Agent の調査はトリアージ → 根本原因分析 → 修復といったフェーズ(agent type:Generic / On-demand / Incident Triage / Incident RCA / Incident Mitigation / Evaluation)に分かれていて、
スキルをそのフェーズに紐づけておくと、関係ないフェーズでは読み込まれず、コンテキスト(作業メモリ)の消費を抑えられます。

参考:

仮説

「Custom Skill にチームの調査ノウハウを書けば、エージェントは実際にそれに従って調査手順を変えるはず」。
この仮説を、Journal で Skill を参照する痕跡と、段階1との調査ステップの差分の、両面から検証します。

書いた Custom Skill

検証用に書いた SKILL.md は、以下の通りです。
趣旨は「Lambda エラーを見るより先に、依存先の DynamoDB スループット指標を確認する」というもので、チームの調査ノウハウを擬似的に表したものになっています。

説明: 
Lambda関数でエラー率が急上昇している場合、またはProvisionedThroughputExceededExceptionが発生している場合に使用する。  
API Gateway → Lambda → DynamoDB構成において、Lambda側の調査より先にDynamoDBのスループット指標を優先的に確認することで、キャパシティ不足による問題を素早く特定する。
指示:

# DynamoDB スループット優先調査

Lambda エラー率の急上昇が観測された場合、Lambda 自体より先に **下流の DynamoDB スループット状況** を確認する。

## Step 1: DynamoDB メトリクスを最初に確認する

以下のメトリクスを対象テーブルで取得する(過去30分、1分粒度):
- `ReadThrottleEvents` — スロットリング発生件数
- `ConsumedReadCapacityUnits` — 実消費 RCU
- `ProvisionedReadCapacityUnits` — プロビジョニング値

`ConsumedReadCapacityUnits``ProvisionedReadCapacityUnits` を超えていれば、それが根本原因候補。

## Step 2: Lambda ログでエラー種別を確認する

CloudWatch Logs で `ProvisionedThroughputExceededException` を検索する。
検出された場合、DynamoDB キャパシティ不足が原因と判断してよい。

## Step 3: ConsistentRead の影響を確認する

Lambda のコードで `ConsistentRead=True` が使われている場合、RCU 消費が2倍になる。
`ConsumedRCU / 呼び出し数` が 1.0 に近ければ ConsistentRead が疑われる。

## Step 4: 緩和策を提案する

- 短期: DynamoDB をオンデマンドモードに変更
- 中期: プロビジョニング RCU を実負荷に合わせて増加
- 長期: ConsistentRead の必要性を見直す(Eventually Consistent で十分な場合は変更)

今回は UI のフォームから直接作ったので、SKILL.md 1枚だけのシンプルな構成です。
参照情報が増えてきたら、zip 形式で references/ フォルダに分けて持たせるのが良さそうです(公式仕様でも、SKILL.md と references/ を分けた構成が定義されていて、例でもそう分けています)。

参考:
DevOps Agent Skills 仕様 — Skill structure

Skill が実際に効いた瞬間

Skill を入れた段階 2 では、調査の序盤でエージェントが自分からこの Skill を読み込みました。Journal の +30s にこう出ています。

「この高いエラー率と Lambda + DynamoDB 構成を考慮して、関連スキル dynamodb-throughput-first-investigation を確認します。」

エージェントは、自分でアラームの内容を読み、Lambda + DynamoDB 構成でエラー率が高いという状況を判断して、
自律的に該当する Skill を選んで読み込んでいました。 私が指示したのは、Skill の description に書いた一文だけです。

その直後、+41s には次のように出ていました。

「このスキルに従い、DynamoDB のスループット状況を優先的に確認します。」

ここで、段階 1との違いが明確になりました。段階1は「cause_category_framework(エージェントが内蔵する、原因をカテゴリに分けて調べる枠組み)に基づいて」4方向を同時に走らせていましたが、
段階 2は Skill の指示どおりに DynamoDB を先に確認するという、意図的な順序の変化が Journal に刻まれていました。 Markdown で書いた調査手順が、エージェントの行動を実際に変えていることが分かりました。

Skill 有り / 無し の比較

同じ障害シナリオで、Skill 有効・無効をそれぞれ実行して、比較しました。

比較項目 Skill 無し(段階1) Skill 有り(段階2)
調査の初手 「cause_category_framework に基づいて」4並列で広く調査 「このスキルに従い、DynamoDB のスループット状況を優先的に確認」と明示
RCA 到達までの所要時間 5分28秒 8分45秒
確認した CloudWatch メトリクス Lambda + DynamoDB Lambda + DynamoDB + API Gateway
特定した根本原因数 1つ 2つ
Journal 上で Skill が読み込まれた箇所 なし +30s「関連スキル dynamodb-throughput-first-investigation を確認します」
agent-second 課金概算 $2.72 $4.36

Skill を入れた方が、遅くなりました。これは想定外の結果でしたが、理由は Skill のせいではないように思います。
段階 2 では DynamoDB を優先的に見つつ、API Gateway のトラフィックやデプロイ履歴まで掘り下げた結果、根本原因を2つ特定しました。

  • 根本原因1
    • DynamoDB のキャパシティ不足(1 RCU でプロビジョニングされ、実負荷の 777 RCU にまったく足りていない)
  • 根本原因2
    • API Gateway への定期的なトラフィックスパイク(05:48 に 1,000 リクエスト → 942 回の Lambda 呼び出し → 777 RCU 要求。キャパシティ不足の DynamoDB を直接スロットリングさせた)

段階1で「1つ」だった根本原因が、API Gateway まで見にいった段階2では「2つ」になりました。調査時間は増えましたが、得られた情報も増えています。

なお、ConsistentRead=True は DynamoDB の「強整合性読み込み」で、常に最新データを読む代わりに、読み取りコスト(RCU)を2倍消費します。

印象的だったのは、調査の過程でエージェントが ConsistentRead=True を一度は疑ったあとで、「これは最初のアラームより後(前回インシデント後)に追加されたものだ」と気づき、自分で原因から外したことです。
一度疑った原因でも、証拠が変われば結論を直す。段階 1 の調査ギャップと同じく、RCA の信頼性という点で良いと思いました (ConsistentRead はスロットリングを悪化させる寄与要因ではありますが、根本原因ではない、という整理です)。

発見:
Skill は「速くする」ものというより「調べる順番を変える」もの。実際、Skill を入れた段階 2 はむしろ段階 1 より時間がかかりました(5m28s → 8m45s)。
同じシナリオを1回ずつ比べただけなので断定はできませんが、少なくとも「Skill を入れれば速くなる」という単純な関係ではなく、変わったのは速さより調査の進め方でした。

書き方のコツ

検証を通じて感じた、効く Skill を書くためのポイントを整理しておきます。

  • description は具体的に書く
    • 「サーバーレス構成のトラブルシューティング」ではなく、「ProvisionedThroughputExceededException を含む Lambda ログを検出したとき」のように、トリガーとなる症状を明示すると良さそうです。(エージェントの視点で書く)
  • Step ごとに分解する
    • 抽象的な指示よりも、具体的な手順の方が、エージェントは追跡しやすいようです
  • 「速くする」ためか「深掘りさせる」ためか、設計の狙いを分けて考える
    • 調査の焦点と優先順位を変える効果はありますが、所要時間の短縮を目的にする場合は、設計上の工夫が必要です

【段階3】複雑な状況下での診断精度

検証の目的

ここからは、現実の運用環境に近づけた検証です。

実際の障害では、根本原因とは関係のない兆候が、同時にいくつも出ていることが多いと思います。
たまたま直前にデプロイがあったり、別のサービスで一時的にアラームが鳴っていたり、無関係なメトリクスがスパイクしていたりなど。
調査でつまずきやすいのは、こうしたノイズに引っ張られて、本物の原因にたどり着くのが遅れることです。

エージェントが同じ状況にどう応答するのかを確かめるための測定が、段階 3 の目的です。

状況設計

検証用ワークロードに対して、以下を意図的に同時に発生させました。

種類 内容 関係性
真の原因 DynamoDB プロビジョンドモード 1 RCU の枯渇 主原因
無関係なノイズ1 障害の5分前に Lambda の環境変数を無害な値で更新 デプロイ履歴に記録が残る。原因とは無関係
無関係なノイズ2 別の独立した小さな Lambda 関数が1回だけエラー終了 同一アカウント内だが、対象アプリケーションとは独立
無関係なノイズ3 障害の時間帯と被る形で、無関係な CloudWatch アラームが発火 同上

これらは、現実の運用で頻繁に遭遇する「ノイズの多い障害状況」を再現したものです。

調査の結果

所要時間は、5分50秒でした(段階 1:5分28秒、段階 2:8分45秒)。

最終的に出力された RCA は、次の通りです。

DynamoDB テーブル devops-agent-experiment-users のプロビジョニング読み取りキャパシティが 1 RCU と極端に低く設定されており、Lambda 関数からのトラフィック増加(1000回/分)に対応できない。
実際の消費 RCU は 725〜777 に達し、プロビジョニング値の 700〜777 倍を超過している。その結果、ReadThrottleEvents が 996 件発生し、Lambda 関数が 794 件の ProvisionedThroughputExceededException を受け取っている。Lambda 関数は ConsistentRead=True を使用しているため、RCU 消費が2倍になり、問題をさらに悪化させている。

観察ポイント

観察軸 結果
真の原因(DynamoDB throttling)を特定したか 正しく特定
無関係なアラームへの言及 なし(完全に無視)
ノイズ Lambda への言及 なし(完全に無視)
Lambda 環境変数の更新への言及 なし(完全に無視)
RCA 完了までの所要時間 5m50s(段階1 +22秒)

3つのノイズは、いずれも Journal に一度も登場しませんでした。
エージェントは devops-agent-experiment-lambda-errors アラームの調査に集中していて、同一アカウント内の別リソースや、無関係なアラームを、調査対象として拾うことはありませんでした。

段階3の考察

ノイズに惑わされなかった理由を考えてみます。

エージェントが今回のノイズを無視できたのは、調査がアラーム(devops-agent-experiment-lambda-errors)を起点に、原因を辿る形で進んだからだと思います。
無関係なアラームや別の Lambda は、この筋から外れているので、自然と調査対象に入りませんでした。

ただし、これは1回の観察からの推測です。今回のロールは ReadOnly で広く、ノイズのリソースにもアクセス自体はできたはずなので、弾いたのは権限ではなく「関連性」だった、と考えるのが自然です。
そして、これはあくまで「無関係なノイズに強い」というだけです。真因に近い紛らわしい情報(真因と同じ Lambda のコード変更など)には、段階 2 で ConsistentRead を一度疑ったように深掘りで引っぱられることがあり、万能のノイズ耐性ではないということがわかります。

なお別の軸の機能として、そもそも調査するインシデント自体を絞り込む使い方もあります。
Incident Triage 型のスキルに条件を書くと、調査不要なインシデント(例:メンテナンス中の低優先度アラーム)を自動でスキップすることができます。

参考: DevOps Agent Skills 仕様 — Incident filtering skill

Skills targeted to the Incident Triage agent type can define criteria for automatically skipping incidents. Use this to filter incidents that don't require investigation. When a new incident matches the skip criteria, AWS DevOps Agent marks it as Skipped.

(Incident Triage 型のスキルは、調査不要なインシデントを自動でスキップする条件を定義できる。条件に合うと Skipped とマークされる)


実運用で役立ちそうなところ

Agent Journal の価値

検証で良いと感じたのは、Journal の事後レビューのしやすさです。エージェントが何を根拠にどの結論を出したのかが、時刻付きで残るので、後から「なぜそう判断したか」を追えます。
Operator App で見たかぎり、Journal の各ステップ(調査の1手ごとの記録)には編集・削除の導線が無く、読み取り専用で提供されていました。

また、根本原因の分析結果(RCA)は、Markdown ファイルとしてダウンロードできます。
影響・根本原因・主な検出結果・仮説・調査ギャップが整理されていて、読みやすい内容でした。

緩和計画の提案

根本原因のあとには、緩和計画も提案してくれます。
今回出てきたのは、準備 → 事前検証 → 適用 → 事後検証 → ロールバック の5ステップに分かれた手順で、それぞれに実行コマンド(AWS CLI)まで添えられていました。
結論だけでなく、適用前の確認や、うまくいかなかったときの切り戻しまで含まれているのが実用的だと感じました。

実コスト

DevOps Agent の料金は、$0.0083/agent-second です(調査・評価・オンデマンドタスク、すべて統一料金)。アイドル時・待機時には課金されません。

参考:AWS DevOps Agent 料金ページ

今回の検証3回分の理論コストは、以下の通りです。

調査時間 理論コスト
段階1(Skill なし) 5分28秒(328秒) $2.72
段階2(Skill あり) 8分45秒(525秒) $4.36
段階3(Skill あり + ノイズ) 5分50秒(350秒) $2.91
合計 1,203秒 $9.99

調査時間 = コストなので、「どこまで深掘りしたか・何を見つけたか」に連動する、という感じですね。
なお、DevOps Agent の実費は、トライアル枠内だったため $0 でした(表は従量料金から計算した理論値です)。


CloudWatch アラームから Slack への自動通知

「CloudWatch アラームが発火したら自動で調査が始まり、結果が Slack に届く」という自動化フローも試してみました。

アーキテクチャ

設定の概要

設定するものは2つです。アラームで調査を自動起動する Webhook と、結果を Slack に通知するコミュニケーション連携です。

① アラームで調査を自動起動する(Webhook)

  1. DevOps Agent コンソールで Generic Webhook を作成し、URL と Secret Key を取得します
  2. Lambda 関数を作成します。EventBridge からアラーム情報を受け取り、HMAC-SHA256 署名を付けて Webhook URL に POST します
  3. EventBridge ルールを作成します。CloudWatch Alarm State Change → ALARM をトリガーに、Lambda を起動します

DevOps Agent には Webhook 機能があり、署名付きの HTTP POST を受け取ると、自動で調査を開始してくれます。
認証は2種類あり、API Key(Splunk / Datadog / New Relic / ServiceNow などネイティブ対応)と HMAC(Generic)です。今回は Lambda から投げるので、HMAC(Generic)を選びました。

シークレットキーは、この画面から離れてしまうと確認できなくなります。値をコピーするか、CSV ファイルをダウンロードして保管しておいてください。

署名の形式(ヘッダ名やペイロードの組み立て)は地味にハマりどころですが、AWS が CloudWatch 連携の公式サンプルを出しているので参考にできます。

参考: AWS DevOps Agent CloudWatch WebHook Tutorial

② 結果を Slack に通知する(コミュニケーション連携)

調査の結果を Slack に流すには、DevOps Agent の「コミュニケーション」設定から Slack 連携を追加します。追加すると、統合一覧に Slack が並びます。

実際に届いたもの

CloudWatch アラームが発火してから数分後、Slack にこのメッセージが届きました。

[Symptom] Lambda 関数 devops-agent-experiment-get-user のエラー率が 37.5% に急上昇

[Observation] ProvisionedThroughputExceededException が大量発生
  Lambda 関数の DynamoDB GetItem 操作(ConsistentRead=True)で発生している。
  テーブルの設定済みプロビジョニングスループットレベルを超過したと明記されています。

[Finding] Lambda 関数コードで ConsistentRead=True を使用し、DynamoDB RCU消費が2倍に

[Finding] DynamoDB テーブルのプロビジョニング読み取りキャパシティが 1 RCU で完全に不足

→ Investigation complete

...
...

Root causes (1)
DynamoDB テーブルのプロビジョニング読み取りキャパシティが 1 RCU で完全に不足

コンソールを開くことなく、アラームの発火から RCA の投稿まで自動で完結しました。


まとめ

① エージェントの動きは Agent Journal で後から追える

「LLM が裏で何をやっているか分からないまま、結論だけ出てくる」のではなく、
推論のステップ、参照した Skill、判断が全部 Journal に残っていて、後から辿ることができますし、それを見て人間側がきちんと判断することができます。

② Custom Skills はきちんと効く。ただし速くなるわけではない

description の書き方と Step の具体性を変えるだけで、エージェントが叩く API の順番まで実際に変わりました。
ただ、効いたのは「速さ」ではなく「どこを見るか、何を優先するか」のほうです。むしろ深掘りが増えて時間は伸びました。
チームに溜まっている障害対応のノウハウ・コツなどを Markdown で書いておけば、それをそのままエージェントに引き継げるので、活用できそうだなと思っています。

③ ノイズの中でも真因を当てた。ただし無条件ではない

無関係なアラームや別 Lambda のエラーなど、3つのノイズを混ぜても、エージェントは真因(DynamoDB の throttling)をきちんと特定して、ノイズには一度も触れませんでした。
ただこれは、調査の起点が特定のアラームに定まっていて、登録した Application(調査対象)の範囲が境界として効いた結果です。
エージェントが「ここだけ見ればいい」と焦点を絞れたから、であって、紛らわしい信号を見分ける力が特別に高いから、ではありません。 実際、今回のロールは ReadOnlyAccess で、ノイズ側のリソースも読もうと思えば読める状態でした。権限がノイズを弾いたわけではない、という点は補足しておきます。
範囲の中に紛らわしいノイズが混ざっていれば、段階2で深掘りに引っぱられた状況と同じになる可能性は十分あります。

この先、試してみたいこと

実際に動かしてみて「次はこうしてみたい」と思った点を、いくつか残しておきます。

1. Slack / Webhook 通知のペイロードを盛ってみる

今回の Webhook Lambda は、必須項目(アラーム名と状態)だけを送る最小構成にしていました。
それでも RCA はちゃんと真因を当ててくれたのですが、Webhook のスキーマには descriptiondata(元イベントのペイロード)といった任意項目も用意されていて、今回はそこを空のままにしていました。

ここに、発火した瞬間のメトリクスや直前のデプロイ情報などを詰めて渡したら、エージェントは最初からもっと手がかりを持って調査を始められるんじゃないか?と思っています。
RCA の中身や所要時間も変わってきそうですし、特にギャップのような「外部の情報がないと埋まらない穴」は、先にペイロードで渡しておけば縮められるかもしれません。
ペイロードを少しずつ盛って(必須のみ、メトリクス付き、デプロイ関連情報など)、同じ障害で RCA の中身・時間・調査ギャップの出方がどう変わるかを並べて見てみたいです。

2. MCP サーバーでコード差分を繋いで、ギャップを埋める

段階1でエージェントは、自分から「コードリポジトリにアクセスできないので、Lambda のコード差分までは見られない」と調査ギャップを申告してきました。
ここは MCP サーバー経由でデプロイ履歴や GitHub を繋いでしまえば埋められるはずで、そうすれば「04:54:46 のデプロイで ConsistentRead が変わったのか」を、推論ではなく事実として確定できます。
RCA の正確さが上がりそうなので、実際に MCP を繋いだ状態で同じ障害を起こして、ギャップが消えるか、根拠の書きぶりがどう変わるかを見てみたいです。

3. Custom Skills を溜めていったら、挙動はどうなるか

今回は、1つ Skill を書いただけでも、エージェントの調査の焦点が実際に変わりました。
だとすると、過去の障害パターンを Skill としてコツコツ溜めていけば、いろんな障害で RCA の精度が上がったりするんじゃないか、と考えています。
いくつかの障害シナリオに対応する Skill をひと通り用意して、Skill あり/なしで所要時間や特定できた根本原因の数を比べてみたいです。
ただ、今回みたいに各シナリオ1回ずつだとブレが大きいので、今度はもう少し複数回して、ならした値で見た方が良さそうです。

4. 自動修復まで繋げてみる

今回は RCA が出たところで止めて、修復などの作業は実施していません。
RCA のあとの対応(たとえば DynamoDB をオンデマンドモードに変える、とか)まで自動で流せれば、検知から復旧までひと続きで回せます。
とはいえ、いきなり全部おまかせにするのはさすがに怖いので、まずは人間の承認を1枚挟む半自動(RCA と推奨対応を出して、人が承認して、実行する)から始めて、どこまでなら人を抜いてよさそうかの線引きを探るなどをしてみたいです。

5. Slack から話しかけられるようにしたい

今回試した範囲だと、DevOps Agent の Slack 連携は、エージェントから Slack へ知らせてくる一方向だけでした。
これが、Slack に届いた CloudWatch アラームのスレッドから「これ調べて」と投げて、調査を起動したり対話したりできるようになると、楽になりそうだなと思っています。
(ただ、現時点では、そもそも双方向のやり取りに対応できるのかどうかも、まだ分かっていません)


ユニファでは一緒に働く仲間を募集しています!
ぜひ以下のリンクからカジュアル面談のご応募お待ちしています。

jobs.unifa-e.com