🔎

プログラミングの知識は「書くため」ではなく「導くため」になった — AIエージェント並列オーケストレーションの先にあったもの

に公開

告知

実際にマルチAIエージェントによる開発をデモするイベントをやることにしました!
https://x.com/nrslib/status/2017413594263261550?s=20

はじめに

以前、AIエージェントが言うことを聞かない問題を解決するために「takt」というマルチエージェントオーケストレーションツールを作った話をしました。

https://zenn.dev/nrs/articles/c6842288a526d7
https://github.com/nrslib/takt

前回の記事では、taktを使い始めてから世界が変わった話をしました。タスクを投げれば、計画、実装、レビュー、修正のサイクルが自動で回る。これまでの大量の粗悪なコードに向き合う必要がない。3つのプロジェクトを並行して進められるようになった。素晴らしい日々です。

ところが、使い込んでいくうちに、新しい不満が生まれてきました。

taktが安定してきた

まずは嬉しい話からしましょう。

taktがだいぶ安定してきました。いまのv0.3.2がいい感じです。日々の開発に使い込んでいるうちに、ワークフローもエージェントも成熟してきて、すごい勢いで開発できるようになってしまいました。

たとえば、GitHubのIssueをAIと一緒に考えて立てます。Issueの内容を詰めたら、あとは次のように実行するだけです。

takt #99

たったこれだけで、taktがIssueの内容を読み取り、計画を立て、実装し、レビューし、修正し、最終確認まで自動で進めてくれます。できあがり。

taktのIssueをご覧になると面白いと思います。AIにIssueを作ってもらって全部このコマンドで実装してます。

https://github.com/nrslib/takt/issues

takt #99 と打ったらIssueが片付く」という体験は、なかなか衝撃的です。もちろん、すべてのIssueがワンショットで完璧に片付くわけではありません。エージェントの出力を確認して手を入れることもあります。しかし、ゼロから自分で実装するのとでは、スタートラインがまるで違います。

精度も上がってきました。以前は「AIエージェントのコード、ツッコミどころだらけだなぁ」と思うことが多かったのですが、エージェントのプロンプトをチューニングし続けた結果、一定の品質が担保できるようになっています。もちろんまだまだチューニングの余地はありますが、バイブコーディングで許容範囲です。

がまんできなくなった

さて、ここからが本題です。

taktが安定して、いい感じにコードが出てくるようになりました。以前は「言うことを聞かない」ことにイライラしていたのに、今度は別のことが気になり始めたのです。

あれ? 待ち時間、長くないですか。

前回の記事でも書きましたが、もともとは、AIエージェントに頻繁に返事を求められるのが嫌でtaktを作りました。「ここはどうしますか?」「この方針で合ってますか?」という問いかけに逐一答えるのが辛かったのです。

taktのおかげで、その問題は解決しました。タスクを投げたら放っておける。途中で質問されることもない。1タスクあたりの拘束時間は激減して、途中は完全に手が離れるようになった。素晴らしい。

しかし、人間というのは贅沢なもので、放っておけるようになると今度は「まだ終わらないの?」と思い始めます。特にレビューフェーズが長い。当初のdefaultワークフローでは、AIレビュー、アーキテクチャレビュー、セキュリティレビューと、多段のレビューが直列に実行されていました。それぞれのレビューアーがじっくりコードを読むので、当然時間がかかります。

3つのプロジェクトを同時に進めているならそんなに気にならないのですが、taktを開発しているときは結構待ち時間があります。takt更新中はtaktを使いづらいので……(takt-stableコマンド作ろうかな)。

とはいえ、レビューの質を下げたくはありません。せっかく多角的なレビューで品質を担保しているのに、それを削っては本末転倒です。

ではどうするか。

独立して実行できるものは、並列に実行すればいいのです。

レビューを並列化した

アーキテクチャレビューとセキュリティレビューは、互いに依存していません。アーキテクチャレビュアーは構造や設計を見ますし、セキュリティレビュアーはインジェクションやデータ保護を見ます。それぞれが独立した観点でコードを評価しているので、同時に走らせても問題ないはずです。

単一のフローからスケールアウトして並列にし、その後またスケールインして単一のフローに戻す。そういうイメージです。

実装は次のようになります。default ワークフローのレビューステップを見てみましょう。

steps:
  # ... 計画、実装、AIレビューのステップ ...

  - name: reviewers
    parallel:
      - name: arch-review
        agent: ../agents/default/architecture-reviewer.md
        rules:
          - condition: approved
          - condition: needs_fix
        instruction_template: |
          アーキテクチャと設計のレビューに集中してください。
          # ...

      - name: security-review
        agent: ../agents/default/security-reviewer.md
        rules:
          - condition: approved
          - condition: needs_fix
        instruction_template: |
          セキュリティレビューを行ってください。
          # ...
    rules:
      - condition: all("approved")
        next: supervise
      - condition: any("needs_fix")
        next: fix

parallel キーワードの下にサブステップを並べるだけです。taktのエンジンが Promise.all でこれらを同時に起動して、すべてのサブステップが完了するまで待ちます。

ここで面白いのが、ルールの集約です。親ステップの rulesall("approved")any("needs_fix") と書くことで、サブステップの結果を集約して次のステップを判断できます。全員が承認すれば次に進む、誰かが修正を求めればフィックスに戻る。投票のようなものですね。

並列実行中の出力は ParallelLogger によってプレフィックスが付きます。ターミナルには次のように表示されます。

[arch-review]     [tool] Read src/models/user.ts
[security-review] [tool] Read src/auth/handler.ts
[arch-review]     構造・設計を確認しています...
[security-review] インジェクション攻撃の検証を行っています...
[arch-review]     APPROVE: 設計に問題ありません
[security-review] APPROVE: セキュリティ上の問題は見つかりませんでした

どのレビュアーが何をしているか、一目で分かります。ツールの呼び出しも [tool] プレフィックスで表示されるので、各レビュアーがどのファイルを読んでいるかまで追えます。色分けもされているので、インターリーブされた出力でも見やすいです。完了時にはサマリーも表示されます。

── reviewers results ──
  arch-review:     approved
  security-review: approved
───────────────────────

この並列化によって、レビューフェーズの所要時間がほぼ半分になりました。以前は直列に2つのレビューを実行していたところを、同時に走らせるのですから当然です。待ち時間が減ったことで、タスクの回転が速くなりました。

普段の開発は expertexpert-cqrs なんかはレビューフェーズが5つも多段になってるので、かなりの短縮になるはずで楽しみです(まだ手を付けてないのでこのあと作っていきます)。

あれ? 自分の仕事は……?

taktが安定して、並列化もできて、開発の速度は上がりました。ここでふと、自分の仕事について考えてしまったのです。

私がやっていることを振り返ってみましょう。

まず、taktをつかいこなすこと。ワークフローを設計し、タスクを分割し、適切なワークフローを選んで実行する。これは確かに仕事です。

次に、taktを更新すること。使っていて不便なところを見つけて、機能を追加し、バグを直す。夜中にtaktを回したり、昼休みにちょこっと触るだけでいつの間にか更新されていきます。

そして、ソフトウェア設計の知見でエージェントを進化させること。DDDやCQRS+ESの知識をエージェントのプロンプトに落とし込み、レビュアーの精度を上げる。これは私の専門性が活きる仕事です。

さらに、UX体験を向上すること。これは自分が受益者でもあります。使いにくいところを直せば、自分の開発体験が良くなる。モチベーションの高い仕事です。

最後に、プロダクションコードの責任を持つこと。AIが書いたコードであっても、本番に出すなら品質の責任は自分にあります。これは避けられません。そして正直に言うと、ここが一番のボトルネックになっています。

コードを書いてはいません。でも、コードに対する責任はあります。レビューして、承認して、デプロイする。その判断は自分がしなければなりません。

楽しさの軸が変わった

プログラミングそのものが楽しくなくなったわけではありません。しかし、楽しさの軸がずれてしまったのは事実です。

以前は、プログラミングの知識そのものが楽しみでした。新しい言語機能を覚える、エレガントなアルゴリズムを実装する、設計パターンを適切に適用する。そういう「書く楽しさ」がありました。

今はどうでしょう。プログラミングの知識は、むしろ「知っているからこそAIにイライラする」原因になっています。「そこは値オブジェクトで書いてよ」「そのRepository、依存の方向が逆だって」。知識があるからこそ、AIの出力に対して細かい不満が出てきます。

その不満をエージェントのプロンプトにフィードバックして、試行錯誤する。それ自体は面白い作業ではあります。しかし、以前のような「コードを書く楽しさ」とは明らかに質が違います。

では、今の楽しさの軸は何なのか。

世の中の課題を解決するのに最速で進んでいる、という実感です。

アイデアを形にするまでの距離が、劇的に短くなりました。「こういう機能がほしい」と思ったら、Issueを立てて takt #99 と打てば動き出す。並列にタスクを回せば、複数の機能が同時に進む。以前なら1週間かかっていたような作業が、1日で終わる。

この「速さ」が、今の楽しさの源泉です。課題を見つけて、解決して、次の課題に進む。そのサイクルを高速で回せること。プログラミングの知識は、もはや「書くため」ではなく「正しい方向に導くため」に使っています。

未来予想図

それほど確かな知見があるわけではないのですが、今の延長線上に見えている未来について少し話させてください。

結局、帰納である

AIエージェントがコードを書く世界で、私たちが向かっている方向を一言で表すなら「帰納」です。

帰納プログラミングという考え方があります。具体的な入出力の例から、プログラムの構造を推論するアプローチです。AIエージェントがやっていることは、まさにこれに近いのではないでしょうか。そもそもML等は帰納ですしね。

私たちは要求を与え、AIがコードを生成する。そのコードが正しいかどうかは、インプットとアウトプットで検証します。インプットに対して期待されるアウトプットが返ってくるなら、その中間にあるプログラムは「正しい」と見なしてよいでしょう。

つまり、インプットとアウトプットを定義し、その結果が正しければ、そのプログラムは正しいだろう。そういう結論で進む世界になりつつあるのではないかと感じています。

TDDなのか、それとも

この考え方は、テスト駆動開発(TDD)に似ています。しかし、おそらく原義のTDDとは少し違うものになるのではないでしょうか。

TDDの原義は「失敗するテストを書いて、成功させて、リファクタリングする」というサイクルです。Red、Green、Refactorの3ステップを繰り返すことで、設計を洗練させていく。

AIエージェントが描く世界では、このサイクルは少し違う形になるかもしれません。失敗するテストを書いて、それを成功させるフェーズは、おそらくAIが一気にやってしまいます。段階的に設計を洗練させるというよりも、インプットとアウトプットを定義して、それが成り立つことを証明する。そこにこそ人間の価値が残る。

もしかすると、それはTDDというよりも、巷で話題のより高次元のSpec Driven Development(仕様駆動開発)のほうがふさわしいのかもしれません。仕様を書いて、AIが実装して、仕様どおりであることを検証する。私たちプログラマの仕事は、仕様を書くことと、それが正しく実装されていることを証明する作業になるのかもしれません。

まだ見えていない部分も多いので断言はできませんが、少なくとも、コードを手で書くことが仕事の中心であり続けるとは思えなくなっています。

いずれにせよ

いずれにせよ、私はいまとても楽しいです。

最初は怖かった。そもそもtaktを作ることが、私自身を否定することにつながっている感覚がありました。AIエージェントにコーディングを任せるツールを作っている。それは「プログラマとしての自分はもう要らない」と宣言しているようなものではないか。

これはAIエージェントを活用し始めた頃に感じた感覚です。いまいる場所が脆くも崩れ去るようなあの感覚。しかもそれを崩しているのが自分自身なのだから、なんとも複雑です。

でも、今は違います。

私の課題を高速で解決できる。それは誰かの課題を解決することにつながる。作りたいものを作る速度が上がっている。その速度は、以前の自分では到底出せなかったものです。

大切で愛しい大事な道具をしまって、この新たな道具で、私がすべきことをする必要があるようです。

taktは、そのための道具です。

https://github.com/nrslib/takt

npm install -g takt
takt メモアプリをReactで作って

Claude Code にログインしていれば、これだけで体験できます。

もちろん、この記事もtaktで書いています。

おまけ

副作用として、Claude Code MaxPlan 20x が見るも無惨なことになっております……。

Discussion