ChatGPTからCodexに開発を指示し、そのまま作業を進めてもらう。コードを書き、テストし、エラーが出れば修正し、次の作業へ進む。最近は、ある程度まとまった開発であってもAIにかなり任せられるようになってきました。
一方で、長時間使っていると妙な問題にぶつかります。Codexそのものではなく、ChatGPTの画面が終わらないのです。
今回は、この問題を何度か経験した結果、「ChatGPTに開発を最後まで見届けさせる必要はない」という結論にたどり着いた話です。
Codexは動いている。でもChatGPTが終わらない
私の環境では、ChatGPTをフロントエンドとして使い、Development MCP経由でVPS上のCodexに開発作業を渡しています。短時間の作業なら特に問題ありませんが、開発が長くなるとChatGPTの画面上に、Codexの起動、状態確認、ツール実行、ログ取得、テスト結果、次の判断といった処理が次々と表示されます。
そして、しばらくすると挙動がおかしくなることがあります。作業中を示す文字が明暗を繰り返したまま先へ進まない。一瞬だけ完了画面が見えたと思ったら、また作業ログの画面へ戻る。停止ボタンを押しても、思考中のような表示が残ることもあります。
仕方なくいったん停止し、「開発状況を教えて」と改めて聞く。ところが、それも思考中から進まない。もう一度停止して、同じ質問を送り直す。そんなことが何度かありました。
ブラウザ版だけの問題かと思いましたが、アプリ版でも似た現象は起きます。Chatを開きっぱなしにしておけば解決するわけでもなく、逆に閉じていたChatを後から開いたら、普通に完了結果が表示されていることもあります。
そこで疑問が出てきました。本当に止まっているのはCodexなのか。それとも、ChatGPTの画面だけなのか。
「開発が止まった」と「画面が止まった」は別だった
Development MCP側を確認すると、Resident Codexには、タスクを開始する機能、状態を取得する機能、追加メッセージを送る機能、タスクをキャンセルする機能が分離して存在しています。
つまり、Codexの開発タスクそのものは、ChatGPTの1回のレスポンスと同じ寿命を持つ必要がありません。ChatGPTがCodexを起動し、Codex側でタスクが受理されたあと、ChatGPTのレスポンスが終了してもResident CodexはVPS上で作業を継続できます。
これまで私は、なんとなく次のような流れを一つのChatGPTレスポンスとして扱っていました。
ChatGPT
↓
Codexを起動
↓
開発
↓
状態確認
↓
開発
↓
テスト
↓
状態確認
↓
完了
しかし、実際にはこうで構いません。
ChatGPT
↓
Codexを起動
↓
正常開始を確認
↓
ChatGPTの応答終了
--------------------
Resident Codex
↓
開発
↓
テスト
↓
修正
↓
完了
ホスト側のChatGPTが、最後まで横で見ている必要はなかったのです。
ボトルネックは「Codex」ではなく「長時間Chatレスポンス」
長時間のAI開発で問題が起きると、モデルの推論速度、コンテキスト長、VPSのCPUやメモリなどを疑いたくなります。もちろん、それらが原因になるケースもあります。
ただ、今回のケースでは別のボトルネックがありました。ChatGPTの1レスポンスを、長時間動き続ける開発コンソールとして使っていたことです。
長時間の開発では、ChatGPT側でも大量のイベントを扱います。MCPを呼び出し、結果を受け取り、モデルが次の判断をし、再びMCPを呼び出す。ログを表示し、さらに次の処理へ進む。これが数十分続けば、Chat画面側には長い実行履歴が積み上がります。
どこで不安定になっているのかを完全に特定したわけではありません。表示の問題なのか、ストリームの再接続なのか、クライアントとサーバー間の状態同期なのか、それ以外なのかは分かりません。
ただし、原因を完全に突き止めなくても、問題そのものを避けることはできます。そもそも長時間レスポンスを維持しなければよいからです。
「開発を開始して」でChatGPTを終わらせる
そこで、Codexへ開発を依頼するときの運用を変えることにしました。ホストChatGPTの仕事を、Resident Codexへのタスク投入と正常開始の確認までに限定します。
例えば、次のように指示します。
Resident Codexで開発を開始してください。今回はResident Codexへのタスク投入と正常開始の確認までをホストChatGPTの仕事とします。開始後の進捗ポーリング、ログ追跡、完了待機は行わず、task IDと初期状態を確認した時点でこのレスポンスを終了してください。Codex側は独立して承認境界または完了まで開発を継続してください。
特に重要なのは、「task IDと正常開始を確認した時点で、このChatGPTレスポンスを終了する」という部分です。
すると、ホストChatGPT側は、
Resident Codexへ開発タスクを投入しました。
Task ID: codextask_xxxxx
Status: running
Codex側で独立して開発を継続しています。
程度を返して、そのターンを終了できます。開発そのものは、その後もVPS上で続きます。
状況を知りたいときだけ確認する
開発開始後、ChatGPTがずっと監視している必要もありません。状況が知りたくなったら、その時点で「開発状況を確認して」と送ればよいだけです。
そのタイミングでResident Codexの状態を1回取得し、RUNNING、DONE、FAILED、WAITING_APPROVALといった状態を確認して結果だけ返します。
こうすると、ChatGPT側のレスポンスは毎回短くなります。開発開始時のレスポンス、状態確認時のレスポンス、承認時のレスポンス。それぞれを独立させるわけです。
「15分後に確認して」も、実は避けた方がよい
以前は、「Codexで開発を続けて。15分後に進捗を確認して」といった指示をよく使っていました。実際、15分後の確認結果まで正常に返ってくることもあります。
ただ、この方式ではホストChatGPT側が長時間実行状態を維持する可能性があります。つまり、Codexを開始したあと、ChatGPTが待機し、15分後に状態を取得して回答するという流れです。
これは、今回避けたい構造そのものです。
それなら、Codexを開始した時点でChatGPTのレスポンスを終了し、必要になったときに新しいレスポンスで状態を確認した方が単純です。
さらに言えば、「15分後に人間が確認する」という作業そのものも、最終的には自動化できます。
ChatGPTのStopとCodexのStopも分けられる
この構造にすると、もう一つメリットがあります。ChatGPTの停止とCodexの停止を分離できることです。
これまでは、ChatGPTの画面がおかしくなってStopを押すと、「これでCodexまで止まっていないか」と不安になります。
しかしResident Codexが独立したタスクとして動いているなら、ChatGPT側のレスポンスを停止しても、Codex側はそのまま動き続けられます。
ChatGPTのレスポンス
↓
Stop
Resident Codex
↓
running
↓
running
Codexを本当に止めたい場合だけ、Codexタスクを明示的にキャンセルすればよい。UIの不具合と、実際の開発停止を分離できるわけです。
ChatGPTは「ターミナル」ではなく「制御盤」にする
今回の変更を一言で表すなら、ChatGPTをターミナルとして使うのをやめ、制御盤として使うということになります。
ChatGPT自身が何十分もログを表示し続ける必要はありません。必要なのは、何を実行するか決めること、Codexへ仕事を渡すこと、正常に開始したことを確認すること、必要に応じて状態を取得すること、承認が必要なら人間へ提示することです。
実際の開発作業はCodex側が担当します。その方が、役割分担としても自然です。
次は「状況を確認して」すら不要にしたい
ここまで来ると、次に気になる部分も明確になります。今はまだ、人間が「そろそろ終わったかな」と思ったタイミングで、「状況を確認して」とChatGPTへ聞いています。
これも本来は自動化できます。Resident Codexの状態がRUNNINGからDONEに変わったとき、あるいはWAITING_APPROVALやFAILEDになったときだけ通知すればよいのです。
例えば、次のような構成です。
Resident Codex
↓
Status
↓
Watcher
↓
Slack / Discord
しかも、CodexのターミナルログをすべてSlackやDiscordへ流す必要はありません。通知したいのは、完了した、失敗した、承認が必要になった、長時間進捗がなく停止している可能性がある、といった状態変化だけです。
そうなれば、「開発を開始して」と指示した後はChatGPTを閉じても構いません。数十分後にスマートフォンへ完了通知が届き、必要ならそこから再びChatGPTを開いて次の判断をする。
私が最初から目指していた「どこからでもAIに開発を指示できる環境」は、むしろこちらの構成の方が近そうです。
長時間AI作業では「レスポンス」と「タスク」を分ける
今回の問題から得た一番大きな教訓は、長時間作業を、長時間Chatレスポンスとして実行しないということです。
数分で終わる処理なら、ChatGPTがその場で最後まで実施しても問題ありません。しかし、数十分から数時間かかる開発まで、一つのChatレスポンスとして抱え続ける必要はありません。
ChatGPTは仕事を開始する。実行系は独立して動く。ChatGPTはいったん終了する。必要なときだけ状態を見る。
この構造にすると、Chat画面の安定性と実際の開発処理を切り離せます。
AIに長時間作業を任せる時代には、「AIに何をさせるか」だけでなく、「その処理をどの寿命の単位で動かすか」も設計対象になるようです。
今回、Codexを長時間使っていて問題になったのは、Codex自身ではありませんでした。
ボトルネックになっていたのは、Codexを最後まで見届けようとしていたChat画面の方でした。
次は、このResident Codexの状態を監視し、SlackやDiscordへ必要なときだけ通知する層を作ってみようと思います。


コメント