スケジューラーエージェント管理ガイド
プロジェクト(CSN)ごとに登録された自動化ランナー(gissue スケジューラーなどのバックグラウンドエージェント)のオンライン/オフライン状態、実行状態・履歴、リアルタイムログを1つの画面で管理します。
🤖 AI に任せて gissue スケジューラーを作る
この文書を AI に渡すと、AI が giip-fde-agent リポジトリ(https://github.com/LowyShin/giip-fde-agent.git)を clone または最新化し、gissue 処理用スケジューラーを PC に インストール・登録·検証まで自動で行います。最初からスクリプトを自作せず、この 手順を 使用します。
プロンプト(コピーしてそのまま使用):
この文書(/help/catquest-schedulers.ja.md) を読み、「インストール手順」に従って gissue スケジューラーをこの PC にインストールしてください。
giip-fde-agent がなければ clone、あれば git pull --ff-only で最新化。ローカル変更がある場合は上書きせず中断して報告してください。
対象 CSN は <CSN>、作業フォルダは <パス> で指定してください。
SK は giipAgent.cnf(または giipAgent.cfg)の sk= 値を読み、ユーザーに 聞かないでください。
各ステップの確認結果を報告してください。
インストール手順
- 事前チェック — 実行 →
git --version、node --version、claude --version、Windows はpowershell -Command $PSVersionTable.PSVersion、Linux はpwsh --version。すべて PATH に あることを確認してから次のステップに進みます。 - giip-fde-agent の確保 — 実行 → なければ
git clone https://github.com/LowyShin/giip-fde-agent.git、あればgit pull --ff-only。ローカル変更がある場合は中断して報告。 - 正規本 SPEC の読取 —
docs/60-operations/hourly-issue-scheduler.md§4~§5 を読み、CSN→workdir マッピング、ハートビート ブロック、SK 位置を確認。 - csn-projects.json の作成 —
scripts/gissue/csn-projects.json.exampleをcsn-projects.jsonにコピー。対象 CSN のworkdir/enabled: trueを記入し、最上位のheartbeatブロックにlssn(サーバー番号)/hostname(この PC 識別子)/skFile(sk= 形式ファイル パス)を必ず指定。ないとこの画面に 行が表示されません。 - シークレットの準備 — 上位フォルダの
giipAgent.cnf(またはgiipAgent.cfg)からsk=値を読む。ユーザーに戻って聞かず、出力にも記録しない。slack-bot/.secrets/giip-accounts.json(.sample.json からコピー)も準備。 - ドライラン —
scripts/gissue/manage-gissue-scheduler.ps1 -Action DryRun -OnlyCsn <CSN>を実行 →[PREFLIGHT-FAIL]ログなしで終われば成功。 - 登録
- Windows —
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\register-hourly-issue-scheduler.ps1 -Action Register -RepoRoot <giip-fde-agent ルート> - Linux — 専用登録スクリプトはなく、
/etc/cron.d/gissue-schedulerのような cron 1 行で登録します(実際の docker 部署と同じ形式):7,27,47 * * * * <一般ユーザー> cd <ルート> && pwsh -NoProfile -NonInteractive -File "<ルート>/scripts/gissue/run-gissue-claude.ps1" -OnlyCsn <CSN> >> <ルート>/scripts/gissue/logs/cron.log 2>&1。必ず root ではなく一般ユーザーで登録します(claude が root で--dangerously-skip-permissionsを拒否して 全 issue が失敗します)。そのユーザーの claude ログイン情報もまた必要 です。 - Docker インスタンス — コンテナ起動時
docker/entrypoint.shが上記 cron を自動登録します(GIIP_ENABLE_SCHEDULERデフォルト true、-OnlyCsnはcsn-projects.jsonから派生)。この場合 7ステップ目はすでに終わっているため、/etc/cron.d/gissue-schedulerの存在だけ確認し、scripts/bootstrap-instance.shで環境(pwsh リンクなど)をチェックします。
- Windows —
- 検証 —
manage-gissue-scheduler.ps1 -Action RunOnce -OnlyCsn <CSN>で1回実行するか次の :07 を待ち、この画面をリフレッシュ →gissue_csn<CSN>行が online で History に実行が残っていれば成功。 表示されない場合はscripts/gissue/logs/gissue_csn<CSN>.logの[WARN][SchedulerState-...]行を確認。
AI がしてはいけないこと
- giip-fde-agent のランナー(
run-gissue-claude.ps1)を新規作成しない - SP を直接呼び出すコードを別途自作しない(インストールされたランナーが処理する)
- SK 値を文書やログに残さない
- giip-fde-agent コードを直接修正しない
📋 概要
スケジューラーエージェント管理は、現在選択中のプロジェクト(CSN)に登録されているすべての自動化エージェント — 例えば gissue の毎時スケジューラーや対話型 Claude Code セッションなど — を表示します。giip の イシュー を猫で可視化する /admin/catquest とは異なり、この画面は 自動化ジョブを実行するエージェント自体 を管理する運用ダッシュボードです。各エージェントが生きているか、現在の実行が正常か、ログはどこで確認できるかを把握します。
🎨 ステータスカラー
エージェントごとに、互いに独立した2つのステータス信号が表示されます — 混同しないでください。
Identity ステータス(エージェント名の横の小さなドット)
個々の実行(run)とは無関係に、エージェントプロセス自体に到達可能かどうかを示します(tSchedulerAgent.status)。
| 色 | ステータス | 意味 |
|---|---|---|
| 🟢 緑 | online | エージェントに到達可能で正常に報告中 |
| 🔴 赤 | error | エージェントがエラー状態を報告 |
| ⚪ グレー(slate-400) | offline | 現在エージェントに到達できない |
| ⚪ 薄いグレー(slate-300) | unknown | まだステータスが報告されていない |
実行ステータス(Status 列のバッジ)
直近のスケジューラー 実行(run) の状態(currentStatus)と stale(停滞)検出結果を反映します。
| 色 | 表示ラベル | 条件 | 意味 |
|---|---|---|---|
| 🟢 緑 | RUNNING | currentStatus = RUNNING かつ stale でない | 正常に実行中 |
| 🔴 赤 | STALE | currentStatus = RUNNING かつ isStale = true | 実行中と表示されているが heartbeat が長時間途絶えている — 停止/ゾンビ実行の可能性 |
| 🟠 オレンジ | STALE | currentStatus = STALE(明示的な値) | バックエンドが実行自体を stale と判定 |
| ⚪ グレー | ENDED | currentStatus = ENDED | 終了(正常完了または正常な停止) |
| ⚪ グレー | (元の値) | それ以外 / 実行履歴なし | 不明 / データなし |
下記の実行履歴モーダルでは、完了した実行が赤色の FAILED として表示されることもあります — ENDED(正常終了)や stale/タイムアウトとは区別される、エラーで終了した実行です。
🔍 画面構成
1. ヘッダー
/admin/catquestに戻る矢印(←)。- Refresh: 現在の CSN のエージェント一覧を再読み込みします。
2. Open Interactive Sessions
アクティブな claude_interactive_session エージェント — つまり現在ホスト上で実行中として登録されている対話型 Claude Code セッション — が1つ以上ある場合のみ、別カードとして表示されます。各行にはセッション名、ホスト、最終通信時刻、そしてエージェントの capabilities にセッション URL が登録されている場合の 「Open session」 リンクが表示されます。
3. エージェント一覧(テーブル)
スケジューラーエージェントごとに1行表示され、以下の情報を含みます。
- Name — identity ステータスドット、エージェント名、OS/エージェントタイプ/バージョンバッジ、
lssn(連携サーバー)、省略された capabilities 要約、最後のエラー(あれば)。 - Host —
hostIdentifier。 - Windows Task — 該当する場合、このエージェントを実行する Windows タスクスケジューラのタスク名。
- Project — プロジェクト名。
- Active — ON/OFF バッジ(
isActive)。 - Last Comm — 最終 heartbeat/通信時刻。
- Status — 上記の実行ステータスバッジと、報告されていれば現在のフェーズ(phase)テキスト。
下部の統計フッターには、表示中の全エージェントの 処理(Processed)/ スキップ(Skipped)/ 失敗(Failed) 件数の合計が表示されます。
4. 実行履歴(Run History)
テーブルの下にある「View History」カードに全エージェントが再度一覧され、行の History ボタンをクリックするとそのエージェントの直近の実行一覧がモーダルで表示されます — 実行モード、ステータス(FAILED を含む)、開始/終了時刻、所要時間、処理/スキップ/失敗件数、フェーズ、サマリー。
5. リアルタイムログビューア(Live Log Viewer)
2ペイン構成のリアルタイム tailing 画面です。
- 左(エージェント→ストリームツリー): エージェントごとにグループ化され、展開すると既知のログストリーム一覧が表示されます(ストリームは
streamKeyで識別され、streamTypeとローテーション世代番号を持ちます)。エージェントは最終通信時刻に基づいて online/offline が表示されます。 - 右(ログストリームカード): ストリームを選択すると直近のログ行が表示され、リアルタイム tailing のために継続的に更新されます。
➕ 別のホストを追加する
この画面にはホストを手動で「追加」するボタンや入力フォームはありません — 一覧は下記2つの自動登録経路の結果だけで構成されます。どちらの経路も CSN(プロジェクト)ごとに発行された Secret Key(SK) を使って giipApiSk4 エンドポイントを呼び出し、tSchedulerAgent/tSchedulerAgentRun へ自身を登録(upsert)する方式です。有効な SK がなければ呼び出し自体が 401 Unauthorized で失敗するため、この手順を知っていても他人のプロジェクトに勝手に偽のエージェントを登録することはできません。
⚠️ 以下の SK/AK の値は常にプレースホルダーです。実際の値を文書やコードにハードコードせず、発行された値は各自安全な方法(シークレットファイル、環境変数、シークレットマネージャーなど)で保管してください。
共通の前提条件
| 項目 | 説明 |
|---|---|
| 対象 CSN | エージェントを登録するプロジェクト番号。このページはセッションの現在の CSN を基準に一覧を表示します。 |
| SK(Secret Key) | 該当 CSN への書き込み(登録)権限を持つシークレットキー。プロジェクト管理者に該当 CSN 用の SK 発行を依頼してください — この画面や API から自分で発行することはできません。 |
| 登録エンドポイント | https://giipfaw.azurewebsites.net/api/giipApiSk4(anonymous 認証 — Function key 不要、リクエストフォームの SK トークンで認証) |
コンソールをこの画面に登録する — そのままコピーしてコンソールに貼り付け
この画面の "Open Interactive Sessions" に、いま使っている Claude Code コンソールが表示されない場合は、下の依頼文をコンソール(Claude Code)にそのまま貼り付けてください。コンソールは下の「方法 A」の仕様(agentKey 規則、SP 呼び出し)だけで登録を行うため、別のスクリプトや他のリポジトリは不要です。<CSN> は登録するプロジェクト番号に置き換えてください。
前提条件: 対象 CSN 用の SK が、この PC の上位フォルダにある
giipAgent.cnf(またはgiipAgent.cfg)にsk=として存在する必要があります(なければプロジェクト管理者にその CSN 用の SK の発行を依頼)。コンソールは SK をユーザーに聞き返さず、そのファイルから読み取ります。
依頼文 1 — いま開いているこのコンソールを 1 回だけ登録
giip スケジューラーエージェント画面(/ja/admin/catquest/schedulers)に、いま開いているこのコンソールセッションを CSN <CSN> の対話型セッションとして 1 回登録して。
この文書(/help/catquest-schedulers.ja.md)の「方法 A — 対話型 Claude Code セッションの登録」を読み、その仕様どおりに実行して。register-interactive-session.ps1 のような別スクリプトは存在しないものとして、文書に書かれた giipApiSk4 の呼び出し(HTTP POST、フォームフィールド text/token/jsondata)を直接実行して。
1. agentKey: 文書の「agentKey 生成規則」の 5 ステップで作って。元 ID は、このセッションの session_id が分かればその値、分からなければ fallback_<COMPUTERNAME>_<PID>。COMPUTERNAME 環境変数がなければ hostname コマンドの結果を使って。
2. SchedulerAgentUpsert: text は "SchedulerAgentUpsert agentKey displayName hostIdentifier windowsTaskName projectName scheduleDesc isActive lssn osType agentType version"。jsondata は agentKey、displayName="Claude Interactive Session (<ホスト名>)"、hostIdentifier=<ホスト名>、windowsTaskName/projectName/scheduleDesc は空文字列、isActive="1"、lssn="0"、osType=Windows または Linux、agentType="claude_interactive_session"、version=""。環境変数 CLAUDE_CODE_BRIDGE_SESSION_ID があれば、text と jsondata の最後に capabilities={"sessionUrl":"https://claude.ai/code/<その値>"} を追加し、なければ capabilities を丸ごと除いて。ほかの値から sessionUrl を作り出さないで。
3. SchedulerAgentRunStart: text は "SchedulerAgentRunStart runIdKey agentKey executionMode totalIssueCount"。runIdKey=<agentKey>_<現在時刻 yyyyMMddHHmmss>、executionMode="interactive"、totalIssueCount="0"。
4. SK は上位フォルダの giipAgent.cnf(なければ giipAgent.cfg)の sk= の値を読み取って token に使って。私に聞き返さず、SK の値を画面・ログ・ファイルのどこにも出力・記録しないで。
5. 確認: 同じ giipApiSk4 で text "SchedulerAgentList csn"、jsondata {"csn":"<CSN>"} を呼び出し、いま作った agentKey の行が is_active=true、current_status=RUNNING であることを確認して。結果と使った agentKey/runIdKey を教えて(SK は除く)。
依頼文 2 — 今後のすべてのセッションが自動登録されるようフックを設定
この PC で Claude Code セッションが開かれたり閉じられたりするたびに、giip スケジューラーエージェント画面へ自動で登録/解除されるように、SessionStart/SessionEnd フックを設定して。対象 CSN は <CSN>。
この文書(/help/catquest-schedulers.ja.md)の「方法 A — 対話型 Claude Code セッションの登録」を読み、その仕様だけで自分で実装して。他のリポジトリからスクリプトを持ってこようとしないで。
1. フック処理スクリプトをユーザーのホーム配下の 1 か所(例: ~/.claude/giip-console-hook.ps1)に作って。引数で Start または End を受け取り、標準入力からフックイベント JSON を読む。Windows 以外では pwsh か bash で書いてもよい。
2. フックの登録は文書の JSON のとおり、~/.claude/settings.json(グローバル)の hooks.SessionStart と hooks.SessionEnd に command フックを追加して。matcher は入れない。既存の hooks 項目は上書きせず配列に追加し、文書の JSON の timeout 値をそのまま使って。
3. ヘッドレスを除外: スクリプトはまず親プロセスをさかのぼり、claude プロセスのコマンドラインに -p または --print があれば何もせず終了して(文書のヘッドレス判定)。CLAUDE_CODE_BRIDGE_SESSION_ID の有無でヘッドレスを判定しないで。
4. Start: agentKey は文書の「agentKey 生成規則」どおり(元 ID = stdin の session_id、なければ fallback_<COMPUTERNAME>_<PID>)に作り、SchedulerAgentUpsert(agentType="claude_interactive_session"、isActive="1"、フィールドと順序は文書の例と同じ)と SchedulerAgentRunStart(executionMode="interactive"、totalIssueCount="0")を呼び出して。runIdKey=<agentKey>_<現在時刻 yyyyMMddHHmmss> とし、End で使うため一時フォルダのファイルに保存して。CLAUDE_CODE_BRIDGE_SESSION_ID があるときだけ capabilities.sessionUrl を入れ、なければ capabilities を除いたまま登録を続けて。
5. End: 同じ規則で agentKey を再計算して SchedulerAgentRunEnd(status="ENDED"、processedCount/skippedCount/failedCount="0")を呼び出し、続けて SchedulerAgentUpsert を isActive="0" で呼び出してオフラインに切り替えて。
6. 呼び出しはすべて giipApiSk4(text/token/jsondata)で行い、フックが失敗してもセッションが止まらないよう、常に終了コード 0 で終えて。
7. SK の値はスクリプトに入れず、実行のたびに giipAgent.cnf(なければ giipAgent.cfg)の sk= から読むよう、そのファイルの絶対パスだけを書いて。私に聞き返さず、SK の値を出力・ログ・ファイルに残さないで。
8. 終わったら、作成または変更したファイルのパス一覧と、新しいセッションで登録されたかを確認する方法を教えて。
- 依頼文 1 で登録したセッションには終了フックがないため、閉じるときに解除するには、コンソールに「教えた agentKey/runIdKey で SchedulerAgentRunEnd を呼び出し、SchedulerAgentUpsert を isActive=0 で呼び出して」と依頼してください。フック(依頼文 2)を使えば、終了時に自動で解除されます。
- 成功の確認: 画面を更新すると、"Open Interactive Sessions" カードとエージェント一覧にセッションが表示されます。詳細な仕様は下の「方法 A」を参照してください。
方法 A — 対話型 Claude Code セッションの登録
Claude Code のような対話型 AI コーディングセッションを「Open Interactive Sessions」カードに表示させるには、セッションの SessionStart/SessionEnd フックで以下の手順を実行するよう設定します。
- 前提条件: 上記の共通前提条件(対象 CSN 用の SK)に加え、セッションを実行するツール(Claude Code など)に SessionStart/SessionEnd フックを設定できる権限。
- セッション開始時(SessionStart) —
SchedulerAgentUpsertを呼び出して identity を登録/更新し、続けてSchedulerAgentRunStartを呼び出して実行開始を記録します。 - セッション終了時(SessionEnd) —
SchedulerAgentRunEndを呼び出して実行終了を記録し、SchedulerAgentUpsertをisActive=0で再度呼び出してオフラインに切り替えます。
agentKey 生成ルール(そのまま適用、判断不要): csn + agentKey の組み合わせは DB 上で UNIQUE 制約 なので、同じセッションを再起動しても常に同じ値になる必要があります(そうしないと再起動のたびに既存行の更新ではなく新規行が作られてしまいます)。以下の手順をそのまま適用して計算してください。
- 元 ID: フック stdin の JSON の
session_idフィールドの値があればそれを使う。なければfallback_<COMPUTERNAME 環境変数の値>_<現在のプロセス PID>を元 ID として使う。 - 正規化: 元 ID から英数字(
a-z、A-Z、0-9)以外の文字をすべて削除する(正規表現置換:[^a-zA-Z0-9]→'')。 - 切り詰め(1回目): 正規化した値が24文字を超える場合、先頭24文字だけ残す。
- 結合:
agentKey = "claude_interactive_" + <COMPUTERNAME 環境変数の値> + "_" + <手順3の結果> - 切り詰め(2回目): 手順4の結果が100文字を超える場合、先頭100文字だけ残す。この最終値を
agentKeyとして使う。
SessionStart/SessionEnd フックの登録場所(そのまま貼り付ける JSON): Claude Code の場合、プロジェクトルートの .claude/settings.json(そのプロジェクトのみに適用)またはユーザーホームの ~/.claude/settings.json(すべてのプロジェクトにグローバル適用)のいずれかを選び、そのファイルの最上位に以下の hooks キーをマージしてください。すでに hooks キーがある場合は、SessionStart/SessionEnd 配列の中に以下のオブジェクトを追加してください(既存の項目を上書きしないこと)。matcher フィールドは追加しません — このフックはすべてのセッションにグローバル適用されます。
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "<セッション開始時に実行する command。例: powershell -NoProfile -ExecutionPolicy Bypass -File \"<登録スクリプトの絶対パス>\" -Action Start>",
"timeout": 15000
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "<セッション終了時に実行する command。例: powershell -NoProfile -ExecutionPolicy Bypass -File \"<登録スクリプトの絶対パス>\" -Action End>",
"timeout": 15000
}
]
}
]
}
}
⚠️ グローバル(matcher なし)フックとして登録した場合のヘッドレス誤判定に注意(giip #1837): 上記のフックには
matcherがないため、このホスト上で実行される すべて の claude プロセス(対話型セッションだけでなく、無人スケジューラーがclaude -pで開くヘッドレス実行も含む)で発火します。そのため、登録スクリプトの中に「今回の実行が対話型かヘッドレスか」を判定するロジックが事実上必須になります。このとき$env:CLAUDE_CODE_BRIDGE_SESSION_ID(Remote Control ブリッジの接続有無)を判定基準に使わないでください — この値はブリッジの接続有無しか示さず、ヘッドレスかどうかとは無関係です。本物の対話型セッションでも、まだ/remote-controlを実行/接続していなければこの値がない場合があります(そのようなセッションまでヘッドレスと誤判定され、登録自体がスキップされる事故が実際に発生しました — giip #1837)。正しい判定方法: このフックを実行するプロセス自身の親をさかのぼって実際のclaude/claude.exeプロセスを見つけ、そのプロセスのコマンドラインに-p/function Test-IsHeadlessClaudeInvocation { try { $checkPid = $PID for ($i = 0; $i -lt 6; $i++) { $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$checkPid" -ErrorAction Stop if (-not $proc) { return $false } if ($proc.Name -eq 'claude.exe') { $cmd = $proc.CommandLine if ($cmd -and ($cmd -match '(^|\s)(-p|--print)(\s|$)')) { return $true } return $false } $checkPid = $proc.ParentProcessId if (-not $checkPid -or $checkPid -eq 0) { return $false } } return $false } catch { return $false } }Windows 以外の環境では、同じ原理(親プロセスのコマンドラインで
-p/
この command は標準入力(stdin)でフックイベントの JSON(session_id などを含む)を受け取ります。この文書に記載されている SP 呼び出し仕様(呼び出し規約、フィールド一覧、agentKey 生成ルール)だけで自己完結的に実装できます — この文書を管理する運用者が個人的に参照している実装があったとしても、そのリポジトリは非公開で他のセッションからはアクセスできないため、どこかからコードを取得しようとせず、この文書の仕様だけを基に自分で実装してください。
ここで agentKey と capabilities.sessionUrl は 異なる値に由来する別々の ID である点に注意してください — この2つを混同すると、「セッション ID がないので URL が作れない」という誤解から登録自体を諦めてしまうことがあります:
agentKey— フック stdin のsession_id(ハーネス内部の UUID、例:~/.claude/projects/*/<uuid>.jsonlのファイル名に使われる値)を基に構成します。「再起動しても同じセッションなら同じキーになる」ようにするための用途であり、URL ではありません。capabilities.sessionUrl— 存在する場合、$env:CLAUDE_CODE_BRIDGE_SESSION_ID(例:session_01JGmSiTajXu9iZmjVZC27Ntのような ULID 形式の値 — フック stdin のsession_idとは異なる別の ID)を使ってhttps://claude.ai/code/<この値>の形式で構成します。
この環境変数はすべてのセッションに存在するわけではありません — 例えば claude.ai/code ブリッジを経由しないローカル CLI セッションには存在しない場合があります。$env:CLAUDE_CODE_BRIDGE_SESSION_ID がない場合、sessionUrl が作れないだけであり、登録が止まるという意味ではありません — その場合は capabilities フィールド自体を呼び出しから完全に外し、残りのフィールドだけで登録を進めてください(下記「sessionUrl が作れない場合」を参照)。
CLAUDE_CODE_BRIDGE_SESSION_ID がいつ設定されるのか、無い場合に後から取得できるのか(公式ドキュメント https://code.claude.com/docs/en/remote-control に基づく、そのまま実行できる手順):
この環境変数は、セッションが Anthropic の「Remote Control」機能に接続されている場合にのみ存在します。下記の条件のいずれか一つでも満たさない場合、そもそも取得不可能であり、これは不具合ではなく正常な状態です — この場合は他の方法を試さず、そのまま capabilities を省略して登録を続けてください。
- ヘッドレス(
claude -p)セッションにはこの機能自体がありません。 Remote Control は対話型セッション専用のため、gissue スケジューラのようにclaude -pで動く無人プロセスはこの値を絶対に持てません。 - API キー(
ANTHROPIC_API_KEY)認証のセッションは Remote Control をサポートしません。 claude.ai アカウントへのログイン(claude実行後に/login)が必要です。 - Amazon Bedrock / Google Vertex / Microsoft Foundry 経由の場合、または
ANTHROPIC_BASE_URLがapi.anthropic.com以外の値(LLM ゲートウェイ・プロキシなど)に設定されている場合はサポートされません。 DISABLE_TELEMETRY、DO_NOT_TRACK、CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC、DISABLE_GROWTHBOOKのいずれかが設定されている場合はサポートされません(設定されている場合はその変数を解除する必要があります)。
上記の条件をすべて満たす通常の対話型セッションなのにこの変数が無い場合、まだ Remote Control が接続されていないだけです。セッションを再起動する必要はなく、そのセッション内で次のコマンドを実行すればすぐに接続され、その瞬間から $env:CLAUDE_CODE_BRIDGE_SESSION_ID が設定されます:
/remote-control
(/rc も同様です)今後のセッションで毎回自動的に接続されるようにするには、セッション内で /config を実行して「Enable Remote Control for all sessions」を有効にするか、ユーザーホームの ~/.claude/settings.json に以下を追加してください:
{
"remoteControlAtStartup": true
}
ここでも絶対禁止(ガイド147行目の原則と同じ): 上記の条件を満たせず(ヘッドレス実行、API キー認証など)CLAUDE_CODE_BRIDGE_SESSION_ID が取得できない場合、フック stdin の session_id や $env:CLAUDE_CODE_SESSION_ID など別の値で代用して sessionUrl を「作り出そう」としないでください — これらの値は claude.ai/code の実際のセッションとは無関係で、開けない(404の)リンクになります。この場合の唯一の正解は capabilities を省略して登録を続行することであり、それ以外の対処を試みる必要はありません。
この判断は完全に機械的です — 人間に尋ねません。 自分のプロセス内で $env:CLAUDE_CODE_BRIDGE_SESSION_ID の有無だけを確認して分岐し、どの値を使うかをユーザーに選択肢として提示したり質問したりすることは絶対にしません。フック stdin の session_id(agentKey の出所)を sessionUrl として再利用することも絶対に禁止です — 別の ID であり、壊れた/404 リンクになります。sessionUrl を内部ツールのリンクや推測 URL など他の値で代用することも禁止です — sessionUrl は claude.ai/code ブリッジリンクであるか、省略された値のいずれかでなければなりません。
sessionUrl を必ず埋めたい場合: この登録を行うセッション「自分自身」が Remote Control ブリッジに接続されていないと $env:CLAUDE_CODE_BRIDGE_SESSION_ID は設定されません。これは各セッションが自分自身で備える状態であり、他の運用者の PC 設定(例: セッション開始時に自動でブリッジに接続する設定)に依存することはできません — 他人の PC 設定はこのセッションには何の影響も与えません。まだ接続していない場合は、/remote-control コマンドを実行するか(対話型セッション内で)、claude --remote-control/--rc フラグを付けて再起動し、自分で接続してください。接続を待っている間も登録自体(Upsert/RunStart)は続行してください — 下記「sessionUrl が作れない場合(capabilities を省略)」の方式に従い、登録をまるごと先送りしないでください。
呼び出し規約(giipApiSk4 共通): HTTP POST、application/x-www-form-urlencoded のフォームフィールド3つ。
⚠️ 位置ベースのパラメータ: これらの SP(
pApiSchedulerAgentUpsertBySKなど)はjsondataのフィールドを SP の個々の位置パラメータ(@p0, @p1, ...)に順番どおりバインドします — 途中のフィールドをスキップすることはできません。後方のフィールド(例:capabilities)まで値を埋めたい場合は、その前のすべてのフィールドも一緒に送る必要があり、実際には使わないフィールドは安全なプレースホルダー値(例:windowsTaskName=''、projectName=''、scheduleDesc=''、lssn='0'、version='')で埋めます。整数型パラメータ(lssnなど)に空文字列を送ると変換エラーになるため、必ず数値文字列にしてください。ただしcapabilitiesはこのフィールドリストの 末尾 にあるため、値がない場合(上記の$env:CLAUDE_CODE_BRIDGE_SESSION_ID不在の状況)はフィールド自体を丸ごと省略しても安全です — 後に続く他のフィールドがないため位置がずれないからです。位置ベースの制約はあくまで 途中のフィールド をスキップできないという意味であり、末尾のフィールドまで必ず埋めなければならないという意味ではありません。
| フォームフィールド | 値 |
|---|---|
text | "<SP名> <フィールド1> <フィールド2> ..."(SP 名は BySK 接尾辞を除いた名前、続けてこの呼び出しで埋めるフィールド名をスペース区切りで列挙) |
token | <YOUR_SECRET_KEY>(対象 CSN の SK) |
jsondata | フィールド名→値のマッピング JSON 文字列、例: {"agentKey":"...","displayName":"..."} |
各ステップで実際に埋めるフィールド:
| ステップ | SP名(text の最初のトークン) | 主なフィールド |
|---|---|---|
| 開始 — identity 登録/更新 | SchedulerAgentUpsert | agentKey(ホスト+セッションごとの一意な識別子)、displayName、hostIdentifier(ホスト名)、windowsTaskName、projectName、scheduleDesc、isActive=1、lssn、osType、agentType(例: claude_interactive_session)、version、capabilities(JSON 文字列、例: {"sessionUrl":"<セッションを開ける URL>"}) |
| 開始 — 実行(run)開始 | SchedulerAgentRunStart | runIdKey(この実行の一意なキー)、agentKey、executionMode=interactive、totalIssueCount |
| 終了 — 実行(run)終了 | SchedulerAgentRunEnd | runIdKey、agentKey、status=ENDED、processedCount、skippedCount、failedCount |
| 終了 — identity をオフラインに | SchedulerAgentUpsert | agentKey、displayName、hostIdentifier、windowsTaskName、projectName、scheduleDesc、isActive=0 |
例(PowerShell、値はすべてプレースホルダー):
$body = @{
text = 'SchedulerAgentUpsert agentKey displayName hostIdentifier windowsTaskName projectName scheduleDesc isActive lssn osType agentType version capabilities'
token = '<YOUR_SECRET_KEY>'
jsondata = (@{
agentKey = 'claude_interactive_<YOUR_HOST>_<UNIQUE_ID>'
displayName = 'Claude Interactive Session (<YOUR_HOST>)'
hostIdentifier = '<YOUR_HOST>'
windowsTaskName = ''
projectName = ''
scheduleDesc = ''
isActive = '1'
lssn = '0'
osType = 'Windows'
agentType = 'claude_interactive_session'
version = ''
capabilities = (@{ sessionUrl = '<任意のセッション URL>' } | ConvertTo-Json -Compress)
} | ConvertTo-Json -Compress)
}
Invoke-WebRequest -Uri 'https://giipfaw.azurewebsites.net/api/giipApiSk4' -Method Post -Body $body
sessionUrl が作れない場合(capabilities を省略): $env:CLAUDE_CODE_BRIDGE_SESSION_ID がなく capabilities を構成できない場合、上記の例から text の capabilities トークンと jsondata の capabilities フィールドだけを外し、残り11個のフィールドはそのまま使ってください。sessionUrl がなくても登録自体は完全に正常に成功します — 唯一の違いは「Open Interactive Sessions」カードに「Open session」リンクが表示されないことだけです(下記「トラブルシューティング」を参照)。
$body = @{
text = 'SchedulerAgentUpsert agentKey displayName hostIdentifier windowsTaskName projectName scheduleDesc isActive lssn osType agentType version'
token = '<YOUR_SECRET_KEY>'
jsondata = (@{
agentKey = 'claude_interactive_<YOUR_HOST>_<UNIQUE_ID>'
displayName = 'Claude Interactive Session (<YOUR_HOST>)'
hostIdentifier = '<YOUR_HOST>'
windowsTaskName = ''
projectName = ''
scheduleDesc = ''
isActive = '1'
lssn = '0'
osType = 'Windows'
agentType = 'claude_interactive_session'
version = ''
} | ConvertTo-Json -Compress)
}
Invoke-WebRequest -Uri 'https://giipfaw.azurewebsites.net/api/giipApiSk4' -Method Post -Body $body
別のホストでこのメカニズムを再現するには、次の2点がそのまま必要です(どちらも固定要件であり、裁量の余地はありません): (a) そのホストのセッション実行ツールにも上記と同じ hooks.SessionStart/hooks.SessionEnd 設定、(b) 登録先の CSN に対する有効な SK。
SK をどこに保管するかは(この手順とは無関係な)純粋なセキュリティ上の判断事項です — 参考までに、この運用者の個人環境(lowyworkenv リポジトリ)ではこの SK を slack-bot/.secrets/giip-accounts.json という JSON ファイル(Slack チャンネル ID → {login_id, sk, csn} のマッピング構造)で保管していますが、これは あくまで参考用の例 です — この特定のファイルパスをそのまま踏襲しろという意味ではなく、他のホスト/運用者は各自安全な方法(OS の資格情報ストア、シークレットマネージャー、環境変数など)で SK を保管すれば構いません。
成功の確認: 画面を再読み込みすると「Open Interactive Sessions」カードにセッションが表示されます。
方法 B — スケジューラーエージェント(自動化ランナー)の登録
gissue スケジューラーのようなバックグラウンド自動化ランナーの登録は、方法 A と同じ SP 系統を使いますが、一度きりではなく 定期的に(heartbeat) 自身の identity と実行状態を更新します。
標準実装は giip-fde-agent です。 最初から自作せず、上記「AI に任せて gissue スケジューラーを作る」手順に従ってください。以下の SP 仕様はランナーが内部的に使う呼び出しであり、直接実装する場合にのみ参照してください。
- 前提条件: 上記の共通前提条件(対象 CSN 用の SK)。
- 初回登録/定期的な identity 更新: プロセス開始時に1回
SchedulerAgentUpsert(方法 A と同じフィールド —agentKey/displayName/hostIdentifier/osType/agentType/version/capabilitiesなど)を呼び出し、以降は最大5分間隔(推奨: 2分間隔)で繰り返し呼び出します。 - 実行(run)開始:
SchedulerAgentRunStart(runIdKey、agentKey、executionMode=scheduled、totalIssueCount)。 - 実行中の進捗更新(heartbeat):
SchedulerAgentHeartbeatPut—runIdKey、agentKey、processedCount、skippedCount、failedCount、currentPhase、currentIssueNum、totalIssueCount。処理単位(例: issue を1件処理し終えるごと)に呼び出し、処理対象がなくアイドル状态的ときも最大2分間隔で呼び出してください — heartbeat が5分以上途絶えると、画面上で STALE と表示されます。 - 実行終了:
SchedulerAgentRunEnd(runIdKey、agentKey、status、processedCount、skippedCount、failedCount、exitCode、summary)。status値はSUCCEEDED/TIMED_OUT/FAILED、exitCodeは数字文字列('0'または'1')。
| SP名 | 認証 | 用途 |
|---|---|---|
SchedulerAgentUpsert | SK | identity の登録/更新 |
SchedulerAgentRunStart | SK | 実行開始の記録 |
SchedulerAgentHeartbeatPut | SK | 実行中の進捗/heartbeat 更新 |
SchedulerAgentRunEnd | SK | 実行終了の記録 |
SchedulerAgentList | AK(ログインセッション) | この画面が一覧を取得する際に使用 — 登録には不要 |
位置引数順序(方式 1):
- Upsert 引数順序:
agentKey、displayName、hostIdentifier、windowsTaskName、projectName、scheduleDesc、isActive - RunStart 引数順序:
runIdKey、agentKey、executionMode、totalIssueCount - HeartbeatPut 引数順序:
runIdKey、agentKey、processedCount、skippedCount、failedCount、currentPhase、currentIssueNum
呼び出し規約は2つの方式がどちらも有効です。方式 1(ランナー内部): giipApiSk2 に token=SK、text="SP名 '値1' '値2' ..."(SP パラメータ宣言順の位置引数、値は小なり符リテラル)、jsondata は空。方式 2(直接実装の場合、方法 A と同じ形式): giipApiSk4 に token=SK、text にフィールド名を空白区切りで、jsondata に {"フィールド名":"値",...} JSON。
補足: このプロジェクトが管理する giipAgentWin/giipAgentLinux(サーバーインフラエージェント)は、この
tSchedulerAgent体系とは 別の登録メカニズム(x-api-key ベースのagent-register/agent-heartbeatAPI)を使用しており、この画面とは無関係です。この画面(admin/catquest/schedulers)に登録するには、上記の SP 系統を呼び出す実装が必要であり、gissue の毎時スケジューラーの標準実装は giip-fde-agent のrun-gissue-claude.ps1です。
成功の確認: 次回の heartbeat/再読み込み後、エージェント一覧テーブルに表示されます。
💡 注意事項
- この画面は 管理者専用 です。
AdminGuard(uLevel ≥ 70)の権限が必要です。 - エージェント一覧、実行履歴、ログカタログはすべてセッションの現在の CSN を基準に取得されます — 別プロジェクトのエージェントを確認するには、上部ナビゲーションでプロジェクトを切り替えてください。
- データ取得には認証済みセッション(AK トークン)が必要です。リクエストが認証エラーで失敗し始めた場合は、再度ログインしてから Refresh を押してください。
- このページは
/admin/catquestとは別のツールです — CatQuest 画面のナビゲーション経由で到達したからといって、CatQuest の猫可視化データや対象ユーザーを共有しているわけではありません。
トラブルシューティング
| 症状 | 原因 | 解決方法 |
|---|---|---|
| 対話型セッションに登録を指示したのに「Open Interactive Sessions」に全く表示されない | グローバルフックのヘッドレス判定ロジックが $env:CLAUDE_CODE_BRIDGE_SESSION_ID の有無だけで判断し、ブリッジ未接続の対話型セッションまでヘッドレスと誤判定して登録自体をスキップした可能性が最も高い(giip #1837) | 上記「グローバルフックとして登録した場合のヘッドレス誤判定に注意」ボックスのプロセスコマンドライン検査方式に判定ロジックを差し替えてください。 |
| 「Authentication required」エラー | AK/セッショントークンが見つからない | 再ログイン後、ページを再読み込みしてください。 |
| エージェント一覧が空 | この CSN に登録されたスケジューラーエージェントがない、またはプロジェクトの選択が誤っている | 上部ナビゲーションで正しいプロジェクト(CSN)が選択されているか確認してください。 |
| ジョブがアイドル状態のはずなのに行が赤い STALE と表示される | エージェントが ENDED に遷移せず実行中に heartbeat 送信が停止(isStale = true) — プロセスがクラッシュまたは強制終了された可能性 | エージェントのホストを直接確認してください。再起動して再度報告が始まればバッジは更新されます。 |
| Live Log Viewer に「No streams yet.」と表示される | エージェントがまだログストリームを登録していない、またはカタログの最終更新以降に出力がない | エージェントの次回実行を待つか、エージェントプロセスが実際にログを書き込んでいるか確認してください。 |
| Open Interactive Sessions に「Open session」リンクがない | 該当エージェントの登録済み capabilities に sessionUrl が含まれていない | 開ける項目はありません — その対話型セッションが到達可能な URL を登録していません。 |
バージョン: 1.1
最終更新: 2026-09-01
ソースファイル: giipv3/public/help/catquest-schedulers.ja.md