Jenkins の監視ジョブを Groovy から Python SDK に移行するプロジェクトを進めています。移行自体はだいぶ進んできたのですが、残っている改善issueが5つ溜まっていて、それぞれ独立した内容だったので「これ、並列でいけるのでは?」と思いました。

ちょうど Claude Code の Agent Teams 機能が気になっていたこともあり、試してみることにしました。

正直に言うと、エージェントに投げて全部終わり――とはなりませんでした。でも、使い方の勘所みたいなものが少し見えてきたので、今の時点での記録を残しておきます。

やろうとしたこと

監視パイプラインの改善issueが5つあります。

どれも「Groovy の旧 Jenkinsfile にあった機能を Python SDK 側に正しく移植する」という共通テーマで、かつそれぞれが異なるジョブに閉じた作業です。これは並列に向いてそうだな、と。

Agent Teams の使い方

Claude Code のターミナルで、5つのissueのURLを渡して「agent teams で作業をしてください」と指示しました。

> agent teams で作業をしてください。
  [issue URL x 5]
  これらのissue にそれぞれのエージェントが対応をしてください。
  issue の内容はgithub cli で確認してください。

すると、まずリードエージェントが GitHub CLI で各issueの内容を確認し、5つのサブエージェントをスポーンしてくれました。

graph TD
    Lead[リードエージェント] --> A1[aggregate-report-agent<br/>issue: 集約レポート]
    Lead --> A2[aws-cpu-check-agent<br/>issue: CloudWatch監視]
    Lead --> A3[metabase-check-agent<br/>issue: BI連携チェック]
    Lead --> A4[sqs-check-agent<br/>issue: キュー監視]
    Lead --> A5[api-usage-check-agent<br/>issue: API利用量]

各エージェントは独立してコードベースを読み、issueの内容を理解し、実装を進めてくれます。リードエージェントが進捗をトラッキングしてくれるのも助かりました。

実装フェーズ:ここまでは順調

約10分ほどで、5つのエージェントがそれぞれ作業を完了しました。

実装内容はざっくりこんな感じです。

全体で15ファイル、+1,154行、-63行の変更。コミットも1つにまとめて、ここまでは「おお、すごいな」という感想でした。

検証フェーズ:念のため確認する

ここで一度立ち止まりました。「実装できた」と「旧ロジックが正しく再現できている」は別の話です。

もう一度 Agent Teams を使って、今度は5つの「検証エージェント」を走らせました。各エージェントに「Jenkinsfile.old のロジックが新しい実装で担保できているか確認してほしい」と指示しています。

検証結果は良好でした。コード削減率は平均87%(Jenkinsfile部分)、機能カバレッジも問題なし。ここまでの判断としては「本番移行していい」というレベルです。

ここから先が本番だった

マージして Jenkins で実行したところ、4つのジョブが同じエラーで落ちました。

ModuleNotFoundError: No module named 'pandas'

……あ、これは。

罠①:依存関係の宣言漏れ

GCP関連の分析処理で pandasseaborn を使っているのですが、setup.pyinstall_requires に入っていませんでした。ローカル開発環境には入っていたから気づかなかったパターンです。

で、もう一つ厄介だったのは、関係ないジョブまで巻き添えを食っていたこと。CLI の __init__.py が起動時にすべてのコマンドモジュールを一括インポートしていたので、キュー監視やBI連携チェックなど GCP とは無関係なジョブでも pandas が必要になっていました。

対処は2段階で進めました。

  1. setup.pypandas, seaborn, matplotlib を追加
  2. __init__.py に遅延インポート(__getattr__)を実装して、使うときだけインポートされるように変更

罠②:遅延インポートの循環参照

ところが、遅延インポートの実装でやらかしました。

# こう書いてしまった(NG)
def __getattr__(name):
    if name == "gcp_graph_helper":
        from monitoring_sdk.monitors.helpers import gcp_graph_helper
        return gcp_graph_helper

これ、monitoring_sdk.monitors.helpers自分自身なんですよね。from 自分 import サブモジュール__getattr__ がまた呼ばれて、無限再帰。RecursionError: maximum recursion depth exceeded が出ました。

正しくは importlib.import_module() を使う必要がありました。

# 正しい実装
def __getattr__(name):
    if name in __all__:
        import importlib
        module = importlib.import_module(f".{name}", package=__package__)
        globals()[name] = module  # キャッシュ
        return module
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

ここは正直、エージェントの最初の修正が不十分で、2回直しました。

罠③:パラメータの二重管理

Jenkinsfile の中にパラメータ定義が残っているジョブがありました。Jenkins のパラメータは DSL ファイル(Groovy)で一元管理する設計にしていたのですが、エージェントが実装時に Jenkinsfile 側にもパラメータブロックを追加してしまっていたケースです。

逆に、DSL ファイルへの追加が漏れているパラメータもありました。Jenkinsfile に書いたから DSL は不要、と判断したのかもしれません。ここは「プロジェクト全体のパラメータ管理方針」をエージェントが理解しきれていなかった部分です。

罠④:OpenAI API のトークン上限

CloudWatch監視ジョブで、分析結果が空で返ってくる現象が起きました。ログを見ると finish_reason='length' で、レスポンスの中身が空文字列。

max_completion_tokens が 2,500 に設定されていたのですが、画像(CPU使用率グラフ)を含む分析では足りなかったようです。4,000 に引き上げて解決しました。

ついでに、設定ファイルに temperature パラメータがあるのに実際の API 呼び出しでは使われていないことにも気づいたので、これも削除しました。こういう「使われていない設定」は地味に混乱の元になります。

罠⑤:プロンプトの重複データ

これはエージェントが見つけてくれた問題です。OpenAI に送るプロンプトに「入力データ(生データ)」と「事前分析結果」の両方が含まれていて、内容がほぼ重複していました。トークンの無駄遣いです。

生データを削除して、構造化された分析結果のみを渡すように修正しました。

全体の流れを振り返る

graph LR
    A[5 issue を<br/>Agent Teams に投入] --> B[約10分で<br/>実装完了]
    B --> C[検証エージェントで<br/>移行確認]
    C --> D[マージ]
    D --> E[本番実行で<br/>4ジョブ失敗]
    E --> F[依存関係修正]
    F --> G[循環参照修正]
    G --> H[パラメータ移行]
    H --> I[トークン上限調整]
    I --> J[動作確認OK]

    style E fill:#f9d6d6
    style F fill:#fff3cd
    style G fill:#fff3cd
    style H fill:#fff3cd
    style I fill:#fff3cd
    style J fill:#d4edda

正直なところ、エージェントが実装してくれた部分(左半分)と、自分で修正した部分(右半分)の労力は、体感的には半々くらいでした。

使ってみて思ったこと

Agent Teams が得意なこと

独立した作業の並列実行は明らかに強いです。5つのissueがそれぞれ別のファイルに閉じていたので、コンフリクトもほぼ起きませんでした。各エージェントがissueを読み、既存コードを理解し、実装する――この一連の流れは人間がやるよりずっと速い。

コードの理解力も高いです。旧 Jenkinsfile(Groovy)と新 Jenkinsfile の差分を読んで、不足している機能を正しく特定できていました。

まだ難しいと感じたこと

プロジェクト全体の設計方針の理解は課題です。パラメータの管理方針(DSL で一元管理)のように、コードには明示的に書かれていないルールは見落としやすい。CLAUDE.md に書いておくべきだったかもしれません。

依存関係のグラフ全体を見るのも苦手な印象です。「このモジュールを変更すると、インポートチェーンを通じて別のジョブに影響する」という間接的な影響を予測するのは、まだ人間が見たほうが確実です。

本番環境との差異は、そもそもエージェントには見えない情報です。ローカルにはあるけど本番にはないライブラリ、のような問題は構造的に発見できません。

次にやるなら変えること

まとめ

Agent Teams は「実装の速度」を劇的に上げてくれます。5つのissueを10分で実装完了、というのは人間には無理です。

ただし、「実装できた」と「本番で動く」の間にはギャップがあって、そこを埋めるのは今のところ人間の仕事です。依存関係の整合性、プロジェクト横断的な設計ルール、本番環境固有の条件――このあたりは、エージェントに任せっぱなしにすると痛い目を見ます。

とはいえ、「エージェントが実装→人間が検証・修正」というサイクル自体は回りました。次はもう少しエージェントへの指示を工夫して、修正の余地を減らしていきたいと思っています。

まだ試行錯誤の途中ですが、ひとまずここまで。

参考:Claude Code をさらに深く学ぶ

Agent Teams の実践的な使い方については、以下の書籍が参考になります。

[📦 商品リンク: moshimo-book-9CeFY]

AIを使った開発手法全般について理解を深めたい場合は、こちらも参考になります。

[📦 商品リンク: moshimo-card-HD5Yl]

[📦 商品リンク: moshimo-card-tP9XC]