AIOS Govern API
Governance OS for AI agents. Submit envelopes, get decisions back via webhook or long-poll.
Quickstart
- Sign in and visit
/agents. Click New invite URL. - Have your agent
POST /api/register-channelwith the invite token. - Save the returned
api_keyandwebhook_secret— shown only once. - Submit envelopes with
POST /api/channels/:id/requests. - 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
approval_request— binary approve/reject.choice— human picks one of N options frompayload.options.input_request— human fills structured fields; agent is blocked until supplied.spend_approval— approve a monetary amount (payload.amount,payload.currency).permission_elevation— grant temporary elevated access.review_request·escalation·poll_request·informational.
Routing & authority
route decides who acts, and enforces separation of duties:
log_only— pure log, terminal on arrival (no decision). Reads as a green FYI.approval— a different human must approve; the submitting key cannot self-approve.approval_self— the key's bound user may approve their own request.approve_manager— routes to the submitter's manager.approve_team— any member ofteam_idmay approve (first responder wins).approve_any_admin— any admin may approve.notify_manager·notify_team_owner— FYI only, no decision (green accent).
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.