# GIIP Agent API -- Reference for the `giip-agent` Skill

This is a condensed, agent-facing reference for the same API documented in
full (with live-tested evidence, dates, and change history) at:

- Korean: `/ko/guides/giip-agent-api`
- Japanese: `/ja/guides/giip-agent-api`
- English: `/en/guides/giip-agent-api`

When this reference and the full guide disagree, the full guide is the
source of truth -- it is updated more frequently and carries dated,
live-verified evidence for every claim. This file exists so the skill does
not require a network fetch of the guide page just to know the shape of the
API.

## Base URL

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

This is a **different, older dispatcher** than the one the `giip-issue`
skill uses (`/api/giipIssues`, a normal REST endpoint with real HTTP status
codes). `giipApiSk2` is a single generic endpoint that always dispatches a
named stored-procedure call, and it works completely differently:

- Auth is a `token` **form field**, not an HTTP header.
- The HTTP response is **always `200 OK`** for any request it can parse at
  all -- there is no `401`/`404`/`500` for a bad key, missing permission,
  or "no work available". The real result is inside the JSON body's
  `data[0].RstVal` field. A non-200 HTTP status here means a genuine
  transport failure (network error, malformed request the router itself
  rejected), not an application-level error.
- Requests always take the same three form fields: `text` (the procedure
  name plus its parameter *names*, space-separated -- never parameter
  *values*), `token` (the SK), and `jsondata` (a JSON object holding the
  actual parameter values).

## Authentication -- per-csn SK as a `token` form field

- Same SK model as the `giip-issue` skill (a project SK, scoped to one
  csn) -- but sent as `token=<sk>` in the URL-encoded POST body, not an
  `x-api-key` header.
- The csn is derived server-side from the SK itself
  (`dbo.lwGetCSNbysk(@sk)`); you never send a csn as a request parameter,
  and there is no client-supplied csn to silently clamp -- unlike
  `giip-issue`'s create endpoint, this API has no "wrong csn" failure mode
  at all for `register`/`poll`. (`report`/KVSPut has a related but
  different check -- see below.)
- An invalid SK does not produce an HTTP 401. It surfaces as
  `RstVal: 401` inside `data[0]` for `AgentAutoRegister`
  (`{"Proc_MSG":"401|Unauthorized - Invalid SK", "RstVal":401, ...}`).

## Endpoints

### `AgentAutoRegister` -- register or heartbeat

```
text=AgentAutoRegister hostname jsondata
token=<sk>
jsondata={"hostname":"...", "os":"...", "cpu":"...", "cpu_cores":N,
          "memory_gb":N, "disk_gb":N, "agent_version":"...",
          "ipv4_global":"...", "ipv4_local":"...",
          "network":[{"name":"...","ipv4":"...","ipv6":"...","mac":"..."}],
          "software":[{"name":"...","version":"...","vendor":"...","type":"..."}],
          "services":[{"name":"...","status":"...","start_type":"...","port":N}]}
```

All `jsondata` fields except `hostname` are optional; omit anything you
cannot honestly determine rather than guessing.

**Hostname is the identity key.** The server looks up an existing row by
`(LSHostname = hostname, CSn = <derived from sk>)`:

- No match -> **INSERT**: a brand-new `lssn` is created
  (`SCOPE_IDENTITY()`), response includes `"action":"new"` and
  `"RstVal":200`.
- Match -> **UPDATE**: the existing row is refreshed as a heartbeat (specs,
  network/software/service inventory, `LSLastHeartbeat`), response
  includes `"action":"update"` and `"RstVal":200`.

**Mandatory hostname convention for AI agents**: `<physical-hostname>-<tool-slug>`,
e.g. `Lowy-DP01-claude-code`, `Lowy-DP01-codex`, `Lowy-DP01-antigravity`.
Each distinct AI tool running on a given host must register its own
hostname (and therefore get its own `lssn`) -- never share one hostname
across tools, and never register the same tool under two different
hostname spellings, since that silently creates a second, orphaned `lssn`
that will never receive heartbeats from the first one.

Response (new registration):

```json
{"data":[{"Proc_MSG":"200|Server auto-registered successfully","lssn":88123,"action":"new","RstVal":200,"RstMsg":"Server auto-registered successfully"}]}
```

Response (heartbeat):

```json
{"data":[{"Proc_MSG":"200|Server updated successfully (heartbeat)","lssn":88123,"action":"update","RstVal":200,"RstMsg":"Server updated successfully (heartbeat)"}]}
```

There is no separate "heartbeat" verb -- calling `AgentAutoRegister` again
with the same hostname *is* the heartbeat. A recommended heartbeat interval
is every 5 minutes (matches production `giipAgentLinux` cron usage);
there is no enforced minimum, but sending it more than once per minute is
pointless.

### `CQEQueueGet` -- poll this lssn's queue once

```
text=CQEQueueGet lssn hostname os op
token=<sk>
jsondata={"lssn":<lssn>,"hostname":"<host>-<tool-slug>","os":"<os>","op":"op"}
```

Response when work is queued:

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

Response when nothing is queued (**normal, not an error**):

```json
{"data":[{"RstVal":"404","ProcName":"[pCQEQueueGetbySK02] no queue 2"}]}
```

`RstVal` can come back as `"0"`, `"404"`, or occasionally `"201"`
(first-ever poll for an `lssn` triggers an implicit re-registration path,
`pLSvrInfoInputSimplebySK`) -- treat `0` and `404` identically as "checked,
no work right now", and `200`/`201` as "there is a response payload to
read". Any other value is a genuine error.

**Recommended poll interval: 60 seconds.** This matches the interval real
`giipAgentLinux` installs use via cron (`* * * * *`). Do not poll in a
tight loop -- the queue is populated on GIIP's own schedule, so polling
faster than once a minute gains nothing and will draw attention as abuse.
This skill's client makes exactly one poll per invocation and never loops
internally; scheduling repetition (cron, a sleep loop, an agent's own task
scheduler) is the caller's responsibility.

**Wrong-lssn is indistinguishable from no-work.** If `lssn` does not
belong to the SK's csn, the query that looks up pending work simply finds
no row and returns the same `RstVal: 404` as an empty queue -- there is no
separate "permission denied" or "lssn not found" response for `poll`. If
you suspect you are polling the wrong `lssn`, re-run `register` (a
heartbeat) and confirm the `lssn` it returns matches what you intended to
poll.

### `KVSPut` (kFactor=`cqeresult`) -- report a result

```
text=KVSPut kType kKey kFactor
token=<sk>
jsondata={"kType":"lssn","kKey":"<lssn>","kFactor":"cqeresult","kValue":{
  "mslsn":<mslsn>, "mssn":<mssn>, "lssn":<lssn>, "status":"...",
  "exit_code":N, "stdout":"...", "stderr":"..."
}}
```

There is no dedicated "complete"/"ack" verb for a CQE queue item --
reporting a result is a generic `KVSPut` write, the same mechanism used
for all of GIIP's key-value telemetry. `kType` must be the literal string
`"lssn"` and `kKey` must be the `lssn` (as a string) that the result
belongs to.

**Unlike `register`/`poll`, this call *does* check ownership and fails
cleanly on a mismatch**: the server verifies `LSsn = kKey AND CGSn =
<derived from sk>` before writing. If the `lssn` does not belong to the
SK's key group, the write is refused:

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

Treat any `RstVal` other than `200` here as a hard failure -- do not retry
it as if it were a heartbeat, and do not silently drop the result.

### No dedicated "unregister"/"deregister" endpoint

There is no delete/deregister call for a logical machine. A machine that
stops sending heartbeats simply goes stale (`LSLastHeartbeat` ages) --
this skill does not attempt to detect or announce that state.

## Timeouts and retries

- Use a request timeout (this skill's client uses 30 seconds -- `KVSPut`
  and `AgentAutoRegister` payloads can be larger than a typical
  `giip-issue` call).
- On timeout or an unclear result, never auto-retry. Re-run `register` (a
  safe heartbeat) to re-confirm the `lssn` is still valid before assuming
  anything about a failed `poll` or `report` call.
