Agent Binaries & Updates
Athena keeps a library of agent binaries on the server and lets you decide which version each operating system runs. You upload a new agent build, mark it active for its OS, then push that version to whichever agents you choose. The server streams the signed binary to each connected agent over the same connection it already uses — no download server, no internet, and every push is written to the audit log. It is the fleet-wide "client version management" a System Center admin expects, kept entirely inside your network.
This page covers keeping already-enrolled agents up to date. For getting the agent onto a fresh host in the first place — installer one-liners, ZIP bundles, and certificates — see Agent Enrollment.
The binary library#
Each uploaded build is stored as an agent binary record. Binaries are keyed by
Os and Version, and each OS has at most one active
version at a time. Every record tracks:
| Field | Meaning |
|---|---|
id | Unique identifier (GUID). |
version | Version string, e.g. 1.2.42. Rejected if it contains path characters (.., /, \, :). |
os | Target operating system — Windows or Linux. |
fileName | Original filename of the uploaded build. |
fileHash | SHA-256 hash of the binary, computed by the server on upload. |
fileSize | Size in bytes. |
signature | Server signature over the hash (see Signing). null only for legacy builds uploaded before signing existed. |
releaseNotes | Optional free-text notes. |
isActive | true when this is the current version for its OS. |
downloadCount | How many times the binary has been served. |
uploadedBy / uploadedAt | Who uploaded the build and when. |
Uploading & signing#
You upload a build with POST api/agent-binaries as a multipart form
(file, os, version, and optional
releaseNotes). Uploads are Admin-only and capped at
500 MB. As it streams the file to disk the server:
- Computes the SHA-256 hash of the binary.
- Signs that hash with the CA private key — an RSA / SHA-256 (PKCS#1)
signature, stored Base64 in the
signaturefield. - Records the metadata and marks the new binary
isActive = truefor its OS.
Because the signature is produced by your server's own certificate authority, an agent can
verify the build it receives is genuine before applying it. Binaries are written to disk under
the folder set by AgentUpdate:BinariesPath (see Configuration).
The os value must be exactly Windows or Linux — the
binary table is matched on that casing. Anything else is rejected with 400.
The active version#
Exactly one binary per OS is the active version. A freshly uploaded build
becomes active automatically, but you can promote any earlier build with
POST api/agent-binaries/{id}/activate — that deactivates every other binary for the
same OS and flips the chosen one on. Activation is Admin-only.
The active version is what push updates and the
agent installer use when no explicit version is given.
GET api/agent-binaries/latest/{os} returns the current active binary for an OS
(404 if none has been uploaded yet), and the bootstrap installer for an OS is
blocked until at least one binary exists for it.
Pushing updates#
To move agents onto a version, push it to a chosen set of agents with
POST api/agent-updates/push (Admin-only). The body lists the
target agents and, optionally, the version and a force flag:
# Update three agents to the latest active version for their OS
POST api/agent-updates/push
{
"agentIds": ["a1…", "b2…", "c3…"],
"targetVersion": null,
"force": false
}
| Field | Meaning |
|---|---|
agentIds | Agents to update. At least one is required, or the call returns 400. |
targetVersion | Version to install. null (or omitted) means the latest active version for each agent's OS. |
force | When true, the agent applies the update even if it is already on that version. |
The server processes each agent independently:
- Looks up the agent to learn its OS and current version, then resolves the correct binary —
the named version, or the OS's latest active build when
targetVersionis null. - Writes an update-history record and sends the agent an update notification (target version, hash, size, signature, and the force flag) over its existing connection.
- Streams the signed binary to the agent over that connection — there is no separate download step for connected agents.
- Writes an audit event for the push (see the callout below).
The response summarises the batch: successCount, failedCount, a
per-agent results map, and an updateIds map linking each agent to its
history record. An agent that is not currently connected can't be reached, so
its history row is marked Failed with "Agent not connected" and it is counted as failed
— reconnect the agent (or wait for it) and push again.
Pushing an update is treated as remote code execution and is always audited — both successful and failed pushes record the agent, hostname, target version, and who initiated it. See Audit & SIEM.
Automatic updates#
Instead of pushing every release by hand, you can let the server keep agents on the active version. Open Settings → Agents → Updates. The Auto Update section has a check box, Enable auto update for agents. It saves as soon as you tick or clear it, with no restart.
While it is ticked, the server pushes the active version for each OS by itself, at two moments:
- When an agent connects. An agent that comes online or reconnects with an older version than the active one for its OS gets the update. This is how agents that were offline during a release catch up.
- When a version becomes active. Uploading a build (which makes it active), activating a build, or ticking a build's Active box pushes it to every online agent of that OS that runs an older version. Offline agents get it the next time they connect. Deactivating a build pushes nothing.
There is no timer that sweeps the fleet. Nothing is pushed between those two events.
An automatic push is the same as a manual push to the latest active version,
without force. It creates the same update-history record and the
same audit event. The user shown is System (auto-update), so you can tell automatic
pushes from manual ones in Update History and the audit log.
Which agents are updated#
- Only older agents. Versions are compared by number, so
1.2.99is older than1.2.113, and1.2.113.0counts as the same as1.2.113. Auto-update never installs an older version over a newer one, and never reinstalls the version an agent already runs. To roll agents back, activate the older build and push it by hand. - Only the active build for the agent's own OS. Windows agents get the active Windows build, Linux agents the active Linux build. If an OS has no active build, its agents are left alone.
- No back-to-back retries. If an update of an agent to that version is
still
Pending,DownloadingorInstalling, or ended without completing, the agent is skipped until the retry window has passed (see below). This includes a manual push to that version. After the window, the agent gets the update again the next time it connects or the next time a build is activated.
The retry window#
Under the check box is Retry a failed or stuck auto-update after (minutes). It takes a whole number from 5 to 1440 minutes (one day). The default is 30. The box is greyed out while auto-update is off. A change applies straight away, with no restart.
The window applies only to automatic pushes. A manual push is never blocked. To retry one agent at once, push the update to it by hand.
With auto-update on and staging off, uploading or activating a build installs it on every online agent of that OS at once. Each install restarts the agent service. Turn on staged rollout to send a new build to a canary group first, then the rest in waves. The rollout stops on its own if a wave fails too often.
How a Windows agent applies an update#
Once the binary has arrived, a Windows agent checks its SHA-256 hash and, if the binary is
signed, the server's signature before it does anything else. If a check fails, the update is reported as failed and nothing
on the machine changes. If both pass, the agent hands the install to a Windows scheduled task
called HermesUpdate. The agent can't replace its own running executable, so the task
does the swap:
- The agent registers
HermesUpdateto run as SYSTEM with highest privileges and starts it straight away. As a fallback, the task also has a trigger about two minutes later, and Run task as soon as possible after a scheduled start is missed is on. The agent also writes an Information event (ID101, sourceHermes.Agent) to the Windows Application log with the old and new versions. - The task stops the
HermesAgentservice. It keeps retrying for up to 120 seconds, then ends anyHermes.Agentprocess that is still running. - It backs up the current
Hermes.Agent.exetoupdates\backup\under the agent data directory. The two most recent backups are kept. - It copies in the new files and retries each copy up to five times. When the update is a
bundle, this also replaces the remote-screen helper (
Hermes.RemoteHelper.exe). If only the helper can't be replaced, the agent is still updated and the helper problem is logged as a warning. - It starts the
HermesAgentservice on the new version, then deletes itself.
The task has these settings so that it runs on any kind of machine:
| Task setting | Value | Why it matters |
|---|---|---|
| Start only if the computer is on AC power | Off | Laptops and tablets on battery still update. |
| Stop if the computer switches to battery power | Off | Unplugging mid-update doesn't stop the install. |
| If the task is already running | Do not start a new instance | Only one install runs at a time. |
| Stop the task if it runs longer than | 30 minutes | A stuck install can't run forever. |
What protects the endpoint#
- The old agent comes back if anything fails. The task starts the service again on the previous version whenever the update fails. For example, the service may not stop in time, the bundle may not extract, or the executable may not be replaced. A failed update never leaves the machine without an agent.
- Service recovery is paused during the swap. The
HermesAgentservice is set to restart on failure. While the files are being replaced, the task clears those recovery actions. That stops Windows from starting the old executable again partway through. The original recovery settings are put back when the task ends, whether the update succeeded or failed. - An interrupted update is picked up again, up to three times. If the agent restarts while the install task is still running, it leaves the task alone. If the task isn't running and a verified update for a different version is still waiting, the agent checks the file's hash again and schedules the install again. After three tries for the same update, it gives up and deletes the waiting files. If the agent is already on the target version, it just cleans up.
Windows agents at version 1.2.98 or earlier use an older install routine, which service
recovery could get in the way of. When you push an update to one of these agents, the server
does the pause for you. It saves the agent's HermesAgent recovery settings, sets
them to Take No Action, and then sends the update. It restores the saved settings
when the update completes, fails, rolls back or times out. The saved settings survive a
server restart. If the agent is offline when the server tries to restore them, the server
logs an error and doesn't try again. Check that machine's service recovery settings on the
Remote Services page.
Update history & status#
Every push creates an update-history record you can review per agent or
fleet-wide. Each record tracks the agent, fromVersion → toVersion,
who initiated it, timestamps, and a status:
| Status | Meaning |
|---|---|
Pending | Update recorded, not yet started. |
Downloading | Agent is receiving the new binary. |
Installing | Agent is applying the update. |
Completed | Agent is confirmed running the target version. |
Failed | The update did not complete. For example, the agent was not connected, verification failed, or the update stalled. |
RolledBack | The agent reverted to its previous version. |
The agent itself confirms completion. Every heartbeat reports the agent's running version. When
that version matches an update that is still in flight (Pending,
Downloading, or Installing), the server marks the record
Completed. Versions are compared by number, so a Windows agent that reports
1.2.98.0 matches an update to 1.2.98. Read history with
GET api/agent-updates/history (optionally filtered by agentId, default
limit 50); history reads are available to Operator or Admin.
In the console, the Update History table at the bottom of
Settings → Agents → Updates updates live. A new push shows up as
Pending, and the row moves through Downloading, Installing,
Completed or Failed without a page reload. Automatic pushes show
System (auto-update) in the Initiated By column.
Updates that never land#
Sometimes an update is still in flight 15 minutes after it was sent, while
the agent keeps sending heartbeats on a different version. The server then marks the record
Failed with a message like this:
Update not applied: agent is still running 1.2.97 15 minutes after the update to 1.2.98 was sent
A healthy update restarts the agent within a minute or two, so this means the install was lost
on the endpoint. The record doesn't stay at Installing forever. The check runs on
heartbeats, so it only applies to agents that are online.
Troubleshooting a Windows update#
If a Windows agent's update shows Failed or never changes version, check these on the endpoint:
| Where to look | What it tells you |
|---|---|
C:\ProgramData\Hermes\Logs\HermesUpdate_<yyyyMMdd_HHmmss>.log | A full transcript of each install attempt: the service stop, backup, each copy attempt, and any UPDATE FAILED: reason, such as Service did not stop in time or Could not replace Hermes.Agent.exe. |
Agent log (C:\ProgramData\Hermes\Logs\hermes-*.log) | Hash and signature verification results, and each startup's decision about a waiting update: kept, scheduled again (attempt N of 3), abandoned, or cleaned up. |
Task Scheduler → HermesUpdate | Whether the install task is waiting, running, or has finished. It is removed after a successful update. |
Event Viewer → Windows Logs → Application (source Hermes.Agent, ID 101) | When the update was handed to the install task, and which versions were involved. |
These paths assume the default agent data directory. See Windows Agent. You can also follow the agent log live from the console with Agent Logs. After you fix the cause, push the update again.
Configuration#
| Setting | Default | Purpose |
|---|---|---|
AgentUpdate:BinariesPath | <Storage:DataRoot>/AgentBinaries (/data/storage/AgentBinaries on the virtual appliance) | Where uploaded agent binaries are stored on the server. Set this only to move this one folder away from the shared storage root. See Data Directories & Backup. |
AgentUpdate:AutoUpdateEnabled | true in the shipped appsettings.json. Treated as false (off) if the key is missing. | Turns automatic updates on or off. Same as the Enable auto update for agents check box under Settings → Agents → Updates. |
AgentUpdate:AutoUpdateRetryMinutes | 30 | The retry window in minutes, from 5 to 1440. A missing or out-of-range value means 30. Same as the Retry a failed or stuck auto-update after (minutes) box. |
A manual push works whether auto-update is on or off. Both auto-update values are copied to other servers by Settings Sync along with the other agent settings. See Configuration for how to change these settings.
AutoUpdateRetryBackoffHours
An earlier setting, AgentUpdate:AutoUpdateRetryBackoffHours, has been deprecated.
If only that key is set, the server converts it to minutes (hours × 60) and writes a warning to
the server log. The next time the agent settings are saved, the server writes
AutoUpdateRetryMinutes and removes the old key.
Roles#
The permission split follows the risk of each action:
| Action | Required role |
|---|---|
| List / view binaries, view latest, read update history | Operator or Admin |
| Upload, activate, delete a binary | Admin |
| Push an update to agents | Admin |
| View the auto-update settings | The settings.view permission |
| Turn auto-update on or off, change the retry window | The settings.manage permission |
Callers without the required role receive 403; unauthenticated callers receive
401. See Roles & Permissions.
REST API#
| Method & path | Purpose |
|---|---|
GET api/agent-binaries | List binaries (optional os filter). |
GET api/agent-binaries/{id} | Get one binary's metadata. |
GET api/agent-binaries/latest/{os} | Latest active binary for an OS. |
POST api/agent-binaries | Upload a binary (multipart; server signs it). Admin. |
POST api/agent-binaries/{id}/activate | Make this binary the active version for its OS. Admin. |
DELETE api/agent-binaries/{id} | Delete a binary. Admin. |
POST api/agent-updates/push | Push an update to selected agents. Admin. |
GET api/agent-updates/history | Update history (optional agentId, limit). |
GET api/agent-updates/history/{agentId} | Update history for one agent. |
GET api/agent-updates/history/record/{id} | A single update-history record. |
GET api/settings/agent | Agent settings, including autoUpdateEnabled and autoUpdateRetryMinutes. Needs settings.view. |
PUT api/settings/agent | Save agent settings, including the two auto-update fields. Needs settings.manage. |
PUT api/settings/agent replaces the whole agent settings block. Read it with
GET, change only the fields you need, and send the whole object back. Secrets that
the GET masks are kept as they are. A retry value outside 5–1440 is rejected with
400 and the message
AutoUpdateRetryMinutes must be a whole number from 5 to 1440.
The installer-facing endpoints of api/agent-binaries (download, install-script, and
ZIP bundle) are covered under Agent Enrollment.
PowerShell#
The Athena module ships cmdlets for the whole binary-and-update lifecycle:
| Cmdlet | Purpose |
|---|---|
Get-AthenaAgentBinary | List binaries, get one by -Id, filter by -Os (Windows/Linux), or fetch the -Latest active build. Operator or Admin. |
Send-AthenaAgentBinary | Upload a build: -Path, -Os (Windows/Linux), -Version, optional -ReleaseNotes. Server signs it. Admin. |
Enable-AthenaAgentBinary | Make a binary the active version for its OS, by -Id. Admin. |
Remove-AthenaAgentBinary | Permanently delete a binary by -Id. Admin. |
Send-AthenaAgentUpdate | Push an update: -AgentId (accepts the pipeline), optional -TargetVersion and -Force. Aliased Push-AthenaAgentUpdate. Admin. |
Get-AthenaAgentUpdateHistory | Read update history, optionally for one -AgentId, with -Limit (1–500, default 50). Operator or Admin. |
Get-AthenaAgentUpdateSetting | Show the auto-update settings: AutoUpdateEnabled and RetryMinutes. |
Set-AthenaAgentUpdateSetting | Change -AutoUpdateEnabled ($true/$false) and/or -RetryMinutes (5–1440). Changes only the values you pass and leaves the other agent settings as they are. Supports -WhatIf. Needs settings.manage. -RetryMinutes needs module 2.12.1 or later. |
# Publish a new Windows build and make it the active version
$bin = Send-AthenaAgentBinary -Path "C:\Build\Hermes.Agent.exe" -Os Windows -Version "1.2.42" -ReleaseNotes "Bug fixes"
Enable-AthenaAgentBinary -Id $bin.Id
# Roll it out to every online agent, then review the results
Get-AthenaAgent -Online | Send-AthenaAgentUpdate
Get-AthenaAgentUpdateHistory -Limit 20
# Let the server keep agents current, retrying a stuck update after an hour
Set-AthenaAgentUpdateSetting -AutoUpdateEnabled $true -RetryMinutes 60
Get-AthenaAgentUpdateSetting
See the PowerShell Module reference for full cmdlet details.
Agent versioning never reaches out to the internet. You bring a new build onto the isolated network, upload it to your server, and the server streams it straight to your agents over the connections they already hold. The whole update path stays inside your perimeter. See Air-Gapped Operation.