エージェントとともにプログラミングする方法
(crawshaw.io)- この記事は、既存のプログラミング経験を 対話型コンピュータ(LLM、エージェント) の世界へ適応させる過程を扱う第2回の内容である
- 第1回の「LLMとともにプログラミングする方法」では、LLMを既存ツールに組み込み、自動補完や検索の代替として活用する方法を説明した
- 今回はもう少し難しいが、そのぶん得るものも大きい エージェントベースのプログラミング の実践的な経験と洞察を共有する
エージェントの定義と実際
- LLM(大規模言語モデル)の文脈で「エージェント」という用語を定義することには意味がある
- AI業界の流行語のように長く使われてきたが、実際に役立つ構造として定着したのは最近である
- その過程で、多くのマーケティング的レトリックや神秘主義が上塗りされてきた
- エンジニアの視点から見ると、今では明確かつ単純に定義できる: エージェントは9行のコード、すなわち LLM呼び出しを含む for ループ である
- このループの中でLLMは命令を実行し、その結果を自ら確認でき、人間の介入なしに反復動作する
- 単純に感じられるかもしれないが、実際にこのように構成すると 純粋なLLMだけを使う場合よりプログラミング能力が飛躍的に向上 する
ホワイトボードプログラミングとエージェントの違い
- ホワイトボードの前に立ち、マーカーでC言語でUTF-8文字列の妥当性を検査する関数を書くと仮定してみると
- (実際に筆者が経験した面接状況であり、よくあるインタビュー課題でもある)
- この作業の成否は、プログラマとしての経験と、外部資料を参照できない制約をごまかす能力に左右される
- UTF-8のエンコーディング規則を覚えている必要があり、Cの文法が他のC系言語と混同しないよう注意しなければならない(名前-型、型-名前の順序など)
- 実際の日常では、コンパイラのフィードバック、ドキュメント検索、
printfなどさまざまな方法でコードを検証し、誤りを見つけられる
- エージェントなしでLLMにコードを書かせるのは、ホワイトボードで外部の助けなしにコードを書くことに近い
- あいまいな記憶を引き出し、非効率なやり方で文法を合わせようとし、とんちんかんなインターフェースを想像する誤りを避けなければならない作業である
- LLMがまったく新しいプログラムを作り出す技術的成果は驚異的だが、GPUにつながれた仮想ホワイトボードだけでは実質的なプログラミング生産性は大きく上がらない
- しかし、LLMに 仮想ホワイトボード以上のものを与えたら どうなるか?
- たとえばコンパイラを呼び出し、コンパイルエラーを確認したうえで自分で修正できるようにしたら?
grep、catで既存ファイルを読み、複数ファイル(ユニットテストを含む)にパッチを当て、反復的にテストまでできるとしたら?
- エージェントはまさにこのようなフィードバックベースのLLMである。
エージェント = フィードバック環境で動作するLLM
- 人間のように フィードバック環境 でうまく動くLLMは、いくつかの見慣れたツールがあるだけで実質的なプログラミング能力を発揮する
bash(cmd): ターミナルコマンド実行(find、cat、grep など)patch(hunks): ファイルへのパッチ適用、コード変更の反映todo(tasks): 作業リスト管理web_nav(url), web_eval(script), web_logs(), web_screenshot()など: Web探索、評価、ログ、スクリーンショットなどkeyword_search(keywords): キーワード検索codereview(): コードレビュー
- bashツールを活用して コードベースを効率的に探索 し、git add/commit などのバージョン管理まで自動化する
- このようなツールを持たず、単純なコード生成だけを行うLLMと違って、エージェントには次のような差別化された利点がある
- API利用の正確性 が大きく向上する(ドキュメント検索および context への直接反映)
- コンパイラフィードバック により文法エラーやインターフェースの取り違えが減る
- 依存関係/バージョン管理 能力の強化(特定バージョンの特性を把握可能)
- テスト失敗による不具合検知とテストコード作成の習慣 が強まる
- コンテキストウィンドウの限界を超えるコードベース処理(必要な部分だけを選択的に読む)
- 実行結果を直接実験 できる: コードを実行し、ブラウザページのスクリーンショットをフィードバックとして受け、CSSを自動調整し、サーバーログでエラーを追跡してテストを追加する
- 欠点もある
- 1文の依頼から数万の中間トークン(ツール呼び出し、Web検索、テスト反復など)が発生し、作業時間が数分以上かかる
- API呼び出しコストも発生するが、ハードウェアの進歩によって徐々に解消される見込みである
- 究極的には 中間労働をCPU/GPUが肩代わり し、開発者の時間を節約して、作りたかったプログラムをより多く完成させられる
- 実際にプロジェクトへエージェントを導入し、小さな作業を任せて結果を確認 してみるのは容易である
例: GitHub App認証の開発
- エージェントを活用して sketch.devのGitHub App認証フロー を実装した実例である
- 3〜4回のフィードバックだけで認証フロー全体を素早く完成させた
- エラーや要求条件が見つかったときに短い一文で説明すると、すぐにコードと動作を改善した
- 反復的で退屈なAPI連携作業、ビルドシステム/パッケージ管理/ライブラリ設定など、実務の「雑務」を最小化して 生産性のモメンタム維持 に大いに役立った
- 初期要件として「ユーザーごとのトークン保存なしで、アプリのグローバル認証情報だけを使う」を入れ、エージェントはそれを反映して実装した
- しかしその結果、深刻なセキュリティ脆弱性 が発生した(誰でもすべてのリポジトリを見られるようになった)
- 問題を1文でフィードバックすると、すぐにユーザーごとの権限チェックを導入し、修正済みコミットを生成した
- 次に 性能問題 が明らかになった
- 次のような構造で、すべてのユーザー×リポジトリの組み合わせについてAPI呼び出しが発生し、スケーラビリティに問題があった
for install := range allAppInstallations { for r := range install.Repositories() { if r.IsCollaborator(user) { // add to available repositories } } } - この問題の根本原因が、「ユーザーごとのトークンを保存しない」という自分の要求条件にあると気づいた
- 要件を変更(ユーザーごとのトークン保存を許可)すると、エージェントは効率的なAPI呼び出し方式で再設計した
- 次のような構造で、すべてのユーザー×リポジトリの組み合わせについてAPI呼び出しが発生し、スケーラビリティに問題があった
- 実際、この過程を文章で説明するために使った単語数のほうが、Sketchで認証コードを得るために入力した総単語数より多かった
- ひと言でいえば、エージェントは今日の開発者を置き換えられるレベルではないが、従来なら数日かかる反復作業を1日で処理 できるよう助けてくれる
- 開発者が「子どもの部屋を掃除しながら」でも仕事を進められるほど、自動化が進んでいる
例: JSONベースのSQLルール適用
- エージェントがよく処理する作業の一つとして、Tailscaleで学んだ独特なSQLスタイル を適用する必要があった
- すべてのテーブルで実カラムは1つ(JSONデータ)のみで、他のカラムはJSONから派生する generated column として扱う
- 例のテーブル構造:
CREATE TABLE IF NOT EXISTS Cookie ( Cookie TEXT NOT NULL AS (Data->>'cookie') STORED UNIQUE, -- PK UserID INTEGER NOT NULL AS (Data->>'user_id') STORED REFERENCES User (UserID), Created INTEGER NOT NULL AS (unixepoch(Data->>'created')) STORED, LastUsed INTEGER AS (unixepoch(Data->>'last_used')) CHECK (LastUsed>0), Data JSONB NOT NULL ); - この方式は一種の poor man’s ORM として機能し、スキーマ拡張が容易になり、SQL制約がJSONデータ品質の検証に役立つ
- 欠点は、行ごとの保存データが増え、すべての INSERT/UPDATE がJSON単位で行われなければならないことだ
- しかしエージェントはこのスタイルを 常に一貫して守れるわけではなかった
- 新しいテーブルを作るときは概ねよく従ったが、例外があると混乱したり、勝手にスタイルを変えてしまうことがあった
- 簡単な解決策: SQLスキーマファイルの先頭に 3文の説明 を追加する
- 「各テーブルは1つの実Data JSONカラムだけを持ち、他のカラムはすべてそこから派生する」というキーワード文を追加
- この規則に従わないテーブルには、別のコメントで例外であることを明示
- その後、エージェントの動作は 目に見えて改善 した
- 興味深い点は、このような説明やコメントを実際の人間エンジニアはたいてい無視するか、効用を低く評価しがちだが、
- LLMベースのエージェントはコメントや説明をコード作成に積極的に反映する
- 説明をうまく書くだけでコード生成品質がはっきり良くなる
「資産」と「負債」のコードモデル
- LLMベースのコード生成ツールに対するよくある批判の一つは、コード生成そのものはソフトウェア全体コストのごく一部にすぎない ということだ
- 実際には、既存コードの依存関係、もつれ、複雑なインターフェースを管理することに大半の時間が費やされる
- 規模が大きく、古く、多数のユーザーを抱える製品は保守コストが圧倒的に大きい
- そのような環境でLLMに「バブルソートをFortranで書いて」と頼むのは、おもちゃか不便な邪魔者のように感じられるかもしれない
- 金融の「資産/負債」概念と比較する議論もあるが、これも完全には当てはまらない
- しかし、すべてのソフトウェアエンジニアリングがそのような大規模・長期プロジェクトだけに当てはまるわけではない
- ほとんどのプログラムは少数の利用者向け、あるいは短命なプロジェクトである
- 大規模保守の経験だけを業界全体の本質にまで一般化すべきではない
- エージェントの価値はコード生成だけに限定されない
- エージェントは複数のツールとLLMを組み合わせて、コードの読み取り、ファイル編集、コード削除/修正など変化そのものを自動化 する
- コードを追加するのと同じくらい、コード削除やリファクタリングも自然に実行 する
- 結局、エンジニアの目標は変化(change)である
- 変化の過程では、担当者が変更を理解しなければならない追加作業もあるが、エージェントは中規模プロジェクトに対しても段階的な変化を生み出す力を示している
- 現時点で十分でなくても、エージェントは正しい方向へ急速に進化している
- さらに、複雑な言語やビルドシステムがプロジェクトの参入障壁として機能する という意見もある
- 容易にコードを書けるツール(LMM、型安全性、ガベージコレクション、パッケージマネジメント、エージェントなど)が参入障壁を下げると品質低下が懸念される、という主張だ
- もし変化の速度を落としたり統制したりすることが目的なら、エージェントのような自動化ツールは向いていない
なぜ今エージェントなのか?
- トランスフォーマーのような複雑なAI原理と違って、LLMにフィードバックループを入れることは直感的に明快 なアプローチである
- 開発者ツールを考える立場から見ると、自然な発展方向に感じられる
- 実際、1年前の sketch.dev の初期バージョンもLLMにgoツールだけをつないだ程度だったが、今使っているエージェントとは 実用性に大きな差 がある
- ML分野でも 強化学習(フィードバックベースの学習) は50年以上にわたる基本原則である
- エージェントの実質的な登場はLLMの進化 と直結している
- 2023年のLLMはツール呼び出し能力が不十分で、エージェントとしての役割は限定的だった
- 2025年のLLMはツール呼び出しと反復作業に最適化 されており、実用的なエージェント活用が可能になっている
- Frontier(最新の商用)モデルは、オープンモデルに比べてツール活用力で大きく先行している
- 今後6か月以内にオープンモデルも追いつくと期待されている
- 有用な反復的ツール呼び出し が可能になったことが、最新LLMの最大の変化である
今後の方向: コンテナと並列実行
- LLMエージェント分野は、まだ大半のエンジニアが実際には導入していない 初期かつ急速に変化する段階 にある
- 現時点では、エージェントは主にIDEやローカルリポジトリで動かす形で活用されている
- VSCodeフォークやコマンドラインツールの導入で簡単に始められる
- しかし 2つの重要な限界 がある
- 第1に、安全装置の不足: 実機に保存された本番認証情報など、機密情報が露出する危険がある
- エージェントがデプロイスクリプトなど意図しないコマンドを実行すると、致命的なセキュリティ事故が起きうる
- コマンド実行のたびに手動確認を要求しても、誤って機密情報を露出させる可能性は残る
- 第2に、並列実行と自動化の限界: 各開発者が自分の環境でエージェントを1つずつしか動かせないため
- エージェント1回の動作ごとに数分かかり、複数の作業を同時進行しづらく非効率である
- 第1に、安全装置の不足: 実機に保存された本番認証情報など、機密情報が露出する危険がある
- sketch.dev ではこれらの限界を コンテナ環境 で解決しようとしている
- 作業ごとに 隔離された開発コンテナ を作り、ソースコードを複製し、gitコミットなどだけを外部へ取り出す
- 複数のエージェントを同時に実行でき、他のエージェントもこの方式を探っている
- 実例: GitHub認証作業と並行して、フォームUI改善を別のエージェントセッションで処理
- 別途イシュートラッカーに登録することなく、スクリーンショットと短い1行の依頼だけでフォームデザイン改善のフィードバックを処理
- 30秒の投資でも、一定水準以上の結果を得られる体験を提供する
- 過去6か月間のUX実験結果:
- エージェントベース開発において、コンテナ(隔離実行環境)が最も実用的だという結論に至った
IDEはどうなるのか?
- エージェントベースの開発環境で IDE(統合開発環境)の役割が何になるのか は、依然として開かれた問いである
- エージェントに指示文を入力して作業を開始し、コンテナ環境で実行し、変更点を diff で確認してブランチ/PRへプッシュすることが実際のワークフローになりうる
- 実際には、エージェントが生成した大半のコミットには ある程度の人手による手直し(クリーンアップ)が必要 である
- 当初はほぼすべてのコミットに手動修正が必要だが、プロンプト作成の習熟度が上がるにつれて修正量は徐々に減っていく
- 修正内容はコメント編集、変数名変更のような簡単なものから、より複雑なリファクタリングまでさまざまである
- コンテナ環境でこうした修正をどう効率化するかが核心である
- sketch.dev などで実験中のワークフロー
- diffビューを直接編集できるインターフェース を提供
- Sketchのdiff画面右側でコードを直接編集すると、そのコミットに反映されてすぐにプッシュされる
- 小さな1行修正には非常に効率的である
- コンテナへのSSHアクセス を提供し
- シェルに直接入ったり、Webターミナルでコードを操作したりできる
vscode://URL で開き、従来のIDEで作業することも可能
- コードレビュー風コメント を diff 上に直接残して、エージェントへのフィードバックとして渡す
- コードレビュー経験を生かし、必要な説明や要求事項を最小限の入力で伝えられる
- diffビューを直接編集できるインターフェース を提供
- 総評
- コンテナ環境はコード生成・修正・検証・レビューを統合的に行えるようにし、
単なるコード記述を超えた真のエージェントベース開発を可能にする - 以前はコンテナで開発したいとは思わなかったが、
エージェントが作った diff をコンテナで整理・修正する体験は非常に興味深く、生産的である
- コンテナ環境はコード生成・修正・検証・レビューを統合的に行えるようにし、
結び
- LLMベース技術を学び実験する過程は、謙虚さを学ぶ時間 でもあった
- これまでマルチコア、SSD導入、ネットワーク拡張など、プログラミングの本質が変わるたびに楽しさを感じてきたが、
LLM、とりわけエージェントは コーディングの「過程そのもの」 を完全に新しくしつつある - アルゴリズム、言語、ライブラリ選択に影響してきた変化とは違い、
エージェントは 作業方法そのものに関するあらゆる前提を根本から再検討 させる - ときには「プログラミングをまったく知らない状態から最初から学び直したほうがよいのでは」と感じるほど、変化は大きい
- そしてこの変化は 今この瞬間も進行中 である
- これまでマルチコア、SSD導入、ネットワーク拡張など、プログラミングの本質が変わるたびに楽しさを感じてきたが、
- 今私たちが経験しているやり方は 6か月前とも完全に異なり、まだ安定化もしていない
- チーム協業、レビューなど開発文化の標準もまもなく大きく変わるだろう
- たとえば、形式的にだけ行われていたコードレビューは、もはや実質的な問題を解決できなくなっている
- コードレビュープロセス自体を新しく発明すべき時点に来ている
- IDEもまた、これまで掲げてきた統合性とは裏腹に、全面的に作り直すべき時が来ている
- 業界でもこの変化は認識されているが、エージェント中心のアプローチ はまだ始まったばかりである
- 今後も大きな変化が予告されており、
好奇心と謙虚さ だけがこの変化をうまく乗り越える方法である - むしろ今は技術系インターネットフォーラムから距離を置き、
こうした議論や要約もエージェントに任せたほうがよいかもしれない
1件のコメント
Hacker Newsのコメント
私は主に自分のための道具だけをコーディングしているので、自分以外の誰か、あるいは何かが代わりにコードを書いて、それをあとで読んで、理解して、直すことに大きなメリットがあるとはあまり思えない。もちろん、APIドキュメントの中から欲しい部分をLLMに探させるのはかなり有用で時間の節約になる。だから、LLMの将来の性能が良くなるかどうかとは無関係に、私はそもそも他人のコードを読むこと自体があまり好きではない
著者が、コードレビューは貧弱でほとんどまともに機能していない、と言っていた点に完全に同意する。エージェントがコードを書く時代では、実際のボトルネックは執筆ではなくコードを読むことだ。人々がレビューを雑に済ませたり、単に各自の好みを表明する手段として使ったりしていると、エージェントは深刻なセキュリティや性能の問題を簡単に紛れ込ませられる。正直なところ、本当の問題はコードを読むだけでは見えず、実際にデバッグしたり前提を検証したりする手作業が必要になることだ
ようやくLLMについて現実的な分析をした文章を見た、という感想だ。「エージェント」という用語は、実質的にはLLMを再帰的に呼ぶ
forループに名前を付けただけなので少しもどかしいが、ネーミングセンスが業界平均で高いわけでもないので、まあ受け入れている「私たちはコンテナがプログラミングにおいて有用で必要だという点に同意している」という部分に関連して、Dockerを作ったSolomon Hykesが、なぜ最近 Container Use というプロジェクトをオープンソースで公開したのかを説明している。エージェントを並列に安全実行できるようにするためだ。Sketchなど一部のプラットフォームは隔離されたローカル開発環境を内蔵しているが、他のコーディングエージェントはそうではない。補足情報として YouTube動画 も勧めている
エージェンティックなループ、機械の中の頭脳、実質的にはルールエンジンの代替に見える。まだ固有の欠点もあるが、多くの識者が本質をよく突いていると思う。「エージェントにツールをつなぎ、ユーザーの要求でプロンプトし、そのまま回して反復実行し、しかもプロンプト自体も状況に応じて動的に変わる」。こうした形で、人間的なインタラクションや問題解決の仕方をわざわざ模倣しなくても、オーケストレーションや多段階の処理、曖昧なタスクの代替や自動化には十分有用だ。以前は曖昧さを直接コードに落とし込まなければならなかったが、それが不要になるかもしれない。本番環境ではdry runなしで実行させることへの懸念もあるが、ツールやサービス自体が進化していくと思う。100を超える類似サービスが一貫したインターフェースで外部世界(たとえばSMS、メール、天気、ソーシャルなど)とつながれば、今よりはるかに強力なアシスタント、あるいはそれ以上のものが出てくると期待している
コードを読むことは常に書くことと同じくらい重要だったが、今ではますます重要になっている。私の悪夢だ。コードを書くのは時に楽しいが、コードを読むのは常に労働だ
エージェントを使っている人のうち、実際に「プログラミング」、つまり問題解決の方法を考え、それをコードで表現する楽しさそのものを好きな人がどれくらいいるのか気になる。最近の多くのエージェント作業を見ると、その過程自体が消え、むしろ自然言語で要求だけ説明して、あとはLLMがバグを作らないことを祈る構図になっている
コーディング時にAIを好んで使う分野がいくつかある(本当に私が書いたことだ!):
divを中央寄せするのも、何度か試行錯誤すればすぐできる「資産」と「負債」についての部分は興味深かったが、同意はしない。多くのプログラムは少数の利用者のために始まりながら、いつの間にか大きなプロジェクトになったりする。過去には、一度きりのつもりで雑に書いた科学用コードが、ある時点で意図せず長期かつ広範囲に使われるようになる例をあまりに多く見てきた。だから私は、自分のコードがもっと長く使われ、もっと広い範囲に及ぶことを念頭に置いて、自分自身や他人への配慮として書く。仲間が作った個人用のサイドプロジェクトを、マネージャーが部署のプロジェクトに格上げした経験があるなら、この問題に共感するはずだ
LLMをコード作成や設計ではなくコードレビューに使うことこそ、本当のキラー機能になりうると思う。今のコードレビュー自体が多くの面で壊れていて、今後はセキュリティ、未定義動作、機能の誤用、コンパイラ警告の再確認などでLLMの活用が大きくなると期待している。個人的にはLLMを検索エンジンのように、エラー診断やデバッグに主に使っているが、正答率は50%くらいで、それでも十分満足している