AIOS Govern API

Governance OS for AI agents. Submit envelopes, get decisions back via webhook or long-poll.

Quickstart

  1. Sign in and visit /agents. Click New invite URL.
  2. Have your agent POST /api/register-channel with the invite token.
  3. Save the returned api_key and webhook_secret — shown only once.
  4. Submit envelopes with POST /api/channels/:id/requests.
  5. Listen for the webhook callback, or call GET /api/requests/:id/wait.

Envelope schema

{
  "type": "approval_request" | "informational" | "permission_elevation"
        | "escalation" | "review_request" | "poll_request"
        | "choice" | "input_request" | "spend_approval",
  "title": "Approve domain transfer",
  "summary": "Agent wants to move example.com to Cloudflare.",
  "risk_level": "low" | "medium" | "high" | "critical",
  "payload": { /* arbitrary JSON */ },
  "approval_rule": { "type": "single" } |
                   { "type": "sequential", "steps": [...] } |
                   { "type": "n_of_x", "required": 2, "approvers": [...] },

  // Routing / authority — WHO acts on this envelope. Default "approval".
  "route": "log_only" | "approval" | "approval_self" | "approve_manager"
         | "approve_team" | "approve_any_admin" | "notify_manager" | "notify_team_owner",
  "team_id": "uuid (required for approve_team / notify_team_owner)",

  // Presentation hints.
  "bg_color": "#1b1b1b",          // card background
  "badge": "URGENT",              // diagonal corner ribbon (red for URGENT)
  "accent_bar": "green",          // left edge bar (notify/log read as green FYI)
  "pulse": "none" | "light" | "strong",
  "top_sort": true,               // pop to top of inbox/lists

  // TTL / expiry modifier.
  "expires_at": "2026-05-31T18:00:00Z",
  "on_timeout": "escalate" | "auto_approve" | "auto_reject" | "expire",

  // Request-changes round-trip.
  "tweak_allowed": true,          // let the human bounce it back with edits
  "parent_envelope_id": "uuid",   // set when responding to a tweak with a NEW card

  "return_mode": "webhook" | "long_poll" | "both",
  "return_webhook": "https://yourapp.example.com/aigos-callback",
  "long_poll_timeout_seconds": 300
}

Request changes (tweak)

If you submit with tweak_allowed: true, a human can bounce the envelope back with edits instead of approving or rejecting. You receive a tweak_requested event — over your return_webhook and on the long-poll response:

{
  "event": "tweak_requested",
  "request_id": "...",
  "tweak_id": "...",
  "request_text": "Reduce the spend cap to $500 and resubmit.",
  "requested_by": "user_uuid",
  "envelope_snapshot": { ... }
}

Process it and usually submit a new envelope with parent_envelope_id set to the original — that resolves the tweak and links the cards into one history. The human can also pull the tweak back, which emits tweak_withdrawn.

Card types

Routing & authority

route decides who acts, and enforces separation of duties:

Submit an envelope

POST /api/channels/{channel_id}/requests
Authorization: Bearer {agent_api_key}
Content-Type: application/json

{ ...envelope... }

Long-poll for the decision

GET /api/requests/{request_id}/wait?timeout=60
Authorization: Bearer {agent_api_key}

200 OK
{
  "request_id": "...",
  "status": "approved" | "rejected" | "acknowledged",
  "approved_by": "user_uuid",
  "decision_time": "2026-05-09T14:12:00Z",
  "comments": "...",
  "envelope_snapshot": { ... }
}

408 Request Timeout
{ "error": { "code": "timeout", "message": "Decision pending" } }

Webhook callback (signed)

On a completed decision AIOS Govern POSTs the same payload as the long-poll response to return_webhook. Verify X-AIGOS-Signature with your webhook_secret:

X-AIGOS-Signature: sha256=<hmac>
X-AIGOS-Timestamp: <unix_seconds>
X-AIGOS-Delivery: <delivery_id>

const expected = "sha256=" + crypto
  .createHmac("sha256", webhook_secret)
  .update(rawBody)
  .digest("hex");
// timing-safe compare expected vs X-AIGOS-Signature header

Poll-request envelopes

AIOS Govern does not host polls. The envelope carries a render hint that points at an external poll provider; the dashboard embeds it.

{
  "type": "poll_request",
  "title": "Approve domain name choice",
  "summary": "Agent ran a poll on AI-Poll.com — review and approve.",
  "payload": {
    "poll_provider": "ai-poll",
    "poll_url": "https://ai-poll.com/p/abc123",
    "poll_id": "abc123",
    "poll_render_hint": { "embed": "iframe", "width": 600, "height": 400 },
    "poll_instructions": "Click through to vote, or review the live tally."
  }
}

Retry policy

Webhook deliveries retry on non-2xx with exponential backoff at 1m, 5m, 15m, 1h, 6h, then mark failed. Admins can replay from /admin/webhooks.