macOSMicrosoft Intune

Intune deployment

macOS uses the universal signed PKG. Windows uses the promoted IntuneWin from the production feed. A signed workflow candidate remains validation-only until the release evidence gates pass and a...

Universal macOS PKG · Signed Windows IntuneWin

macOS uses the universal signed PKG. Windows uses the promoted IntuneWin from the production feed. A signed workflow candidate remains validation-only until the release evidence gates pass and a reviewed feed update points to the same package hashes.

macOS

Current package versions and checksums are published with the release artifacts. See Download artifacts.

Before deployment, subscribe to installer updates.

Create the profile

Create a macOS Enterprise Installer token with Microsoft Intune selected. The deployment ID in the profile must match the token.

The token is reusable for Macs in this scoped deployment until it expires or is revoked. Keep it only in the restricted Intune app script. Rotate it immediately after exposure and revoke it when the deployment ends.

Save the following as AgentKeeper.mobileconfig. Replace the organization and deployment values:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadContent</key>
  <array>
    <dict>
      <key>PayloadType</key>
      <string>com.apple.ManagedClient.preferences</string>
      <key>PayloadIdentifier</key>
      <string>com.agentkeeper.runtime.preferences.intune</string>
      <key>PayloadUUID</key>
      <string>561A15C9-3A42-4821-A56F-71EBA5FA0F60</string>
      <key>PayloadVersion</key>
      <integer>1</integer>
      <key>PayloadEnabled</key>
      <true/>
      <key>PayloadContent</key>
      <dict>
        <key>com.agentkeeper.runtime</key>
        <dict>
          <key>Forced</key>
          <array>
            <dict>
              <key>mcx_preference_settings</key>
              <dict>
                <key>api_url</key>
                <string>https://agentkeeper.dev</string>
                <key>org_id</key>
                <string>YOUR_AGENTKEEPER_ORG_ID</string>
                <key>mdm_provider</key>
                <string>intune</string>
                <key>mdm_deployment_id</key>
                <string>YOUR_AGENTKEEPER_DEPLOYMENT_ID</string>
              </dict>
            </dict>
          </array>
        </dict>
      </dict>
    </dict>
  </array>
  <key>PayloadDisplayName</key>
  <string>AgentKeeper Runtime</string>
  <key>PayloadIdentifier</key>
  <string>com.agentkeeper.runtime.intune</string>
  <key>PayloadOrganization</key>
  <string>AgentKeeper</string>
  <key>PayloadScope</key>
  <string>System</string>
  <key>PayloadType</key>
  <string>Configuration</string>
  <key>PayloadUUID</key>
  <string>9DAD3BCB-0FF0-46E5-BBDE-EAB2C5A1383A</string>
  <key>PayloadVersion</key>
  <integer>1</integer>
</dict>
</plist>

In Intune, create a macOS Custom configuration profile, upload the file, and select Device channel. Assign it to the same macOS device group as the PKG. Do not use User channel: the LaunchDaemon reads the computer-level profile from /Library/Managed Preferences/com.agentkeeper.runtime.plist. Do not add a UPN, local account name, or dynamic user variable. User affinity is not required for AgentKeeper enrollment.

Before assigning the PKG, verify the installed value:

#!/bin/bash
set -euo pipefail

PROFILE="/Library/Managed Preferences/com.agentkeeper.runtime.plist"
if [[ ! -f "$PROFILE" || -L "$PROFILE" ]]; then
  echo "AgentKeeper profile is missing or invalid" >&2
  exit 1
fi
for key in api_url org_id mdm_provider mdm_deployment_id; do
  sudo /usr/bin/plutil -extract "$key" raw -o - "$PROFILE" 2>/dev/null \
    | /usr/bin/grep -q '[^[:space:]]' || exit 1
done
if [[ "$(sudo /usr/bin/plutil -extract mdm_provider raw -o - "$PROFILE")" != "intune" ]]; then
  echo "AgentKeeper profile has the wrong MDM provider" >&2
  exit 1
fi
if sudo /usr/bin/plutil -extract enrollment_token raw -o - "$PROFILE" >/dev/null 2>&1; then
  echo "Remove enrollment_token from the AgentKeeper profile" >&2
  exit 1
fi
echo "AgentKeeper device profile ready"

Never add enrollment_token to the profile. The runtime checks for profile changes each minute, but profile-first assignment keeps deployment results deterministic.

Add the PKG app

  1. Verify the PKG against checksums.txt, its Developer ID Installer signature, stapler, and Gatekeeper.
  2. In the Intune admin center, go to Apps > All apps > Create.
  3. Choose macOS app (PKG) and upload the package using the unmanaged PKG app type.
  4. Remove any incorrectly inferred entries from Included apps. Do not invent an .app bundle ID; AgentKeeper installs a LaunchDaemon and command line runtime.
  5. In Program, add this Post-install script, replacing the token placeholder. The script runs after the PKG and stages the token through standard input. Intune requires Microsoft Intune management agent version 2309.007 or later for PKG pre- and post-install scripts:
#!/bin/bash
set -euo pipefail
set +x

AGENTKEEPER_ENROLLMENT_TOKEN='PASTE_ENTERPRISE_INSTALLER_TOKEN'
trap 'unset AGENTKEEPER_ENROLLMENT_TOKEN' EXIT

BIN="/Library/Application Support/AgentKeeper/bin/agentkeeper"
REMEDIATE="/Library/Application Support/AgentKeeper/helpers/agentkeeper-macos-remediate.sh"

if [[ "$(id -u)" -ne 0 || ! -x "$BIN" || ! -x "$REMEDIATE" ]]; then
  echo "AgentKeeper PKG is not ready for enrollment" >&2
  exit 1
fi

printf '%s' "$AGENTKEEPER_ENROLLMENT_TOKEN" | "$BIN" \
  stage-managed-enrollment \
  --token-stdin \
  --program-data "/Library/Application Support/AgentKeeper" \
  --install-dir "/Library/Application Support/AgentKeeper"
unset AGENTKEEPER_ENROLLMENT_TOKEN

"$REMEDIATE"
  1. Assign the app as Required to the target macOS device group.

The package installs the runtime. The Post-install script stages a root-only 0600 token and starts enrollment and reconciliation. A Platform Script may report package, LaunchDaemon, and status-helper state, but it must not become a second installer.

Machine enrollment can complete before anyone signs in. After a regular non-root user signs in, the runtime resolves the active console account through macOS Directory Services and reconciles that account automatically. It repeats this after a user switch and never scans /Users.

Verify

pkgutil --pkg-info dev.agentkeeper.runtime
sudo launchctl print system/com.agentkeeper.runtime
sudo "/Library/Application Support/AgentKeeper/helpers/agentkeeper-macos-status.sh"

Status must show enrollment_state="enrolled", managed_profile_state="ready", hook_matrix.config_json=true, and credential_state="valid". Then restart one selected AI agent and confirm a fresh live Activity event.

Before sign-in, status can show targeting_mode="active_console_user", no active_console_user, and maintenance_state="waiting_for_user" while the machine is already enrolled. After sign-in or a user switch, wait for the one-minute maintenance tick or run the installed remediation helper; do not add a username to the profile.

Intune reports the PKG app as installed even when its Post-install script fails. Use the status command above, not the app installation result, to confirm enrollment. enrollment_state="managed_token_missing" means the metadata profile arrived but the token-staging script did not complete.

The Intune unmanaged PKG app type has no Uninstall assignment. Run the installed AgentKeeper uninstall helper before retiring a Mac. See Uninstall and rollback.

Microsoft documents the app type in Add an unmanaged macOS PKG app.

Windows

Windows uses agentkeeper-runtime-windows-latest.intunewin and its package-matched PowerShell helpers. Follow Windows enterprise install for the current download, install, detection, and uninstall commands. The macOS PKG and Post-install script on this page do not apply to Windows.

  1. Download agentkeeper-runtime-windows-latest.intunewin and its matching agentkeeper-runtime-intunewin-source.zip.
  2. Create a Windows app (Win32) in Intune.
  3. Enter the app information and Program fields manually. An .intunewin is a content container and does not populate install commands, detection rules, requirements, or assignments.
  4. Set Install behavior to System, Device restart behavior to No specific action, and select both x64 and ARM64 under Requirements.
  5. Use the package-matched install and uninstall commands through %SystemRoot%\Sysnative\WindowsPowerShell\v1.0\powershell.exe.
  6. Under Detection rules, choose Use a custom detection script and upload detect.ps1 extracted from that exact source ZIP. Set Run script as 32-bit process on 64-bit clients to No.
  7. Assign the app as Required to the intended Windows device group.

Available for enrolled devices does not install the app automatically; it waits for the user to select Install in Company Portal. Use the complete Windows enterprise install walkthrough for test-device enrollment, Enterprise Installer token creation, every portal field, device-group assignment, manual sync, status interpretation, upgrade, and log collection.

AgentKeeper supports Microsoft Entra automatic enrollment and Windows Autopilot. Neither is required for a small test: a licensed user can enroll an existing Windows device through Company Portal without Microsoft Entra ID P1 or P2, provided the Windows account doing the enrollment is a local administrator.

Do not configure detection as a PowerShell command. The uploaded detector contains the package's immutable exact version. Every package upgrade must replace both the .intunewin and the uploaded detect.ps1; reusing the prior detector intentionally makes the upgraded app report as not installed.

Create the token in Settings > Access > API keys > Enterprise Installer tokens. Choose Windows / Intune, and make the token deployment ID and surface scope match the install command. The -MdmDeploymentId value must be the exact Deployment ID shown under the token's Deployment scope, not the token's display Name. Do not use a fleet API key, Microsoft Graph secret, or manually assigned machine ID.

Run the helpers with Windows PowerShell 5.1 through %SystemRoot%\Sysnative.

The package installs one canonical all-IDE hook at C:\ProgramData\AgentKeeper\agentkeeper-ide-hook.ps1. Cursor, Windsurf, Copilot CLI, Gemini CLI, and Codex use machine-managed configuration under C:\ProgramData; Copilot's policy file is C:\ProgramData\GitHub\Copilot\policy.d\agentkeeper.json. Antigravity stores its hook configuration in the resolved developer profile, but that configuration points to the same canonical hook under C:\ProgramData. Claude Code uses the runtime's dedicated Claude and SessionStart forwarders from the machine-managed base file at C:\Program Files\ClaudeCode\managed-settings.json.

Claude Code's configuration reference documents Windows file-based managed settings under C:\Program Files\ClaudeCode. AgentKeeper does not use the retired C:\ProgramData\ClaudeCode location or managed-settings.d for its Windows hooks. A developer's %USERPROFILE%\.claude\settings.json is considered only for safe cleanup of legacy AgentKeeper entries after the managed repair succeeds.

The default IdeTargets=all selection requires exactly one strong Windows account, SID, and mounted profile because it includes Antigravity. Set TargetUser or TargetUserUpn when Intune cannot identify exactly one active developer session. AgentKeeper persists that target so Antigravity repair, detection, status, and uninstall do not guess again. Any selection that omits Antigravity is machine-scoped, including Claude Code, and does not require an interactive target user. For mixed all, Builtin Users receives the narrow runtime-asset access needed by machine-scoped hooks while the resolved SID is used for Antigravity's profile config.

Repair preserves unrelated customer hooks. If a selected JSON or TOML config is malformed, AgentKeeper leaves it unchanged and reports a nonzero repair/detection result. Any selected hook repair failure fails the unified install instead of reporting a partial installation as healthy.

Inventory sync

Intune inventory sync is optional identity enrichment. Microsoft Graph credentials stay in the server-side AgentKeeper MDM connection and never belong in endpoint configuration.