# Operate the product with your own agent or HTTP tools

CitusIO exposes its existing versioned HTTP admin API, machine-readable task
catalog and web panel. Use any agent or HTTP tooling that supports your site's
authentication and TLS. No supplied client, browser automation framework or
Python/Bun/Node installation is required on the deployment host.

The offline `agent-tasks.json` describes all 25 stable API operations: operation
ID, method, path, inputs, bounds, role, effects, idempotency and completion rules.
The same catalog is available at `/assets/panel-contract/agent-tasks.json` on
the panel origin; `/assets/panel-contract/openapi.json` provides request and
response schemas. Installed versions may differ: match API major 1 and contract
0.1.0, and inspect response headers `X-Nginz-Iot-Api-Version` and
`X-Nginz-Iot-Contract-Version`. Offline discovery grants no authority or installed
availability. Read the catalog before constructing a request.

## Establish the origin, identity and live scope

Use the site's reviewed same-origin HTTPS/SSO boundary and its existing session
or authorization mechanism. Keep credentials in your tool's private credential
storage, out of URLs, reports and repositories. Do not send role/principal
assertions or use the internal trusted routes. Preserve TLS and hostname
verification. Evaluation/Core/Integration examples allow controlled local reads
and block governed writes; Enterprise uses its configured authenticated edge.

Read these resources through the approved origin:

```http
GET /api/v1/admin/identity
Accept: application/json

GET /api/v1/admin/dashboard
Accept: application/json
```

Require verified `current_authority` from `trusted_edge` for a governed write.
The role must match the task's `required_role` or `compatible_roles`; a role in
an offline catalog or a caller-supplied header is not authentication.

Identity `availability` version 1 supplies `compiledTier`, `runtimeProfile`,
view IDs and workflow IDs. The selected profile can expose less than the
compiled ceiling. Before a write, require its workflow and exact matching
dashboard scope: `node` to node `name`, `routingGeneration`, `writerTerm`,
`ringGeneration` and `configDigest`. Preserve all versions as strings, including
unsigned 64-bit generation/term inputs. Missing/mismatched scope blocks a new
intent. Do not infer permissions from tier names or visible panel pages.

Require a live, compatible dashboard with `mutationsAllowed=true` and fresh
`generatedAt` (within 30 seconds of the response's server `Date`, allowing at
most 5 seconds of future skew). Recheck identity, scope and governance after
an outage, session change or fence change. Retained stale evidence is useful for
diagnosis; it cannot authorize a command. The daemon enforces final admission.

## Inspect the owning resources

Use the task catalog's GET operation and bounded inputs. For example:

```http
GET /api/v1/admin/clients?offset=0&limit=50
GET /api/v1/admin/events?offset=0&limit=50
```

Assess each collection's page, next offset and freshness independently. A GET
success or a loaded panel does not establish routing readiness. Use `/ready`
and daemon-owned ownership/readiness facts before assigning traffic. A broker
ACK does not prove sink commitment. Config preflight validates an existing
staged reference; configuration deployment remains the documented native
setup process. These APIs do not provide arbitrary credential, rule, sink or
HA editing.

## Review and submit one authorized intent

Validation, submission, observation and recovery are steps an agent implements
using the catalog and existing API. Local validation checks the task's exact
inputs, bounds, current role and live governance through GETs; it reserves
nothing and cannot predict final admission.

For an authorized node drain, retain one intent record privately: operation ID,
target, canonical decimal generation/writer term and one idempotency key. After
review, send one POST to the task's declared path, with URL-encoded query inputs
and the required CSRF marker. For example, replacing these illustrative values
with the exact reviewed live intent:

```http
POST /api/v1/admin/drain?idempotency_key=ONE_INTENT_KEY&expected_generation=7&expected_writer_term=11&target=node-a
Accept: application/json
X-Iot-Admin-CSRF: 1
Content-Length: 0
```

Use the site's authenticated session on this request. A bridge-drain path `id`
must match query `target`. Config/support requests use their explicit bounded
staged/incident references. The daemon checks authority, fencing, durability,
target and idempotency; an agent must not bypass a refusal.

Do not follow a POST redirect or retry POST automatically. For 401/403, restore
the site's authenticated session/role; for 409 inspect fences and original
intent; for 429 honor backoff. Transport failures and server failures may leave
the POST outcome unknown. Preserve its original inputs/key and observe existing
evidence before deciding whether any identical retry is authorized. Never
generate a new key merely to obtain status.

## Observe completion and recover a lost response

Retain the returned `commandId` and `auditId`, then read:

```http
GET /api/v1/admin/commands/ORIGINAL_COMMAND_ID
Accept: application/json
```

HTTP acceptance and `state=accepted_pending` are pending. `acceptedOnly` stays
true even after reconciliation. Require the original command ID, exact intent,
`state=reconciled`, a nonempty audit ID and `reconciliation.evidence` before
claiming completion. `blocked`, `rejected` and `failed` are terminal failures.
An event label or an HTTP success does not establish completion. Reading status
does not cause reconciliation; closing the panel does not cancel backend work.

Use bounded observation (for example, at most one GET per second for 60 seconds,
10-second request deadlines, respecting longer `Retry-After` delays). A new
command may briefly return 404 before its first status snapshot. When a budget
ends, retain the last record as pending; if subsequent reads fail, mark it stale.
Resume by reading the same ID rather than submitting again.

If the POST response lost its ID, read retained events and nominate candidate
IDs by command type and target. Inspect each candidate's status; require the
response ID to match the event ID and a unique exact match of command type,
target, idempotency key, expected generation and writer term. A bounded strategy
is to read `events?offset=0&limit=1` for `page.total`, then at most the newest
three 200-event pages and at most 32 candidate statuses within 30 seconds. Check
pagination metadata and response bounds. Missing/expired or ambiguous evidence
requires audit investigation; it does not authorize another submission.

Status/recovery uses GETs only and remains usable after write authority is
withdrawn, subject to the edge's read authentication. Do not require current
write availability merely to observe an earlier command.

## Use the panel and hand off evidence

The panel is an optional inspection/review surface for the same backend. Its
Overview, Triage and Command Center lead to scoped detail views. Use the image's
`panel-operations` skill for navigation, roles and confirmations. Browser
availability and an agent's API checks both follow daemon-owned scope; neither
can grant ownership or move traffic.

Record image/backend/panel versions, origin identity, timestamp, task, exact
intent, command/audit IDs, redacted outcome and first unfinished action. Keep
authentication, payloads, raw logs, private inputs and DSNs out of shared
reports. Require bounded JSON objects (a 1 MiB response cap is appropriate),
reject incompatible versions and restricted secret-bearing projections, and
never copy HTTP error bodies into evidence. Review support artifacts before
sharing. These are tool-independent operating rules, not a required client.
