Device Health Auditor
A worked example of an advanced workflow: a Claude-managed scheduled agent that, once a day, lists the devices at a fixed set of Datto RMM sites, checks each device's health, flags everything with an antivirus problem, a stale check-in, or a pending reboot, and notifies your team: quietly when the fleet is clean, with a Slack canvas when it is not. There are no servers and no code to deploy: the agent is a saved prompt plus a schedule plus two MCP connectors, running in Claude's cloud.
What it builds
The finished workflow runs unattended on a daily cron. Each run it lists the devices at each of its configured sites, reasons about which ones are unhealthy, groups the findings by site, and notifies your team, turning a scattered fleet into a single device-health report with a Slack trail. When nothing is wrong it posts one quiet "all clear" line and stops.
Prerequisites
Before building, your Claude account needs all of the following:
| Requirement | Notes |
|---|---|
| WYRE MCP Gateway connector | Connected in claude.ai (https://mcp.wyre.ai/v1/mcp). Provides the datto_* tools. See the Gateway overview. |
| Datto RMM enabled in the gateway | The gateway's Datto RMM API user must be able to read sites and devices. |
| Slack connector | The first-party Slack connector connected in claude.ai (https://mcp.slack.com/mcp). Provides slack_create_canvas and slack_send_message. |
| Scheduled routines access | Created via the /schedule capability; managed at claude.ai/code/routines. |
| A destination Slack channel | e.g. #sw-dev, plus its channel ID. The Slack connector must have access to it. |
Known gotchas
These are the things that cost real time the first time through. Account for them up front and the build genuinely takes minutes.
- The
datto_list_devicespayload is heavy — scope the routine to a fixed set of sites. Each device record carries audfblock of 300 custom fields, almost allnull. Across a large fleet that bloat swamps a single routine run before it can finish — the run produces no output. Until the gateway slims that payload, bake a fixed set of roughly six site UIDs into the routine prompt rather than sweeping every site. - Read health fields from the list payload — don't call
datto_get_deviceper device. Thedatto_list_devicesrecord already containsonline,lastSeen,rebootRequiredand anantivirusobject. One list call per site is all the routine needs; a per-device call across the fleet risks the 60-second tool timeout. - Backup health is not on the gateway. Datto RMM exposes device and patch data, but backup status lives in the separate Datto BCDR product, which the gateway does not surface. This routine audits RMM device health only; a backup monitor would need a different data source.
-
permitted_toolsmust be populated per connector. A routine with a connector attached but an emptypermitted_toolslist runs with no tools and silently does nothing — no error, no output. List the exact tool names the routine needs. - A routine reaches only its attached connectors. The routine sandbox blocks arbitrary network egress, so notifications must go through the Slack connector's tools, not an outbound webhook. Attach every connector the workflow touches.
The one-shot build prompt
With the connectors above in place, paste this to Claude. It confirms the gateway, creates the routine, and verifies it end to end.
Build me a scheduled Device Health Auditor agent. Do all of this end to end:
1. Confirm the WYRE MCP Gateway works and Datto RMM is reachable: call
datto_list_sites and check it returns your managed sites.
2. Pick the sites this audit should cover. Datto's datto_list_devices payload
carries a large per-device "udf" block (300 custom fields, mostly null), so
sweeping a big fleet in one routine run is not viable - the run drowns in
that payload. Choose a fixed set of about six sites and record each site's
siteUid. These siteUids get baked into the routine prompt.
3. Confirm a Slack connector is connected. Note the destination channel name
and ID (e.g. #sw-dev). If Slack does not show in the /schedule connector
list, read its connector_uuid and url from an existing routine that already
uses Slack (RemoteTrigger list -> get -> mcp_connections).
4. Create a Claude-managed scheduled routine named "Device Health Auditor":
- Schedule: daily, cron "0 12 * * *" (07:00 America/New_York = 12:00 UTC
in winter, 08:00 in summer). Faster-than-hourly cadences are rejected.
- Attach TWO connectors, each with permitted_tools populated:
* WYRE MCP Gateway: datto_list_devices
* Slack: slack_create_canvas, slack_send_message
An empty permitted_tools list = the routine runs with no tools.
- Routine prompt: every run, list devices for each of the baked-in sites,
flag devices with an antivirus problem, a stale check-in, or a pending
reboot, build a report grouped by site, and notify Slack. Use the exact
routine prompt below, with your own siteUids.
5. Trigger a manual run and verify: if the fleet has concerns a canvas titled
"Device Health - <date>" was created and a one-line summary landed in the
destination channel; if the fleet is clean a single "all clear" line landed
in the channel and nothing else. The resulting routine prompt
This is the lean prompt the build process installs into the scheduled routine itself. Substitute your own site UIDs and destination channel.
You are the Device Health Auditor. You run once a day. Keep it lean.
Use ONLY: datto_list_devices, slack_create_canvas, slack_send_message.
Do NOT call datto_list_sites - the sites are listed below.
Sites to check (siteUid - name):
- <site-uid-1> - <site name 1>
- <site-uid-2> - <site name 2>
- ... about six sites total ...
1. For each site above, call datto_list_devices with that siteUid and max 200.
2. For each device, read these fields only - ignore the large udf block.
A device is a CONCERN if any of:
- AV problem: the antivirus object is missing, or antivirus.antivirusStatus
is not "RunningAndUpToDate".
- Stale check-in: lastSeen (epoch ms) is more than 14 days before today.
- Reboot pending: rebootRequired is true.
List every concern that applies to a device.
3. Build a report grouped by site: site name, total devices, concern count,
and each concerning device's hostname with its concern(s).
4. If there are NO concerns anywhere, slack_send_message to #sw-dev a single
line: "Device health: all clear across 6 sites." Post nothing else.
5. If there ARE concerns, slack_create_canvas titled "Device Health -
<today's date>" with the full grouped report, then slack_send_message to
#sw-dev a one-line summary ("Device health: N devices with concerns across
6 sites - see canvas") linking the canvas.
6. If a site cannot be read, list it in a "could not check" section instead of
skipping it silently. How it works
A daily cadence, by design
Device health is a fast-moving signal — an antivirus engine can fall out of date, a machine can drop off the network, or a pending reboot can pile up overnight. The routine runs every morning so a fresh picture is waiting before the day's work starts. Daily is the right cadence here: frequent enough to catch problems while they still matter, still kind to the API at one sweep per day.
The green path stays quiet
When no device anywhere has a concern, the routine posts a single line ("Device health: all clear across 6 sites.") and nothing else. A clean fleet should not produce a report a teammate has to open and scan to learn nothing is wrong. The detailed canvas appears only when there is something to act on.
Three concern signals
A device is flagged as a concern if any of three things is true, and the report lists every concern that applies:
- AV problem — the
antivirusobject is missing, or itsantivirusStatusis anything other thanRunningAndUpToDate. A device with no working, current antivirus is a security gap. - Stale check-in —
lastSeen(an epoch-millisecond timestamp) is more than 14 days before the run date. A machine that has not checked in for two weeks is effectively unmanaged. - Reboot pending —
rebootRequiredistrue. Pending reboots block patches from finishing and leave the device in a half-applied state.
It covers a fixed set of sites, not the whole fleet
Each datto_list_devices record carries a 300-field udf
block that is almost entirely empty. Listing every device across a large fleet
floods a single routine run with that null data and the run never reaches the
report. So the routine is scoped to a fixed set of roughly six sites whose combined
device count a run can comfortably hold. Widening it to the whole fleet is a
gateway change — datto_list_devices needs to omit the udf
block — not a routine change.
Delivery is a Slack canvas plus a summary
The full site-by-site report can be long, so when there are concerns the routine publishes it as a Slack canvas, a durable document teammates can scroll and reference, and posts only a one-line summary to the channel linking it. The channel stays readable; the detail lives in the canvas. See delivery adapters for other ways to surface a routine's output.
Extending it
The natural next step is whole-fleet coverage: once the gateway's
datto_list_devices can return device records without the
udf block, the routine can drop the baked-in site list and call
datto_list_sites to sweep everything. From there, repeat offenders are
worth escalating — a device flagged on the same concern several days running could
open a PSA ticket through the gateway's autotask tools instead of just
appearing in the canvas again, turning a passive report into tracked remediation work.
Questions or a workflow you'd like documented?
Open an issue
in the msp-claude-plugins repository.