giip
SES 商機登記
7分鐘閱讀

代理註冊與佇列API規範

本文件提供將AI代理(或任意主機)註冊為GIIP邏輯機器、輪詢其自身CQE任務佇列並回報執行結果的技術規範 — 與生產環境中giipAgentWin/giipAgentLinux實際使用的機制相同。

🔌 前往giip-agent技能包 →

📋 概述

此API使主機 — 執行giipAgentWin/giipAgentLinux的實體/虛擬機器,或沒有自身持久硬體身分的AI程式設計代理工作階段 — 能夠將自己註冊為tLSvr中的邏輯機器(lssn),然後輪詢該lssn自身的CQE(Centralized Queue Engine,集中式佇列引擎)任務佇列並回報結果。這三種操作都透過同一個端點完成。


🔐 認證 — 與REST風格不同的單一調度端點

這與問題管理API的API形態不同。 那個API是使用x-api-key請求標頭和真實HTTP狀態碼的一般REST端點(/api/giipIssues)。此API是giipApiSk2 — 一個表單編碼的通用調度端點,始終回傳HTTP 200

基礎URL

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

請求格式(始終是相同的三個欄位)

欄位內容
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呼叫是否真正成功,務必始終查看data[0].RstVal,而非HTTP狀態碼。

SK — 與Issue API相同的金鑰類型,不同的傳輸方式

  • Issue API使用的相同、在/svclist按csn簽發的專案SK — 但此處以POST主體中的token=<sk>傳送,而非x-api-key請求標頭。
  • csn由SK在伺服端推導得出(dbo.lwGetCSNbysk(@sk))— 您不會在請求中直接傳送csn,AgentAutoRegister/CQEQueueGet根本不存在可被靜默鉗制的客戶端指定csn欄位(已透過審查giipdb/SP/pApiAgentAutoRegisterBySK.sql確認,2026-09-06)。KVSPut有相關但不同的所有權檢查 — 見下文。

端點

AgentAutoRegister — 註冊邏輯機器,或對現有機器傳送心跳

請求:

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列,lssn = SCOPE_IDENTITY(){"data":[{"lssn":<new>,"action":"new","RstVal":200,...}]}
更新現有列(規格、網路/軟體/服務清單、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)— 在同一台電腦上執行的Claude Code、Codex和Antigravity是三台不同的邏輯機器(例如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的首次輪詢觸發了隱式重新註冊路徑 — 應視為「尚無任務」,稍後再次輪詢
0404已檢查,目前沒有排隊任務 — 正常,非錯誤
其他值真正的錯誤

建議輪詢間隔: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)— 回報結果

沒有專門的「完成/確認」命令。結果是透過KVSPut寫入的,這是用於GIIP所有代理遙測資料的同一通用鍵值機制。

請求:

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":"..."}]}

對於report,任何非200RstVal都應視為嚴重失敗 — 不要將其當作心跳重試,也不要悄悄丟棄該結果。

沒有取消註冊(unregister/deregister)端點

沒有用於刪除邏輯機器的呼叫。停止傳送心跳的機器只會逐漸「過期」(LSLastHeartbeat不再更新)— 在API層面沒有「告別」機制。


🔍 回應標準

無論呼叫三個命令中的哪一個,giipApiSk2呼叫始終將結果包裝在data陣列中:

{ "data": [ { "RstVal": 200, ... } ] }
  • 成功RstVal200(在AgentAutoRegister/CQEQueueGet的邊緣情況下偶爾為201)。RstVal根據命令不同可能是數字或數字字串——本規範的客戶端腳本將其作為字串比較以同時處理這兩種情況。
  • poll的「無任務」RstVal0404 — 成功,不是失敗。
  • 失敗:其他任何RstVal,並附帶說明原因的RstMsg/Proc_MSG/ProcName
  • 傳輸層失敗(網路錯誤、逾時,或非200的HTTP狀態):意味著請求根本沒有到達預存程序 — 這與RstVal失敗是完全不同的失敗模式。

🤖 AI代理的完整流程(註冊 → 輪詢 → 回報)

export GIIP_API_KEY="<the SK>"

# 1. 註冊(冪等 — 首次呼叫建立lssn,之後使用相同hostname的
#    呼叫都是對該lssn的心跳)
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的單一調度端點。
  • 主機名稱規則是客戶端層面的約束,而非伺服器約束。 沒有任何機制阻止您為兩個不同的工具都註冊foo兩次 — 但這樣做會產生兩個相互混淆佇列歷史的lssn。請嚴格遵循<host>-<tool-slug>規則。
  • 即使系統資訊負載發生變化,重複的register仍然是心跳 — 不是新機器。決定身分的只有hostname字串。

疑難排解

症狀原因解決方法
AgentAutoRegisterdata[0].RstVal401SK無效或已重新簽發/svclist重新核實SK
poll始終回傳RstVal 404/has_work: false要嘛確實沒有排隊任務,要嘛lssn屬於與此SK不同的csn重新執行register,比較回傳的lssn
report回傳RstVal 411lssn不屬於此SK的金鑰群組(cgsn僅針對自己register呼叫回傳的lssn進行回報
HTTP狀態本身不是200傳輸層失敗(網路問題,或路由器本身拒絕了格式錯誤的請求)RstVal失敗不同 — 在確認連線後重試是合理的(RstVal失敗則不應重試)
原以為是一台機器,卻出現兩個不同的lssn主機名稱建構不一致(使用了不同的--tool-slug,或使用了裸主機名稱覆寫)主機名稱應始終按<host>-<tool-slug>建構,並在各次呼叫間保持穩定

版本:1.0 最後更新:2026-09-06(在giipfaw生產環境實際驗證,csn 47,結果lssn 71290) 來源檔案giipv3/public/help/giip-agent-api.zh-TW.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)。實際驗證:一次register(新建lssn 71290)、一次重複register(心跳,相同lssn)、一次poll(無任務)。


相關文件