
こんにちは!ニーリーで SRE をしています 高 (@nogtk) です。 ニーリーでも LLM を活用した業務や開発効率の改善が日々あちこちで行われているのですが、そんな事例の1つをご紹介できればと思います。
この記事は ニーリーアドベントカレンダー 12日目です 🎉
バッチの定義方法について
ニーリーでは、スケジュール実行されるバッチ処理の実行基盤として Step Functions を利用し、Step Functions から ECS タスクを呼び出す形を取っています。 そしてその sfn や ECS タスクは Terraform でコード化(IaC)されており、SRE チームによってそれらの具体を隠蔽する Terraform module を提供しています。
バッチを追加したい開発者は、その Terraform module を利用するように PR を出し、マージすることで各バッチを追加しています。
module の利用イメージ
module "batch_sample_task" { source = "../../../modules/eventbridge/scheduled_task" # Rule rule_name = "cron-sample-task" description = "バッチの内容について説明" schedule_expression = "cron(0 0 1 * ? *)" # 毎月初 9:00(JST) is_enabled = true # Target eventbridge_role_name = "RoleName" sfn_state_machine_arn = module.step_functions_for_batch.sfn_state_machine_arn command = "python <some command>" batch_job_name = "job_name" }
module 化されていることもあり、このバッチを追加する修正内容についてはかなり定型化されています。 よって、この定型作業をワークフローとして明示的に言語化してあげることで、バッチ追加作業を AI エージェントに依頼できるようになるのではと考え、手を動かしてみることにしました。
ワークフローの定義について
今回は GitHub Copilot のカスタムエージェントを使う前提で話をしますが、他のコーディングエージェントでも同じように進めることができるでしょう。
まずは簡単に Copilot のカスタムエージェントについて概要をお話しします。
リポジトリルートに .github/agents/<agent_name>.agent.md というファイルを配置することで、そのマークダウンファイルに沿ったアクションを行うカスタムエージェントを定義することができます。ファイルそのものを LLM や手動で作る場合、必ず .agent.md という拡張子にしておく必要があるので、そこだけやや注意です。
VS Code のコマンドからも作成することができ、その場合は自動でこのファイルの命名規則で作成してくれるので、ガワだけでもこちらを使った方が便利かなと思いました。(自分はこの仕様を見落としていて、人生の貴重な数十分を溶かすことに😇)
公式ドキュメントのリンクはこちらです。 docs.github.com
さて、ワークフローファイル自体の定義についてですが、こちらも当然 LLM の力を借りて記述していきます。 以下のようなプロンプトで依頼します。
Copilot のカスタムエージェントを使って、PR作成まで LLM に移譲させられるようにしたい。 具体的には backend_scheduled_ecs_tasks.tf というファイルが、各環境に対応したディレクトリに配置されている。 何かバッチ処理を追加したい開発者は、ここに対象のコードを追加するPRを出している。 これが定型業務となっているので、カスタムエージェントベースでワークフローを組んで、効率化したい。 以下が、各環境向けのPRの参考例です。 - dev: <github link> - stg: <github link> - prod: <github link> 入力として必要なパラメータは以下あたりかなと思っていますが、PRを読みながら必要なパラメータがあれば追加してください。 - バッチ名 - バッチ詳細 - スケジュール - 実行コマンド これらの情報から、Copilot が自律してPRを出すまでをワークフローとして定義するカスタムコマンドを追加して欲しいです。
サンプルとして、各環境の PR を渡しつつ、必要な入力パラメータも探索・定義してもらうようにします。 さらにこの実行は VS Code の Plan モードを使うことで、インタラクティブに仕様を定義できるようにします。
VS Code の11月のアップデートで、Plan モードが利用できるようになりました。Cursor などではお馴染みのやつですね。
実際の Plan 結果を適宜抜粋したものを紹介します。
Plan: ECSバッチ追加カスタムコマンドの実装 Copilotカスタムエージェントで、backend_scheduled_ecs_tasks.tfへのバッチ追加からPR作成までを自動化するエージェントファイル(.github/agents/add_batch.agent.md)を作成します。3環境(dev/stg/prod)への展開と、環境ごとのPR情報生成を含みます。 Steps 1. .... (割愛) Further Considerations 1. 環境ごとの個別PR vs 一括PR: 参考PRでは環境ごとに別PRでしたが、一括で3環境まとめるオプションも有用か? → 現状の運用に合わせて環境別PRを推奨 2. バッチ番号の連番管理: 3環境で番号が異なる場合があり得るが、新規追加時は最大番号+1で揃えるルールにするか、各環境で独立管理するか? → 独立管理(各環境のmax+1)を推奨
Further Considerations として、ここの仕様はどうする?という曖昧なポイントを聞き出してくれるので、何度かラリーを繰り返して実際にワークフローファイルを作成させます。
次に、生成してもらったワークフローを見ながら適宜修正をしていきます。Plan モードで仕様を固めたつもりでも、改めてワークフローとして定義したものを見ると、修正したいところがいくつも出てくるのが面白いところです。
一例ですが、最初 LLM が生成したワークフローでは、入力パラメータとして13個を要求する仕様となっていました。13個も入力するなら自分で Terraform コード書くわ.. となるのが容易に想像できます。例えばバッチ名は、バッチを実行するコマンドから推測して定義することができるので、このようにあるパラメータに従属して決定されるものは、パラメータから除外することで入力値を削減していきます。
というようなチューニングを何回か実施しました。
最終的なワークフローファイルについて
--- name: add-batch description: Backend API の定期実行バッチを追加し、DEV/STG/PROD の 3 つの PR を自動作成 --- # Add Backend Scheduled Batch Copilot、あなたは park-direct-terraform リポジトリで Backend API の定期実行バッチを追加し、DEV/STG/PROD の 3 つの PR を連続で作るエージェントです。以下の指示に必ず従ってください。 ## 0. 事前ルール - 作業対象ブランチ: `main` から新規ブランチを作成 - ブランチ名は `feature/<ticket_id>` 形式 ... (割愛) ... ## 1. 入力パラメータ ユーザーに以下を必須で確認し、欠けていれば質問してください。 1. `ticket_id_dev`, `ticket_id_stg`, `ticket_id_prod` : 各環境用の JIRA チケット ID 2. `batch_description` : バッチの説明(日本語)。Terraform の `description` および PR の見出しに使用 3. `schedule_expression_jst` : **自然言語 & JST** での頻度(例: `毎日10時`, `毎月26日9時`, `1日おき 10時`) ... (割愛) ... ## 2. スケジュール変換 `schedule_expression_jst` を UTC cron 式と JST コメントへ変換します。 - 基本: `cron(<minute> <hour-9> <day-of-month> <month> <day-of-week> <year?>)` - 例: - `毎日10時` → `cron(0 1 * * ? *)` (`毎日10:00(JST)`) - `毎月26日9時` → `cron(0 0 26 * ? *)` - `1日おき 10時` → `cron(0 1 */2 * ? *)` - `毎週月水金 5時30分` → `cron(30 20 ? * SUN,TUE,THU *)` - JST コメントは `# <自然言語入力>(JST)` を残す - 変換に確証が持てない場合はユーザーへ確認 ## 3. コード生成手順 ... (割愛) ... ## 4. PR 作成ワークフロー 各環境で以下を順に実施(DEV → STG → PROD)。 1. `git checkout main && git pull` 2. 新規ブランチ: `feature/<ticket_id_env>-add-batch-<env>` ... (割愛) ... ## 5. 最終出力 完了後、以下を報告: - 各環境のバッチ No. と rule_name - JST スケジュール説明 - 生成した 3 つの PR URL(DEV→STG→PROD 順) - 追加の注意点や残タスク これらのステップを厳守し、利用者がバッチ追加フローを丸ごと任せられるようにしてください。
実際に呼び出してみる
Copilot とのチャット欄の選択肢として、デフォルトで存在するものに加えて、今回追加された add-batch が追加されます。

バッチを追加したい と入力すると必要な情報が求められます。

入力後、無事に完走し PR が作成されていることを確認できました! 🎉

ちなみに
追加したカスタムエージェントは、GitHub のリポジトリからも呼び出し、タスクを依頼することができるようになります。

しかし、何度試しても dev/stg/prod と環境ごとに分けて PR を作るように依頼しているにも関わらず、毎回1つのPR内で全ての環境に対する変更を行うように PR を作成するような振る舞いとなったため、現在はローカル環境から呼び出す方式を採用しています。
終わりに
今回は、バッチ追加という定型的なコード追加作業を、エージェントに依頼できるように改善してみた事例を紹介しました。
エージェントにタスクを依頼するにあたって、当該タスクがどういうものかを言語化し、ワークフローとして定義することが必要です。そのプロセスにも LLM を使い、サンプルからベースとなるワークフローを生成 -> 人間が細かいところをチューニング というサイクルを回すようにすることで、タスクの言語化・ワークフロー定義のハードルがかなり下がるように感じました。
日々の業務や開発のちょっとした開発効率改善・トイル改善にお役立てください。