こんにちは。Esperna です。
組み込みファームウェアの開発をしています。この記事は、AIに開発を投げて、自分は別の仕事をする。そんな働き方にたどり着くまでの話です。想定読者は「AIコーディングを日々の開発にもっと組み込みたい」と思っているエンジニア全般で、組み込みの前提知識は要りません。
面倒なことを一つずつ潰していったら、私の開発は最終的に二段のループになりました。開発そのものを回すループと、そのループを回す道具つまりスキル自体を改善するループです。そして、それぞれのループには必ず制約を付けています。このループと制約という形が、この記事を通して言いたいことです。
改善のきっかけ
きっかけは、ごく個人的な「嫌だ」でした。
commit して push する。しばらくしてCIが落ちる。直す。また push する。この往復が、とにかく時間の無駄で嫌だったのです。
自分のセッション履歴を振り返ってみると、失敗の大半は派手なバグではありませんでした。多かったのは、フォーマット崩れ(clang-format)と静的解析(cppcheck)の細かい指摘です。軽い。軽い内容なのにパイプラインは失敗する。「Format On Save なり、これくらいは push する前に片付けておきたい」と思わされる類のものでした。
であれば、push する前に全部終わらせてしまえばいい。そう考えて、手を動かし始めました。
push まわりを先に片付ける
最初にやったのは、push 前の工程です。
まず、push 前チェックを一気通貫にしました。実装してテストを生成し、静的解析とビルドとテストを回す修正ループを通して、最後にフォーマットをかける。ここまでをひとつにまとめました。ポイントは2つあります。
- 修正ループは最大3サイクルで止める。直しては壊し、を延々と繰り返してAIが暴走しないための制約です。3回試して直らないなら、それは人間が見るべきサインだと割り切りました。
- テストは実装直後、同じコンテキストで生成する。実装の意図がまだコンテキストに残っているうちに書くほうが、意図した挙動を正確に写し取れるからです。コードの挙動をその場で固定する万力としての価値が高い。ただし同じコンテキストは、実装に引きずられてバイアスがかかる裏返しでもあります。そのバイアスのない検査は、あえて次のレビュー工程に分けて持たせています(このあと触れます)。
次に手を付けたのは、レビューです。ここで一つ学びがありました。自分の実装コンテキストのままレビューさせると、レビューが甘くなるのです。書いた本人も、相棒のAIも、どうしても自分の実装に引きずられます。
そこで、レビューは隔離した別エージェントに見せることにしました。しかも、
- コード差分そのものへのレビュー
- 変更ファイル全体へのレビュー
- MR(説明文の文脈を含む)へのレビュー
の3系統を別々のエージェントに並列で担当させ、結果を統合したうえで、もう一体の「Redチーム」役エージェントに全体整合の観点から深掘りさせています。各エージェントは自分の担当範囲しか見ないので一発で浅くなりがちですが、観点を分けて重ねることで、人間が一人で見るより漏れにくくなりました。
todesking さんが書いているように、大事なのは「AIが書いたかどうか」ではなく「検品と責任を果たしたか」だと思います。だから、書く工程はAIに任せても、検品の工程は別エージェントと私とで二重に持つようにしています。
あわせて commit 後には、TODO や「仮」「暫定」、命名規約から外れた snake_case といったやり残しをスキャンさせています。
最後に、push の先も自動化しました。MRを作る、チケットを更新する。この手作業が手間に見合わないと感じたからです。成果物のMRは、説明欄とコメントの二重に記録させています。同じ処理を何度流しても結果が壊れない、いわゆる冪等になるよう作ってあるので、安心して任せられます。
これで、実装からレビュー、後工程までが一つのループになりました。
ボトルネックはコンテキスト整理へ移った
ところが、全部自動化して気づいたことがあります。ボトルネックは消えませんでした。移動しただけでした。
push 周りが楽になった結果、今度は「AIに渡すコンテキストを整理する」工程に時間を取られるようになったのです。
たとえば、こんなプロンプトをその都度手で書いていました。
再起動コマンドが送られてきたら再起動したい。そのために決めるべきことを洗い出して設計を詰めたい。少なくともコマンドのパケットは決める必要がある。再起動中に再起動要求が来たらどう扱うか(受け付けなくてよいと思う)も整理したい。過去製品ではどんなケースで再起動していたか、現行の設計資料に再起動への言及があるかも確認したい。最終的に、作るべき設計ドキュメントとブランチをチケットの説明欄に書いてほしい。使えるところは並列で進めて。
実際はもっと具体的に書くのですが、毎回、書く中身は違うのに、書いている「型」はいつも同じでした。要求を整理し、過去を調べ、現状を確認し、成果物を定義する。この骨格を手で書き直し続けているのが、どうにもDRY原則違反な感じがして嫌だったのです。
そこで、この「型」自体をスキルに切り出していきました。
一つ目は要求整理スキルです。「何を作るか」より「なぜ作るか」を掘ることに振り切りました。何を・なぜ・どこまでという観点で曖昧さを自分で判定し、足りないところだけ私に質問してきます。逆に「どう作るか」は聞いてきません。そこはAIの仕事だからです。
二つ目は実装計画スキルです。設計ドキュメントが複数に散っていて参照が面倒だったので、計画をチケットに書き出して参照させるようにしました。ここでは設計と現状のギャップを、file:line 付きの表で出させています。実装済みの行まで明示させるのがコツです。
実装計画でもう一つ大事なのが、分割です。大きいまま出すと、いわゆる巨大MRになってレビューしづらい。だから分割します。
ただ分割には、「どのMRを土台(main)にして、どれを積み上げる(stacked)か」という関係設計が要ります。ここを間違えると、レビューでの修正が別のMRに反映されない、といった抜け漏れが起きます。だから、修正やマージの順序まで計画に含めます。
そしてここにも制約です。計画には「触るファイル数の概算」を書いておき、実装ループ側は実際の変更がその概算の約2倍に膨らんだら、いったん止めてスコープを問い直します。さらに、計画そのものを工数・依存・リスクなどの観点から攻撃する「自己批判役」のエージェントを1体挟み、出した計画を一度疑わせています。
自動化して変わったこと
要求整理、実装計画、実装。この3つが揃うと、仕事の仕方が変わりました。
[要求整理] → [実装計画] → [実装(テスト・実機spec生成まで)] なぜ作るか 何を・どう分けて ループで自動的に回る
以前は、AIとずっと壁打ちを繰り返して、ペアプログラミングをしているような感覚でした。もちろん今も壁打ちや議論はします。でも、一度コンテキストを作ってしまえば、実装計画から先はほぼ任せきりです。しかも可能な限り、複数のトピックを同時にAIへ投げて並列で走らせています。
ただし、同時に走らせる重めのタスクは1つだけと決めています。残りは、スキルの小さな改善や重複排除、軽いリファクタリング、テスト追加、ドキュメント拡充といった、大きな判断を要さない軽めのタスクに絞る。
似たことは Peter Steinberger さんも書いていて、RAG やサブエージェントのような凝った仕組みより「ただ対話しろ(Just talk to it)」だと言い切っています。変更の影響範囲(blast radius)を見ながら複数を並列で回す感覚も近いなと思いました。
手を動かす時間は減り、代わりに指示を出す時間が増えました。投げた作業はループとして設計してあるので、単体テストと別エージェントのレビューが通るまで、勝手に進み続けます。ここでも形は同じ、ループと制約です。
体感で言うと、残業が1時間は減った気がします。私は早く家に帰る、寝る。その間もAIは働いている。これはなかなかいい状態です。
そして今、実機テストもループに入れようとしています。いわゆる HW in the Loop です。組み込みなので、最後は実物のデバイスで動かさないと安心できません。今のところは、
- テストの spec を自動生成する
- スクリプトで JLink を起動する
- 人間がデバイスに ICカードをかざす(あるいはシェルコマンドを叩く)
- そのログをAIが判定する
という形です。AIが司令塔で、人間がアクチュエータ、という役割分担になっています。
AIが「次はこの操作をして」と指示し、人間が物理的な手足としてカードをかざす。役割が逆転していて、最初は少し変な感じがしました。 もちろんこの辺りは Arduino を始めとしたマイコン、ラズベリーパイなどでモーターを回せばよい、という話はあるのですが、それでもまだボトルネックは残ります。試作機の台数に限りがあり、自動チェック専任の機械には仕立てられていません。ただ、フェーズが進めば、CIの回帰テストを「実機で正しく動くこと」まで含む形に持っていきます。
もう1つのループ
開発をループにする話は、ここまでです。あとになって、もう1つループがあることに気づきました。 それは道具(スキル)そのものを改善するループです。
たとえば、他の人の書いた記事を読んで、ためになるなと思ったらそこで得た知見を自分のスキルに取り込む。これも専用のスキル(記事取り込みスキル)にしてあります。さらに、日々の作業で得た学びを、スキル自身が「改善候補」として溜めていく仕組みを入れています。 ただ、AIが暴走して勝手に自分のルールを書き換えていくのも嫌なので、
- 改善候補は、一定回数以上・一定期間以上観測されて初めて昇格する(すぐ上げたいと思ったときは、その場で更新します)
- しばらく使われなければ降格する
- そして何より、書き換えは必ず人間がチェックする。これで、触ってはいけない凍結ルールを絶対に書き換えさせないようにしています
ここでも結局、形は同じでした。ループと制約です。
おわりに
振り返ると、私がやってきたのは「面倒くさいを一つずつ潰す」だけでした。その結果として、開発のループと、そのループを育てるループという二段構えに行き着きました。
ここで一番伝えたいのは、自動化に終わりはないということです。一つボトルネックを潰すと、それは消えてなくなるのではなく、別の場所へ移動します。push がボトルネックなら push を潰す。すると今度はコンテキスト整理がボトルネックになる。だから次はそれを潰す。この繰り返しです。
そして、この移動には続きがありました。個人の開発フローを潰しきると、ボトルネックはついに自分自身、つまりAIのアウトプットを判断する人間に移ってきたのです。一度、重めのタスクを3つ同時に走らせてみたら、Claude Code is waiting for you! という催促の声があちこちで同時に鳴り、脳内のコンテキストスイッチが追いつかずに音を上げました。今は、同時に走らせる重めのタスクは1つだけと決めています。
ここから先は、もう一人では潰しきれない気がしています。AIが量産する時代に律速になるのは、結局「検品と判断」です。そしてそれを一人で抱えるほど、詰まる。だとすれば私の次のボトルネックは、検品と責任を、個人で抱えるのではなくチームでどう分担し、共有していくか、という設計なのだと思います。
だからこそ、道具はループと制約で設計し、道具自体も育て続ける。そして人間は、空いた時間でひとつ上のレイヤー、つまり何をどこまで作るかという要求と境界の設計へ移っていく。そうやって人の手を離れても回る範囲が広がっていくのは、素直に良いことだと思います。開発の対象が、プログラムや製品そのものから、それらを生み出す環境作りにシフトしてきた感があります。
次に潰すべきボトルネックは、たぶんもう、コードの中にはあまり残っていないのかもしれません。
参考にした記事
- Peter Steinberger「Just talk to it」 — https://steipete.me/posts/just-talk-to-it 凝った仕組みより対話を、という実践。複数を並列で回す感覚や blast radius の考え方が、自分のやり方と重なっていて心強かった一本です。
- todesking「ちょっとしたアイデアをAIで長文記事にして公開するのをやめろ」 — https://zenn.dev/todesking/articles/fba4cc93baf0a9 「AIが書いたかどうかではなく、検品と責任を果たしたか」。本文で書いた制約という発想を補強してくれました(……この記事もそれなりの長さになってしまいましたが、検品と責任は果たしたつもりです)。
株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp
Akerunにご興味のある方はこちらから akerun.com










