Amazon Web Services ブログ

リファクタリングを正しく行う:プログラム解析により AI エージェントの安全性と信頼性を高める方法

AI コーディングアシスタントに簡単なこと、例えば関数名の変更やファイルの移動を依頼すると、突然復旧作業に追われることがあります。インポートが壊れたり、参照が存在しないファイルを指したりします。5 分前にコンパイルできていたコードベースが、至る所でエラーを投げ始めます。20 秒で終わるはずのリファクタリングが、5 分間のデバッグとクリーンアップセッションに変わってしまうのです。

エージェントにとってリファクタリングが難しい理由

リファクタリングは単なる大規模な検索置換ではありません。コードベースのセマンティック構造全体にわたるグラフトラバーサル問題なのです。関数名を変更すると、変更は連鎖します。ワークスペース全体のすべての呼び出し箇所、それを参照する型定義とインターフェース、import/export 文、テスト、そして(オプションで)ドキュメントとコメント。ファイルの移動はさらに複雑な波及効果を引き起こし、すべての依存ファイルのインポートパス、バレルファイル(index.ts)と再エクスポート、tsconfig パスやバンドラー設定に組み込まれたモジュール解決の前提、Webpack 設定のような散在する設定ファイルなどに影響します。ここに根本的なミスマッチがあります。LLM はパターンマッチングを通じてもっともらしいコードを生成することに優れていますが、リファクタリングはもっともらしさよりも精度を要求します。これは創造的なタスクではなく、シンボルの関係、言語固有のセマンティクス、プロジェクトの依存関係グラフの正確な理解を必要とする制約充足問題なのです。「正しく見える」が、深くネストさ れたモジュールの 1 つのインポートを見逃したエージェントは、単に小さなエラーを犯しただけではありません。本番環境まで表面化しないランタイム障害を導入したのです。これが、どれほど洗練されていたとしても、テキスト生成が構造的なコード変換において信頼性に欠けるツールである理由です。

問題:エージェントが効率的ではなく、非効率に動作するとき

多くの AI エージェントがリファクタリングでつまずくのは、構造的な編集をテキスト編集として扱うからです。開発者が直面し続けている失敗モードをいくつか紹介します。

依頼内容:「このメソッドの名前を変更して」

従来の失敗:エージェントはメソッド定義を更新しましたが、プロジェクト全体の呼び出し箇所を見逃しました。プロンプトで参照を更新するよう明示的に依頼した場合でも、プロセスは遅くエラーが発生しやすいループになりました。古い名前を検索して置換するのです。このプロンプトを考えてみましょう。expression.jsget_loose_identifier を、それが何をするかをよりよく反映するように名前変更してください。このシンボルの名前変更は 4 つのファイルに伝播し、8 つの参照と 3 つのインポートに影響します。次の図の左側(従来のアプローチ)は、専用のリファクタリングツールなしでこの操作がどのように展開されるかを示しています。最初のファイル(expression.js)でシンボルの名前を変更した後、エージェントはコードベースで get_loose_identifier を検索し、複数の LLM 呼び出しとツール呼び出しを通じて CallExpression.jsAssignmentExpression.js を更新します。努力したにもかかわらず、残りの参照を見逃しています。

Kiro の対処法:開発者が IDE でこのタスクを手動で実行する方法を考えてみましょう。get_loose_identifier で F2 を押し、新しい名前を入力して、Enter を押します。IDE は、コードベース全体の 8 つの参照と 3 つのインポートすべてを更新しながら、自動的に名前変更を実行します。これがまさにセマンティックリネームツールが行うことです。次の図の右側(新しいアプローチ)は、Kiro が単一のツール呼び出しで名前変更全体を適切に実行する方法を示しています。

依頼内容:「このファイルの lint エラーを修正して」

従来の失敗:エージェントは linter の出力をテキスト編集の ToDo リストとして扱いました。1 つのファイルでシグネチャの関数名を camelCase から snake_case に変更しましたが、他のファイルで「参照が見つからない」や「インポートが見つからない」エラーを導入しました。すべての使用箇所への変更の伝播に失敗したのです。

Kiro の対処法:ユーザーが直接名前変更を依頼しなくても、エージェントがセマンティックリネームツールから恩恵を受ける例を示します。ユーザーはエージェントに「text_helpers.py の lint エラーを修正して」と依頼します。lint エラーは、utils/text_helpers.py 内の normalizeTextslugifyTitle を snake_case に変更する必要があることを示しています。コードベースの部分的なスナップショットを以下に示します。

これらの修正をテキスト編集として扱うエージェントは、関数定義の名前を変更し、ローカル参照を修正するかもしれませんが、他の場所のインポートや呼び出し箇所を見逃す可能性が高く、実行時に ImportError/NameError を引き起こします。セマンティックリネームツールを使用することで、Kiro は定義だけでなく、api/routes.pyservices/indexer.py のインポートと呼び出しも更新します。以下の画像の通りです。

依頼内容:「コンポーネントを再編成して – Button.tsxsrc/components/ から src/shared/ui/ に移動して」

従来の失敗:エージェントはタスクを単純なファイル操作として扱いました。ファイルの移動は成功しましたが、古い場所を指すすべてのインポート文が壊れています。エージェントはその後、検索置換操作でファイルごとにインポートを修正しようとしましたが、動的インポートを見逃しました。import('../components/Button')

Kiro の対処法:Kiro がインポートパスを自動的に更新する具体的な例を示します。図は、プロジェクト構造の部分的なスナップショットと依存するコードスニペットの一部を示しています。

Button.tsxsrc/components/ から src/shared/ui/ に移動した後、Kiro は移動したファイルに関連するすべてのインポート文を自動的に更新します。

主な利点:

  • 組み込みの言語サーバーが編集を処理するため、手動の検索置換は不要です。

  • 言語認識:TypeScript/JavaScript モジュール解決を理解します。

  • より安全:動作するコードを壊す可能性が低くなります。

  • エッジケースの処理:パスエイリアス、モノレポなどに対応します。

これは、VSCode のエクスプローラーでファイルをドラッグアンドドロップしたときに起こることとまったく同じです。セマンティックリネームツールはエージェントベースの同等機能です!

Kiro エージェントのリファクタリング方法

IDE は、エージェント AI の台頭以前にこの問題をすでに解決していました。VSCode でシンボルの名前を変更するために F2 を押すと、IDE は推測しません。コードの構造を理解する言語サーバーに相談し、ワークスペース全体の編集を計算し、安全に適用します。VSCode のワークスペース編集機能により、単なるテキストパターンではなく、コードの構造を理解するプログラマブルなセマンティック検索置換が可能になります。Kiro エージェントは、LLM 推論だけでリファクタリングをシミュレートしようとはしません。代わりに、エージェントは上記と同じメカニズムを使用して、これらの実証済みの IDE 機能をプログラム的に公開する 2 つの新しいリファクタリングツールを登録します。エージェントがシンボルの名前を変更したりファイルを移動したりする必要がある場合、意図をインテリジェントに認識し、適切なリファクタリングツールを選択して呼び出します。エージェントはリファクタリングワークフローを調整し、IDE の言語サーバーが正確性の検証を支援します。

これらのエージェント登録リファクタリングツールが内部でどのように機能するかを見てみましょう。

セマンティックリネームツール:正しいリネームを実現

このツールは、VSCode のシンボル名前変更 API に直接接続します。F2 を押したときに使用するのと同じものです。vscode.prepareRename を使用してシンボルが名前変更可能かどうかを検証し(例:キーワードではない)、vscode.executeDocumentRenameProvider を使用してワークスペース全体で必要なすべての変更を含むワークスペース編集を生成します。TypeScript、JavaScript、TSX、JSX の場合、組み込みの VSCode 名前変更プロバイダーがすべてを処理します。Python、Go、Java などの場合、ツールはインストールされた言語拡張機能とそれらが提供する言語サーバーに依存します。

スマートリロケートツール:すべてを壊さずにファイルを移動

このツールは、VSCode のファイル移動機能を使用して、すべての参照を自動的に更新しながらファイルを再配置します。VSCode のエクスプローラーでドラッグアンドドロップするのと同等のプログラム的な操作ですが、エージェントがあなたのために実行できます。vscode.WorkspaceEdit.renameFilevscode.workspace.applyEdit を使用して、ツールは複数のファイルにわたる包括的な変更を生成し、影響を受けるインポートを更新します。

これが重要な理由

創造性よりも精度:リファクタリングは、コードがどのように見えるべきかを LLM に想像させる必要はありません。コードが実際に何であるかを理解し、外科的に変更できるツールが必要なのです。

実証済みのインフラストラクチャを通じた信頼:これらは実験的な LLM 機能ではなく、開発者が日常的にすでに依存しているリファクタリングインフラストラクチャとの直接統合です。F2 を押したときに機能すれば、エージェントが実行したときにも機能します。

言語に依存しない:重い作業は言語サーバーによって行われるため、このアプローチは技術スタックと言語全体に一般化されます。

生産性の維持:20 秒の手動リファクタリングが、5 分間の AI 生成リカバリーミッションになるべきではありません。適切なツールを使用すれば、操作は高速でアトミックなままです。

より大きな視点

構築による正確性という私たちの哲学に基づいて、IDE 診断統合を導いたのと同じ原則で、VSCode のリファクタリング機能の全範囲をカバーするようにこのアプローチを拡張しています。エラーが複合する前にキャッチするためにリアルタイム診断を統合したのと同様に、これらの実証済みの決定論的 IDE 機能を、新しい内部スマートリロケートおよびセマンティックリネームツールに拡張しました。

しかし、リファクタリング機能は名前変更と再配置で止まりません。VSCode の言語サーバーは、エージェントが活用すべき豊富な自動コード変換スイートを提供します。コードブロックを再利用可能な関数に抽出するメソッド/関数の抽出、コードを簡素化する変数/関数のインライン化、すべての呼び出し箇所でメソッドパラメータを更新するシグネチャの変更、アロー関数への変換やその他の言語固有の変換は有力な候補です。

このアプローチを取ることで、エージェントが実行される基盤に正確性、セキュリティ、信頼性を組み込むことができます。これらのツールで確立したパターンは、ツールキットへの新しい追加を導きます。LLM に脆弱なテキスト置換スクリプトを生成するよう依頼する代わりに、インテリジェントなコーディングエージェントは、開発者がすでに信頼しているこれらの実証済みの IDE 操作を活用し続けます。IDE が正しく実行する方法を知っているとき、私たちはそれに作業をさせます。エージェントがより有能になるにつれて、これはその出力をより信頼できるものにするための良いテクニックでもあります。

違いを体験する準備はできましたか?Kiro を無料で始めて、開発ワークフローをどのように変革できるかを確認してください。Discord の成長するコミュニティに参加して、フィードバックを共有し、質問をし、AI 支援コーディングで構築している他の開発者とつながりましょう。

謝辞

エンジニアリングの洞察と貴重なフィードバックを提供してくれた Al Harris に感謝します。

本記事は 2026 年 2 月 5 日に公開された Pardis Pashakhanloo と Rajdeep Mukherjee による “Refactoring made right: how program analysis makes AI agents safe and reliable” を翻訳したものです。翻訳は Solutions Architect の吉村が担当いたしました。