opbox

Autonomy Levels

Autonomy levels are how Opbox controls what an AI Agent or external MCP client is allowed to do. Every API key carries an autonomyLevel (0-3) set at creation. The MCP router enforces it before dispatching any tool call.

The Four Levels

LevelMeaningExamples
L0Read-onlysearch, list_*, get_*, agent_queue_list, get_notifications, execute_sql (read-only), search_system_docs
L1Read + internal writescreate_invite, mark_notifications_read, agent_queue_claim, doc-gen patcher reads, add_subtask, add_comment
L2Read + mutations with external side effectscall_api_endpoint (GET only), run_saved_query, billable workflow runs, sending notifications
L3FullAll registered tools, subject to per-tool gate flags (some tools are L3-only by their declaration)

Default for new keys: L0. Admins must explicitly raise the level when minting the key.

Enforcement

Tool registration declares its required level. The MCP router checks before dispatch:

if (tool.minAutonomyLevel > ctx.autonomyLevel) {
  return { error: 'AUTONOMY_LEVEL_REQUIRED', ... }
}

The same autonomy enforcer is used by both the in-process Agent Worker and the MCP HTTP router, so the rule is identical regardless of execution path.

Denied calls are audit-logged. The AUTONOMY_LEVEL_REQUIRED security event records the tool name, the calling key, and the level required vs supplied.

Why Tiers Are Coarse

The four levels are deliberately coarse. We considered per-tool grants but rejected them:

  • Operator cognitive load - admins can reason about “read-only” or “full” much faster than ticking 405 boxes.
  • Forward compat - new tools land regularly. A coarse tier auto-classifies them via minAutonomyLevel. A fine-grained ACL would require a manual edit on every release.
  • Audit clarity - “this key is L1” is a stronger story than “this key has these 47 tools.”

Per-tool gating still happens, but inside each level. For example, execute_sql is L0 (it’s read-only) but also requires the workspace ADMIN role at the API boundary - so even an L3 key from a non-admin user can’t run it.

Choosing the Right Level

Use caseLevelRationale
Developer using Claude Code on their laptop for read-only investigationL0Can’t accidentally write. Safe default.
Personal automation - drafting comments, taking notesL1Internal writes only - no external side effects.
Agent Bridge running production doc-genL1 or L2Doc-gen needs agent_queue_claim (L1). Cloud fire-and-forget hits webhooks (L2).
CSP firm overseer running cross-workspace auditsL0Read-only across the whole client base. Lots of leverage, no risk.
Full automation - end-to-end matter completionL3Trusted internal tooling only.

OpenClaw Bidirectional Auth

When the OpenClaw provider is configured, the same bearer that opbox uses to call OpenClaw also authenticates inbound MCP calls (OpenClaw → opbox). The autonomy level for those inbound calls is set separately on the org config:

SettingDefaultEffect
Inbound autonomy level (openclawInboundAutonomyLevel)L3 (full)What tools OpenClaw can invoke when calling /api/mcp/* with the bearer. L0-L3 same matrix as above.

The OpenClaw bearer authenticates as the OpenClaw principal user (auto-seated as OPBOX_AGENT role on the org when OpenClaw is enabled). All the same role / autonomy / cell-locking gates apply - the bearer just supplies an alternative credential, not new privileges. Audit log entries carry apiKeyId = openclaw:<orgId> to distinguish bidirectional activity from cp_live_* MCP keys.

Crossing Tenant Boundaries

The _targetWorkspaceId cross-workspace swap does not change the autonomy level. An L0 overseer key remains read-only against subordinate workspaces. The autonomy level is a property of the key, not of the target.

This means an overseer can run “look at my client base read-only” without having to mint a separate per-client key per workspace.

L3 Per-Tool Gates

Some tools are L3-only by declaration regardless of caller. Examples:

  • bulk_update_dashboard - bulk widget rewrite.
  • set_dashboard_config - replace entire config.
  • delete_table / delete_column - destructive schema changes.
  • update_document (full structured-JSON replace) - destructive content overwrite.

These are L3-only because their blast radius is large enough that a “full automation” justification is the right minimum bar.

Rotating Levels

You can change the autonomy level on an existing key without rotating the secret:

PATCH /api/agent/api-keys/[id]
{ "autonomyLevel": 2 }

Requires ADMIN/OWNER role + CSRF. The change is audited. New tool calls immediately respect the new level - in-flight calls finish on the old level.

API Key Creation

EndpointMethodPurpose
POST /api/agent/api-keysMint a new keyADMIN/OWNER only. JSON body with name and autonomyLevel. Returns the cleartext key once - it’s not retrievable again.
GET /api/agent/api-keysList existing keys (masked)ADMIN/OWNER.
PATCH /api/agent/api-keys/[id]Update name / autonomy / disabled stateADMIN/OWNER + CSRF.
DELETE /api/agent/api-keys/[id]RevokeADMIN/OWNER + CSRF.

The cleartext key is shown once at creation. Copy it to your env / MCP config immediately. It’s stored hashed in the DB; the cleartext is unrecoverable.

What L0 Can Still Do

Even L0 (the most restrictive level) is meaningfully powerful in Opbox:

  • Full search across CRM, matters, documents, KB.
  • Read-only SQL against the workspace database.
  • Page through audit logs (admin-gated separately).
  • Run RAG queries against extracted content.
  • Read the full doc-gen briefing for any matter step.
  • Cross-tenant reads if the home workspace has oversight.

A common production pattern: one L0 overseer key per analyst, doing the entire reading job; a small L3 service account for the unattended automations.

See Also