Docs / Platform

AI agents & governance

Agents are API-first citizens with guardrails. They discover their own capabilities, run product actions freely, but route destructive and code actions through a human — once — with a tamper-evident audit trail and a kill-switch behind it all.

whoami mapapproval-gatedhash-chain auditkill-switch

Capability discovery

Mint an agent key with role:"agent" (read+write, never admin). It sees a product-only surface; account-admin actions are hidden.

GET /v1/whoami bearer

Identity plus a per-action map of allowed | approval | denied, so an agent can self-discover what it may do without trial and error. The map reuses the real authorization check, so it can never drift from enforcement.

curl
curl https://api.ollanode.com/v1/whoami \
  -H "Authorization: Bearer $AGENT_KEY"
Response
{ "actor_type":"agent", "role":"api_key", "is_owner":false,
  "scopes":["read","write"], "extra_scopes":["videos:read"],
  "capabilities":{ "videos:write":"allowed", "videos:delete":"approval",
    "dns:write":"approval", "functions:write":"approval",
    "logs:read":"allowed", "approvals:create":"allowed" } }
Use cases
  • An agent inspects its own capabilities before planning actions.
  • A UI renders what an agent key can and can’t do.

Approval gating

For agents, any delete plus functions:write (code deploy) and dns:write are gated: the call returns 202 without running, a human decides, and the agent replays the exact same request once with X-Approval-Id. The approval is bound to a request digest (key + action + resource + body hash), so replays or payload substitutions match nothing and are rejected.

the 202 → decide → replay flow
# 1) agent attempts a gated action -> 202, nothing changed
curl -i -X DELETE https://api.ollanode.com/v1/videos/vid_123 \
  -H "Authorization: Bearer $AGENT_KEY"
# HTTP/1.1 202  { "status":"pending_approval", "approval_id":"apr_abc", "message":"...resubmit with X-Approval-Id..." }

# 2) a human approves (an API/agent key can never decide)
curl -X POST https://api.ollanode.com/v1/approvals/apr_abc/decide \
  -H "Authorization: Bearer $SESSION" \
  -H "Content-Type: application/json" -d '{"decision":"approved"}'

# 3) agent replays the SAME request once, with the approval id
curl -X DELETE https://api.ollanode.com/v1/videos/vid_123 \
  -H "Authorization: Bearer $AGENT_KEY" -H "X-Approval-Id: apr_abc"
POST /v1/approvals approvals:create

File an approval request explicitly (action, optional resource_id, payload).

GET /v1/approvals approvals:read

List approval requests and their state.

POST /v1/approvals/{id}/decide admin (human)

Approve or reject. Requires a signed-in human admin — never an API/agent key — and the decider cannot approve their own request. The decision is fail-closed audited.

Human-only guardrails

Team/user management, API-key lifecycle, approval decisions, and owner-only org actions are never agent-grantable — they return 403 for agents and show as denied in the capability map. Agent keys are structurally prevented from holding admin. Billing is intentionally not an API capability at all.

Tamper-evident audit

Every mutation is recorded in a hash-chain (prev_hash/entry_hash over all immutable fields), so tampering is detectable.

GET /v1/audit admin · agent · logs:read

Recent audit entries (actor, action, resource, request id), newest first.

curl
curl "https://api.ollanode.com/v1/audit?limit=50" -H "Authorization: Bearer $OLLANODE_API_KEY"
GET /v1/audit/verify bearer

Verify this project’s per-entry hash-chain integrity.

curl
curl https://api.ollanode.com/v1/audit/verify -H "Authorization: Bearer $SESSION"
Response
{ "scope":"project", "checked":128, "skipped_legacy":0, "intact":true, "tampered":[] }

Kill-switch

POST /v1/admin/disable-agents?project_id=… X-Admin-Token

Kill-switch: revoke ALL agent keys for a project at once (platform-operator credential, fail-closed audited).

curl
curl -X POST "https://api.ollanode.com/v1/admin/disable-agents?project_id=proj_abc" \
  -H "X-Admin-Token: $ADMIN_TOKEN"
# -> { "agents_revoked": N }
Agents can drive the API directly, or via the MCP server which exposes these endpoints as typed tools (list_videos, ingest_video, create_zone, request_approval, …). The full contract is at GET /openapi.json (OpenAPI 3.1).