---
title: "oz0 tenant tool-policy set"
description: "Change a tenant's tool policy."
canonical_url: "https://docs.oz0.ai/reference/cli/oz0/tenant/tool-policy/set"
---
# oz0 tenant tool-policy set

> Change a tenant's tool policy.

For: Operators and developers looking up a command.

Change a tenant's tool policy. --read-only, --destructive, --open-world and --undeclared take allow, approve or refuse. Each --rule is \<tool>.\<function>=\<action>, where * in the name matches anything, such as github.merge=refuse or web.*=allow, or names one plugin's functions by address, such as github/oz0_github.*=approve; the first rule that matches a function decides.

A rule may end with conditions after if: plugin=\<names>, publisher=\<names> and source=\<kinds> (git, workspace, bundle, oci, hub, mcp) for the calling plugin, other-plugins for calls of another plugin's functions only, and kind=\<kinds> (read_only, not_read_only, destructive, open_world, undeclared).

It may end with a CEL condition over each call after when: args, mcp.tool.name, mcp.tool.target, caller.plugin, caller.agent and the like, with has() as the only macro; the rule then decides only the calls it holds for, in the runtime and again at the edge, and a condition that fails to evaluate never loosens a decision. --rule replaces the rules the policy had, unless --keep-rules adds to them; --defaults starts again from the defaults.

A rule that approves may say who decides: decided-by=\<who>,... where each is role:admin, team:\<name>, user:\<name> or key:\<API key ID> (an integration that decides with that key; no other key may), and not-starter refuses the job's starter as the decider (four eyes). --recheck-after is how long an approval or a question may wait before it is checked again when it resolves (an hour by default).

--taint-default-when narrows the built-in taint-default rule to the calls its CEL condition holds for, such as a service the tenant trusts left out; it loosens, so it takes a reason. To add, change or remove one rule, with flags instead of conditions inside its text, use oz0 policy.

## Usage

```bash
oz0 tenant tool-policy set [flags]
```

## Flags

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --approval-deadline
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        24h
      </code>
    </td>
    
    <td>
      how long the tenant's approvals wait at most when nothing more specific says, 1m to 720h
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --decision-ref
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      the decision or case the change follows, such as a case number (at most 200 characters)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --defaults
      </code>
    </td>
    
    <td>
      bool
    </td>
    
    <td>
      
    </td>
    
    <td>
      start from the default policy instead of the tenant's
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --destructive
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      what happens to calls to destructive functions: allow, approve or refuse
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --escalation
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      the tenant's escalation ladder: default, off (with --escalation-reason), or steps such as 0.25:deciders,0.5:owner,0.75:admins
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --escalation-reason
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      why the tenant's ladder is off; the audit trail keeps it
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --gate-rule
      </code>
    </td>
    
    <td>
      stringArray
    </td>
    
    <td>
      
    </td>
    
    <td>
      add an origin or sequence rule as JSON, such as '{"match":"mail.send","action":"refuse","origins":{"to":"request"}}' or '{"match":"*","action":"approve","sequence":{"after":{"labels":{"level":"confidential"}},"then":{"outbound":true},"within":"tree"}}'; repeatable; mode, expires_at and rationale as for any rule
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      bool
    </td>
    
    <td>
      
    </td>
    
    <td>
      print JSON instead of a table
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --keep-rules
      </code>
    </td>
    
    <td>
      bool
    </td>
    
    <td>
      
    </td>
    
    <td>
      add --rule to the policy's rules instead of replacing them
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --label-egress
      </code>
    </td>
    
    <td>
      stringArray
    </td>
    
    <td>
      
    </td>
    
    <td>
      add a rule that refuses calls of functions that can send data out once the job read something at LEVEL or above (LEVEL, or LEVEL:approve to ask a person instead); it starts in shadow mode, so it decides nothing until it is promoted; repeatable
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --no-origin-record
      </code>
    </td>
    
    <td>
      stringArray
    </td>
    
    <td>
      
    </td>
    
    <td>
      stop vouching for a pattern given with --origin-record; repeatable
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --open-world
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      what happens to calls to open-world functions: allow, approve or refuse
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --origin-default
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      on, or off: the built-in rule that asks a person when a sensitive argument's value is below the floor its schema sets (x-oz0-origin); off loosens and needs a reason
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --origin-record
      </code>
    </td>
    
    <td>
      stringArray
    </td>
    
    <td>
      
    </td>
    
    <td>
      vouch for a function's results as tenant records (&lt;tool>.&lt;function>, * for anything) when its schema says x-oz0-origin-source: record; repeatable; loosens and needs a reason
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --preset
      </code>
    </td>
    
    <td>
      stringArray
    </td>
    
    <td>
      
    </td>
    
    <td>
      add a shipped sequence rule: untrusted-then-consequential or confidential-then-egress; repeatable; a preset the policy has is kept as it is
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --read-only
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      what happens to calls to read-only functions: allow, approve or refuse
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --reason
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      why, required for every governance change (at most 500 characters; default $OZ0_REASON); the audit log keeps it
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --recheck-after
      </code>
    </td>
    
    <td>
      duration
    </td>
    
    <td>
      
    </td>
    
    <td>
      check an approval again when it resolves after waiting longer than this, such as 1h (at least 1m)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --rule
      </code>
    </td>
    
    <td>
      stringArray
    </td>
    
    <td>
      
    </td>
    
    <td>
      &lt;tool>.&lt;function>=&lt;action>, * matching anything in the name; repeatable, in order
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --taint-default
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      on, or off: the built-in rule that asks a person before a tainted job's outbound calls; off loosens and needs a reason
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --taint-default-when
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      the taint-default rule's CEL condition, to narrow it (its own is job.tainted && tool.outbound); loosens and needs a reason
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --tenant
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      tenant
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --undeclared
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      
    </td>
    
    <td>
      what happens to calls to functions without annotations, or silent on destructiveHint: allow, approve or refuse
    </td>
  </tr>
</tbody>
</table>

## Inherited flags

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --context
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        $OZ0_CONTEXT or &lt;config dir>/orchestrator-zero/context.json
      </code>
    </td>
    
    <td>
      CLI context file written by server init
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --log-level
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        info
      </code>
    </td>
    
    <td>
      log level: debug, info, warn or error
    </td>
  </tr>
</tbody>
</table>

See [all `oz0` commands](https://docs.oz0.ai/reference/cli/oz0) and the [global flags](https://docs.oz0.ai/reference/cli/oz0#global-flags).


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
