Agent
rmm-agent.exe is a Go program that runs as the Windows service
RMMAgent (LocalSystem). Source: entrosity-axis-agent/, with the transport,
executor, secret store, logging, service wrapper and updater shared with
the connector in entrosity-shared-go/agentkit.
Installation
The MSI (entrosity-axis-agent/installer/Package.wxs, WiX v4) installs the service and
enrolls in one step:
msiexec /i rmm-agent.msi /qn ENROLLMENT_TOKEN=<token> SERVER_URL=<url>
| Property | Meaning |
|---|---|
ENROLLMENT_TOKEN | Agent enrollment token (hidden from logs). |
SERVER_URL | The server's public URL. |
A failed enrollment rolls the install back. Without the properties, the
service waits until rmm-agent.exe enroll is run. Upgrades use WiX
MajorUpgrade, and downgrades are allowed (the self-update rollback needs
them).
Command line
rmm-agent <command> [flags]
run run the agent (foreground, or as a service under the SCM)
--server URL --token T enroll first if not enrolled yet
enroll enroll this machine: --server URL --token T [--force]
inventory collect the inventory and print it: [--json] [--delta]
status show enrollment state
install install the Windows service
uninstall remove the Windows service
version print the version
RMM_DATA_DIR overrides the data directory. inventory works without a
server, which is useful when working on collectors.
Files
%ProgramData%\RMM\
agent.dat DPAPI-encrypted (machine scope) {agent_id, agent_key, server_url}
config.json last config from the server
state.json pending / in-progress job ids (+ detection metadata) for crash recovery
logons.json sign-outs not yet delivered to the server (at most 256)
cache\ downloaded packages by SHA-256 (LRU, 2 GiB cap, .verified marker)
update\ self-update MSIs, update.ps1, result.json
logs\agent.log rotating log
logs\remote-helper.log remote desktop capture helper (emptied above 5 MiB)
logs\user-notice.log restart/shutdown notices shown to users
Warnings and errors also go to the Application event log (source
RMMAgent).
Behaviour
| What | When |
|---|---|
| Heartbeat (CPU, memory, disks, logged-on user, uptime, pending reboot, CPU temperature) | Every 60 s |
| Full inventory | At start and every 24 h |
| Delta inventory (software, disks, services) | Every 4 h |
| Reconnect | Exponential back-off 1 s → 5 min with 20 % jitter |
| HTTP polling fallback | After 10 failed WebSocket attempts, every 5 min, while retrying the WebSocket in the background |
The server can change the intervals with config.update.
Inventory collectors
System (OS, hardware, last boot, user), software (registry, machine
and per-user; winget IDs added when winget is present), disks, network
adapters, services, Windows updates and local users. A collector that
fails is reported in errors[] and its section is left untouched on the
server.
Jobs
inventory, install_package, uninstall_package, run_script,
reboot, shutdown, update_agent, winget_search, remote_desktop.
Jobs run one at a time, except remote_desktop, which has a lane of
its own so a consent prompt waiting for an answer does not hold up other
jobs. Before executing, the agent records the job in state.json; if
it crashes or restarts, it reports each leftover job on start (succeeded
if detection shows the intended state, otherwise agent_restarted).
Details: Protocol.
Capabilities
The agent announces winget (when winget is available), run_as_user
(Windows) and remote_desktop (Windows) in its hello. Agents before 0.5
answer run_as_unsupported to run-as-user jobs; the server refuses remote
desktop sessions for agents without remote_desktop (remote_unsupported).
Sign-ins
Every 10 seconds the agent lists the Windows sessions
(WTSEnumerateSessions, skipping session 0 and sessions without a user)
and identifies each sign-in by session id and logon time. It sends a
session.report on every change, on every (re)connect and at least every
15 minutes. Sign-outs it could not deliver are kept in logons.json and
sent with the next report. Remote Desktop sign-ins carry the client's
name or address. See Sign-ins.
CPU temperature
Each heartbeat carries the hottest thermal zone in °C (rounded to 0.1),
read through the Windows performance counters
(\Thermal Zone Information(*)\Temperature, the same ACPI data as WMI's
MSAcpi_ThermalZoneTemperature) with one query kept open for the agent's
lifetime, so no process starts per heartbeat. Implausible readings (0 K,
outside -40..150 °C) are dropped; without a usable sensor, common on
virtual machines, the heartbeat has no temperature and the agent tries
the counters again after an hour.
User notices
Before a reboot or shutdown (device actions and package reboot policies),
the agent shows every signed-in user a notice in the product's design: it
starts rmm-agent.exe notice --kind=<restart|shutdown> --deadline=<unix seconds> --message=<text> in each active session (SYSTEM token moved to
the session, like the remote desktop helper), right after shutdown.exe
accepted the restart. The notice counts down to the deadline, closes on
Dismiss and quits by itself 10 minutes after the deadline. A notice
that cannot be shown is logged and never fails the job. It replaces the
plain msg.exe box of earlier agents. notice is internal and not listed
in the usage text.
Remote desktop
A remote_desktop job (Remote desktop)
is handled like this:
- Consent. When the job asks for it and a user is signed in to the
console session, the service starts
rmm-agent.exe remote-consent --viewer=<technician> --mode=<mode> --timeout=60in that session (same token and desktop as the helper below). It shows the Remote support request window (Entrosity design, Decline focused, Allow, countdown) and answers with its exit code:20allowed,21declined,22timed out. Anything but20, including a crash, fails the job withremote_declined; a consent window that cannot be started at all isremote_unavailable. A locked session is declined at once (the user cannot answer).remote-consentis internal and not listed in the usage text. - Helper. The service (LocalSystem, session 0) cannot see the
desktop, so it starts
rmm-agent.exe remote-helper --mode=<mode> --viewer=<technician> --banner=<true|false>in the active console session (or the first active session) onwinsta0\default, with a copy of its own SYSTEM token moved to that session. Running as SYSTEM lets the helper follow the input desktop: the sign-in and lock screens and UAC prompts are captured and controllable. The helper talks to the service over its standard input and output (4-byte length, 1-byte kind, payload) and inherits no other handles; it logs tologs\remote-helper.login the data directory (emptied when it is over 5 MiB).remote-helperis internal and not listed in the usage text. - Stream. The service opens
wss://<server>/api/agent/v1/remote/<session_id>with its agent key and relays between the helper and the server. The job succeeds (remote session started) and the stream carries on until either side closes it; the helper is then stopped. Failures before that areremote_unavailable.
The helper is per-monitor DPI aware and captures with GDI (BitBlt of
the composed desktop, with the cursor drawn in) at up to 15 frames per second,
sending changed 64×64 tiles as JPEG. Input uses SendInput: absolute
pointer coordinates over the whole virtual desktop, keys by scan code (so
the device's keyboard layout applies) and typed text as Unicode. View-only
sessions ignore input in the helper too.
Unless the job sets hide_banner (administrators only; --banner=false),
the helper also shows the user a bar in the portal's style (logo, green
dot, 4000 the user ended the session.
Capture errors while Windows switches desktops (lock screen, UAC, Ctrl+Alt+Del)
are retried with back-off; only 15 s of continuous failure ends the session.
When the console session changes (sign-out, fast user switching, RDP taking
the console), the helper exits with code 10 and the service starts a new one
in the new session on the same stream, at most 5 times a minute; a newly
signed-in user is asked for consent again when the session required it. Any
other helper exit closes the stream with 4004.
A device has one session at a time: a new session stops the previous one.
The Ctrl+Alt+Del button calls SendSAS, which Windows allows only
when the Disable or enable software Secure Attention Sequence policy
(HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System,
SoftwareSASGeneration) is set to Services (1) or Services and Ease
of Access applications (3). Otherwise the technician sees an error;
set the policy with Group Policy where it is needed. The agent checks the
policy first and reports Ctrl+Alt+Del is blocked by policy when it is
not set.
Development builds on macOS and Linux
The agent builds and runs on macOS and Linux for development:
go run ./agent/cmd/rmm-agent run --server http://localhost:8080 --token <token>
Collectors report a stub summary and credentials are stored unencrypted in
~/.rmm-agent (override with RMM_DATA_DIR).