giip
SES案件登録
9分で読了

エージェント登録およびキューAPI仕様

この文書は、AIエージェント(または任意のホスト)をGIIP論理マシンとして登録し、自身のCQEタスクキューをポーリングし、実行結果を報告するための技術仕様である — 本番環境のgiipAgentWin/giipAgentLinuxが実際に使用しているものと同じ仕組みである。

🔌 giip-agentスキルバンドルへ →

📋 概要

このAPIは、ホスト — giipAgentWin/giipAgentLinuxを実行する物理/仮想マシン、または自身のハードウェア的な識別情報を持たないAIコーディングエージェントセッション — が自身をtLSvrに論理マシン(lssn)として登録し、そのlssnのCQE(Centralized Queue Engine)タスクキューをポーリングし、結果を報告できるようにする。3つの操作はすべて1つのエンドポイントを通る。


🔐 認証 — REST系とは異なる単一ディスパッチャーエンドポイント

課題管理APIとはAPIの形が異なる。 そちらはx-api-keyヘッダーと実際のHTTPステータスコードを使う通常のRESTエンドポイント(/api/giipIssues)である。このAPIはgiipApiSk2 — フォームエンコード方式の単一汎用ディスパッチャーエンドポイントで、常にHTTP 200を返す

ベースURL

https://giipfaw.azurewebsites.net/api/giipApiSk2

リクエスト形式(常に同じ3つのフィールド)

フィールド内容
textストアドプロシージャの「コマンド」名とそのパラメータをスペース区切りで列挙(例: AgentAutoRegister hostname jsondata)— パラメータのではない
tokenSK、通常のフォームフィールドとして送信。HTTPヘッダーではない。
jsondata実際のパラメータ値を保持するJSONオブジェクト
curl -s -X POST "https://giipfaw.azurewebsites.net/api/giipApiSk2" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "text=AgentAutoRegister hostname jsondata" \
  --data-urlencode "token=${GIIP_API_KEY}" \
  --data-urlencode 'jsondata={"hostname":"Lowy-DP01-claude-code","os":"Windows 10"}'

HTTPステータスコードはほとんど何も教えてくれない

このエンドポイントが解析できるリクエストはすべて200 OKを返す。 無効なSKに対する401も、存在しないlssnに対する404も、権限問題に対する403もない。実際の結果は常にJSONボディのdata[0].RstValに含まれる(giipfaw/giipApiSk2/run.ps1のソースレビューおよびライブテストで確認、2026-09-06):

{"data":[{"Proc_MSG":"401|Unauthorized - Invalid SK","RstVal":401,"RstMsg":"Unauthorized - Invalid Secret Key"}]}

上記の応答もHTTP 200である。giipApiSk2呼び出しの実際の成功・失敗は、HTTPステータスではなく常にdata[0].RstValで判断すること。

SK — Issue APIと同じ鍵種、異なる伝送方式

  • Issue APIが使うものと同じ、/svclistで発行されるcsn単位のプロジェクトSKである — ただしここではx-api-keyヘッダーではなくPOSTボディのtoken=<sk>として送信する。
  • csnはSKからサーバー側で導出される(dbo.lwGetCSNbysk(@sk))— リクエストにcsnを直接送ることはなく、AgentAutoRegister/CQEQueueGetにはクライアント指定のcsnを暗黙にクランプする余地自体が存在しない(giipdb/SP/pApiAgentAutoRegisterBySK.sqlのレビューで確認、2026-09-06)。KVSPutは関連するが異なる所有権チェックを行う — 下記参照。

エンドポイント

AgentAutoRegister — 論理マシンの登録、または既存マシンのheartbeat

リクエスト:

text=AgentAutoRegister hostname jsondata
token=<sk>
jsondata={
  "hostname": "Lowy-DP01-claude-code",
  "os": "Windows 10",
  "cpu": "...", "cpu_cores": 8, "memory_gb": 32, "disk_gb": 512,
  "agent_version": "giip-agent-skill/1.0.0",
  "ipv4_global": "...", "ipv4_local": "...",
  "network": [{"name":"eth0","ipv4":"...","ipv6":"...","mac":"..."}],
  "software": [{"name":"...","version":"...","vendor":"...","type":"..."}],
  "services": [{"name":"...","status":"...","start_type":"...","port":80}]
}

hostnameのみ必須で、他のフィールドはベストエフォートであり省略可能。

識別キーは(hostname, csn)である。 ストアドプロシージャ(pApiAgentAutoRegisterBySK)はLSHostname = hostname AND CSn = <SKから導出>の条件でtLSvrを検索する:

既存行あり?動作応答
なし新しいtLSvr行をINSERTlssn = SCOPE_IDENTITY(){"data":[{"lssn":<new>,"action":"new","RstVal":200,...}]}
あり既存行をUPDATE(スペック、ネットワーク/ソフトウェア/サービスのインベントリ、LSLastHeartbeat{"data":[{"lssn":<same>,"action":"update","RstVal":200,...}]}

ライブ検証済み(2026-09-06、csn 47):

$ python scripts/giip_agent.py register --tool-slug claude-code
{"success": true, "hostname": "Lowy-DP01-claude-code", "lssn": 71290, "action": "new"}
$ python scripts/giip_agent.py register --tool-slug claude-code   # 繰り返し呼び出し
{"success": true, "hostname": "Lowy-DP01-claude-code", "lssn": 71290, "action": "update"}

必須のホスト名規則: <物理ホスト名>-<tool-slug>。同じホスト上の異なるAIツールはそれぞれ自身のホスト名で(したがって自身のlssnで)登録しなければならない — 同じPCで動くClaude Code、Codex、Antigravityは互いに異なる3つの論理マシンである(例: Lowy-DP01-claude-codeLowy-DP01-codexLowy-DP01-antigravity)。これはサーバーが強制する制約ではなく、文書/クライアント側の規律である — サーバーはどんなホスト名を送っても、そのまま作成してしまうため、この規律は呼び出す側が守らねばならない。

無効なSKは401を返さず、data[0]内でRstVal: 401として表現される({"Proc_MSG":"401|Unauthorized - Invalid SK",...})。

CQEQueueGet — このlssnのキューを一度だけポーリング

リクエスト:

text=CQEQueueGet lssn hostname os op
token=<sk>
jsondata={"lssn":71290,"hostname":"Lowy-DP01-claude-code","os":"Windows 10","op":"op"}

応答、作業あり:

{"data":[{"RstVal":"200","ms_body":"<script or payload text>","mslsn":8032,"script_type":"sh","mssn":123}]}

応答、キューなし(ライブ検証、2026-09-06)— これは成功でありエラーではない:

{"data":[{"RstVal":"404","ProcName":"[pCQEQueueGetbySK02] no queue 2"}]}
$ python scripts/giip_agent.py poll --lssn 71290 --tool-slug claude-code
{"success": true, "lssn": 71290, "has_work": false}

RstValの意味giipdb/SP/pApiCQEQueueGetbySK.sqlのレビューで確認、2026-09-06):

RstVal意味
200キューに作業あり; ms_body/mslsn/mssn/script_typeが入力される
201新規lssnへの初回ポーリングが暗黙の再登録経路を発動 — 「まだ作業なし」と同様に扱い、少し待って再ポーリング
0または404確認したが現在キューなし — 正常、エラーではない
それ以外実際のエラー

推奨ポーリング間隔: 60秒。 実際のgiipAgentLinuxインストールがcronで使う間隔(* * * * *)と一致する。このAPI自体はポーリングをレート制限しないが、それより速くポーリングする理由はない — キューはGIIP自身のスケジュールで埋められる。

誤ったlssnは「作業なし」と区別がつかない。 ポーリングするlssnがそのSKのcsnに属していない場合、保留中の作業を探す結合(tMgmtScriptList ms inner join tLSvr ls on ... where ls.csn = @csn and ms.lssn = @lssn)は該当行を見つけられず、空のキューと同じRstVal: 404を返す。別個の「権限なし」や「lssnなし」応答は存在しない — 誤ったlssnをポーリングしていると疑う場合は、registerを再実行して比較すること。

KVSPut(kFactor=cqeresult)— 結果の報告

専用の「完了/ack」コマンドは存在しない。結果は、GIIPのすべてのエージェントテレメトリで使われるのと同じ汎用キーバリューメカニズムであるKVSPutで書き込む。

リクエスト:

text=KVSPut kType kKey kFactor
token=<sk>
jsondata={
  "kType": "lssn", "kKey": "71290", "kFactor": "cqeresult",
  "kValue": {"mslsn": 8032, "mssn": 123, "lssn": 71290,
             "status": "success", "exit_code": 0,
             "stdout": "...", "stderr": ""}
}

kTypeは文字列リテラル"lssn"でなければならず、kKeyは結果が属するlssn(文字列)でなければならない。

register/pollと異なり、この呼び出しは所有権を検証し、きれいに失敗するgiipdb/SP/pApiKVSPutbySk.sqlのレビューで確認、2026-09-06):SPは書き込み前にEXISTS(SELECT 1 FROM tLSvr WHERE LSsn = @kKey AND CGSn = <SKから導出>)を確認する。lssnがそのSKのキーグループの所有でない場合:

{"data":[{"RstVal":411,"RstMsg":"..."}]}

report200以外のRstValはすべて致命的な失敗として扱うこと — heartbeatのように再試行せず、結果を黙って破棄しないこと。

登録解除(unregister/deregister)エンドポイントなし

論理マシンを削除する呼び出しは存在しない。heartbeatを送らなくなったマシンは単に古くなっていくだけである(LSLastHeartbeatが古くなる)— API上の「さようなら」は存在しない。


🔍 応答標準

3つのコマンドのどれを呼び出しても、giipApiSk2呼び出しは常に結果をdata配列で包む:

{ "data": [ { "RstVal": 200, ... } ] }
  • 成功: RstVal200AgentAutoRegister/CQEQueueGetのエッジケースでは201のこともある)。RstValはコマンドによって数値または数値文字列である — この仕様のクライアントスクリプトは両方に対応するため文字列として比較する。
  • pollの「作業なし」: RstVal 0または404 — 成功であり失敗ではない。
  • 失敗: それ以外のRstValと、理由を説明するRstMsg/Proc_MSG/ProcName
  • トランスポート層の失敗(ネットワークエラー、タイムアウト、200以外のHTTPステータス): リクエストがストアドプロシージャに到達すらしなかったことを意味する — RstVal失敗とはまったく異なる失敗モードである。

🤖 AIエージェントのための完全な手順(登録 → ポーリング → 報告)

export GIIP_API_KEY="<the SK>"

# 1. 登録(冪等 — 初回呼び出しはlssnを作成し、同じhostnameへの
#    以降の呼び出しはそのlssnへのheartbeatになる)
python scripts/giip_agent.py register --tool-slug claude-code
# {"success": true, "hostname": "Lowy-DP01-claude-code", "lssn": 71290, "action": "new"}

# 2. 一度ポーリング。自身のスケジュール(~60秒)で繰り返すこと -- 内部でループしないこと。
python scripts/giip_agent.py poll --lssn 71290 --tool-slug claude-code
# {"success": true, "lssn": 71290, "has_work": false}

# 3. has_workがtrueならms_bodyを処理し、結果を報告。
python scripts/giip_agent.py report --lssn 71290 --mslsn 8032 --mssn 123 \
  --status success --exit-code 0

⚠️ 重要な注意事項

  • 課題管理APIとは異なるAPI系統である。 両者を混同しないこと: giip-issueのクライアントはSKをx-api-keyヘッダーとして実際のHTTPステータスコードを持つRESTエンドポイントに送り、giip-agentのクライアントはSKをtokenフォームフィールドとして常にHTTP 200を返す単一ディスパッチャーエンドポイントに送る。
  • ホスト名規則はサーバー制約ではなくクライアント側の規律である。 異なる2つのツールに対してfooを2回登録することを止める仕組みはない — しかしそうすると、互いのキュー履歴を混乱させる2つのlssnが生まれる。<host>-<tool-slug>規則を厳格に守ること。
  • システム情報のペイロードが変わっても、繰り返しのregisterは依然としてheartbeatである — 新しいマシンではない。識別を決定するのはhostname文字列のみである。

トラブルシューティング

症状原因解決策
AgentAutoRegisterdata[0].RstVal401SKが無効または再発行された/svclistでSKを再確認
pollが常にRstVal 404/has_work: false実際にキューがないか、lssnがこのSKと異なるcsnに属しているregisterを再実行し、返されたlssnを比較
reportRstVal 411を返すlssnがこのSKのキーグループ(cgsn)の所有ではない自分のregister呼び出しが返したlssnにのみ報告する
HTTPステータス自体が200でないトランスポート層の失敗(ネットワーク、ルーター自体が拒否した不正なリクエスト)RstVal失敗とは異なる — 接続確認後の再試行は合理的(RstVal失敗は再試行禁止)
1つのマシンだと思っていたのに異なるlssnが2つ現れるホスト名の構成が一貫していない(異なる--tool-slugの使用、またはbareホスト名でのオーバーライド)ホスト名は常に<host>-<tool-slug>で構成し、呼び出し間で安定させること

バージョン: 1.0 最終更新: 2026-09-06(giipfaw本番環境でライブ検証、csn 47、結果lssn 71290) ソースファイル: giipv3/public/help/giip-agent-api.ja.md

v1.0(2026-09-06、giip #2081): 初回リリース。giipdb/SP/pApiAgentAutoRegisterBySK.sqlpApiCQEQueueGetbySK.sqlpApiKVSPutbySk.sqlgiipfaw/giipApiSk2/run.ps1のソースレビューと、giipAgentLinuxscripts/giip-auto-discover.shlib/cqe.shlib/kvs.shcqe/giipCQE.sh)の本番クライアント動作に基づき、giipApiSk2ディスパッチャー上のAgentAutoRegisterCQEQueueGetKVSPut(kFactor=cqeresult)を文書化した。ライブ検証: register1回(新規lssn 71290)、繰り返しregister1回(heartbeat、同一lssn)、poll1回(キューなし)。


関連文書: