Skip to content

Deployment

Deploying Agent

Per-platform, exhaustively — this is where trials die.

Every path below includes silent-install flags, a verification command, uninstall, and log locations. If a path you need is missing, that is a documentation bug and we want to hear about it.

Windows

MSI with a transform

cmd
msiexec /i agent-1.8.2-x64.msi TRANSFORMS=site.mst ^
  ENROLL_TOKEN=<token> DEVICE_GROUP="Standard Laptops" ^
  /qn /norestart /l*v C:\Windows\Temp\agent-install.log
PropertyPurposeRequired
ENROLL_TOKENSingle-use enrollment token from EnrollmentYes
DEVICE_GROUPInitial Fleet group. Determines which Guardrail policy applies.No
TENANTOnly needed for multi-tenant MSP deploymentsNo
PROXYExplicit egress proxy, e.g. http://proxy:3128No

Intune / Autopilot

  1. 01Wrap the MSI with IntuneWinAppUtil. Install command as above; uninstall command msiexec /x {PRODUCT-GUID} /qn.
  2. 02Detection rule: file %ProgramFiles%\\Koop\\agent.exe, version greater than or equal to 1.8.2.
  3. 03Assign to a device group, not a user group. Agent is a machine-scoped service.
  4. 04Set Device restart behaviour to No specific action. Agent never requires a reboot to install.

GPO

Computer Configuration → Policies → Software Settings → Software Installation. Assign, do not publish. Place the MSI on a UNC path readable by Domain Computers, and pass the token via a transform rather than a startup script — a token in a script is a token in SYSVOL.

RMM script deployment

ConnectWise Automate / NinjaOne / Kaseya — PowerShell
$token = "<token>"
$url   = "https://dl.getkoop.ai/agent/1.8.2/agent-1.8.2-x64.msi"
$msi   = "$env:TEMP\agent.msi"

Invoke-WebRequest -Uri $url -OutFile $msi -UseBasicParsing

# Verify the Authenticode signature before installing. Do this even though
# you trust the URL — especially in an RMM, where the script is the
# highest-value target on the machine.
$sig = Get-AuthenticodeSignature $msi
if ($sig.Status -ne 'Valid' -or
    $sig.SignerCertificate.Subject -notlike '*Koop Systems*') {
  throw "Signature check failed: $($sig.Status)"
}

Start-Process msiexec -ArgumentList @(
  "/i", "`"$msi`"", "ENROLL_TOKEN=$token", "/qn", "/norestart"
) -Wait -NoNewWindow

& "$env:ProgramFiles\Koop\agent.exe" status

winget

winget install Koop.Agent --silent \
  --override "ENROLL_TOKEN=<token> /qn"

Verify, uninstall, logs

# verify
& "$env:ProgramFiles\Koop\agent.exe" status
Get-Service AgentAgent

# uninstall
msiexec /x {A7F2C104-9E31-4B8D-95CE-0D2B7A1F6E44} /qn

# logs
%ProgramData%\Koop\logs\agent.log
%ProgramData%\Koop\logs\actions\

macOS

The PKG is signed with a Developer ID and notarised. Verify before deploying at scale:

spctl -a -vvv -t install Agent-1.8.2.pkg
pkgutil --check-signature Agent-1.8.2.pkg
READ THIS
Deploy the TCC/PPPC profile before the package. An unapproved consent prompt appearing on 500 Macs at once is a support catastrophe, and there is no way to suppress it after the fact.

The PPPC profile

Copy-paste this payload into Jamf (Configuration Profiles → Privacy Preferences Policy Control), Kandji or Mosyle. The designated requirement is fixed; do not retype it.

PPPC payload — XML
<key>Services</key>
<dict>
  <key>SystemPolicyAllFiles</key>
  <array>
    <dict>
      <key>Identifier</key>
      <string>io.koop.agent</string>
      <key>IdentifierType</key>
      <string>bundleID</string>
      <key>CodeRequirement</key>
      <string>identifier "io.koop.agent" and anchor apple generic
        and certificate leaf[subject.OU] = "K3STR3LSYS"</string>
      <key>Authorization</key>
      <string>Allow</string>
    </dict>
  </array>
</dict>

Agent requires SystemPolicyAllFiles to read diagnostic metadata across the filesystem. It does not request ScreenCapture, Camera, Microphone, Accessibility or ListenEvent, and the notarised bundle contains no such entitlement — which you can verify yourself with codesign -d --entitlements.

Jamf, Kandji, Mosyle

  1. 01Upload the PPPC profile and scope it to the target smart group. Confirm it lands before proceeding.
  2. 02Upload the signed PKG as a package.
  3. 03Create a policy with a script payload that writes the enrollment token to /var/tmp/koop-enroll and then installs.
  4. 04Scope to the same smart group. Set the trigger to enrollment complete plus recurring check-in.
verify / uninstall / logs
# verify
/usr/local/bin/agent status
launchctl print system/io.koop.agent

# uninstall
sudo /usr/local/bin/agent uninstall --purge

# logs
/Library/Logs/Koop/agent.log
log show --predicate 'subsystem == "io.koop.agent"' --last 1h

Linux

Debian / Ubuntu
curl -fsSL https://dl.getkoop.ai/apt/koop.gpg \
  | sudo tee /usr/share/keyrings/koop.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/koop.gpg] \
  https://dl.getkoop.ai/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/koop.list
sudo apt update && sudo apt install agent
sudo agent enroll --token <token> --group "Servers"
RHEL / Rocky / Alma
sudo rpm --import https://dl.getkoop.ai/yum/koop.asc
sudo tee /etc/yum.repos.d/koop.repo <<'EOF'
[koop]
name=Koop
baseurl=https://dl.getkoop.ai/yum/stable
gpgcheck=1
gpgkey=https://dl.getkoop.ai/yum/koop.asc
EOF
sudo dnf install agent
sudo agent enroll --token <token>
Ansible
- hosts: endpoints
  become: true
  roles:
    - role: koop.agent
      vars:
        agent_enroll_token: "{{ vault_koop_token }}"
        agent_device_group: "Servers"
        agent_version: "1.8.2"
verify / uninstall / logs
# verify
systemctl status agent
agent status

# uninstall
sudo apt remove --purge agent     # or: sudo dnf remove agent

# logs
journalctl -u agent -f
/var/log/koop/agent.log

Network egress

Agent makes outbound connections only. It opens no listening port on any platform.

DestinationPortPurpose
ingest.getkoop.ai443 (gRPC/mTLS)Telemetry, action dispatch, results
standdown.getkoop.ai443Halt — deliberately separate infrastructure from ingest
dl.getkoop.ai443Agent and Playbook bundle downloads
ocsp.getkoop.ai80Certificate revocation checking
KNOWN LIMITATION
TLS-inspecting proxies break the mTLS channel — the agent pins our intermediate and will refuse an intercepted connection rather than fall back. Add the four hostnames above to your inspection bypass list. This is intentional and we will not add a flag to disable pinning.