この記事の目的
ChatGPTのGPT-5.5 Pro(高推論設定)はソフトウェア設計で高い能力を発揮するがcodexでは使用できず、筆者の運用では計画立案をチャット上で行っている。筆者はこれまでチャットでISSUE群のファイルを作成し、スクリプトでGithubに登録していた。
この記事は、ChatGPTのチャットからGitHub Issueを直接作成し、そのIssueをCodex CLIの/goalに渡して実装を進めるための再現手順をまとめたものです。
行いたいループは次のようなものです。
ChatGPT
-> GitHubの状態確認
-> Issue draft作成
-> 承認後にIssue登録
GitHub Issue
-> 作業単位・状態管理DB
Codex CLI
-> Issue番号を読んで /goal で自走
-> 実装・検証・PR・進捗記録
ChatGPT
-> Issue / PR / CI / コメントを確認
-> 必要ならfollow-up Issueを登録
なお、この記事では「設計思想」ではなく「再現手順」を扱います。GitHubを状態管理DBとして使う設計や、ChatGPT / Codex CLI / GitHubの責務分離は別記事で扱う想定です。
注意: すべてのChatGPT環境で再現できるとは限りません。筆者の環境でも同一チャット内で、登録が成功したり失敗したりすることがあります。
この記事の手順は、GitHub connectorのwrite action、特にcreate_issueやupdate_issue相当のactionがChatGPTのチャット内で使える環境を前提にしています。
OpenAIのヘルプでは、ChatGPTのGitHub接続はリポジトリのコード、README、ドキュメントを読み取り、分析・検索・引用する用途として説明されています。一方で、ChatGPT Apps全体としては、アプリと設定によって外部サービス上の情報を作成・更新するwrite actionを実行できる場合があります。
そのため、この記事では最初に必ずaction discoveryを行います。
create_issue / update_issue が見える -> 直接登録を試す
create_issue / update_issue が見えない -> 直接登録はせず、Issue draftまたはgh CLI fallbackに切り替える
つまり、この記事の結論は「ChatGPTなら常にIssue登録できる」ではありません。
自分の環境でwrite actionが露出しているかを確認し、露出している場合だけIssue直接登録ループを使う
というrunbookです。
手元で確認できたこと
私の環境では、ChatGPTのGitHub connectorから次の一連の操作が成功しました。
create_issue
-> update_issue
-> fetch_issue
-> close issue
-> update closed issue body
smoke testでは、以下も確認しました。
| 操作 | 結果 |
|---|---|
| Issue作成 | 成功 |
| label付与 | 成功 |
| 本文更新 | 成功 |
| fetchによる取得確認 | 成功 |
| close | 成功 |
state_reason=not_planned |
成功 |
| close後の本文更新 | 成功 |
検証時のIssueは以下です。
repo: itdojp/ae-framework
Issue: #3524 [ACP-SMOKE] Connector issue write smoke test
final state: closed
state_reason: not_planned
label: area:docs
公開範囲に応じて、実repo名やIssue番号は<owner>/<repo>、#123のように匿名化してください。
用語整理
この記事では、以下の言葉を使います。
| 用語 | 意味 |
|---|---|
| connector / app | ChatGPTから外部サービスを参照・操作するための接続 |
| action | ChatGPTがconnector経由で呼び出せる操作。例: create_issue, update_issue
|
| action discovery | そのチャットで利用可能なactionを確認すること |
| Issue pack | 複数Issueをまとめて登録する入力データ |
| pack id | Issue pack全体を識別するID。重複登録防止に使う |
| issue-key | pack内の論理ID。例: DEV-001
|
| placeholder create | 短い仮本文でIssueを先に作ること |
| full body update | Issue番号確定後、依存関係を解決した本文に更新すること |
重要なのは、この記事に出てくるJSON風の断片は、多くの場合「読者が直接実行するコマンド」ではなく、ChatGPTに内部tool callとして実行させるための指示例です。
前提条件
ChatGPT側
- GitHub connector / appが利用可能であること
- 対象repoがChatGPTから読めること
- Issue登録には
create_issue/update_issue相当のwrite actionが必要 - 変更操作では毎回確認が出る設定を推奨
- Workspace管理下では、対象appのAction controlでIssue作成・更新が許可されていること
App permissionsは「新しい権限を付与する設定」ではなく、「既に接続済みのapp actionを使う前に、いつ確認を求めるか」を制御する設定です。GitHub側またはWorkspace側でwrite actionが許可されていなければ、App permissionsだけを変えてもIssue作成はできません。
推奨は次です。
App permissions: Any changes
読み取りは自動でよい一方、Issue作成・本文更新・closeなどの変更操作では確認を入れる運用にします。
GitHub側
- 対象repoでIssuesが有効
- repoがarchivedではない
- connectorの認証主体が対象repoにアクセスできる
- labelを付ける場合、対象labelが存在する
- assignee / milestoneを指定する場合、認証主体に十分な権限がある
GitHub REST APIでは、Issue作成自体にはpull accessが必要ですが、labels / milestone / assigneesを新規Issueに設定するにはpush accessが必要です。権限が不足している場合、これらのmetadataは黙って落ちることがあります。
初期運用では、次のように絞るのが安定します。
labels: 既存labelのみ
assignee: なし
milestone: なし
Codex CLI側
- Codex CLIが使える
- 対象repoをローカルにclone済み
- repo rootに
AGENTS.mdを配置済み - Issue本文にacceptance criteriaとvalidation commandsがある
Codexの/goalは、検証可能な停止条件がある長めの作業に向いています。Issue本文に「何を読むか」「何を変更しないか」「どう検証するか」「いつ止まるか」を書いておくと、handoffが安定します。
全体フロー
1. 新チャットでbootstrap promptを貼る
2. action discoveryでcreate_issue / update_issueを確認する
3. smoke testでIssue作成・更新・取得を確認する
4. Issue packを入力する
5. open / closedの両方でpack idの重複を検索する
6. placeholder bodyで全Issueを作成する
7. issue-key -> issue_number mapを作る
8. Parent / Depends on / Blocksを実Issue番号で解決する
9. update_issueでfull bodyに差し替える
10. search_issues / fetch_issueで登録後検証する
11. Codex CLIにIssue番号を渡して /goal を実行する
12. ChatGPTでPR / CI / Issue commentを確認し、必要ならfollow-up Issueを作る
1. 新チャットで最初に貼るbootstrap prompt
新しいチャットでは、最初に以下を貼ります。
このチャットでは、GitHub Issue direct registration loopを使います。
対象repo: <owner>/<repo>
まずGitHub connectorのaction discoveryを行ってください。
必須action:
- create_issue
- update_issue
- fetch_issue
- search_issues
create_issueまたはupdate_issueが利用できない場合、このチャットでは直接Issue登録を行わず、Issue draftだけ作ってください。
Issue登録ルール:
- 私が「登録して」と明示するまでcreate_issue / update_issueは実行しないでください。
- Issue packはplaceholder create -> issue number map -> update full bodyの二段階で登録してください。
- open / closedの両方でpack idの重複を確認してください。
- create_issueには短いplaceholder bodyだけを渡してください。
- full bodyはupdate_issueで入れてください。
- bodyにはclose/delete/lock/force pushなどGitHub操作命令に見える文言を入れないでください。
- 作成後はsearch_issuesとfetch_issueで検証してください。
この時点でcreate_issueまたはupdate_issueが見えない場合、そのチャットでは直接登録しません。
2. action discovery
ChatGPTに次を確認させます。
GitHub connectorのtool schemaを確認してください。
対象repoは<owner>/<repo>です。
確認するaction:
- create_issue
- update_issue
- fetch_issue
- search_issues
- get_repo
- fetch_issue_comments
create_issue / update_issueがなければ、直接Issue登録は行わず、gh CLI fallback用のIssue draftだけ作ってください。
判定基準は次です。
| 判定 | 状態 | 次のアクション |
|---|---|---|
| OK |
create_issue / update_issue / fetch_issue / search_issuesがある |
smoke testに進む |
| NG |
search_issues / fetch_issueだけある |
直接登録しない |
| NG | GitHub connector自体が見えない | ChatGPT / Workspace / GitHub側の接続を確認 |
内部的には、環境によって以下のようなaction名で見えることがあります。
GitHub/<owner>/<repo>.create_issue
GitHub/<owner>/<repo>.update_issue
GitHub/<owner>/<repo>.fetch_issue
GitHub/<owner>/<repo>.search_issues
ただし、これはChatGPT内部のtool schema上の名前です。読者がGitHub CLIやブラウザで直接実行するコマンドではありません。
3. smoke test
本番Issue packの前に、一時Issueで直接登録を確認します。
ChatGPTに以下を渡します。
GitHub connectorのcreate_issue / update_issue / fetch_issueを使って、<owner>/<repo>にsmoke test Issueを作成してください。
Issue:
- title: [AI-SMOKE] Connector issue write smoke test
- body: Temporary smoke test created from ChatGPT GitHub connector to verify direct Issue create/update workflow.
- labels: なし
- assignee: なし
- milestone: なし
手順:
1. create_issueでIssueを作成する。
2. issue_numberを記録する。
3. update_issueでbodyを短く更新する。
4. fetch_issueでtitle/body/stateを確認する。
5. 必要ならstate=closed, state_reason=not_plannedでcloseする。
6. close後にbodyを更新できるか確認する。
作成前に最終確認を表示してください。
最初はlabelなしで試す方が切り分けやすいです。Issue作成・更新・取得が成功してから、既存labelを付けるテストに進みます。
確認する結果:
- Issue numberが返る
- state=openで作成される
- update_issueでbodyが更新される
- fetch_issueで更新後のbodyが読める
- 必要に応じてcloseできる
- close後でもbody更新できる
4. Issue packの入力形式
Issue packにはpack idとissue-keyを入れます。
例:
pack_id: ai-dev-loop-2026-06-22
issues:
- key: DEV-001
title: "[DEV-001] Epic: Improve AI development loop"
labels: [type:epic, priority:p1, ai:ready-for-codex]
- key: DEV-002
title: "[DEV-002] Add status check command"
labels: [type:task, priority:p1, ai:ready-for-codex]
parent: DEV-001
- key: DEV-003
title: "[DEV-003] Add follow-up issue template"
labels: [type:task, priority:p2, ai:ready-for-codex]
parent: DEV-001
depends_on: DEV-002
issue-keyは作成前の論理IDです。GitHub Issue番号が確定した後で、Parent / Depends on / Blocksを実Issue番号に変換します。
5. 二段階登録にする理由
Issue番号はcreate_issueするまで分かりません。
したがって、Issue pack内で依存関係を書きたい場合、最初から完成版bodyを作れません。
DEV-002 depends_on DEV-001
これをGitHub Issue上では次のようにしたいです。
Depends on: #1201
そのため、次の二段階にします。
placeholder create
-> Issue番号を確定する
-> issue-key -> issue_number mapを作る
-> full body update
この方式にすると、Issue pack内の依存関係を実Issue番号で解決できます。また、最初のcreate_issue payloadを短くできるため、失敗時の切り分けもしやすくなります。
6. Step 1: 重複確認
ChatGPTに以下を指示します。
pack id `<pack-id>`について、<owner>/<repo>のopen / closed Issueを両方検索してください。
検索条件:
- query: "<pack-id>"
- state: open
- state: closed
既存Issueがあれば、新規作成せず、既存Issue番号を使ってupsert方針を提示してください。
判定:
既存なし: 新規create_issue
既存あり: update_issueによるupsertを検討
closed Issueも検索する理由は、過去に同じpack idで作ったIssueを見落とすと、同じ作業単位を再登録してしまうためです。
7. Step 2: placeholder bodyで作成
最初から長いbodyをcreate_issueに渡しません。
placeholder body:
<!-- ae-issue-pack: <pack-id>; issue-key: <issue-key> -->
Placeholder. Full body will be applied after issue numbers are available.
ChatGPTへの指示:
各Issueを短いplaceholder bodyでcreate_issueしてください。
create_issueに渡すもの:
- title
- placeholder body
- 既存labelのみ
create_issueに渡さないもの:
- 長いfull body
- assignee
- milestone
- close / delete / lock / force pushなどを含む文章
初期導入ではlabelも外してよいです。Issue作成が安定してから、既存labelだけ追加します。
8. Step 3: issue-key mapを作る
各create_issueの戻り値からmapを作ります。
例:
{
"DEV-001": 1201,
"DEV-002": 1202,
"DEV-003": 1203
}
このmapを使って、依存関係を実Issue番号に変換します。
DEV-002 parent DEV-001
=> Parent: #1201
DEV-003 depends_on DEV-002
=> Depends on: #1202
9. Step 4: full bodyに更新
full bodyの標準形式:
<!-- ae-issue-pack: <pack-id>; issue-key: <issue-key> -->
Parent: #1201
Depends on: #1202
Blocks: —
Codex lane: `implementation/backend`
## Background
## Goal
## Scope
## Target files / areas
## Codex CLI instructions
## Implementation tasks
- [ ] ...
## Acceptance criteria
- [ ] ...
## Validation commands
- `pnpm test`
- `git diff --check`
## Out of scope
ChatGPTへの指示:
issue-key -> issue_number mapを使ってParent / Depends on / Blocksを実Issue番号に解決してください。
その後、各Issueをupdate_issueでfull bodyに差し替えてください。
注意:
- bodyにはGitHub操作命令に見える文言を入れないでください。
- close/delete/lock/force pushなどの文言を避けてください。
- 状態遷移はIssue bodyではなくoperator actionとして扱ってください。
10. Issue bodyで避ける表現
手元検証では、Issue body内にGitHub操作命令のような文言があると、安全性チェックに引っかかる可能性がありました。
避ける表現:
close issue with state_reason=...
delete branch
remove issue
lock issue
force push
代替表現:
Completion state is expected to be recorded by the operator.
State transition is out of scope for this Issue body.
このルールにより、Issue bodyは「作業仕様」に限定し、GitHubの状態変更はconnector actionまたは人間操作として分離できます。
11. Step 5: 登録後検証
ChatGPTに以下を指示します。
登録後検証を行ってください。
確認:
1. search_issuesでpack idを検索する。
2. 作成されたIssue数が期待数と一致する。
3. fetch_issueで代表Issueを取得する。
4. 各bodyにpack id markerとissue-keyがある。
5. Parent / Depends on / Blocksが実Issue番号になっている。
6. labelsが期待通り付いている。
7. Acceptance criteriaがある。
8. Validation commandsがある。
確認結果を表で出してください。
検証結果の表は、次の形式にすると見やすいです。
| issue-key | Issue | state | labels | body marker | deps resolved | validation commands | result |
|---|---|---|---|---|---|---|---|
| DEV-001 | #1201 | open | OK | OK | OK | OK | OK |
| DEV-002 | #1202 | open | OK | OK | OK | OK | OK |
12. ChatGPTにIssue pack登録を依頼する最終プロンプト
以下をそのまま使えます。
GitHub connectorのcreate_issue / update_issueを使って、<owner>/<repo>にIssue packを直接登録してください。
pack id: <pack-id>
Issue pack:
<ここにIssue一覧を貼る>
手順:
1. create_issue / update_issue / search_issues / fetch_issueが利用可能か確認する。
2. pack idの重複をopen / closedの両方で検索する。
3. 既存がなければplaceholder bodyで全Issueをcreate_issueする。
4. create_issueの戻り値からissue-key -> issue_number mapを作る。
5. Parent / Depends on / Blocksを実Issue番号に解決する。
6. update_issueでfull bodyに差し替える。
7. search_issuesとfetch_issueで登録後検証する。
制約:
- 私が「登録して」と明示するまでcreate_issue / update_issueは実行しない。
- create_issueには短いplaceholder bodyだけを渡す。
- labelsは既存labelのみ使う。
- assigneeとmilestoneは指定がなければ空欄にする。
- bodyにはclose/delete/lock/force pushなどGitHub操作命令に見える文言を入れない。
- コード変更、branch作成、PR作成、mergeは行わない。
13. Codex CLIへの/goal handoff
Issue登録後、Codex CLIにはIssue番号を渡します。
/goal Complete GitHub issue #123 until the implementation is ready for human review.
Read first:
- GitHub issue #123
- AGENTS.md
- README.md
- Files mentioned in the issue
Workflow:
1. Confirm the exact scope of issue #123.
2. Create or use branch codex/issue-123-short-title.
3. Make the smallest safe implementation.
4. Add or update tests.
5. Run validation commands from the Issue.
6. Self-review the diff.
7. Open or prepare a PR referencing issue #123.
8. Record progress in an issue comment or `.codex-progress/issue-123.md`.
Constraints:
- Do not modify unrelated files.
- Do not expand scope; record follow-up candidates instead.
- Do not merge PRs.
- Do not close Issues unless explicitly instructed by the operator.
/goalでは、目的と停止条件を明確にすることが重要です。Issue本文のAcceptance criteriaとValidation commandsが曖昧だと、Codex CLI側の自走も不安定になります。
14. AGENTS.mdの最小例
repo rootにAGENTS.mdを置きます。
# AGENTS.md
## Operating model
- GitHub Issues are the source of truth for task scope.
- One Issue should map to one branch and one PR unless explicitly stated.
- Use branch name: `codex/issue-<number>-<short-title>`.
- PRs should reference the Issue with `Refs #<number>`.
- Do not push to `main`.
- Do not merge PRs.
- Do not close Issues unless explicitly instructed by the operator.
- Record follow-up candidates instead of expanding scope.
## Progress reporting
For long-running work:
- Update the related Issue with a short progress comment if GitHub write access is available.
- Otherwise write progress to `.codex-progress/issue-<number>.md`.
## Done when
- Implementation is complete.
- Validation commands pass or failures are documented.
- Diff is self-reviewed.
- PR is ready for human review.
- Known follow-up candidates are documented.
15. 状態確認プロンプト
Codex CLI作業後に、ChatGPTでGitHubの状態を確認します。
GitHub connectorを使って<owner>/<repo>の現在状態を確認してください。
対象:
- open issues with labels: ai:ready-for-codex, codex:running, codex:blocked, codex:needs-review
- open PRs
- PRに紐づくIssue
- 直近のworkflow runs / CI status
- Issue comments内のCodex進捗報告
出力:
1. Issueごとの現在状態
2. 紐づくPR / branch / commit / CI
3. blocked項目
4. review待ち項目
5. 完了候補
6. 新規Issue化すべきfollow-up候補
制約:
- まだIssueは作成しない
- GitHub上で確認できた事実と推測を分ける
- 根拠としてIssue番号、PR番号、commit、workflow runを示す
16. follow-up Issue作成プロンプト
GitHub connectorを使って<owner>/<repo>のIssue #123、関連PR、Codex進捗コメント、CI結果を確認してください。
目的:
- #123から派生したfollow-up候補を抽出する
- 既存Issueと重複しない候補だけIssue draftにする
出力:
1. follow-up候補一覧
2. 既存Issueとの重複チェック結果
3. Issue化すべきもの / しないもの
4. Issue draft
制約:
- まだIssueは作成しない
- Codexの推測だけに基づいてIssue化しない
- GitHub上の根拠をIssue本文に入れる
- 実装タスクと調査タスクを分ける
登録する場合:
follow-up候補1と3をIssue登録してください。
labels:
- follow-up
- ai:ready-for-codex
- priority:p2
元Issue #123と関連PRを本文にリンクしてください。
作成前に最終確認を表示してください。
17. トラブルシュート
| 症状 | 推定原因 | 対応 |
|---|---|---|
create_issueが見えない |
GitHub connectorのwrite actionが露出していない | そのチャットでは直接登録しない。Issue draftまたはgh CLI fallbackに切り替える。 |
update_issueが見えない |
write action不足 | placeholderだけ作る運用も不可。直接登録を停止する。 |
| readはできるがcreateできない | Action controlまたはrepo権限不足 | Workspace / connector / repo権限を確認する。 |
| Issue作成はできるがlabelsが付かない | label不存在またはpush access不足 | 既存labelに絞る。初期運用ではlabelなしにする。 |
| assigneeが付かない | assignee権限または候補不正 | assigneeは空欄で作成し、後で人間が設定する。 |
| milestoneが付かない | milestone不存在またはpush access不足 | 初期運用ではmilestoneを使わない。 |
| body更新がブロックされる | body内表現が安全性チェックに引っかかった可能性 | bodyを短くする。GitHub操作命令に見える表現を避ける。段階更新する。 |
| 既存Issueと重複した | duplicate check不足 | open / closedの両方でpack idを検索する。 |
| 422が返る | validation error、spam判定、secondary rate limitなど | 連続作成を減らす。bodyを短くする。間隔を空ける。 |
| Issueは作れたがCodexが迷う | Issueのacceptance criteria / validation commandsが曖昧 | Issue templateを見直す。 |
18. 直接登録できない場合のfallback
直接登録できないチャットでは、ChatGPTにIssue draftだけ作らせ、gh CLIやスクリプトで登録します。
このチャットではcreate_issue / update_issueが使えないため、直接登録は行わないでください。
代わりに、gh CLI登録用のIssue pack JSONを作ってください。
出力:
- title
- body
- labels
- parent / depends_on / blocks
- acceptance criteria
- validation commands
gh CLI例:
gh issue create \
--repo <owner>/<repo> \
--title "[DEV-002] Add status check command" \
--body-file issue-body.md \
--label "ai:ready-for-codex" \
--label "priority:p1"
19. 公開時の匿名化チェック
公開記事では、次を匿名化できます。
実repo: <owner>/<repo>
実Issue番号: #123
実pack id: <pack-id>
実label: ai:ready-for-codex などの一般名へ置換
社内URL: 削除
内部プロジェクト名: 汎用名へ置換
一方で、検証済み操作の列挙は残すと再現性が伝わります。
create_issue -> update_issue -> fetch_issue -> close -> update closed issue body
まとめ
このRunbookの要点は次です。
- 新チャットでは最初にaction discoveryする
- create_issue / update_issueがなければ直接登録しない
- 本番前にsmoke testでcreate/update/fetchを確認する
- Issue packはplaceholder create -> full body updateの二段階で登録する
- bodyにはGitHub操作命令に見える文言を入れない
- 登録後はsearch/fetchで検証する
- Codex CLIにはIssue番号を/goalで渡す
この手順にすると、ChatGPTで計画、GitHub Issueで状態管理、Codex CLIで実装、ChatGPTで再確認とfollow-up登録、というループを別チャットでも再現しやすくなります。
参考
- OpenAI Help: Connecting GitHub to ChatGPT
- OpenAI Help: Apps in ChatGPT
- OpenAI Help: Admin controls, security, and compliance in Apps
- OpenAI Developers: Follow a goal | Codex use cases
- GitHub Docs: REST API endpoints for issues