Amazon Q Developer CLIのAI Agentにdraw.ioでAWS構成図を描かせてみた

記事タイトルとURLをコピーする

さとうです。

皆さんはどのようにAWSの構成図を描きますか? VisioやCacooなど作図専用のサービスは多々ありますが、個人的にはdraw.ioが好きです。 draw.ioはXMLで構造化されているのでLLMで作図してくれるのではないかと思い、タイトルの通り試してみました。

Amazon Q Developer CLIのAI Agentについて

概要

以下のAWSのブログにあるように、先日Amazon Q Developer CLI にAIエージェントの機能が追加されました。 LLMには Claude 3.7 Sonnetを使用しています。 本記事ではこの機能のことをCLI Agentと呼ぶことにします。

Amazon Q Developer CLI での超高速な新しいエージェント型のコーディング体験 | Amazon Web Services ブログ

料金

CLI Agent自体はAmazon Q Developerに内包された機能なので、Amazon Q Developerの無料利用枠を使用するか有料のProを契約することになります。

無料利用枠とProの違いはAmazon Q Developerの利用料金から確認できるのですが、CLI Agentに関する記載は2025/04/09時点ではありませんでした。

free版のCLIの利用枠 50 回のチャット/月 に内包されているのか、別に利用枠があるのかはドキュメントからは確認できませんでした( 本機能を利用するための専用のインターフェースやオプションなどはなく q chat から従来のチャットと同じように利用するので 、おそらく前者だとは思われます)。

インストール方法

MacまたはLinuxのみに対応しているため、Windowsの場合はWSL(Ubuntu)に導入する方法が簡単です。 それぞれの導入方法は以下のブログを参考にしてください。

q chatからチャットで対話可能になればOKです。

古いバージョンでCLI Agentに対応していない場合は、 q updateでアップデートするか、最新のバージョンをインストールし直すようにしてください。

blog.serverworks.co.jp

blog.serverworks.co.jp

描かせてみた

CLI Agentを使用して実際に作図をさせてみます。 Proライセンスを使用していますが、freeでも上限に抵触しない範囲で同様に利用可能です。

実行環境

WSL上のUbuntuから実行しています。

$ cat /etc/os-release  | grep VERSION_ID
VERSION_ID="24.04"
$ q --version
q 1.7.1

描かせる構成

CloudFormation(以下、CFn)で以下のリソースを作成します。 パブリックサブネットにEC2を置くシンプルな構成です。 セキュリティグループやIAMロールがアタッチされています。

構築されるリソース

  • VPC(10.100.0.0/16)
  • Internet Gateway
  • パブリックサブネット(10.100.1.0/24)
  • ルートテーブル(パブリックサブネット用)
  • セキュリティグループ(public-sv-securitygroup)
  • IAMロール(EC2SSMProfile)
  • キーペア(public-sv-keypair)
  • EC2(public-sv)

CFn

AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  VpcCidrBlock:
    Type: 'String'
    Default: '10.100.0.0/16'

  PublicSubnetCidrBlock:
    Type: 'String'
    Default: '10.100.1.0/24'

  KeyPairName:
    Type: String
    Default: 'public-sv-keypair'

  AmazonLinux2AMI:
    Type: AWS::EC2::Image::Id
    Default: 'ami-0adbac418540bb63d'

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidrBlock
      InstanceTenancy: default
      EnableDnsSupport: true
      EnableDnsHostnames: true

  InternetGateway:
    Type: 'AWS::EC2::InternetGateway'

  InternetGatewayAttachment:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PublicSubnetCidrBlock
      MapPublicIpOnLaunch: 'true'
      VpcId: !Ref VPC
  
  PublicRouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPC

  PublicRoute:
    Type: 'AWS::EC2::Route'
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  SecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupName: public-sv-securitygroup
      GroupDescription: Security group for public-sv
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
          Description: SSH access from AnyWhere
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
          Description: no limit access to anywhere

  IAMRoleForEC2:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: EC2SSMProfile
      Description: Role to use SSM on EC2
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Tags:
        - Key: Name
          Value: EC2SSMProfile
            
  InstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Path: "/"
      Roles:
        - !Ref IAMRoleForEC2

  KeyPair:
    Type: "AWS::EC2::KeyPair"
    Properties:
      KeyName:
        Ref: KeyPairName
      KeyType: rsa
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete

  PublicSV:
    Type: 'AWS::EC2::Instance'
    Properties:
      InstanceType: t3.nano
      SubnetId: !Ref PublicSubnet
      BlockDeviceMappings:
        - DeviceName: '/dev/xvda'
          Ebs:
            VolumeType: 'gp3'
            VolumeSize: 8
      ImageId: !Ref AmazonLinux2AMI
      KeyName: !Ref KeyPair
      SecurityGroupIds:
        - !Ref SecurityGroup
      Tags:
        - Key: Name
          Value: public-sv
      IamInstanceProfile:
        !Ref InstanceProfile

シンプルな命令で作らせてみた

プロンプト

そのままCFnを読ませてもいいのですが、手動構築も想定してAWS CLIでデプロイ後の構成を読み取ってもらいます。 念のため、ReadOnlyAccessを付与したプロファイルを使うように指定しています。 プロンプトはあまり考えず最低限のものです。

VPC"<VPC ID>"の内部にあるリソースをdraw.ioで構成図にしてください。
プロファイル"<プロファイル名>"を使ってAWSの構成情報を読み取ってください。

アウトプット

出てきた構成図をdraw.ioで読み込ませたものがこちらです。

このまま使うのは厳しいですね。プロンプトの重要性を実感します。

漂う「コレジャナイ」感

課題

作図の作法は人それぞれですが、多くの方は以下のような部分が気になるのではないでしょうか。

  • アイコン・境界線と文字が重ねっている
  • 使用しているアイコンが古い
  • IAM Roleが表現されていない
  • アイコン下部の文字列の記載粒度にばらつきがある
  • 余白が少ない

命令を具体化してリトライしてみた

プロンプト

違和感をなるべく言語化して具体的な指示にしてみました。

矢印は不使用としています。

以下の条件で、VPC"<VPC ID>"の内部にあるリソースをdraw.ioで構成図にしてください。
・プロファイル"<プロファイル名>"を使ってAWSの構成情報を読み取ってください。
・アイコンはdraw.ioの"AWS 2025"を利用してください。
・境界線やアイコンに文字を重ねないでください。余白を作り、視認性を上げることに努めてください。
・ルートテーブルの表現は不要です。
・アイコンのサイズは48×48で統一してください。
・矢印は使用しないでください。
・アイコン以下の説明分は以下に統一してください。
    1. サービス名
    2. リソース名(IDは記載しないこと)
・境界線は以下の通り表現してください。
    1. AWS Cloud
    2. Region
    3. VPC ※末尾に()でCIDRを記入
    4. Availability Zone
    5. Subnet ※末尾に()でCIDRを記入
    6. Security Group
・拡張性を考慮して、境界線の余白は多めにしてください。
・視認性をよくしたいのでアイコン同士はなるべく近くに配置してください。
・Internet Gatewayのアイコンについては、VPCの境界線の境目に設置してください。
・IAM Roleはグローバルリソースなので、AWS Cloudの境界線下に記載し、EC2のインスタンスプロファイルでIAM Roleが関連付けられていることがわかるように記載してください。

アウトプット

かなり改善しましたね!ぱっと見で視認できるレベルになりました。

リソースの概念をざっと説明するには必要十分な構成図なので、ドラフト版の図を作成するには重宝します。

プロンプトで期待値を明示することは必要になりますが、視認性に関する汎用的な命令が殆どなのでテンプレート化も容易だと思います。

IAM Roleの置き場所が歯がゆい

もう少し複雑な構成だとどうなるのか?

より実践的なユースケースでも実用に耐えうるのか検証します。

CFnの記載は省略しますが、以下のようなネスト構造でALB、EC2、Auroraを構築しつつCloudTrailやConfigなどの管理系サービスも構築しています。

.
├── 01_network
│   ├── sg.yml
│   ├── vpc.yml
├── 02_log
│   ├── cloudtrail_and_config.yml
├── 03_computing
│   ├── alb.yml
│   ├── aurora_mysql.yml
│   ├── ec2_bastion.yml
│   ├── ec2_web.yml
│   ├── keypair.yml
├── main.yml

人力で構成図を作成すると以下のような構成になります。

プロンプト

./main.ymlはネストされたCloudFormationスタックです。
ネストされたスタック全体の内容を読み取り、以下の条件で構築されるリソースをdraw.ioで構成図にしてください。
./aws_architecture.drawioとしてファイルにエクスポートしてください。
・アイコンはdraw.ioの"AWS 2025"を利用してください。
・境界線やアイコンに文字を重ねないでください。余白を作り、視認性を上げることに努めてください。
・ルートテーブルの表現は不要です。
・アイコンのサイズは48×48で統一してください。
・矢印は使用しないでください。
・アイコン以下の説明分は以下に統一してください。
    1. サービス名
    2. リソース名(IDは記載しないこと)
・境界線は以下の通り表現してください。
    1. AWS Cloud
    2. Region
    3. VPC ※末尾に()でCIDRを記入
    4. Availability Zone
    5. Subnet ※末尾に()でCIDRを記入
    6. Security Group
・拡張性を考慮して、境界線の余白は多めにしてください。
・視認性をよくしたいのでアイコン同士はなるべく近くに配置してください。
・Internet Gatewayのアイコンについては、VPCの境界線の境目に設置してください。

アウトプット(失敗)

が、こちらはうまくいきませんでした。タイムアウトが発生しています。

CFnの各コードの読み取りは滞りなく進みますが、 構成図を出力する段階でタイムアウトしてしまうようです。 エージェントも検知後に自律的にタスクを細分化する試みは見られますが結果的に成功していません。

それでは、draw.ioで構成図を作成します。
...(中略)...
すみません、タイムアウトしてしまいました。より小さなステップに分けて作業を進めましょう。
まず、CloudFormationテンプレートから構築されるAWSリソースを特定し、その後draw.ioの構成図を作成します。
...(中略)...
Fake message - actual message took too long to generate

プロンプトを変えてリトライ

作業を細分化するため、VPCだけを読み取るように先ほどのプロンプトに以下の条件を加えてみます。

単体のファイルだとうまくいくようです。

ただし、./01_netowork/vpc.ymlのみを構成図の作成対象としてください。
ファイル名は./vpc_structure.drawioとしてください。

プロンプトで明示的に描き方を指定していない要素は違和感が出る印象

その後、さらに上記で作成された構成図をベースにEC2を書き足すように命令してみます。

./vpc_structure.drawioに以下のスタックの情報を書き足して構成図にしてください。
書き足した後の構成図は./vpc_structure_with_computing.drawioとしてファイルに出力してください。
・./03_computing/ec2_bastion.yml
・./03_computing/ec2_web.yml
作図条件は./vpc_structure.drawioと同一です。

「このまま細分化すればうまくいくか…?」と思っていましたが、こちらは先ほどと同じように何回かタイムアウトを繰り返した末に失敗してしまいました。 単に命令を細分化すれば成功するわけでもないようです。

まず、追加で必要なファイルを確認して、EC2インスタンスの情報を構成図に追加します。
...(中略)...
I apologize for the delay. Let's break this down into smaller steps:

1. First, let me understand the EC2 instances we need to add to the diagram
2. Then create the updated diagram with those instances

I apologize for the delay. Let me break this down into smaller steps:

1. First, let me understand what EC2 instances need to be added to the diagram
2. Then I'll create an updated diagram with those instances

From the files I've reviewed:
• We need to add a bastion host (ec2-prd-bastion) in the Public Subnet A with IP 10.0.11.4
• We need to add two web servers:
  • ec2-prd-web-01 in Protected Subnet A with IP 10.0.12.4
  • ec2-prd-web-02 in Protected Subnet C with IP 10.0.22.4
...(中略)...
Fake message - actual message took too long to generate

(考察)CLI Agentには出力トークンに制限があるかもしれない

Amazon Q Developer CLIはオープンソースになっており、今回の検証と同様のエラーが報告されていることは確認できます。 ただし、これ自体はエラーの根本原因を説明するものではありません。

(今回検証したバージョンは 1.7.1 ですが、以下によると最新バージョンだとエラー文言が変わっているかもしれません)

"Fake message - actual message took too long to generate" returned after sending prompt · Issue #817 · aws/amazon-q-developer-cli · GitHub

ドキュメントから明示的な仕様の記載を見つけられなかったため検証ベースの推測となりますが、アウトプットが肥大化していった結果としてLLMの出力トークンの制限値に抵触していることが原因ではないかと考えられました。

たとえば以下のように意図的に出力トークンを浪費させる命令をすると事象が再現することから、入力ではなく出力でタイムアウトになっていることが推定されるためです。

> 20,000文字の"あ"を標準出力するPythonスクリプトを作ってみてください。ただし、"あ"は全てスクリプト内にハードコーディングしてください。つまり、演算子などを使わずに20,000文字の"あ"が含まれたスクリプトを作成する必要があります。
スクリプトは./a.pyとして保存してください。

20,000文字の"あ"をハードコーディングしたPythonスクリプトを作成します。

20,000文字の"あ"をハードコーディングしたPythonスクリプトを作成します。まずは小さく始めて、段階的に構築していきましょう。

Fake message - actual message took too long to generate

ちなみに先ほど生成されたVPCのみの構成図は122行で13,308字と結構なボリュームがあります。 参考程度にOpenAI's tokenizer websiteでトークンを見積もると4,791トークンでした。 閾値を探る検証は割愛しますが、このあたりに天井があるのかもしれません。

まとめ

ほとんどプロンプト紹介記事のようになってしまいましたが、CLI Agentを利用して作図をしてみた所感は以下のようなものでした。

  • プロンプトで条件を詳細に指定すれば期待値の80%くらいの作図は期待できそう
  • Q Developerの仕様として出力トークンの制限が行われている可能性がある(検証ベースの推測)

仮に出力トークンの制限が行われていることが正だとすると、本記事のようなユースケースではCline + Bedrockなどの構成でクォータを自分で調整できるLLMを用意した方がよいかもしれません。無料ないし定額のサービスなので致し方なしではありますが。

佐藤 航太郎(執筆記事の一覧)

エンタープライズクラウド部 クラウドモダナイズ課
2025年1月入社で何でも試したがりの雑食系です。