Epic の sub-issue に `S-N-A` / `S-N-H` の通し番号 prefix を付けて AI エージェントと人間で開発を分担する
Epic issue を複数の sub-issue に分割してから実装に入るとき、Claude Code や OpenAI Codex のような AI エージェントに任せる sub-issue と、人間が手を動かす sub-issue が混ざる状態が増えてきました。ここでの「AI エージェント」は、issue 本文と関連コードを読み、ブランチを切って PR を投げるところまでを担うコーディングエージェントを指しています。
以前は sub-issue 単位で担当を分けきれておらず、1 つの sub-issue の本文チェックリストの中に AI エージェントに任せられるタスクと、人間しか手を出せないタスク(本番相当のクレデンシャル更新、外部連携先との調整、UX 上の判断など)が混在していました。エージェントは自分で処理できるチェックボックスだけ埋めて PR を返してくるので、残りのチェックボックスを人間が拾いに戻る前提だったのですが、実際にはその「拾いに戻る」動きが後回しになり、close できずに残る sub-issue が積み上がっていきました。
これを解消するために、sub-issue のタイトル冒頭に付けている通し番号 prefix (S-1, S-2 …) の後ろに -A(Agent)または -H(Human)を続けて、S-1-A / S-1-H のような形にする運用に切り替えました。S-N は 1 つの作業単位を表し、その中で AI エージェント担当分を S-N-A、人間担当分を S-N-H の別 sub-issue に分けます。両方が要る作業では S-N-A と S-N-H を並べて立て、片方だけで完結する作業ではどちらか一方だけを立てます。1 つの sub-issue の中身が必ず単独担当で完結するので、以前の「AI が終わっているのに close できずに残る sub-issue」が発生しなくなりました。以下、そのルールと理由をまとめます。
通し番号 prefix に付ける形にした理由
sub-issue の担当区分を明示する場所は他にもあります。ラベルを新設する、assignee を「AI エージェント担当」用の bot アカウントと人間で分ける、GitHub Projects 上のカスタムフィールドで持つ、といった選択肢があります。ただし、うちではラベル運用や専用 assignee は導入せず、sub-issue 機能 の通し番号 prefix に -A / -H を付けるだけにしています。
通し番号 prefix はタイトルの一部として表示先を選ばずに残ります。sub-issue の一覧、Projects のボード、通知メールの件名、Slack の GitHub 連携 経由の投稿、そして PR タイトル(後述するように sub-issue のタイトルをそのまま流用することが多い)まで、追加の設定なしに S-N-A / S-N-H が視野に入ります。
このシンプルさが、日々複数の repo で多数の issue を横断して追いかける立場でも、1 つの Epic の実装を進めるメンバーの立場でも、状況把握のコストを揃えてくれます。デイリースタンドアップやチームミーティングで Epic 全体を並べて見るときに、-A と -H の並びだけで「今この Epic は人間側で詰まっている」といった話ができるようになりました。
実際の命名ルール
命名は 3 点だけ決めています。
1 点目は、S-N を「1 つの作業単位」を指す通し番号として扱い、その末尾に -A または -H を付けて sub-issue を立てる、というものです。1 つの作業に AI エージェントの手番と人間の手番の両方が要るときは、S-N-A と S-N-H の 2 本を並べて立てて、それぞれ独立に close します。片方だけで完結する作業では、対応する片方だけを立てます。Epic の親 issue にはこの suffix は付けません。Epic は分担の単位ではなく、複数の sub-issue をまとめる単位だからです。
2 点目は、-A は「AI エージェントが単独で完了させる想定の sub-issue」、-H は「人間が単独で完了させる想定の sub-issue」を指す、というものです。両方が並ぶ S-N-A / S-N-H の場合も、それぞれの sub-issue の中身は担当が単独で完了させられる形に切り分けます。close 条件を混ぜないためです。
3 点目は、担当が途中で切り替わった場合の扱いです。たとえば S-3-A として着手した sub-issue で AI エージェントが 2 回連続で PR を通せなかった場合は、そのまま S-3-A で頑張らせるのではなく、末尾を -H に書き換えて S-3-H として人間が引き取るか、S-3-A をそのまま close し隣に S-3-H を新設するかのどちらかにします。通し番号 S-3 は共通で残るので、Epic 一覧を眺めれば、同じ作業単位に対する Agent 側と Human 側の状況が縦に揃って読めます。
タイトルの例は以下のような形になります。S-2 は 1 つの作業単位を -A と -H の 2 本に分けている例です。
[Epic] 決済画面のリファクタリング
├─ S-1-A [feat] Stripe Webhook の型定義を openapi-typescript で自動生成
├─ S-2-A [feat] 決済失敗時のリトライダイアログを追加
├─ S-2-H [chore] 決済失敗時ダイアログのコピー・アクセシビリティ最終確認
├─ S-3-H [refactor] レガシー PaymentGateway クラスの責務分割
└─ S-4-H [chore] ステージング環境の Stripe テストキー再発行-A と -H の切り分けの目安
どちらに振るかは、以下の 4 つの観点で判断しています。基準は絶対ではなく、Epic ごとに見直します。
1 つ目は、変更対象の局所性です。1〜3 ファイルの範囲で完結し、既存テストで挙動が固定されている変更は -A に寄せます。逆に、複数モジュールをまたぐ責務再分配や、対象範囲を決めること自体が判断を要する変更は -H に置きます。
2 つ目は、外部システムやシークレットに触るかどうかです。本番相当のクレデンシャル・課金アカウント・不可逆な API 呼び出しを含む sub-issue は -H にします。エージェントに一切触らせない、というよりは、承認を挟む位置を明示的に人間側に固定するための切り分けです。
3 つ目は、要件の曖昧さです。「ユーザー体験としてどこまで作り込むか」が sub-issue 内で判断を要する場合は -H にします。エージェントは書かれた要件どおりに実装しますが、要件の妥当性そのものを問い直す動きは苦手なので、判断を含む部分は人間側に残します。
4 つ目は、レビュー負荷の非対称性です。書くのが速くてもレビューに時間がかかる sub-issue(アーキテクチャの選択が伴うものなど)は -A で下書きさせるより、-H で人間が書いた方が結果的にサイクル全体が短くなります。逆に、type 定義の生成や CRUD エンドポイントの追加のように、書くのは面倒だがレビューは軽い sub-issue は、-A に振り分けたときにサイクル全体の時間短縮効果が出やすい領域です。
PR タイトルへの流し込み
sub-issue のタイトルは PR タイトルにそのまま使うことが多いので、S-N-A / S-N-H prefix は PR タイトルにもそのまま残る運用です。エージェントが立てた PR には S-N-A、人間が立てた PR には S-N-H が付きます。
これによって、コードレビューの場面でも「AI エージェントが書いた PR かどうか」が事前に分かります。Claude Code や Codex が書いた PR は、レビュー観点として「ハルシネーションによる架空 API 呼び出し」「テストの assertion が実装と同じ思い込みに寄っていないか」「エラーハンドリングが過剰・過少になっていないか」を優先的に確認するようにしています。人間が書いた PR とは違うレビュー方針を差し込む前提で、PR タイトルの prefix を目印として使う形です。
検索性を求めるならラベル併用も選択肢
この運用は数チームで並行して回していますが、正式なガイドラインとしてドキュメント化しているわけではなく、Epic ごとにローカルルールとして周知しています。私自身はいまのところ視認性だけで足りていて、検索性や自動化の物足りなさは感じていません。ただ、集計や GitHub Actions などの自動化フックを効かせたいチームであれば、-A / -H に対応する agent / human ラベルを併用する発展形はアイデアとして選択肢に入ると思います。ラベル側は label:agent is:open のような検索でそのまま拾えますし、Projects の自動化ルールとも噛み合います。私はタイトルの視認だけで意思決定できているのでラベルは付けていない、というだけです。
以上、Epic の sub-issue の通し番号 prefix に -A / -H を付けて AI エージェントと人間の分担を GitHub 上で一目で読めるようにした、現場からお送りしました。