こんにちは、クラウド事業部の山路です。
今回は2025年7月14日にプレビュー版がリリースされたKiroを使ってみました。KiroはAWSの開発したAI IDEなので、ここではAWSリソースの要件定義からCloudFormationファイルの生成までを試しました。
なお、私はこれまでCursorなどのAI IDEやClaude Codeなどは触ったことがなく、普段はGeminiやChatGPTといった対話型AIのチャット機能を使っています。今回は使ってみた使用感や感想をメインに紹介しますが、このあたりを前提に読んでいただければ幸いです。
Kiroとは
Kiroはトップページで The AI IDE for prototype to production
と掲げており、AIによる開発コードをプロトタイプで終わらせず本番運用にも耐えるものにすることを支援します。
Kiroは Spec-driven development (仕様駆動開発)
を特徴としており、利用者は Spec
という機能を利用することで最初に要件やタスクリストを生成し、それに沿ってコード生成などのタスクを実行できます。これにより利用者はアプリケーションの機能の検討などを通じて、開発物の仕様を十分に検討・精査することができます。またAIにタスクを依頼する際にも、求める仕様を詳細に記載したドキュメントを渡すことで、利用者の意図を伝えやすく、よりよい成果物が出来上がりやすくなることが期待できます。
またKiroには Hook
という機能も備わっています。これはKiro上で特定のイベントが発生したときに、事前に定義したアクションを自動的に実行する機能です。例えば開発者がコードをコミットする前にテストコードやREADMEを更新したり、コミットするファイル上に秘匿情報が含まれないかをチェックする、といったアクションが可能となります。これにより定型的な作業をもれなく実行し、コードの安全性や一貫性を担保できます。
Kiroには大きく以下のような機能が備わっています。
- VSCode-likeなIDE: 利用者も多いVSCodeライクな操作画面を提供します。VSCode拡張のインポートも可能です。
- Spec: 利用者がChat欄から入力したプロンプトをもとに、要件の分解や設計ドキュメントの作成、タスクリストの生成などを行います。既存プロジェクトの要件をインポートしたい場合は手動でのインポートのほか、MCPとの統合も利用できます。
- Vibe-coding: Kiroは
Go from vibe coding to viable code
を目指す製品ですが、従来のVibe-codingにも対応しています。 - Hooks: Kiro上の特定のイベントに応答し、事前定義したアクションを実行する機能です。
- Steering: プロジェクトの目的や技術的制約といった情報をMarkdown形式のファイルに記述し、Kiroに前提となる知識を与えます。
Kiroを使ってCloudFormationファイルを用意する
ここから実際にKiroを使う様子を紹介します。今回はKiroの目玉機能である Spec
を利用し、要件定義からAWSリソースの設計、CloudFormationファイルの生成までを実施しました。作成後は手動でデプロイし動作確認を行います。
Kiroのインストール
※2025/7/18追記: 現時点ではWaitlistになっており、すぐにインストールはできなくなっております。
Kiroのインストール方法は公式ドキュメントに従って行います。なお今回はWindows端末を使いましたが、MacOS / Linuxもサポートしています。
手順は簡単ですので該当箇所を折りたたんでおきます。興味のある方は以下をクリックして展開してください。
Kiroインストール方法
Kiroのトップページからインストーラーをダウンロードします。インストーラーをダブルクリックするとセットアップ画面が表示され、最終的に以下のような画面が表示されれば完了です。
Kiroを開くと、最初に任意のプロバイダーでログインすることを求められます。今回はGitHubを選択しました。
GitHubの場合は以下のような画面が表示されるので、 Authorize kirodotdev
を選択しログインを完了します。
VSCode拡張機能をインポートするか質問されます。今回はスキップしました。
テーマの選択やShellのセットアップを行って完了です。
インストールから初期セットアップを完了すると、以下のような状態になります。
ここでは Open a project
を選択して任意のフォルダ (kiro_test_project
) を用意します。
Specによる要件書の作成
ここからKiro上での実際の操作を行います。
まずは上記画面から Spec
モードを選択し、Kiroへの命令文を入力します。なお今回使用するモデルは Claude Sonnet 4.0
、Autopilotはオフにしています。
※Kiroは現状2つのモデル (Claude Sonnet 4.0
Claude Sonnet 3.7
) を選択できます。またAutopilotをオフにすると、Kiroが変更を加えるたびに利用者の承認を要求されます。
今回は以下のような命令文を入力し、API Gateway + Lambdaで文字列を返すだけの簡単なものを要求しました。具体的な挙動やリソース名は記載していますが、実際に構築するとなるといくつか足りないリソースもある、くらいの内容にしています。
あるURLにアクセスすると “Hello Kiro” という文字列を返すだけの機能が欲しいです。デプロイはAWS CloudFormation経由で実施するので、Amazon API GatewayとAWS Lambdaを定義するCloudFormationファイルを納品物としたいです。
上記命令文を実行するとIDEの右側にChat欄が登場し、Kiroの処理内容や進行状況、利用者への操作ボタンなどが表示されます。なお処理中や待機中はChat欄のKiroのアイコンが目線を動かしたり瞬きしてます。
Kiroは最初に requirements.md
というファイル上に要件を出力します。利用者はファイルの内容を確認し、問題なければ Move to design phase
というボタンを選択して次の工程に進みます。
修正したい場合はファイルを直接修正するかChat欄から命令します。ここではすべて日本語で書くように命令しています。
この時にできた requirements.md
はこちらです。命令文に含まれる要件を分解して受け入れ基準を設定するほか、不足する要件も追加しています。今回作りたかったものとしてはオーバースペックな気もしますが、いったんKiroに従ってみます。
requirements.md
# 要件書 ## 概要 この機能は、特定のURLにアクセスすると"Hello Kiro"という文字列を返すシンプルなAPIを提供します。インフラストラクチャはAWS CloudFormationを使用してAmazon API GatewayとAWS Lambdaで構築され、完全にサーバーレスアーキテクチャで実装されます。 ## 要件 ### 要件1 **ユーザーストーリー:** 開発者として、特定のURLにアクセスして"Hello Kiro"のレスポンスを受け取りたい。これによりAPIが正常に動作していることを確認できる。 #### 受け入れ基準 1. ユーザーがAPIエンドポイントにGETリクエストを送信した時、システムは"Hello Kiro"をプレーンテキストとして返す 2. APIが呼び出された時、システムはHTTPステータスコード200で応答する 3. APIがGET以外のHTTPメソッドを受信した時、システムは適切なエラーレスポンスを返す ### 要件2 **ユーザーストーリー:** DevOpsエンジニアとして、CloudFormationを使用してインフラストラクチャをデプロイしたい。これにより一貫性があり再現可能な方法でリソースを管理できる。 #### 受け入れ基準 1. CloudFormationテンプレートをデプロイした時、システムはAPI Gateway REST APIを作成する 2. CloudFormationテンプレートをデプロイした時、システムはLambda関数を作成する 3. CloudFormationテンプレートをデプロイした時、システムはAPI GatewayとLambda間の統合を適切に設定する 4. CloudFormationスタックがデプロイされた時、システムはAPIエンドポイントURLを出力する ### 要件3 **ユーザーストーリー:** システム管理者として、Lambda関数に適切なIAM権限を設定したい。これによりセキュリティ問題なく適切に実行できる。 #### 受け入れ基準 1. Lambda関数が作成された時、システムは適切な実行ロールを割り当てる 2. Lambda関数が実行される時、最小限必要な権限のみを持つ 3. API GatewayがLambda関数を呼び出す時、システムは適切なリソースベースポリシーを通じて呼び出しを許可する ### 要件4 **ユーザーストーリー:** 開発者として、APIをインターネットからアクセス可能にしたい。これによりどの場所からでもテストできる。 #### 受け入れ基準 1. API Gatewayがデプロイされた時、パブリックにアクセス可能である 2. APIエンドポイントにアクセスする時、認証を必要としない 3. インターネット上のどの場所からAPIが呼び出された時でも、正常に応答する
次に Move to design phase
を選択し、 design.md
に設計書を作成します。
design.md
の内容は以下の通りとなり、簡単なアーキテクチャ図やリソース、エラーハンドリングにテスト戦略、CloudFormationのテンプレート構造まで記載されています。
design.md
※記事中の表示の都合上、実際のファイル中のグレイヴ・アクセント (`) はシングルクォーテーション (') に置き換えています。
# 設計書 ## 概要 この機能は、AWS CloudFormationを使用してサーバーレスアーキテクチャでシンプルなAPIを構築します。API GatewayがHTTPリクエストを受け取り、Lambda関数を呼び出して"Hello Kiro"という文字列を返します。 ## アーキテクチャ '''mermaid graph TD A[インターネット] --> B[API Gateway] B --> C[Lambda関数] C --> D["Hello Kiro"レスポンス] D --> B B --> A E[CloudFormation] --> F[IAM実行ロール] E --> B E --> C F --> C ''' ### アーキテクチャの特徴 - **サーバーレス**: サーバー管理不要、使用量に応じた課金 - **スケーラブル**: 自動スケーリング対応 - **高可用性**: AWSマネージドサービスによる冗長化 - **セキュア**: IAMによる最小権限の原則 ## コンポーネントと インターフェース ### 1. Lambda関数 - **名前**: HelloKiroFunction - **ランタイム**: Python 3.11 - **ハンドラー**: index.lambda_handler - **メモリ**: 128MB(最小構成) - **タイムアウト**: 30秒 **インターフェース**: '''python def lambda_handler(event, context): # API Gatewayからのイベントを処理 # "Hello Kiro"を返す ''' ### 2. API Gateway - **タイプ**: REST API - **リソース**: /hello - **メソッド**: GET - **統合タイプ**: Lambda Proxy Integration - **認証**: なし(パブリックアクセス) **レスポンス形式**: '''json { "statusCode": 200, "headers": { "Content-Type": "text/plain" }, "body": "Hello Kiro" } ''' ### 3. IAM実行ロール - **名前**: HelloKiroLambdaExecutionRole - **管理ポリシー**: AWSLambdaBasicExecutionRole - **権限**: CloudWatch Logsへの書き込みのみ ## データモデル ### Lambda関数のイベント構造 '''json { "httpMethod": "GET", "path": "/hello", "headers": {}, "queryStringParameters": null, "body": null } ''' ### レスポンス構造 '''json { "statusCode": 200, "headers": { "Content-Type": "text/plain" }, "body": "Hello Kiro" } ''' ## エラーハンドリング ### Lambda関数内のエラー処理 1. **予期しないエラー**: 500 Internal Server Errorを返す 2. **不正なHTTPメソッド**: 405 Method Not Allowedを返す 3. **ログ出力**: CloudWatch Logsにエラー詳細を記録 ### API Gatewayレベルのエラー処理 1. **Lambda関数エラー**: 502 Bad Gatewayを返す 2. **タイムアウト**: 504 Gateway Timeoutを返す 3. **権限エラー**: 403 Forbiddenを返す ## テスト戦略 ### 1. 単体テスト - Lambda関数の動作確認 - 正常系: "Hello Kiro"が返されることを確認 - 異常系: エラーハンドリングの確認 ### 2. 統合テスト - API Gateway + Lambda統合の確認 - HTTPリクエスト/レスポンスの確認 - エラーレスポンスの確認 ### 3. CloudFormationテンプレートテスト - テンプレートの構文チェック - デプロイ/削除の確認 - 出力値の確認 ### 4. エンドツーエンドテスト - 実際のHTTPリクエストでの動作確認 - 異なるHTTPメソッドでのテスト - レスポンス時間の確認 ## CloudFormationテンプレート構造 ### リソース構成 1. **AWS::IAM::Role** - Lambda実行ロール 2. **AWS::Lambda::Function** - Hello Kiro Lambda関数 3. **AWS::ApiGateway::RestApi** - REST API 4. **AWS::ApiGateway::Resource** - /helloリソース 5. **AWS::ApiGateway::Method** - GETメソッド 6. **AWS::ApiGateway::Deployment** - APIデプロイメント 7. **AWS::ApiGateway::Stage** - prodステージ 8. **AWS::Lambda::Permission** - API Gatewayからの呼び出し許可 ### 出力 - **ApiEndpoint**: デプロイされたAPIのエンドポイントURL ## セキュリティ考慮事項 ### 1. IAM権限 - Lambda実行ロールは最小権限(CloudWatch Logsのみ) - API GatewayからLambdaへの呼び出し許可のみ設定 ### 2. ネットワークセキュリティ - パブリックアクセス(認証なし) - HTTPS通信(API Gatewayデフォルト) ### 3. ログとモニタリング - CloudWatch Logsでの実行ログ記録 - API Gatewayアクセスログ(オプション)
※生成されたアーキテクチャ図が問題なく表示できることも確認しました。
最後に tasks.md
に実装計画を記述します。
出来上がった tasks.md
はこちらです。
tasks.md
# 実装計画 - [ ] 1. プロジェクト構造とLambda関数の実装 - プロジェクトディレクトリ構造を作成 - "Hello Kiro"を返すPython Lambda関数を実装 - Lambda関数の単体テストを作成 - _要件: 1.1, 1.2_ - [ ] 2. CloudFormationテンプレートの基本構造作成 - CloudFormationテンプレートファイルを作成 - テンプレートのメタデータとパラメータセクションを定義 - 出力セクションでAPIエンドポイントURLを定義 - _要件: 2.1, 2.4_ - [ ] 3. IAM実行ロールの定義 - Lambda関数用のIAM実行ロールをCloudFormationで定義 - AWSLambdaBasicExecutionRole管理ポリシーをアタッチ - 最小権限の原則に従った権限設定を実装 - _要件: 3.1, 3.2_ - [ ] 4. Lambda関数リソースの定義 - CloudFormationでLambda関数リソースを定義 - Python 3.11ランタイム、適切なメモリとタイムアウト設定 - IAM実行ロールとの関連付けを設定 - インラインコードまたはZipファイル参照を実装 - _要件: 2.2, 3.1_ - [ ] 5. API Gateway REST APIの定義 - CloudFormationでAPI Gateway REST APIリソースを定義 - API名と説明を設定 - エンドポイント設定(REGIONAL)を実装 - _要件: 2.1, 4.1_ - [ ] 6. API Gatewayリソースとメソッドの定義 - /helloリソースをCloudFormationで定義 - GETメソッドを定義し、Lambda統合を設定 - Lambda Proxy Integrationを有効化 - メソッドレスポンスの設定を実装 - _要件: 1.1, 1.3, 4.2_ - [ ] 7. API Gatewayデプロイメントとステージの設定 - CloudFormationでAPI Gatewayデプロイメントリソースを定義 - prodステージを作成し、適切な設定を実装 - ステージ変数やログ設定を構成 - _要件: 2.1, 4.1_ - [ ] 8. Lambda呼び出し許可の設定 - API GatewayからLambda関数への呼び出し許可を定義 - AWS::Lambda::Permissionリソースを実装 - 適切なソースARNとプリンシパルを設定 - _要件: 3.3_ - [ ] 9. CloudFormationテンプレートの統合テスト - テンプレートの構文検証を実行 - 依存関係とリソース参照の確認 - 出力値の正確性を検証 - _要件: 2.1, 2.2, 2.3, 2.4_ - [ ] 10. エラーハンドリングの実装 - Lambda関数に適切なエラーハンドリングを追加 - 不正なHTTPメソッドに対する405レスポンスを実装 - 予期しないエラーに対する500レスポンスを実装 - CloudWatch Logsへのエラーログ出力を追加 - _要件: 1.3_ - [ ] 11. デプロイメントドキュメントの作成 - CloudFormationスタックのデプロイ手順を文書化 - 必要なAWS権限とプリリクイジットを記載 - テスト方法とトラブルシューティングガイドを作成 - _要件: 2.1, 2.4, 4.3_
ここまでの内容に問題がなければ finalize task list
Accept all
を選択します。
タスクリストに従ってコードを生成する。
ここからは生成したドキュメントに従ってコードを生成します。
コードを生成するには tasks.md
にある Start task
をクリックします。クリックすると各タスクが開始され、Chat欄で進行状況などが表示されます。
タスクが完了すると Task completed
と表示されるので、次のタスクを順に実行します。
タスクによってはテストコマンドが表示され、Kiro上からコマンドの実行を指示できます。
他のタスクが完了していない状態で別のタスクを開始しようとすると、以下のようにタスクの実行は保留され、別タスクの完了とともに実行されました。
Kiroの処理内容を少し見ると、 tasks.md
や作成中のファイルを読み取り、必要ならファイルの作成や修正を行います。次にタスクリストの内容を網羅したか確認し、完了したかをチェックします。
一連のタスクを完了し、CloudFormationファイルが生成されたので手動でデプロイしました。タスク完了直後のファイルにはいくつか問題がありデプロイに失敗したので、その都度Kiroにエラー文を渡すことでテンプレートを修正します。
最終的に出来上がったのは以下のようなテンプレートです。
template.yaml
AWSTemplateFormatVersion: '2010-09-09' Description: 'Hello Kiro API - Simple serverless API that returns "Hello Kiro" message' Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "API Configuration" Parameters: - StageName - ApiName - Label: default: "Lambda Configuration" Parameters: - LambdaTimeout - LambdaMemorySize ParameterLabels: StageName: default: "API Gateway Stage Name" ApiName: default: "API Name" LambdaTimeout: default: "Lambda Function Timeout" LambdaMemorySize: default: "Lambda Function Memory Size" Parameters: StageName: Type: String Default: prod Description: The name of the API Gateway stage AllowedValues: - dev - test - prod ApiName: Type: String Default: hello-kiro-api Description: The name of the API Gateway REST API MinLength: 1 MaxLength: 128 LambdaTimeout: Type: Number Default: 30 Description: Lambda function timeout in seconds MinValue: 1 MaxValue: 900 LambdaMemorySize: Type: Number Default: 128 Description: Lambda function memory size in MB AllowedValues: - 128 - 256 - 512 - 1024 Resources: # API Gateway REST API RestApi: Type: AWS::ApiGateway::RestApi Properties: Name: !Ref ApiName Description: 'Hello Kiro API - Simple serverless API that returns "Hello Kiro" message' EndpointConfiguration: Types: - REGIONAL Policy: Version: '2012-10-17' Statement: - Effect: Allow Principal: '*' Action: 'execute-api:Invoke' Resource: '*' Tags: - Key: Project Value: HelloKiroAPI - Key: Environment Value: !Ref StageName # IAM Role for API Gateway CloudWatch Logs ApiGatewayCloudWatchRole: Type: AWS::IAM::Role Properties: RoleName: !Sub '${AWS::StackName}-apigateway-cloudwatch-role' Description: 'IAM role for API Gateway to write to CloudWatch logs' AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: apigateway.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs Tags: - Key: Project Value: HelloKiroAPI - Key: Environment Value: !Ref StageName # API Gateway Account Configuration ApiGatewayAccount: Type: AWS::ApiGateway::Account Properties: CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchRole.Arn # IAM Role for Lambda Function HelloKiroLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub '${AWS::StackName}-lambda-execution-role' Description: 'IAM role for Hello Kiro Lambda function execution' AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: CloudWatchLogsPolicy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-hello-kiro-function' - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-hello-kiro-function:*' - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/apigateway/${AWS::StackName}-${ApiName}' - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/apigateway/${AWS::StackName}-${ApiName}:*' Tags: - Key: Project Value: HelloKiroAPI - Key: Environment Value: !Ref StageName # API Gateway Resource for /hello path HelloResource: Type: AWS::ApiGateway::Resource Properties: RestApiId: !Ref RestApi ParentId: !GetAtt RestApi.RootResourceId PathPart: hello # API Gateway Method for GET /hello HelloMethod: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref RestApi ResourceId: !Ref HelloResource HttpMethod: GET AuthorizationType: NONE Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloKiroFunction.Arn}/invocations' IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: "'*'" method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'" method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" MethodResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Headers: true ResponseModels: application/json: Empty - StatusCode: 400 ResponseParameters: method.response.header.Access-Control-Allow-Origin: true ResponseModels: application/json: Error - StatusCode: 500 ResponseParameters: method.response.header.Access-Control-Allow-Origin: true ResponseModels: application/json: Error # OPTIONS method for CORS preflight requests HelloOptionsMethod: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref RestApi ResourceId: !Ref HelloResource HttpMethod: OPTIONS AuthorizationType: NONE Integration: Type: MOCK IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: "'*'" method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'" method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" ResponseTemplates: application/json: '' RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Headers: true ResponseModels: application/json: Empty # API Gateway Deployment ApiDeployment: Type: AWS::ApiGateway::Deployment DependsOn: - HelloMethod - HelloOptionsMethod Properties: RestApiId: !Ref RestApi Description: !Sub 'Deployment for ${ApiName} API' # API Gateway Stage ApiStage: Type: AWS::ApiGateway::Stage Properties: RestApiId: !Ref RestApi DeploymentId: !Ref ApiDeployment StageName: !Ref StageName Description: !Sub '${StageName} stage for ${ApiName} API' Variables: Environment: !Ref StageName Version: '1.0' MethodSettings: - ResourcePath: '/*' HttpMethod: '*' LoggingLevel: INFO DataTraceEnabled: true MetricsEnabled: true ThrottlingBurstLimit: 100 ThrottlingRateLimit: 50 AccessLogSetting: DestinationArn: !GetAtt ApiGatewayLogGroup.Arn Format: '{"requestId":"$context.requestId","ip":"$context.identity.sourceIp","caller":"$context.identity.caller","user":"$context.identity.user","requestTime":"$context.requestTime","httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath","status":"$context.status","protocol":"$context.protocol","responseLength":"$context.responseLength","responseTime":"$context.responseTime","error":"$context.error.message","integrationError":"$context.integration.error"}' Tags: - Key: Project Value: HelloKiroAPI - Key: Environment Value: !Ref StageName # CloudWatch Log Group for API Gateway Access Logs ApiGatewayLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/apigateway/${AWS::StackName}-${ApiName}' RetentionInDays: 14 Tags: - Key: Project Value: HelloKiroAPI - Key: Environment Value: !Ref StageName # Lambda Function HelloKiroFunction: Type: AWS::Lambda::Function Properties: FunctionName: !Sub '${AWS::StackName}-hello-kiro-function' Runtime: python3.11 Handler: index.lambda_handler Role: !GetAtt HelloKiroLambdaExecutionRole.Arn Timeout: !Ref LambdaTimeout MemorySize: !Ref LambdaMemorySize Description: 'Lambda function that returns Hello Kiro message' Code: ZipFile: | import json import logging # Configure logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): """ Lambda function handler for Hello Kiro API Args: event: API Gateway event object context: Lambda context object Returns: dict: HTTP response with status code, headers, and body """ try: logger.info(f"Received event: {json.dumps(event)}") # Create response with Hello Kiro message response_body = { "message": "Hello Kiro" } # Create HTTP response response = { "statusCode": 200, "headers": { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET", "Access-Control-Allow-Headers": "Content-Type" }, "body": json.dumps(response_body) } logger.info(f"Returning response: {json.dumps(response)}") return response except json.JSONDecodeError as e: # Handle JSON serialization errors error_message = f"JSON serialization error: {str(e)}" logger.error(error_message) return create_error_response(400, "Bad Request", error_message) except KeyError as e: # Handle missing required fields in event error_message = f"Missing required field in event: {str(e)}" logger.error(error_message) return create_error_response(400, "Bad Request", error_message) except Exception as e: # Handle all other unexpected errors error_message = f"Internal server error: {str(e)}" logger.error(error_message, exc_info=True) return create_error_response(500, "Internal Server Error", "An unexpected error occurred") def create_error_response(status_code, error_type, error_message): """ Create standardized error response Args: status_code (int): HTTP status code error_type (str): Type of error error_message (str): Error message for logging Returns: dict: HTTP error response """ try: error_body = { "error": error_type, "statusCode": status_code } response = { "statusCode": status_code, "headers": { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET", "Access-Control-Allow-Headers": "Content-Type" }, "body": json.dumps(error_body) } logger.error(f"Error response created: {json.dumps(response)}") return response except Exception as e: # Fallback error response if even error handling fails logger.critical(f"Failed to create error response: {str(e)}") return { "statusCode": 500, "headers": { "Content-Type": "application/json" }, "body": json.dumps({ "error": "Critical Error", "statusCode": 500 }) } # Lambda Permission for API Gateway to invoke the function LambdaInvokePermission: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref HelloKiroFunction Action: lambda:InvokeFunction Principal: apigateway.amazonaws.com SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*' Outputs: ApiEndpoint: Description: URL of the deployed API Gateway endpoint Value: !Sub 'https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/${StageName}/hello' Export: Name: !Sub '${AWS::StackName}-ApiEndpoint' LambdaFunctionArn: Description: ARN of the Lambda function Value: !GetAtt HelloKiroFunction.Arn Export: Name: !Sub '${AWS::StackName}-LambdaFunctionArn' RestApiId: Description: ID of the REST API Value: !Ref RestApi Export: Name: !Sub '${AWS::StackName}-RestApiId' StackName: Description: Name of the CloudFormation stack Value: !Ref 'AWS::StackName' LambdaExecutionRoleArn: Description: ARN of the Lambda execution IAM role Value: !GetAtt HelloKiroLambdaExecutionRole.Arn Export: Name: !Sub '${AWS::StackName}-LambdaExecutionRoleArn'
上記テンプレートをデプロイしたところ、問題なくデプロイが完了し、出力された ApiEndpoint
にアクセスすると Hello Kiro
の文字列が表示されるのを確認できました。
使ってみて気になった点
KiroのSpecを使った操作の大まかな流れは上記の通りですが、使ってみて気になった点をいくつか紹介します。ただし現状はプレビュー版なので、今後改善される可能性は十分あります。
Retryがたびたび発生する
Kiroがタスクを処理している最中、処理が途中で中断する事態に何度か遭遇しました。Kiroからはモデルの変更と再実行を要求されますが、モデルを変更せず何度かRetryして対応しました。これは現状でKiroが提供するモデルの利用形態によるものかと思うので、正式リリース後は有料版などを利用すれば解消されるんじゃないかと思います (有料プランの予定はこちら) 。
Spec機能で仕様を定義するプロセス中にRetryを実行すると、 requirements.md
の生成から再実行されました。
タスクリスト作成以降の処理では (途中までタスクが進捗していれば) タスクの中断された箇所から再開しました。これは各タスクのプロセスの最初にファイルを読み取る工程が含まれており、その内容に沿ってタスクを開始しているからかと思われます。
テストフェーズを省略することがある
Kiroの処理中にテストコードの生成と実行を行うことが何度かありましたが、テストの再実行を繰り返したりRetryを行うと、そのステップを省略することがありました。
例えばCloudFormationファイルを修正するタスク中に aws cloudformation validate-template
コマンドで静的チェックを行おうとすることがありました。今回は私が設定するデフォルトのシェル環境にAWS CLIがインストールされていないので失敗しました。
テストが失敗すると、Kiroは様々な代案を提案します。例えばPythonのテストコードが実行できなかったときはシェル環境にあるPythonのバージョンを確認しようとしたり、あるいは別のツールを使ったテストコマンドを提案します。
ただしこういったやり取りを何度か繰り返すと、最終的にKiroがテストの処理自体をあきらめたのか (?) タスクリストのチェックを行い、タスクが完了したとみなすケースを何度か見ました。
なぜこのような挙動をとるのかはよくわかりませんが、利用するモデルへの度重なるリクエストを避けるため、だったりするのでしょうか。
さいごに
今回はAWSの提供するAI IDEのKiroを触ってみました。普段インフラをメインで扱うエンジニアの目線から見ると、Specはかなり魅力的に感じています。インフラの要件定義や設計を行うと、特に非機能要件を考えたり悩まされる場面が多くなりますが、Kiroはその辺もある程度カバーしつつコードにも反映できそうな点が良いと感じました。あとアイコンがかわいい。
まだ使い始めたばかりなので詳しい挙動などは見えていませんが、しばらく使って見ようと思います。
最後に、APCはAWS Advanced Tier Services(アドバンストティアサービスパートナー)認定を受けております。
その中で私達クラウド事業部はAWSなどのクラウド技術を活用したSI/SESのご支援をしております。
また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。