Skip to main content

Policy and Approval

Before the runtime executes a tool, it runs a policy decision.

Decision order

The current decision flow is:

  1. managed deny: if the tool matches an internally tracked managed-scope deny pattern, reject with managed_deny
  2. curated view/tool set: if the active mode is curated and the tool is outside the selected tool set, reject with curated_deny
  3. approval: if the tool requires approval and the request did not grant it, reject with approval_required
  4. otherwise allow execution

Where approval requirements come from

A tool can require approval because of either:

  • x-cli-safety.requiresApproval on the OpenAPI operation (possibly added by an overlay)
  • a config pattern under policy.approvalRequired

CLI users grant approval with:

ocli --approval ...

HTTP API clients set:

{ "approval": true }

Example policy block

{
"mode": { "default": "curated" },
"curation": {
"toolSets": {
"support": {
"allow": ["tickets:listTickets", "tickets:getTicket", "tickets:createTicket"],
"deny": ["**"]
}
}
},
"agents": {
"profiles": {
"support": {
"mode": "curated",
"toolSet": "support"
}
},
"defaultProfile": "support"
},
"policy": {
"approvalRequired": ["tickets:createTicket"]
}
}

Important implementation nuance: policy.deny

The config schema exposes policy.deny, and the loader merges those patterns. The current execution-time policy engine, however, checks only the managed-scope deny list directly.

Practical takeaway:

  • use managed scope policy for hard organization-wide deny rules
  • use curated tool sets for visibility and execution shaping
  • use approvalRequired for interactive gates

Do not rely on project/user/local policy.deny as a hard enforcement layer in the current implementation.

Pattern semantics

Pattern matching uses Go's path.Match plus a special ** catch-all.

Examples:

  • tickets:*
  • tickets:createTicket
  • **

For MCP-backed services, policy patterns are also validated at catalog-build time against sources.<id>.disabledTools. If an approvalRequired, managed deny, or curated tool-set pattern matches only MCP tools that were disabled, build fails closed. Broad patterns that still match at least one surviving tool remain valid.

Audit behavior

Allowed and denied tool execution attempts are both written to the audit log. The denial reason becomes the audit reasonCode.