StableOps
Agents

Agent policies

Limits, allow-lists, and approval gates for Agent actions.

An agent policy controls what the MCP server is allowed to do on behalf of your workspace. Policies live at the organization + environment level. Every agent session in the same workspace sees the same rules, so new sessions don't have to be re-authorized.

If no policy exists, defaults are conservative: only read-only tools are allowed, every write requires approval, and no spending limits are set.

Fields

FieldTypeDefaultNotes
allowed_toolsAgentToolName[]the read-only setWhitelist of tool names.
per_action_limitdecimal string | nullnullMax amount per single create_payment_order.
daily_limitdecimal string | nullnullCumulative cap per rolling 24h.
require_approvalbooleantrueWhen true, every non-read tool returns pending_approval.

per_action_limit and daily_limit are decimals in settlement-asset units ("100.00" means 100 USDC). They only apply to tools that carry an amount argument: currently create_payment_order.

allowed_tools is enforced before any limit check. A tool that is not in the list returns 403 tool … not allowed by policy.

Read the current policy

curl -X GET $STABLEOPS_API_URL/v1/agent/policy \
  -H "authorization: Bearer $STABLEOPS_API_KEY" \
  -H 'x-stableops-env: sandbox'
{
  "id": "agp_01",
  "allowed_tools": ["get_order", "list_events", "list_webhook_deliveries"],
  "per_action_limit": null,
  "daily_limit": null,
  "require_approval": true
}

Update the policy

POST /v1/agent/policy performs an upsert. Only fields you send are touched.

curl -X POST $STABLEOPS_API_URL/v1/agent/policy \
  -H "authorization: Bearer $STABLEOPS_API_KEY" \
  -H 'x-stableops-env: sandbox' \
  -H 'content-type: application/json' \
  -d '{
    "allowed_tools": [
      "get_order",
      "list_events",
      "create_payment_order",
      "request_action_approval"
    ],
    "per_action_limit": "100.00",
    "daily_limit": "500.00",
    "require_approval": false
  }'

Send null to clear a limit:

{ "per_action_limit": null }

Decision flow

tool call ─▶ /v1/agent/actions

              ├─ tool in allowed_tools?            no ─▶ 403 not allowed

              ├─ amount ≤ per_action_limit?        no ─▶ 403 exceeds per_action_limit

              ├─ amount + last 24h ≤ daily_limit?  no ─▶ 403 exceeds daily_limit

              ├─ require_approval == true?         yes ─▶ pending_approval (queue for human)
              │                                    no  ─▶ auto_allowed (agent proceeds)
              └─ read-only tool?                   ─▶ auto_allowed

The dashboard surfaces every pending_approval action, the requested arguments, and the agent session that asked for it. Approving an action unblocks the tool call on the next retry; rejecting it records the operator's reason in the audit log.

Strict: fully manual review, useful for the first live integration:

{
  "allowed_tools": ["get_order", "list_events", "list_webhook_deliveries"],
  "require_approval": true
}

Capped: let the agent open small orders on its own, escalate the rest:

{
  "allowed_tools": [
    "get_order",
    "list_events",
    "create_payment_order",
    "request_action_approval"
  ],
  "per_action_limit": "50.00",
  "daily_limit": "500.00",
  "require_approval": false
}

Audit-only: keep approvals on but let read tools fan out widely:

{
  "allowed_tools": ["get_order", "list_events", "list_webhook_deliveries"],
  "require_approval": true
}

Tips

  • Keep per_action_limit and daily_limit set even in sandbox. Agents cannot exceed them, and you'll catch policy drift on the way to live.
  • Revoking an agent session is separate from the policy: it blocks one conversation; updating the policy blocks every session.
  • Approvals are stamped with the operator's id (the dashboard user or the approver_id you send to /v1/agent/actions/:id/approve). The audit trail is queryable per session.

How is this guide?

Last updated

On this page