scope_not_granted (403)
What you’ll see
{
"error": "Permission denied",
"reason": "scope_not_granted",
"correlation_id": "...",
"report_hint": { /* ... */ }
}HTTP status 403. The agent has not been granted the scope it tried to use for this platform.
Why
Every POST /v1/actions call carries a scope field. The proxy looks up
the agent’s permission row for the requested platform and checks that
the scope is in the granted set. If it isn’t, the call is denied before
any upstream HTTP request is made, and an audit row is written with
result = "denied".
This is the platform working as designed: scopes are the granular
control for what an agent can do. A 403 scope_not_granted is the
correct response when an agent overreaches.
Fix
There are two legitimate reasons for this error and one agent-misbehaviour reason. Triage in this order:
1. The scope is genuinely missing from the agent’s matrix
Open Agents → your agent → Permissions. Find the platform row. If the scope isn’t checked, the agent doesn’t have it. Grant it if the expansion is intentional.
The dashboard’s Permissions table shows every scope the platform
supports. If the scope you need isn’t listed at all, the platform’s
catalogue may be out of date — superadmin can re-sync via the
Platform Sync card on /superadmin.
2. The scope was revoked and the agent hasn’t been told
You revoke a scope, the agent’s MCP host has cached the platform catalogue from boot, the agent calls the old scope, gets 403. The MCP server refreshes its platform list on the next call, but the call that triggered the 403 still fails. This is a one-shot recovery — the second call will reflect the revocation.
3. The agent is misbehaving
The agent should never be calling a scope it doesn’t have. If you see this 403 alongside other anomalous activity, that’s the circuit breaker territory: 3 consecutive failures will auto-suspend the agent.