Skip to content

Agent preferences

The mngd agent has three layers of preferences. Each layer overrides the one before it: a user’s local choice, an org-wide policy pushed from the admin portal on every check-in, and a Configuration Profile pushed via MDM that locks fields the user can’t change.

Local preferences (Settings window)
↓ overridden by
Org policy (managed-preferences API → /checkin response)
↓ overridden by
MDM Configuration Profile (com.mngd.agent + com.mngd defaults domains)

A field set via MDM wins over anything the org pushes, which wins over whatever the user picked locally. Locked fields appear in the Settings window with a “Managed by your admin” label and a disabled control — the agent never silently applies a policy without showing the user what’s in force.

The agent only reads org policy on a successful check-in. It re-applies MDM overrides immediately after, so a server push can’t accidentally unlock a managed field.

For a new admin who wants to verify a single Mac is reporting back to the mngd dashboard.

Click the mngd icon in the menu bar, then click the gear in the popover footer. Or right-click the icon and choose Preferences….

In the General tab, pick a value from Check for updates. Daily is the default. Every 4 hours is a common production choice; Hourly is fine for testing.

Leave Auto-install updates off until you’ve verified the device is appearing in the dashboard with its inventory populated. When you turn it on, the agent installs available updates on its next sync cycle without prompting the user.

You’re done. The first check-in lands within 60 seconds. The device shows up in Devices in the admin portal with installed apps and detected updates. Settings changes take effect on the next sync cycle (5 minutes by default) — there is no separate Save button.

On startup and on every sync cycle (5 minutes by default), the agent:

  1. Loads local preferences saved by the Settings window.
  2. Reads any Configuration Profile keys macOS has bridged into the com.mngd.agent and com.mngd defaults domains.
  3. Calls /api/v1/agent/v1/checkin. If the response includes an agent-config block, applies those fields to the in-memory copy.
  4. Re-applies MDM overrides on top so a server push can’t clobber an admin-locked field.
  5. Reflects the merged result in the Settings window. Any field with an MDM override is disabled and labeled Managed by your admin.

What the agent does not do:

  • The agent does not install updates unless Auto-install updates is on. Vulnerability scans and patch detection still run; nothing installs until the toggle is flipped, either by the user or by the org-wide policy.
  • The agent does not phone home for preferences outside the regular check-in cycle. Click the sync icon in the popover header to force one.
  • The agent does not push MDM-managed fields back to the server. If an admin has locked the Slack channel via Configuration Profile, the agent’s UI shows the locked value but refuses to overwrite it on the server side.

Auto-install is off by default. A fresh install on a Mac with no Configuration Profile and no org policy reports inventory and shows notifications. It does not patch anything until Auto-install updates is enabled — locally, by org policy, or by MDM.

Each Mac stores these in its own preferences. Most of these fields are also pushable org-wide via the managed-preferences API below and lockable via MDM.

FieldDefaultNotes
Check for updatesDailyHourly · Every 4 hours · Daily · Weekly · Manual only
Auto-install updatesOffWhen on, installs detected updates on the next sync cycle
Auto-patch background appsOnOnly applies when Auto-install updates is on; updates apps that aren’t currently running so users aren’t interrupted
Scheduled updatesOffRun installs only inside a recurring time-of-week window instead of as soon as updates land
Default scheduleunsetThe recurring window — days of week, hour, minute
Notification frequencyImmediateImmediate · Daily digest · Weekly digest · Critical only
Notification channelsLocalAny of Local · Slack · Microsoft Teams · Discord
Slack / Teams / Discord webhook URLunsetRequired when the matching channel is enabled
Show menu bar iconOn
Show in DockOnOverridden by the MDM DisplayMode key
Hide apps without auto-update supportOffHides apps the agent can’t update from the Installed tab
Auto-update InstallomatorOnAllow the agent to update its embedded Installomator script
Lock Installomator versionOffWhen on, pin to a specific Installomator version
Notify your MDM after installOnPokes Jamf / Kandji / Addigy so its inventory updates without waiting
MDM notification targetAutomaticAutomatic · Disabled · Jamf Pro only · Kandji only · Addigy only
Patch policy deadlinesCritical 7d · High 14d · Medium 30d · Low 90dPer-severity deadlines and notification rules

Org-wide and per-device defaults are managed through the managed-preferences API. There is no dedicated UI page in the admin portal today — this is the canonical surface. Each preference is a single key/value row scoped either to the entire org (appliesTo: "ALL_DEVICES") or to a list of devices (appliesTo: "SPECIFIC_DEVICES" with deviceIds).

Authentication is a Bearer token (PASETO v4 session token or an API key starting with mngd_). The caller must have the org:manage permission on the target org.

Terminal window
curl https://api.mngd.app/api/v1/orgs/acme/managed-preferences \
-H "Authorization: Bearer $MNGD_API_KEY"

Response:

{
"preferences": [
{
"id": "8f20…",
"key": "updateCheckFrequency",
"value": "every_four_hours",
"appliesTo": "ALL_DEVICES",
"deviceIds": [],
"note": "tightened for security review",
"createdAt": "2026-04-22T10:11:12Z",
"updatedAt": "2026-04-28T08:32:00Z"
}
],
"count": 1
}

POST upserts by (org, key). There’s one POST per preference key — the API doesn’t accept a single blob with many keys. Re-POSTing the same key updates it in place.

Terminal window
curl -X POST https://api.mngd.app/api/v1/orgs/acme/managed-preferences \
-H "Authorization: Bearer $MNGD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "updateCheckFrequency",
"value": "every_four_hours",
"appliesTo": "ALL_DEVICES",
"note": "tightened for security review"
}'
Terminal window
curl -X POST https://api.mngd.app/api/v1/orgs/acme/managed-preferences \
-H "Authorization: Bearer $MNGD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"key": "autoInstallUpdates",
"value": "true",
"appliesTo": "SPECIFIC_DEVICES",
"deviceIds": [
"0a1b2c3d-4e5f-6789-abcd-ef0123456789",
"11111111-2222-3333-4444-555555555555"
]
}'

A device receives a preference if either an ALL_DEVICES row matches or a SPECIFIC_DEVICES row lists its UUID. If both apply, the specific row wins.

Update the value of an existing preference

Section titled “Update the value of an existing preference”

PUT to the preference’s ID. You don’t change the key after creation; if you need to retire a key, DELETE it.

Terminal window
curl -X PUT https://api.mngd.app/api/v1/orgs/acme/managed-preferences/8f20… \
-H "Authorization: Bearer $MNGD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"value": "daily",
"note": "rolled back to daily after pilot"
}'
Terminal window
curl -X DELETE https://api.mngd.app/api/v1/orgs/acme/managed-preferences/8f20… \
-H "Authorization: Bearer $MNGD_API_KEY"

The value column is text. The agent coerces them to the right type on receipt. Use the formats below:

  • Booleans as "true" / "false" (or "1" / "0").
  • Integers as decimal strings, e.g. "240".
  • Arrays and objects as inline JSON, e.g. "[{...}]" or '{"critical":0,"high":1,"medium":3,"low":5}'.

Pretty-printed for readability:

{ "key": "maintenanceWindows", "value": "[{\"day\":\"tue\",\"start\":\"02:00\",\"end\":\"04:00\"}]" }
{ "key": "maxPostponesBySeverity", "value": "{\"critical\":0,\"high\":1,\"medium\":3,\"low\":5}" }
KeyValue typeDescription
updateCheckFrequencyStringhourly, every_four_hours, daily, weekly, manual
autoInstallUpdatesBooleanOrg-wide auto-install policy
autoPatchIdleAppsBooleanUpdate background apps only
scheduledUpdatesEnabledBooleanForce scheduled-updates mode
notificationScheduleStringimmediate, daily_digest, weekly_digest, critical_only
slackWebhookURL / teamsWebhookURL / discordWebhookURLStringWebhook URLs
autoNotifyMDMBooleanWhether the agent pokes the local MDM after an install
mdmNotificationPreferenceStringautomatic, disabled, jamf_only, kandji_only, addigy_only
hideAppsWithoutAutoUpdateBooleanHide unmanaged apps in the Installed tab
installomatorVersionLockedBooleanPin Installomator across the fleet
installomatorLockedVersionStringSpecific Installomator version to pin
syncIntervalMinutesIntegerHow often the agent calls /checkin. Clamped to a minimum of 1 (default 5)
updateCheckIntervalMinutesIntegerHow often the agent runs Installomator-based update detection. Clamped to a minimum of 5 (default 60)
maintenanceWindowsJSON arrayTime windows when scheduled installs are allowed to fire
maxPostponesBySeverityJSON objectHow many times a user can defer an install for a given severity (default {critical:0, high:1, medium:3, low:5})
criticalBypassScheduleBooleanWhen true, critical-severity installs ignore maintenanceWindows (default true)
scheduledUpdateGracePeriodInteger (minutes)Soft countdown before a scheduled install runs (default 15)
defaultBlockingPolicyJSON objectWhat to do when an install’s destination app is running. {"mode":"defer"}, {"mode":"prompt"}, or {"mode":"force"} (default defer)

Fields set on the patch policy, not via managed-preferences

Section titled “Fields set on the patch policy, not via managed-preferences”

Two fields ride the same /checkin response but are stored in the patch_policies table, not managed_preferences. Set them through the patch-policy API instead:

FieldDefaultDescription
allowForceQuitAtDeadlinefalseAt a hard deadline, allow the agent to ask macOS to terminate the running app. Off by default
nagIntervalHours4How often the user is re-nudged about a pending update. Clamped to 1–168

Deploy a Configuration Profile to the com.mngd.agent domain (preferred for new deployments) and com.mngd (legacy domain still read for operational keys). Any key set here becomes the locked value on every Mac that receives the profile. The Jamf Pro deployment guide walks through uploading a profile end-to-end; the keys themselves are the same on Kandji, Addigy, and any other MDM that supports custom configuration payloads.

<?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>EnrollmentToken</key>
<string>mngd_K7X2-M9QR-4WPN</string>
<key>ServerURL</key>
<string>https://api.mngd.app</string>
<key>OrgID</key>
<string>acme</string>
<key>DisplayMode</key>
<string>MenuBarOnly</string>
<key>UpdateCheckFrequency</key>
<string>every_four_hours</string>
<key>AutoInstallUpdates</key>
<true/>
<key>ForcedNotificationChannel</key>
<string>#mngd-alerts</string>
<key>ForcedQuietHoursStart</key>
<integer>18</integer>
<key>ForcedQuietHoursEnd</key>
<integer>9</integer>
<key>ForcedQuietOnWeekends</key>
<true/>
<key>ForcedMaxNudgesPerDay</key>
<integer>3</integer>
</dict>
</plist>
KeyDomainTypeDescription
EnrollmentTokencom.mngd.agent (fallback com.mngd)StringSingle-use token consumed on first launch to enroll the device silently. Issued under Settings → Enrollment in the admin portal.
ServerURLcom.mngd.agent (fallback com.mngd)StringBase URL for the mngd API. Defaults to https://api.mngd.app; override only for self-hosted deployments.
OrgIDcom.mngd.agent (fallback com.mngd)StringOrganization identifier. Required for silent enrollment. The legacy key OrganizationID is also read.
DisplayModecom.mngdStringMenuBarOnly, DockOnly, or Both. Controls whether the agent shows up in the Dock, the menu bar, or both.
UpdateCheckFrequencycom.mngdStringLocks the update-check cadence. Same values as the local preference.
AutoInstallUpdatescom.mngdBooleanLocks auto-install on or off across the org.
ForcedNotificationChannelcom.mngdStringLocks the Slack channel for nudge notifications. Settings UI shows Managed by your admin.
ForcedQuietHoursStartcom.mngdInteger (0–23)Locks the start hour for quiet hours. Out-of-range values are ignored.
ForcedQuietHoursEndcom.mngdInteger (0–23)Locks the end hour for quiet hours.
ForcedQuietOnWeekendscom.mngdBooleanLocks weekend-quiet behavior.
ForcedMaxNudgesPerDaycom.mngdInteger (1–10)Locks the per-user nudge ceiling. Out-of-range values are ignored.
CertificatePinscom.mngdArray<String>Override the SPKI hash list used for certificate pinning. Use only when the server cert rotates ahead of an agent release.
PinnedDomainscom.mngdArray<String>Override which domains pinning applies to.

The activity feed lives at GET /api/v1/orgs/{orgID}/activity, with optional filter params device_udid, severity, before (RFC3339), and limit (max 100). Each entry has the shape:

{
"id": "01HW…",
"event_type": "device.enrolled",
"title": "Device enrolled",
"body": "MacBook Pro (14.7.1)",
"severity": "info",
"device_udid": "0A1B2C3D-…",
"device_name": "Avery's MacBook Pro",
"actor_id": null,
"actor_name": null,
"metadata": {},
"created_at": "2026-04-28T14:32:01Z"
}

Today the agent and server emit four event types that surface in the feed:

event_typeTitleBody
device.enrolledDevice enrolled<HardwareModel> (<OSVersion>)
patch.cve_detected<N> CVE(s) detected<N> critical, <N> high
patch.remediated<AppName> patchedUpdated to <Version>
user.assignedUser assignedAssigned to <email>

There is no Activity Log entry today for a managed-preference push landing on a device, MDM overriding an org-pushed value, or a user changing a local setting in the agent’s Settings window. Those flows happen silently — to verify a config change reached a device, query the device directly:

Terminal window
ssh user@device "defaults read com.mngd.preferences"
ssh user@device "defaults read com.mngd"

A future release will emit a config.applied event so a managed- preferences POST is auditable end-to-end through the activity feed. This page will be updated when that ships.

A setting is greyed out and shows “Managed by your admin”

Section titled “A setting is greyed out and shows “Managed by your admin””

A Configuration Profile sets that key. Run defaults read com.mngd.agent and defaults read com.mngd on the Mac to see which keys are present, adjust the matching profile in your MDM, and re-push it. The agent picks up the change on the next sync cycle.

An org-policy change isn’t taking effect on a device

Section titled “An org-policy change isn’t taking effect on a device”

The agent only reads org policy on a successful check-in. There is no Activity Log entry for managed-preference pushes today, so verify by inspecting the device directly:

  1. Click the sync icon in the popover header to force a check-in.
  2. On the device, run defaults read com.mngd.preferences and confirm the new value is present.
  3. If the value isn’t there, list the org’s managed preferences with GET /api/v1/orgs/{orgID}/managed-preferences and confirm the row exists with the right appliesTo / deviceIds. A row scoped to SPECIFIC_DEVICES only reaches devices whose UUID is in the list.
  4. If check-ins themselves are failing, the most common cause is certificate pinning blocking a rotated server certificate — see the troubleshooting guide for the recovery steps.

Auto-install is one condition out of several. Most common reasons it doesn’t fire:

  • A scheduled-update or maintenance window is gating the install. Verify the current time falls inside an allowed window, or turn off Scheduled updates to install on detection.
  • The privileged background helper isn’t approved. On the Mac, open System Settings → General → Login Items & Extensions and turn on mngd. Without approval the agent refuses every install path.
  • The device isn’t checking in. Click the sync icon in the popover header, then look in Devices → [Device] → Activity for the most recent check-in.

Settings changes don’t persist across launches

Section titled “Settings changes don’t persist across launches”

The agent saves preferences to the user’s defaults under com.mngd.preferences. Confirm the domain exists with defaults read com.mngd.preferences. If it’s wiped on every login, look for a profile-removal or device-management script that runs defaults delete com.mngd.preferences and remove that step.

MDM is locking a field the user expects to control

Section titled “MDM is locking a field the user expects to control”

This is by design. Anything in the com.mngd.agent or com.mngd defaults domain wins over both the user’s UI choice and any org-wide push. Remove the key from the Configuration Profile if the field should be user-controlled.