最近、「AIハーネス」という言葉を知りました。
最初は「また新しいAI用語が出てきたな」くらいに思っていたのですが、調べているうちに、だんだん見覚えのある話になってきました。
これ、YAMATOでやっていることでは?
YAMATOを作り始めたころ、AIハーネスという言葉は知りませんでした。やりたかったのは、iPhoneからChatGPTに頼んだ仕事を、そのままMac miniで進めることです。
ところが実際にAIへ開発を任せてみると、作業場所を分けたくなり、GitHubに仕事を残したくなり、最後には本当に動いたのか確認する仕組みまで必要になりました。
困るたびに一つずつ直していったら、いつの間にか今のYAMATOになっていました。
今回は、なぜこの形になったのかを、実際のアプリ開発も交えながら書いてみます。
「AIハーネス」という言葉を知った
最近、「AIハーネス」という言葉を知りました。
最初は、また新しいAI用語が出てきたのだと思っていました。ところが調べてみると、LLMにツールや実行環境を与え、仕事の状態を管理しながら結果を検証する仕組みを指しているようです。説明を読み進めるうちに、だんだん見覚えのある話になってきました。
これ、YAMATOでやっていることでは?
僕はここ数か月、ChatGPTからMac miniへ開発作業を渡し、その先でCodexやClaude Codeに実装させる仕組みを作ってきました。ただし、AIハーネスを作ろうと思ったことは一度もありません。そもそも、その言葉自体を最近まで知りませんでした。
では、なぜ今のYAMATOはAIハーネスと呼べるような形になったのか。
振り返ってみると、最初から設計図があったわけではありません。AIに実際の仕事を任せようとするたびに問題が起き、そのたびに必要なものを足してきた結果でした。
最初は、iPhoneから開発したかっただけ
始まりはかなり単純です。
「iPhoneからChatGPTに頼んだら、そのままMac miniで開発まで進められないだろうか」
当時から、ChatGPTにコードを書いてもらうことはできました。生成されたコードをXcodeへ貼り、エラーが出れば、その内容をもう一度ChatGPTへ渡せばいいからです。
ただ、この使い方では結局Macの前に座る必要があります。
Xcodeを開いて対象ファイルを探し、コードを反映します。そのあとビルドして、Gitの状態を確認し、必要ならcommitしてpushします。場合によってはPRも自分で作らなければなりません。
つまり、AIにコードを書いてもらっても、その前後にある開発作業はかなり残っていました。
そこで考えたのが、コードを書く部分だけではなく、その周囲にある作業までまとめてAIへ渡すことです。常時動かしているMac miniを使い、ChatGPTからその先へ仕事を流せれば、iPhoneからでも開発を進められるのではないかと考えました。
ところが、実際にやってみると、コード生成とは別の問題が次々に出てきます。
mainを直接触らせるのは怖い
最初に困ったのは、AIにどこで作業させるかでした。
いくら便利でも、mainを直接変更できる状態にはしたくありません。別の作業と変更が混ざるのも困りますし、途中で失敗したときに元の環境まで壊れると復旧にも時間がかかります。
そこで、作業ごとにGit Worktreeを用意するようにしました。AIはその仕事専用のWorktreeでコードを変更するため、別のIssueで進んでいる作業とは混ざりません。もし途中で失敗しても、mainまで巻き込む可能性を抑えられます。
これはAIの精度を上げるために追加したものではありません。AIが失敗することを前提に、影響する範囲を狭くするために必要でした。
チャットだけでは、仕事の状態が分からなくなる
次に困ったのは、何を頼んだのかを残す場所です。
ChatGPTとの会話だけで開発を進めていると、依頼内容も途中で決めたことも、すべてチャットの中へ入っていきます。その日のうちは問題なくても、数日後に続きを始めようとすると、「何を直そうとしていたのか」「どこまで終わっていたのか」を会話から探し直すことになります。
そこで、開発作業はGitHub Issueへ残すようにしました。
不具合なら、起きている現象を書きます。修正する範囲も決めます。さらに、壊してはいけない部分や、何を確認できれば完了なのかもIssueへ入れます。
こうすると、ChatGPTとの会話が切れても仕事そのものはGitHubに残ります。また、AI側から見ても、開発を始めるときに確認する場所を一つにできます。
こうして、GitHubが仕事の正本になりました。
AIが「終わりました」と言っても、本当に終わったとは限らない
作業場所と依頼の置き場所を決めれば終わりかと思ったのですが、まだ問題は残りました。
AIが「実装しました」と報告しても、その変更が本当に使えるとは限りません。ビルドが通っていない場合もありますし、要求した内容と違っていることもあります。さらに、修正した場所とは別の機能を壊している可能性もあります。
そのため、実装と確認を分ける必要が出てきました。
現在のYAMATOでは、Ubuntu Docker Executorで作業したあと、必要に応じてMac側でも検証します。僕が開発しているものにはiOSアプリがあるため、Xcodeを使った確認はDockerだけでは完結しません。
つまり、ファイルを書き換えられたことと、その変更が実際に動くことは別です。その二つを分けて扱うために、YAMATOにはVerifyの工程が入りました。
完了ではなく、結果を残すようにした
さらに、完了の扱いも変えました。
Draft PRが作られたからといって、その変更を採用してよいとは限りません。YAMATOがDONEになった場合も同じです。
そこで、作業を始める前に成功条件を決め、実行後にはResultを残すようにしました。そして、そのResultを最初の成功条件と照らし合わせます。
これによって、AIが作業を終えたことと、その変更を採用してよいことを分けられるようになりました。実装はAIに任せても、採用するかどうかの判断までは自動化していません。
CodexとClaude Codeを使い始めたら、今度は振り分けが必要になった
その後、CodexとClaude Codeの両方を使うようになると、今度は「どちらに任せるか」という判断が増えました。
最初のうちは、ChatGPTへ依頼したあとに「今回はCodexで」「これはClaude Codeで」と自分で決めていました。ただ、実装そのものをAIへ任せているのに、その手前の振り分けだけを毎回人間がやるのも面倒です。
そこで、YAMATO 3.2ではCodexとClaude Codeを正式なExecutorとして扱い、Task Contractから次の指定を使えるようにしました。
auto
codex
claude-code
codexを指定すればCodexへ渡し、claude-codeならClaude Codeへ渡します。一方、autoの場合は、そのまま実行には進まず、利用できるExecutorや作業内容などを確認したうえで、実行前にどちらを使うか決めます。
こうして、以前は人間が行っていた振り分けもYAMATO側へ移しました。
ここまでを振り返ると、途中で目標が変わったわけではありません。
最初から最後まで、やりたかったのは「AIに実際の開発作業を任せること」です。ただ、それを本当にやろうとすると、仕事を置く場所、作業する場所、検証する仕組み、結果を残す方法などが必要になりました。
それらを足していった結果、現在のYAMATOがあります。
現在|今は、iPhoneから依頼して結果を見るところまでつながった
現在は、開発作業をiPhoneから始められます。
たとえば、「記 -Shirushi-」で表示した写真を、ピンチ操作で拡大できるようにしたいとします。
まずChloeへ要望を伝えます。そこで、どの画面を対象にするのか、既存の操作へ影響しないか、何を確認できれば完了とするのかを決めます。
開発作業として内容が固まればGitHub Issueへ移し、その先をYAMATOへ渡します。
YAMATOはIssueを受け取ると、利用するExecutorを決め、専用のWorktreeで実装を進めます。その後、必要なテストを行い、Macで確認しなければならない内容があれば、そこまで処理します。最後にGitHubへ結果を戻し、Draft PRとResultを残します。
現在の流れを一枚にしたものが、次の図です。
図にすると工程は多く見えますが、僕から見た使い方はかなり単純になりました。
以前なら、ChatGPTへ相談したあとにMacの前へ移動し、対象ファイルを探していました。その後もbranchを用意し、コードを反映してビルドし、Gitの状態を確認してpushします。途中でAIの処理が止まれば、どこまで進んだのかも自分で調べていました。
現在は、その途中にあった作業の多くをYAMATOへ渡しています。
自分でコードをXcodeへ貼ることはなくなりましたし、どのファイルを変更するのかを毎回探す場面も減りました。また、CodexとClaude Codeのどちらを使うかも、以前ほど意識しなくなっています。
その一方で、自分がやることがなくなったわけではありません。
むしろ、何を作るのか、どこまでできれば完成なのか、実際に使ったときに問題はないか、その変更を採用するのかといった判断は、以前より意識するようになりました。
YAMATOによって減ったのは、開発に必要な判断ではありません。判断したあとに発生していた作業です。
実際のアプリ開発で使うと、違いが分かりやすい
「記 -Shirushi-」のVersion 8.0を作っていたとき、左メニューの操作を何度か変更しました。
最初に実装したものをTestFlightで使ってみると、左端から一定量スワイプしたあとにメニューが開く方式では、求めていた操作感になりませんでした。
そこで次のIssueでは、単に「もっと使いやすくする」とは書かず、実際にどう動いてほしいのかを具体的にしました。
指を右へ動かしている間は、左メニューもその動きについてくるようにします。また、移動量に合わせて背景表示も変えます。指を離したときは、それまでの移動量や速度を見て開閉を決めます。
ただし、メニューの動きだけを直せばよいわけではありません。HomeやCalendarでは縦スクロールを壊さず、Mapではpanやzoomを優先します。さらに、詳細画面ではNavigationStackの戻る操作を邪魔しないようにします。
このように、作りたい動きと、残したい操作の両方をIssueへ入れました。
あとはYAMATOへ渡し、実装されたものをTestFlightで確認します。使ってみて違和感が残っていれば、その内容を次のIssueへ入れて修正します。
この流れになってから、Swiftのコードを一行ずつ自分で書く場面はかなり減りました。
その一方で、実機を触る時間は減っていません。むしろ、コードそのものを見る時間が減った分、「実際に使うとどうなのか」を確認する割合が増えています。
ここまで来て、ようやくAIハーネスという言葉とYAMATOがつながりました。
AIに実仕事を任せるために、その都度必要になったものを追加してきました。その結果をまとめて見ると、AIを実行環境へ接続し、仕事を管理し、検証し、人間へ結果を戻す仕組みになっています。
つまり、最初からAIハーネスを作ったのではありません。
AIに仕事を任せ続けていたら、AIハーネスが必要になったのです。
AIハーネスそのものも、AIを使って作っていた
さらに振り返ってみると、YAMATO自体の作り方にも同じことが言えます。
RunnerやExecutorの振り分け処理を、僕が最初から自分で書いたわけではありません。実際に使って問題が見つかれば、AIと原因を調べ、どう直すかを決め、その修正もAIへ渡してきました。
たとえば、途中で処理が止まれば、その理由を調べます。安全性に不安があれば、どこで作業を分離すべきかを考えます。Claude Codeを使いたくなれば、Executorとして接続する方法を検討します。毎回Executorを指定するのが面倒になれば、自動で振り分けられるようにします。
そして、修正したら終わりではありません。実際の仕事で再び使い、そこで問題が出れば、また直します。
YAMATO 3.2の完成図を最初に作り、それに沿って実装してきたわけではありません。
実仕事の中で困ったことがあり、その都度AIを使って直してきました。
結果として、AIに仕事を任せるためのAIハーネスを、AIと一緒に作っていたことになります。
次のAIが出ても、開発の仕組みまで作り直したくない
今後、CodexやClaude Code以外のAIを使うこともあると思います。
そのとき、新しいAIが出るたびに開発環境まで一から作り直すつもりはありません。新しいAIをExecutorとしてYAMATOへ接続し、今ある開発経路をそのまま使えた方が都合がいいからです。
仕事はGitHub Issueから受け取ります。実装するときは専用の場所へ分け、必要な検証を通します。その後、GitHubへ結果を戻し、公開や本番反映など人間が判断したいところでは止めます。
この流れは、使うAIが変わっても残せます。
そして、新しいExecutorをYAMATOへ接続するときも、その実装にはAIを使うはずです。新しいAIが登場したら、そのAI自身にYAMATOへ接続するコードを書かせることも考えられます。
数か月前、僕はAIハーネスという言葉を知りませんでした。
やりたかったのは、iPhoneからChatGPTへ頼んだ仕事を、そのままMac miniで進めることです。
実際に始めてみると、仕事を残すためにGitHub Issueが必要になりました。安全に作業するためにWorktreeを使い、実装したものを確認するためにVerifyを入れました。さらに、結果を判断できるようにResultを残し、CodexとClaude Codeを使い分けるためにExecutorの振り分けも加えました。
そうして出来上がったものに、あとから「AIハーネス」という名前があることを知りました。
僕の場合、AIハーネスを作ろうとして作ったわけではありません。
AIに実際の仕事を任せようとした結果、必要になったものをAIと一緒に作っていったら、いつの間にかAIハーネスになっていました。
