この記事で伝えたいこと
Codex などの AI コーディングエージェントを使うと、コードを書く時間そのものは短くなる。一方で、実際に使い込むほど「エージェントへ指示を出す」「結果を確認する」「失敗したら再実行する」「別の作業をもう一つ投げる」といった運用に時間を取られるようになった。
気がつくと PC の前に張り付き、ターミナルを 4 窓から 8 窓くらい開き、どの作業がどこまで進んでいるのかを追い続けていた。これはこれで便利ではあるが、開発体験としてはまだ人間がかなり忙しい。
そこで、GitHub Issue をキューとして使い、VPS 上の agent runner が Codex CLI を非対話で動かす仕組みを作った。この記事ではプログラムの細部ではなく、なぜ作ったのか、GitHub Actions と何が違うのか、どんな構成で動かしているのか、そして何が変わったのかを整理する。
「agent runner」 はあくまで自作のプロダクト名であり、前回の記事 さくらのサーバーでCodexをcronで動かしてブログ記事を自動リライトさせる をさらに進化させた形である。
想定読者
この記事は、すでに AI コーディングエージェントを使っている開発者に向けて書いている。
特に次のような人を想定する。
- Codex CLI や Claude Code などのエージェントを日常的に使っている
- ターミナルを複数開いて並行作業している
- GitHub Issue や PR を開発の入口として使っている
- CI/CD とは別に、AI エージェントへの作業依頼をうまく管理したい
導入: AI 駆動開発は便利だが、人間が忙しい
AI コーディングエージェントを使うと、実装、調査、テスト修正、ドキュメント作成などをかなり任せられる。
ただし、使えば使うほど別の課題が出てくる。
- ターミナルをいくつも開いて、複数のエージェント作業を見張る必要がある
- どの作業に何を指示したか分からなくなりやすい
- 失敗した作業を再投入するたびに、文脈を思い出して指示し直す必要がある
- PC の前にいないと、次の指示を出しにくい
エージェントは作業を進めてくれる。しかし、作業を投げる入口がターミナルに閉じていると、人間は結局ターミナルの前から離れにくい。
この状態を変えたかった。
なぜ Codex GitHub Action ではないのか
最初に考える選択肢は GitHub Actions だと思う。GitHub のイベントをトリガーにして処理を走らせるなら、Actions は自然な選択肢だ。
Codex GitHub Action や Claude Code GitHub Actions なるものがリリースされているので、それを使おうかとも考えた。
ただ、こちらの条件とは少し合わなかった。
まず、Codex GitHub Action には利用時間の制約がある。便利ではあるが、「あと何分使えるか」を考えながら作業依頼を出すのは、自分が欲しかった体験とは違った。
また、Actions から動かす場合は Codex API を使う前提になり、さらに課金が発生する。もちろん必要な場面ではそれでよいが、今回は手元や VPS で使っている Codex CLI をそのまま活かしたかった。
だから、GitHub Actions が悪いという話ではない。Actions は決まった処理を、GitHub のイベントに応じて即時に走らせる仕組みとして非常に強い。
一方で、今回作りたかったのは「GitHub Issue を操作盤にして、開発作業そのものをエージェントへ渡す仕組み」だった。
作ったものの全体像
作ったものは、GitHub Issue や PR に実行待ちの状態を付けると、VPS 上の runner がそれを検知し、Codex CLI を非対話で実行する仕組みだ。
「実行待ち」の状態をどうやって表現するかだが、ここでは GitHub のラベル機能を利用して codex:queued codex:done codex:running codex:failed のように状態管理することにした。
大まかな流れは次のようになる。
- GitHub Issue にやってほしいことを書く
- Issue にラベル
codex:queuedを付けて実行待ちにする - VPS 上の agent runner が定期的に GitHub を確認する
- 対象を見つけたら作業用ブランチを用意する
- Codex CLI を非対話で実行する
- 必要な確認を行う
- 変更があればコミットし、PR を作成する
- 結果を Issue / PR に残す
構成図は次のようなイメージになる。
ポイントは、GitHub を「指令を出す場所」と「結果を見る場所」にしていることだ。ターミナルではなく GitHub Issue を入口にすることで、PC からでもスマホからでも同じように作業を投げられる。
サーバー構成と必要なもの
必要なものは次のようになる。
- VPS
- GitHub CLI
- Codex CLI
- systemd timer
- agent runner 本体
- GitHub にアクセスするための認証
- 作業対象を限定するための設定
runner は VPS 上で定期的に起動し、GitHub CLI を通じて Issue / PR を確認する。対象があれば Codex CLI に依頼内容を渡し、作業結果を GitHub 側へ戻す。
要するに Issues をポーリングして、Codex CLIに渡していることが格となる。
VPSでなくとも自宅のPCでも良いが、私の場合はエージェント管理を少しでも切り離したかったためVPSを契約した。サクラサーバーのメモリ1GBの年額1万円程度のスペックで十分動く。
また、systemd timer は cronに置き換えても良い。
サーバーに常駐させることで、手元の PC を開いていなくても作業を進められる。ここが大きい。
実行フロー
具体的なプログラム詳細は省くが、全体の流れはシンプルだ。
まず、GitHub Issue に作業内容を書く。次に、その Issue を runner の処理対象にする。runner は定期的に GitHub を見に行き、対象があれば実行中の状態へ移す。
その後、runner は対象リポジトリの作業場を用意し、ベースブランチから作業ブランチを作る。Codex CLI は Issue 本文やコメント、ブランチ情報、許可された作業範囲などを受け取り、非対話で作業を進める。
作業が終わったら、runner は必要に応じてテストや確認コマンドを実行する。変更があればコミットし、リモートへ push し、PR を作成する。完了したら GitHub 上の状態を更新する。失敗した場合も、失敗として分かる状態にして止める。
重要なのは、失敗時に勝手に何度も retry しないことだ。AI エージェントは便利だが、何でも自動で回し続けると危険な場合がある。失敗したら人間が確認して、必要なら再投入するくらいが扱いやすい。
GitHub Actions との違い
GitHub Actions との一番分かりやすい違いは、トリガーの性質だ。
Actions は GitHub のイベントに反応して即時に動く。push、pull request、workflow dispatch など、決まったきっかけに対して決まった処理を走らせるのに向いている。
一方、この agent runner はポーリングで動く。つまり、GitHub を定期的に見に行くため、Actions のような即時性はない。数分程度の遅延が発生する前提の仕組みだ。
ただ、その代わりに「開発作業をキューに入れる」という感覚で使える。
Actions は CI/CD の実行基盤。agent runner は、GitHub Issue を入口にして AI エージェントへ開発作業を渡すための運用基盤。このように役割が違う。
お金や仕組みにこだわらなければ、CI の中で同じようなことをしてもよいと思う。この記事で伝えたいのは「自前ポーリングが最強」という話ではない。
本質は、スマホひとつで Issue を作り、そこから PR 作成まで進められる開発体験の変化にある。
何が変わったか
一番大きい変化は、PC の前に張り付かなくてよくなったことだろう。
以前は、複数のターミナルを開き、それぞれのエージェント作業を見ながら、完了したら次の指示を出していた。これは便利ではあるが、常に人間がエージェントの進行管理をしている感覚があった。
agent runner を作ってからは、作業を GitHub Issue に積めるようになった。
スマホからでも Issue を作れる。ラベルを付ければ、あとは VPS 上の runner が拾ってくれる。結果は GitHub に戻ってくる。PR までできていれば、レビューすればよい。
これはかなり体験が変わる。私の言葉では「世界線が変わった」と言っても過言ではない。
Claude Code による AI 駆動開発入門 を読んでいると同じようなことを GitHub Actionsで実現していた。
そこではAI 駆動開発をパラダイムシフトと表現していた。実際にこの仕組みを使うと、その感覚にかなり近いものがある。とうとう次の時代に入った感じだ。
AI がコードを書けること自体も大きい。しかし、それ以上に「開発の入口が PC のターミナルから GitHub Issue に移る」ことのインパクトはさらに大きかった。
運用上の安全策
Issue 投稿とラベル操作だけで処理が進む仕組みは便利だが、当然リスクもあるので注意が必要。
自分だけのプライベートリポジトリであれば、ある程度シンプルな運用でも問題になりにくい。しかし、チーム開発で使う場合は、誰が作った Issue をエージェントに渡してよいのか、誰が実行対象にできるのかを厳格に考える必要がある。
最低限、次のような安全策は必要になる。
- 対象リポジトリを設定で限定する
- protected branch に直接 push しない
- 作業ブランチを作って PR 経由にする
- 同じ Issue / PR を多重実行しない
- 失敗時は自動 retry せず、人間が確認できる状態で止める
- トークンや秘密情報は記事やログに出さない
- チーム利用では、実行を許可する作成者や操作者を制限する
AI エージェントに任せる範囲が広がるほど、入口の権限管理が重要になる。
まとめ
この仕組みを作って一番よかったのは、開発作業をキュー化できるようになったことだ。
ターミナルを何窓も開いて、エージェントの進行を見張り続ける必要が減った。PC の前にいなくても、スマホから GitHub Issue を作れば作業を依頼できる。うまくいけば PR まで作られる。
これは、単に CI を自作したという話ではない。
開発の入口が変わった話だ。
GitHub Issue にやりたいことを書き、AI エージェントがそれを拾い、PR まで持ってくる。個人開発や小規模チームでは、この非同期な開発スタイルはかなり効く。
