Skip to main content
Enforce installs client hooks that apply security controls before agent actions run. Unlike Detect (which discovers configurations), Enforce actively controls shadow MCP usage and, when full session scanning is enabled, policy-checks local tool inputs and outputs in real time.

How It Works

When Enforce is installed, it intercepts supported client hook events before execution:
  1. User invokes a tool — The AI assistant requests an MCP or local tool call
  2. Intercept — The call is captured before reaching the MCP server or before the local tool runs
  3. Policy evaluation — The call is checked against your organization’s policies
  4. Decision — The call is either:
    • Allowed — Proceeds normally
    • Blocked — Prevented and logged for security review
  5. Audit logging — MCP source decisions and enabled hook events are logged for visibility
Enforce and Sessions events are attributed through the same device identity model as Detect. See User and Identity Mapping for how AI Watch maps OS usernames to Runlayer users.

Enforcement Paths

Enforce has two real-time paths:
  • Shadow MCP source enforcement — blocks MCP servers configured outside Runlayer unless the source is allowed. A source is allowed when it is a Runlayer-managed proxy URL, a Runlayer-managed stdio command, a remote URL on your remote-URL allowlist, a local package on your stdio package allowlist, or a built-in MCP server permitted for that client. This path stays active once enforcement hooks are installed, even if full session scanning is disabled.
  • Local tool lifecycle enforcement — sends non-MCP tool inputs and outputs, such as shell commands and file reads, through the pre-tool and post-tool scanner pipeline, and denies any built-in client tool whose type is on your block list. This path requires Full session scanning APIs and the target Hook client to be enabled under SettingsGeneral.
Sessions telemetry and blocking are independent. Enforce hooks forward session and event telemetry to Runlayer whenever Sessions is enabled — even with Enforcement off, which is the default monitoring-only posture. Actual blocking of shadow MCP sources and local tool calls happens only when Enforcement=true (AIWATCH_ENFORCEMENT=1). So you can run full Sessions visibility without blocking anything, then flip Enforcement on when you are ready. See Monitoring-only rollout.

What Gets Intercepted

Enforce intercepts tool calls from shadow MCP servers — those configured directly in the client rather than through Runlayer. This includes MCP servers embedded in native client plugins (e.g. Claude Code marketplace plugins). The hook resolves MCP endpoints from installed plugin manifests and enforces the same source rules. Tool calls to Runlayer-managed MCPs (server, plugin, and skill proxy URLs) are recognized as managed and allowed through. All other remote MCP URLs are blocked unless they appear on the allowlist. For supported hook clients, Enforce also intercepts local non-MCP tools. These calls are evaluated by your scanner settings: organizations with no blocking scanner configuration allow by default; organizations with blocking scanner actions can block before execution or block untrusted output after execution.

Can users bypass approved plugins and skills?

Not at the MCP layer, once Enforce hooks are installed. How each artifact type is governed:
  • Approved (Runlayer-managed) plugins and skillsPlugins bundle connectors behind a single Runlayer proxy URL, so every tool call still goes through your organization’s policies and access controls. During install, plugin manifests are rewritten to accept only Runlayer proxy URLs. Managed skills are security-scanned on publish, with a configurable risk policy that blocks high-risk skills by default.
  • Unapproved local plugins — MCP servers embedded in locally installed plugins are subject to the same shadow MCP source enforcement described above: blocked unless they resolve to a Runlayer-managed URL or an allowlisted remote URL.
  • Unapproved local skills — Skills are instruction files, not tool endpoints, so there is no skill-specific blocking path; Detect discovers and risk-classifies shadow skills but never blocks them. The actions a shadow skill drives still run through tool calls, which are covered by shadow MCP source enforcement and — where enabled — local tool lifecycle scanning.
Without Enforce hooks installed, nothing is blocked on the device; Detect still provides discovery and risk classification of shadow MCPs, skills, and plugins.

Enforce policy

Once Enforce hooks are installed, the Enforce policy governs which unmanaged tool sources are allowed and which built-in client tools are blocked. Admins with the Manage org settings capability edit it under SettingsMDM Configuration. It has four independent, fail-closed dimensions — an allowlist of remote MCP URLs, an allowlist of local (STDIO) packages, blocked built-in tool types, and an API-only built-in MCP server allowlist. Anything Enforce cannot positively match to a Runlayer-managed source, an allowlist entry, or a permitted built-in is blocked.

Enforce policy configuration

Configure the allowlists and built-in tool blocks: remote MCP URLs, local (STDIO) packages, built-in MCP servers, built-in tool types, and one-click promotion from Detect sightings.

Supported Clients

Enforce uses client hooks, so this matrix is intentionally smaller than Detect’s scan matrix. Additional hook client support is in active development. Check SettingsGeneralHook clients for the latest tenant-enabled client list.

Deployment

Enforce is a capability flag on the same AI Watch .pkg / .msi that runs Detect and Sessions. A single signed aiwatch binary handles scanning, aiwatch hook decisions, and session event hooks, all authenticated by one organization API key — no enrollment keys. If AI Watch is already deployed, enabling Enforce is setting Enforcement in your Configuration Profile (macOS) or the AIWATCH_ENFORCEMENT MSI property (Windows).
TLS trust: The MDM-deployed aiwatch binary (scan + aiwatch hook) verifies HTTPS through the OS trust store — macOS Keychain (login + System), Windows certificate stores (Current User + Local Machine). Corporate root CAs pushed via MDM, GPO, or Intune are honored automatically with no extra config. If your corporate root is not installed system-wide and hooks fail with CERTIFICATE_VERIFY_FAILED, see Troubleshooting for --ca-bundle, RUNLAYER_CA_BUNDLE, SSL_CERT_FILE, and REQUESTS_CA_BUNDLE overrides.

How the bootstrap flow works

When Enforcement or Sessions is set, the .pkg / .msi runs an idempotent hook bootstrap: it writes Runlayer hook entries into the Cursor, VS Code, Claude Code, GitHub Copilot CLI, Codex, Hermes, and Goose configuration files as the command string aiwatch hook --client <name>. Existing third-party hooks are preserved. The hooks authenticate to your tenant with the same organization API key carried in the tenant config — no per-device enrollment step. Per-platform triggers:
VS Code, Claude Code, Hermes, and Goose hooks are currently written to console-user locations for MDM scope. VS Code hooks live in ~/.copilot/hooks/runlayer.json / %USERPROFILE%\.copilot\hooks\runlayer.json. GitHub Copilot CLI managed hooks use the GitHub policy directory (/etc/github-copilot/policy.d/runlayer.json on macOS/Linux and C:\ProgramData\GitHub\Copilot\policy.d\runlayer.json on Windows). Claude Code hooks are written to ~/.claude/settings.json / %USERPROFILE%\.claude\settings.json rather than the enterprise managed-settings location, due to a Claude Code issue with hooks in managed/enterprise settings. Hermes has no native enterprise hook directory, so MDM scope writes the console user’s ~/.hermes/config.yaml / %USERPROFILE%\.hermes\config.yaml. Goose hook plugins are user-level, so MDM scope writes ~/.agents/plugins/runlayer-hooks/hooks/hooks.json / %USERPROFILE%\.agents\plugins\runlayer-hooks\hooks\hooks.json.
The hook bootstrap is idempotent — repeat ticks re-write the same command strings and preserve third-party entries. Flip Enforcement off and re-push to stop blocking; if Sessions stays enabled, hooks remain installed for monitoring-only telemetry. Disable both Enforcement and Sessions for Detect-only deployment with no hook install. Changes are picked up on the next aiwatch hook fire (no .pkg / .msi reinstall).

MDM Deployment

Use Deploy AI Watch for managed rollout. In the MDM Configuration wizard, turn on Enforce policies. The downloaded macOS profile sets Enforcement; the Windows install command sets AIWATCH_ENFORCEMENT.

Deploy AI Watch

Install the package once, then configure Detect, Enforce, and Sessions.
For non-Intune Windows MDMs, call aiwatch.exe setup hooks check/install --mdm from a SYSTEM-context recurring task.

Monitoring-only rollout (no blocking)

To roll Enforce out in observe-without-blocking mode, set the Enforcement MDM field to false or leave it absent. Hooks still register and forward events to Runlayer when Sessions is enabled (the default), but never block tool calls. Useful for a baseline phase before flipping enforcement on. This is the MDM equivalent of the --no-enforcement flag on runlayer setup hooks --install. Flip back to enforce by re-pushing the profile / MSI with the field set to true / 1; aiwatch hook picks up the change on the next fire (no restart, no .pkg / .msi reinstall). For Detect-only deployment with no hooks, disable Sessions too (Sessions=false / AIWATCH_SESSIONS=0).

Manual installation (single-device)

For testing or individual device setup without an MDM, install the runlayer CLI and run the operator-facing hook installer. Step 1 — Install the Runlayer CLI:
Restart your terminal after installing so ~/.local/bin (macOS/Linux) or %USERPROFILE%\.local\bin (Windows) is on PATH. Step 2 — Log in to your Runlayer instance:
Credentials are stored in your OS keychain when available, with a fallback to ~/.runlayer/config.yaml. Step 3 — Install Enforce:
The MDM-deployed .pkg / .msi runs aiwatch setup hooks install automatically via aiwatch bootstrap. The runlayer setup hooks --install command above is the operator-facing path for non-MDM use — it uses the same hook endpoints and client hook shapes, but writes through the full CLI’s per-user installer.
Use --no-enforcement when you want visibility without blocking requests. Hooks still forward events where the corresponding event endpoints are enabled, but no policy enforcement is applied. This is useful for a rollout phase where you want to observe before enforcing. Uninstall:

Sessions and Enforce

To collect detailed Sessions timelines, hooks must register the full event/session set, not just the shadow-MCP enforcement hooks. Managed deployments control this with the Sessions package flag in Deploy AI Watch. Manual installs can add --event-hooks (or the --all-events alias) to the runlayer setup hooks --install invocation. Local tool lifecycle scanning uses Enforce hooks, but its backend scanner path is also gated by Full session scanning APIs and the target Hook clients under SettingsGeneral. Shadow MCP source blocking remains active without full session telemetry.

Troubleshooting

  1. Restart the AI client after installation — Cursor, VS Code, Claude Code, Codex, Hermes, and Goose only read hook configs at process start.
  2. Confirm the hook configs are installed:
    Exit 0 = compliant. Exit 1 = hook configs drifted (the next bootstrap tick will rewrite them).
  3. Confirm Enforcement is enabled in the tenant config:
    If Enforcement is 0 / <false/>, hooks register but never block — re-push the profile / MSI with Enforcement enabled.
  4. Check that the client is supported (see table above).
The bootstrap hasn’t (re-)written the hook configs yet. Causes:
  • Bootstrap daemon not loaded (macOS) — Check:
    If it returns Could not find service, the .pkg postinstall didn’t bootstrap it. Re-deploy the .pkg, or kick it: sudo launchctl kickstart -k system/com.runlayer.aiwatch.bootstrap.
  • No hook-installing capability enabled — the bootstrap installs hooks when Enforcement=true or Sessions=true (the default). For blocking, verify Enforcement is enabled with the defaults read / Get-ItemProperty command above.
  • AIWatchHooks task not running (Windows) — the MSI-registered AIWatchHooks task runs aiwatch setup hooks install --mdm as SYSTEM (it writes SYSTEM-scoped paths under Program Files / ProgramData). Check it exists and its last result: Get-ScheduledTaskInfo -TaskPath "\Runlayer\" -TaskName "AIWatchHooks" | Select-Object LastRunTime, LastTaskResult. Force a run with Start-ScheduledTask -TaskPath "\Runlayer\" -TaskName "AIWatchHooks", or repair/reinstall the app if the task is missing.
  1. Check your Runlayer instance connectivity.
  2. Review the number of policies being evaluated.
  3. Contact Runlayer support if issues persist.

Enforce policy configuration

Allowlists and built-in tool blocks, field by field

Shadow MCP Overview

Understanding the shadow MCP problem

Detect

Discover shadow servers via scheduled scans

Policies

Configure access control policies

Audit Logs

View intercepted tool calls