AIエージェントを用いたモノリスリファクタリングの教訓
1Passwordは、AIエージェントを使用して大規模なGoモノリスをリファクタリングした経験を共有。依存関係分析と抽出順序のためにエージェントツールチェーンを構築し、クリーンアップタスクでは高い自動化を達成したが、複雑なサービス抽出では20〜30%の生産性向上にとどまり、厳密な仕様が必要だった。主な教訓:非決定性を決定論的ツール内に封じ込め、明示的な仕様を提供し、並列性のために分離を確保すること。
4月20日、1Passwordチームは、AIエージェントを活用して大規模なGoモノリス(コードネームB5)をリファクタリングした実践について詳しく報告した。このアプリケーションは数百万行のコードを持ち、1Password製品の基盤であるが、Unified Access機能の高リクエスト率と低レイテンシ要件に対応するため、チームはより明確なサービス境界と独立したスケーラビリティを必要としていた。そこで、AIエージェントを使ってシステムの分解を分析・計画することにした。
最初のステップは分析レイヤーの構築だ。チームはGo SSA解析、SQL解析、DataDog実行時結合データを組み合わせ、エージェントツールチェーンを構築し、ドメイン所有権マップ、結合グラフ、優先順位付き抽出順序を生成した。結果は経験豊富なエンジニアの判断とほぼ一致し、Vaultから始め、次にBilling、AuthN/AuthZ、最後にIdentityを残す順序が推奨された。重要なパターンは、エージェントを使って決定論的ツール(SSAアナライザなど)を構築し、継続的な解釈に依存しないことだ。これにより安定した基盤が得られ、さらにエンドツーエンドのトランザクション可視性が向上した。
人間とエージェントの最適比率を探る過程で、チームは長年未処理だったクリーンアップタスクに取り組んだ。Goサーバーでデータベーストランザクションを開始するMustBegin(失敗時にパニック)を、エラーを返すように置き換えるものだ。3000以上の呼び出し箇所のマニフェストを生成し、少数のパターンに分類、明示的なテンプレートを定義し、失敗モードと停止・エスカレーション条件を含む詳細な実行手順書を作成した。複数のエージェントをgit worktreeで並列実行し、実際の修正は数時間で完了した。重要な発見は、タスクが完全に指定され制約されている場合、エージェントは高速かつ正確であり、仕様外の事象に遭遇するとシステムはそれを表面化する点だ。
しかし、より複雑なサービス抽出タスクでは、エージェントのパフォーマンスは限定的だった。小さなサービスでも、エージェントは順序と不変条件の問題を起こした。例えば、新しい行を挿入するコードを更新する前にUUID列をバックフィルしようとし、サイレントデータ損失を引き起こした。また、共有テーブルを新しいサービスが独立して所有していると誤解し、デプロイ時の競合を生んだ。チームは「推測」行動も観察した。エージェントが文脈不足の時、もっともらしいが検証されていない仮定で穴埋めをする。例えば、識別子フォーマットをULIDと誤って推測し、一連の変更にその仮定を伝播させ、最終的にセッション全体をロールバックする必要があった。このクラスのタスクでは生産性向上は20〜30%にとどまり、注意深い調整とレビューの必要性は変わらなかった。
これらの経験から、1Passwordは4つの主要な教訓を導き出した。1. エージェントリファクタリングのボトルネックはコード生成ではなく、順序制約や巻き戻しが困難な決定(スキーマ変更、デプロイ順序など)の管理にある。2. 非決定性は注意深く封じ込める必要があり、エージェントで決定論的ツールを構築し、その出力に後続作業を制約するのが有効。3. 不完全な仕様はエージェントに暗黙の仮定をさせ、唯一の対策は不変条件、順序制約、エスカレーションパスを含む明示的な仕様を提供すること。4. 並列実行は、変更が独立し衝突が構造的に排除されている場合にのみ効果的。
現在、1Passwordはエンジニアリング組織全体にエージェントツールを展開しているが、その適用範囲は明確に定義されている。エージェントは問題がよく定義されている場合に最も効果的であり、エンジニアはシステム境界の定義、依存関係のモデル化、順序の正確性確保を引き続き担当する。これらの洞察は、エンジニアがコードを書いたりモデルにプロンプトを与えたりするのではなく、安全かつ予測可能に実行できるシステムを設計することに集中するシフトをもたらす。