Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

openclaw policy

openclaw policy is provided by the bundled Policy plugin. Policy is an enterprise conformance layer over existing OpenClaw settings. It does not add a second configuration system. policy.jsonc defines authored requirements, OpenClaw observes the active workspace as evidence, and policy health checks report drift through doctor --lint. The final conformance signal is a clean doctor --lint run; policy contributes findings to that shared lint surface instead of creating a separate health gate. Policy currently manages configured channels, MCP servers, model providers, network SSRF posture, Gateway exposure posture, agent workspace posture, OpenClaw config secret provider/auth profile posture, and governed tool declarations. For example, IT or a workspace operator can record that Telegram is not an approved channel provider, restrict MCP servers and model refs to approved entries, require private-network fetch/browser access to remain disabled, require Gateway bind/auth/HTTP exposure to stay within reviewed bounds, require agent workspace access and tool denies to stay in a reviewed posture, require OpenClaw config SecretRefs to use managed providers, require config auth profiles to carry provider/mode metadata, require governed tools to carry risk and sensitivity metadata, then use doctor --lint as the shared conformance gate. Use policy when a workspace needs a durable statement such as “these channels must not be enabled” or “governed tools must declare approval metadata” and a repeatable way to prove that OpenClaw still conforms to that statement. Use regular config and workspace docs alone when you only need local behavior and do not need policy findings or attestation output.

Quick start

Enable the bundled Policy plugin before first use:
openclaw plugins enable policy
When policy is enabled, doctor can load policy health checks without activating arbitrary plugins. The plugin remains enabled if policy.jsonc is missing, so doctor can report the missing artifact. Policy is authored, not generated from the user’s current settings. A minimal policy for channels, MCP servers, model providers, network posture, Gateway exposure, agent workspace posture, OpenClaw config secret provider/auth profile posture, and tool metadata looks like this:
{
  "channels": {
    "denyRules": [
      {
        "id": "no-telegram",
        "when": { "provider": "telegram" },
        "reason": "Telegram is not approved for this workspace.",
      },
    ],
  },
  "mcp": {
    "servers": {
      "allow": ["docs"],
      "deny": ["untrusted"],
    },
  },
  "models": {
    "providers": {
      "allow": ["openai", "anthropic"],
      "deny": ["openrouter"],
    },
  },
  "network": {
    "privateNetwork": {
      "allow": false,
    },
  },
  "gateway": {
    "exposure": {
      "allowNonLoopbackBind": false,
      "allowTailscaleFunnel": false,
    },
    "auth": {
      "requireAuth": true,
      "requireExplicitRateLimit": true,
    },
    "controlUi": {
      "allowInsecure": false,
    },
    "remote": {
      "allow": false,
    },
    "http": {
      "denyEndpoints": ["chatCompletions", "responses"],
      "requireUrlAllowlists": true,
    },
  },
  "agents": {
    "workspace": {
      "allowedAccess": ["none", "ro"],
      "denyTools": ["exec", "process", "write", "edit", "apply_patch"],
    },
  },
  "secrets": {
    "requireManagedProviders": true,
    "denySources": ["exec"],
    "allowInsecureProviders": false,
  },
  "auth": {
    "profiles": {
      "requireMetadata": ["provider", "mode"],
      "allowModes": ["api_key", "token"],
    },
  },
  "tools": {
    "requireMetadata": ["risk", "sensitivity", "owner"],
    "profiles": {
      "allow": ["messaging", "minimal"],
    },
    "fs": {
      "requireWorkspaceOnly": true,
    },
    "exec": {
      "allowSecurity": ["deny", "allowlist"],
      "requireAsk": ["always"],
      "allowHosts": ["sandbox"],
    },
    "elevated": {
      "allow": false,
    },
    "denyTools": ["group:runtime", "group:fs"],
  },
}
The rules are the authority. A category block is only a namespace; checks run when a concrete rule is present. OpenClaw reads current channels.* settings mcp.servers.*, models.providers.*, selected agent model refs, network SSRF settings, Gateway bind/auth/Control UI/Tailscale/remote/HTTP posture, OpenClaw config agent sandbox workspace access and tool deny posture, config secret provider and SecretRef provenance, config auth profile metadata, configured global/per-agent tool posture, and TOOLS.md declarations as evidence, then reports observed state that does not conform. If a policy denies non-loopback Gateway binds, omit gateway.bind only when you are willing to review the runtime default; set gateway.bind=loopback for strict config conformance. For read-only agent posture, configure sandbox mode on the applicable defaults or agent and set workspaceAccess to none or ro; omitted or off sandbox mode does not satisfy a read-only/no-write policy. agents.workspace.denyTools supports exec, process, write, edit, and apply_patch; OpenClaw config group:fs covers file mutation tools and group:runtime covers shell/process tools. Tool posture policy observes tools.profile, tools.allow, tools.alsoAllow, tools.deny, tools.fs.workspaceOnly, tools.exec.security, tools.exec.ask, tools.exec.host, tools.elevated.enabled, and the same per-agent agents.list[].tools.* overrides. It does not read runtime/operator approval state such as exec-approvals.json, and it does not enforce tool calls at runtime. Secret evidence records provider/source posture and SecretRef metadata, never raw secret values. Policy does not read or attest per-agent credential stores such as auth-profiles.json; those stores remain owned by the existing auth and credential flows.

Policy rule reference

Each policy field below is optional. A check runs only when the matching rule is present in policy.jsonc. The observed state is existing OpenClaw config or workspace metadata; policy reports drift but does not rewrite runtime behavior unless a repair path is explicitly available and enabled.

Channels

Policy fieldObserved stateUse when
channels.denyRules[].when.providerchannels.* provider and enabled stateDeny configured channels from a provider such as telegram.
channels.denyRules[].reasonFinding message and repair hint contextExplain why the provider is denied.

MCP servers

Policy fieldObserved stateUse when
mcp.servers.allowmcp.servers.* idsRequire every configured MCP server to be in an allowlist.
mcp.servers.denymcp.servers.* idsDeny specific configured MCP server ids.

Model providers

Policy fieldObserved stateUse when
models.providers.allowmodels.providers.* ids and selected model refsRequire configured providers and selected model refs to use approved providers.
models.providers.denymodels.providers.* ids and selected model refsDeny configured providers and selected model refs by provider id.

Network

Policy fieldObserved stateUse when
network.privateNetwork.allowPrivate-network SSRF escape hatchesSet to false to require private-network access to stay disabled.

Gateway

Policy fieldObserved stateUse when
gateway.exposure.allowNonLoopbackBindgateway.bindSet to false to require loopback Gateway binding.
gateway.exposure.allowTailscaleFunnelTailscale serve/funnel Gateway postureSet to false to deny Tailscale Funnel exposure.
gateway.auth.requireAuthgateway.auth.modeSet to true to reject disabled Gateway auth.
gateway.auth.requireExplicitRateLimitgateway.auth.rateLimitSet to true to require explicit auth rate-limit config.
gateway.controlUi.allowInsecureControl UI insecure auth/device/origin togglesSet to false to deny insecure Control UI exposure toggles.
gateway.remote.allowRemote Gateway mode/configSet to false to deny remote Gateway mode.
gateway.http.denyEndpointsGateway HTTP API endpointsDeny endpoint ids such as chatCompletions or responses.
gateway.http.requireUrlAllowlistsGateway HTTP URL-fetch inputsSet to true to require URL allowlists on URL-fetch inputs.

Agent workspace

Policy fieldObserved stateUse when
agents.workspace.allowedAccessagents.defaults.sandbox.workspaceAccess and agents.list[].sandbox.workspaceAccessAllow only sandbox workspace access values such as none or ro.
agents.workspace.denyToolsGlobal and per-agent tool deny configRequire workspace/runtime mutation tools such as exec, process, write, edit, or apply_patch to be denied.

Secrets

Policy fieldObserved stateUse when
secrets.requireManagedProvidersConfig SecretRefs and secrets.providers.* declarationsSet to true to require SecretRefs to point at declared providers.
secrets.denySourcesSecret provider sources and SecretRef sourcesDeny sources such as exec, file, or another configured source name.
secrets.allowInsecureProvidersInsecure secret-provider posture flagsSet to false to reject providers that opt into insecure posture.

Auth profiles

Policy fieldObserved stateUse when
auth.profiles.requireMetadataauth.profiles.* provider and mode metadataRequire metadata keys such as provider and mode on config auth profiles.
auth.profiles.allowModesauth.profiles.*.modeAllow only supported auth profile modes such as api_key, aws-sdk, oauth, or token.

Tool metadata

Policy fieldObserved stateUse when
tools.requireMetadataGoverned TOOLS.md declarationsRequire governed tools to declare metadata keys such as risk, sensitivity, or owner.

Tool posture

Policy fieldObserved stateUse when
tools.profiles.allowtools.profile and agents.list[].tools.profileAllow only tool profile ids such as minimal, messaging, or coding.
tools.fs.requireWorkspaceOnlytools.fs.workspaceOnly and per-agent tools.fs overridesSet to true to require workspace-only filesystem tool posture.
tools.exec.allowSecuritytools.exec.security and per-agent exec securityAllow only exec security modes such as deny or allowlist.
tools.exec.requireAsktools.exec.ask and per-agent exec ask modeRequire approval posture such as always.
tools.exec.allowHoststools.exec.host and per-agent exec host routingAllow only exec host routing modes such as sandbox.
tools.elevated.allowtools.elevated.enabled and per-agent elevated postureSet to false to require elevated tool mode to stay disabled.
tools.denyToolstools.deny and agents.list[].tools.denyRequire configured tool deny lists to include tool ids or groups such as group:runtime and group:fs.
Run policy-only checks during authoring:
openclaw policy check
openclaw policy check --json
openclaw policy check --severity-min error
policy check runs only the policy check set and emits evidence, findings, and attestation hashes. The same findings also appear in openclaw doctor --lint when the Policy plugin is enabled. Example clean JSON output includes stable hashes that can be recorded by an operator or supervisor:
{
  "ok": true,
  "attestation": {
    "policy": {
      "path": "policy.jsonc",
      "hash": "sha256:..."
    },
    "workspace": {
      "scope": "policy",
      "hash": "sha256:..."
    },
    "findingsHash": "sha256:...",
    "attestationHash": "sha256:..."
  },
  "checksRun": 5,
  "checksSkipped": 0,
  "findings": []
}

Configure policy

Policy config lives under plugins.entries.policy.config.
{
  "plugins": {
    "entries": {
      "policy": {
        "enabled": true,
        "config": {
          "enabled": true,
          "path": "policy.jsonc",
          "workspaceRepairs": false,
          "expectedHash": "sha256:...",
          "expectedAttestationHash": "sha256:...",
        },
      },
    },
  },
}
SettingPurpose
enabledEnable policy checks even before policy.jsonc exists.
workspaceRepairsAllow doctor --fix to edit policy-managed workspace settings.
expectedHashOptional hash-lock for the approved policy artifact.
expectedAttestationHashOptional hash-lock for the last accepted clean policy check.
pathWorkspace-relative location of the policy artifact.
Set plugins.entries.policy.config.enabled to false to disable policy checks for a workspace while leaving the plugin installed. Tool metadata requirements are authored in policy.jsonc with tools.requireMetadata, for example ["risk", "sensitivity", "owner"].

Accept policy state

Example JSON output:
{
  "ok": true,
  "attestation": {
    "checkedAt": "2026-05-10T20:00:00.000Z",
    "policy": {
      "path": "policy.jsonc",
      "hash": "sha256:..."
    },
    "workspace": {
      "scope": "policy",
      "hash": "sha256:..."
    },
    "findingsHash": "sha256:...",
    "attestationHash": "sha256:..."
  },
  "evidence": {
    "channels": [
      {
        "id": "telegram",
        "provider": "telegram",
        "source": "oc://openclaw.config/channels/telegram",
        "enabled": false
      }
    ],
    "mcpServers": [
      {
        "id": "docs",
        "transport": "stdio",
        "source": "oc://openclaw.config/mcp/servers/docs",
        "command": "npx"
      }
    ],
    "modelProviders": [
      {
        "id": "openai",
        "source": "oc://openclaw.config/models/providers/openai"
      }
    ],
    "modelRefs": [
      {
        "ref": "openai/gpt-5.5",
        "provider": "openai",
        "model": "gpt-5.5",
        "source": "oc://openclaw.config/agents/defaults/model"
      }
    ],
    "network": [
      {
        "id": "browser-private-network",
        "source": "oc://openclaw.config/browser/ssrfPolicy/dangerouslyAllowPrivateNetwork",
        "value": false
      }
    ],
    "gatewayExposure": [
      {
        "id": "gateway-bind",
        "kind": "bind",
        "source": "oc://openclaw.config/gateway/bind",
        "value": "loopback",
        "nonLoopback": false,
        "explicit": true
      }
    ],
    "agentWorkspace": [
      {
        "id": "agents-defaults-workspace-access",
        "kind": "workspaceAccess",
        "source": "oc://openclaw.config/agents/defaults/sandbox/workspaceAccess",
        "scope": "defaults",
        "value": "ro",
        "sandboxMode": "all",
        "sandboxModeSource": "oc://openclaw.config/agents/defaults/sandbox/mode",
        "sandboxEnabled": true,
        "explicit": true
      },
      {
        "id": "agents-defaults-tool-exec",
        "kind": "toolDeny",
        "source": "oc://openclaw.config/tools/deny",
        "scope": "defaults",
        "tool": "exec",
        "denied": true,
        "explicit": true
      }
    ],
    "secrets": [
      {
        "id": "vault",
        "kind": "provider",
        "source": "oc://openclaw.config/secrets/providers/vault",
        "providerSource": "env"
      },
      {
        "id": "oc://openclaw.config/models/providers/openai/apiKey",
        "kind": "input",
        "source": "oc://openclaw.config/models/providers/openai/apiKey",
        "provenance": "secretRef",
        "refSource": "env",
        "refProvider": "vault"
      }
    ],
    "authProfiles": [
      {
        "id": "github",
        "source": "oc://openclaw.config/auth/profiles/github",
        "validMetadata": true,
        "provider": "github",
        "mode": "token"
      }
    ],
    "tools": [
      {
        "id": "deploy",
        "source": "oc://TOOLS.md/tools/deploy",
        "line": 12,
        "risk": "critical",
        "sensitivity": "restricted",
        "capabilities": ["IRREVERSIBLE_EXTERNAL"]
      }
    ]
  },
  "checksRun": 30,
  "checksSkipped": 0,
  "findings": []
}
The policy hash identifies the authored rule artifact. The evidence block records the observed OpenClaw state used by the policy checks. The workspace.hash value identifies that evidence payload for the checked scope. The findings hash identifies the exact finding set returned by the check. checkedAt records when the evaluation ran. The attestation hash identifies the stable claim: policy hash, evidence hash, findings hash, and whether the result was clean. It intentionally does not include checkedAt, so the same policy state produces the same attestation across repeated checks. Together, these form the audit tuple for this policy check. If a later gateway or supervisor uses policy to block, approve, or annotate a runtime action, it should record the attestation hash from the last clean policy check. checkedAt stays in JSON output for audit logs, but is not part of the stable attestation hash. Use this lifecycle when accepting policy state:
  1. Author or review policy.jsonc.
  2. Run openclaw policy check --json.
  3. If the result is clean, record attestation.policy.hash as expectedHash.
  4. Record attestation.attestationHash as expectedAttestationHash.
  5. Re-run openclaw doctor --lint in CI or release gates.
If policy rules change intentionally, update both accepted hashes from a clean check. If workspace settings change intentionally but policy stays the same, only expectedAttestationHash usually changes. Enabling or upgrading agents.workspace rules adds agentWorkspace evidence to the workspace hash and attestation hash. Operators should review the new evidence and refresh accepted attestation hashes after enabling these rules. Enabling or upgrading tool posture rules adds toolPosture evidence in the same way. openclaw policy watch runs the same check repeatedly and reports when the current evidence no longer matches expectedAttestationHash:
openclaw policy watch --json
Use --once in CI or scripts that only need one drift evaluation. Without --once, the command polls every two seconds by default; use --interval-ms to choose a different interval.

Findings

Policy currently verifies:
Check idFinding
policy/policy-jsonc-missingPolicy is enabled but policy.jsonc is missing.
policy/policy-jsonc-invalidPolicy cannot be parsed or contains malformed rule entries.
policy/policy-hash-mismatchPolicy does not match configured expectedHash.
policy/attestation-hash-mismatchCurrent policy evidence no longer matches the accepted attestation.
policy/channels-denied-providerAn enabled channel matches a channel deny rule.
policy/mcp-denied-serverA configured MCP server is denied by policy.
policy/mcp-unapproved-serverA configured MCP server is outside the allowlist.
policy/models-denied-providerA configured model provider or model ref uses a denied provider.
policy/models-unapproved-providerA configured model provider or model ref is outside the allowlist.
policy/network-private-access-enabledA private-network SSRF escape hatch is enabled when policy denies it.
policy/gateway-non-loopback-bindGateway bind posture permits non-loopback exposure when policy denies it.
policy/gateway-auth-disabledGateway authentication is disabled when policy requires auth.
policy/gateway-rate-limit-missingGateway auth rate-limit posture is not explicit when policy requires it.
policy/gateway-control-ui-insecureGateway Control UI insecure exposure toggles are enabled.
policy/gateway-tailscale-funnelGateway Tailscale Funnel exposure is enabled when policy denies it.
policy/gateway-remote-enabledGateway remote mode is active when policy denies it.
policy/gateway-http-endpoint-enabledA Gateway HTTP API endpoint is enabled while denied by policy.
policy/gateway-http-url-fetch-unrestrictedGateway HTTP URL-fetch input lacks a required URL allowlist.
policy/agents-workspace-access-deniedAgent sandbox mode or workspace access is outside the policy allowlist.
policy/agents-tool-not-deniedAn agent or default config does not deny a tool required by policy.
policy/tools-profile-unapprovedA configured global or per-agent tool profile is outside the allowlist.
policy/tools-fs-workspace-only-requiredFilesystem tools are not configured with workspace-only path posture.
policy/tools-exec-security-unapprovedExec security mode is outside the policy allowlist.
policy/tools-exec-ask-unapprovedExec ask mode is outside the policy allowlist.
policy/tools-exec-host-unapprovedExec host routing is outside the policy allowlist.
policy/tools-elevated-enabledElevated tool mode is enabled when policy denies it.
policy/tools-required-deny-missingA global or per-agent tool deny list does not include a required denied tool.
policy/secrets-unmanaged-providerA config SecretRef references a provider not declared under secrets.providers.
policy/secrets-denied-provider-sourceA config secret provider or SecretRef uses a source denied by policy.
policy/secrets-insecure-providerA secret provider opts into insecure posture when policy denies it.
policy/auth-profile-invalid-metadataA config auth profile is missing valid provider or mode metadata.
policy/auth-profile-unapproved-modeA config auth profile mode is outside the policy allowlist.
policy/tools-missing-risk-levelA governed tool declaration is missing risk metadata.
policy/tools-unknown-risk-levelA governed tool declaration uses an unknown risk value.
policy/tools-missing-sensitivity-tokenA governed tool declaration is missing sensitivity metadata.
policy/tools-missing-ownerA governed tool declaration is missing owner metadata.
policy/tools-unknown-sensitivity-tokenA governed tool declaration uses an unknown sensitivity value.
Policy findings can include both target and requirement. target is the observed workspace thing that does not conform. requirement is the authored policy rule that made it a finding. Both values are addresses today, usually oc:// paths, but the field names describe their policy role rather than the address format. Example JSON finding:
{
  "checkId": "policy/channels-denied-provider",
  "severity": "error",
  "message": "Channel 'telegram' uses denied provider 'telegram'.",
  "source": "policy",
  "path": "openclaw config",
  "ocPath": "oc://openclaw.config/channels/telegram",
  "target": "oc://openclaw.config/channels/telegram",
  "requirement": "oc://policy.jsonc/channels/denyRules/#0",
  "fixHint": "Telegram is not approved for this workspace."
}
Example tool finding:
{
  "checkId": "policy/tools-missing-risk-level",
  "severity": "error",
  "message": "TOOLS.md tool 'deploy' has no explicit risk classification.",
  "source": "policy",
  "path": "TOOLS.md",
  "line": 12,
  "ocPath": "oc://TOOLS.md/tools/deploy",
  "target": "oc://TOOLS.md/tools/deploy",
  "requirement": "oc://policy.jsonc/tools/requireMetadata"
}
Example MCP finding:
{
  "checkId": "policy/mcp-unapproved-server",
  "severity": "error",
  "message": "MCP server 'remote' is not in the policy allowlist.",
  "source": "policy",
  "path": "openclaw config",
  "ocPath": "oc://openclaw.config/mcp/servers/remote",
  "target": "oc://openclaw.config/mcp/servers/remote",
  "requirement": "oc://policy.jsonc/mcp/servers/allow"
}
Example model-provider finding:
{
  "checkId": "policy/models-unapproved-provider",
  "severity": "error",
  "message": "Model ref 'anthropic/claude-sonnet-4.7' uses unapproved provider 'anthropic'.",
  "source": "policy",
  "path": "openclaw config",
  "ocPath": "oc://openclaw.config/agents/defaults/model/fallbacks/#0",
  "target": "oc://openclaw.config/agents/defaults/model/fallbacks/#0",
  "requirement": "oc://policy.jsonc/models/providers/allow"
}
Example network finding:
{
  "checkId": "policy/network-private-access-enabled",
  "severity": "error",
  "message": "Network setting 'browser-private-network' allows private-network access.",
  "source": "policy",
  "path": "openclaw config",
  "ocPath": "oc://openclaw.config/browser/ssrfPolicy/dangerouslyAllowPrivateNetwork",
  "target": "oc://openclaw.config/browser/ssrfPolicy/dangerouslyAllowPrivateNetwork",
  "requirement": "oc://policy.jsonc/network/privateNetwork/allow"
}
Example Gateway exposure finding:
{
  "checkId": "policy/gateway-non-loopback-bind",
  "severity": "error",
  "message": "Gateway bind setting 'gateway-bind' permits non-loopback exposure.",
  "source": "policy",
  "path": "openclaw config",
  "ocPath": "oc://openclaw.config/gateway/bind",
  "target": "oc://openclaw.config/gateway/bind",
  "requirement": "oc://policy.jsonc/gateway/exposure/allowNonLoopbackBind"
}
Example agent workspace finding:
{
  "checkId": "policy/agents-workspace-access-denied",
  "severity": "error",
  "message": "agents.defaults sandbox workspaceAccess 'rw' is not allowed by policy.",
  "source": "policy",
  "path": "openclaw config",
  "ocPath": "oc://openclaw.config/agents/defaults/sandbox/workspaceAccess",
  "target": "oc://openclaw.config/agents/defaults/sandbox/workspaceAccess",
  "requirement": "oc://policy.jsonc/agents/workspace/allowedAccess"
}

Repair

doctor --lint and policy check are read-only. doctor --fix only edits policy-managed workspace settings when workspaceRepairs is explicitly enabled. Without that opt-in, policy checks report what they would repair and leave settings unchanged. In this version, repair can disable channels that are enabled in OpenClaw config but denied by channels.denyRules. Enable workspaceRepairs only after the policy file has been reviewed, because a valid deny rule can turn off a configured channel:
{
  "plugins": {
    "entries": {
      "policy": {
        "config": {
          "workspaceRepairs": true,
        },
      },
    },
  },
}

Exit codes

Command012
policy checkNo findings at the threshold.One or more findings met the threshold.Argument or runtime failure.
policy watchNo findings and accepted hash is current.Findings exist or accepted attestation is stale.Argument or runtime failure.