Endpoint Enrollment Guide
Bring every employee’s and guest’s AI usage under governance — with the lightest touch that meets your policy. Dream big, build fast.
Audience: the customer’s IT / network / security team. This guide explains how devices reach AgentWatch, how they enroll, how they’re attributed to a person, and the three deployment models — with an honest split of what AgentWatch provides vs what you configure on your network.
1. The two things to keep separate
Section titled “1. The two things to keep separate”| Axis | What it means | How AgentWatch does it |
|---|---|---|
| Access | letting a device onto the network / to the internet | gated on enrollment (the device trusts our CA so traffic can be governed), released by your NAC/gateway |
| Attribution | knowing which person the traffic belongs to | a separate signal: Connect client X-Zscaler-User, a LAN‑IP→user map, the observed LLM‑account email, or a portal‑verified email |
Content inspection (DLP/redaction) is a third, optional layer — it needs the CA installed on the endpoint. You can run visibility-only (destinations + volume, no content) with zero content inspection.
2. Enrollment portal (what AgentWatch ships)
Section titled “2. Enrollment portal (what AgentWatch ships)”A tenant‑branded captive/enrollment portal at https://<gateway>/portal:
- Identity modes (per tenant):
sso(your IdP),otp(emailed one‑time code — proves mailbox control),domain(allow‑listed email, no code),none(any input, monitoring‑only). Configure under Admin → Enrollment Portal (/portal-admin.html). - Multi‑domain
allowedDomains(e.g.example.com example2.com) — employees + contractors, no pre‑known email list required. - Per‑OS: macOS/Windows/Linux → Connect client or profile; iOS/Android → profile only.
- Enrolled devices skip the portal. Branding (logo/colors/copy) is tenant‑configurable.
Access is gated on enrollment, not the email — so a name/OTP/SSO is about attribution strength, not letting them online.
3. How a device reaches the portal on join — the three models
Section titled “3. How a device reaches the portal on join — the three models”Model B — DNS trigger (lightest; one setting) ✅ turnkey
Section titled “Model B — DNS trigger (lightest; one setting) ✅ turnkey”Point your DHCP/router DNS at the AgentWatch resolver and enable captive steering:
AGENTWATCH_DNS_CAPTIVE=1 # folds the OS captive-probe hosts into the steer setThe resolver answers the OS probe hosts (captive.apple.com, connectivitycheck.gstatic.com, www.msftconnecttest.com, …) with the gateway IP; the gateway 302s the probe path (/generate_204, /hotspot-detect.html, /connecttest.txt) to /portal, so the device auto-pops “Sign in to network.”
- Hosted resolver:
https://dns.interplay.iterate.ai/dns-query(DoH) — or run thedns-servercontainer on‑prem. - What you configure: one DNS setting (DHCP option 6). Also push a Chrome/Edge Secure DNS off policy so browsers don’t bypass system DNS.
- Limit: DNS nudges enrollment; it cannot hard‑block un‑enrolled devices. Use for monitoring‑first rollouts.
Model A — Captive portal via your Wi‑Fi/NAC (block‑until‑enrolled) — integration
Section titled “Model A — Captive portal via your Wi‑Fi/NAC (block‑until‑enrolled) — integration”Your controller (Meraki / Aruba / UniFi / Cisco ISE / ClearPass / pfSense) runs the walled garden and points its external captive portal at https://<gateway>/portal. On enrollment the portal calls your controller back to admit the device.
- What AgentWatch provides: the portal + an admit webhook (
admitWebhookUrl, HMAC‑signed, CoA‑shaped) — see §5. - What you configure: the SSID’s external‑portal URL, the walled‑garden allowlist (AgentWatch host + your IdP), and the admit callback (RADIUS CoA or the controller’s API).
Model C — Inline gateway (full control) — deployment topology
Section titled “Model C — Inline gateway (full control) — deployment topology”Route AI traffic through an AgentWatch gateway container. You do NOT change your L3 default gateway — AgentWatch is an application‑layer proxy, not a router. See §6.
4. Managed employees vs. guests / BYOD
Section titled “4. Managed employees vs. guests / BYOD”| Managed employee device | Guest / BYOD | |
|---|---|---|
| Method | Connect thick client via MDM (Jamf/Intune/JumpCloud) | mobileconfig (CA + DoH) — light consent |
| Consent | the MDM’s (silent to user) | user approves a profile (a few taps) |
| API key | the employee’s own key, issued at enrollment (org enrollment token in the MDM profile) | none needed — org by gateway egress IP |
| Identity | MDM per‑user email, else the signed‑in OS user + your email domain, or a sign‑in approval (§7e) | OTP‑verified portal email + observed LLM‑account email |
| Removable by user? | No (MDM‑locked) | Yes (their device — you cannot lock a personal device) |
| Off‑network coverage | yes, by design | only while the profile persists (they can remove it) |
Guidance: default guests to mobileconfig (keyless, removable, network‑scoped). Reserve the Connect thick client for managed devices. If a guest opts into Connect, the portal issues a per‑device, revocable key after OTP — never the shared org key.
5. Admit webhook (Model A) — sample payload + NAC recipes
Section titled “5. Admit webhook (Model A) — sample payload + NAC recipes”On enrollment, AgentWatch POSTs to your configured admitWebhookUrl:
POST https://your-nac-bridge.example/agentwatch/admitContent-Type: application/jsonX-AgentWatch-Signature: sha256=<hmac-sha256(body, admitWebhookSecret)>
{ "event": "device.admit", "org": "example", "deviceKey": "<hash>", "framedIp": "10.20.30.40", "action": "coa-reauthorize", "at": 1699999999999 }Verify the HMAC, then move the device to “authorized.” Sample bridge → RADIUS CoA (FreeRADIUS radclient):
# /agentwatch/admit receiver (pseudo): verify HMAC, then:echo "Framed-IP-Address=$framedIp,Acct-Session-Id=$sid" \ | radclient -x <nas-ip>:3799 coa "$COA_SECRET"Controller API alternatives: Meraki POST /networks/{id}/clients/{mac}/policy (allowed); Aruba ClearPass POST /api/session/{id}/disconnect + re‑auth; UniFi cmd/stamgr authorize-guest; Cisco ISE CoA via pxGrid. Set admitWebhookUrl + admitWebhookSecret in Admin → Enrollment Portal.
6. Inline gateway (Model C) — Docker, with/without HAProxy
Section titled “6. Inline gateway (Model C) — Docker, with/without HAProxy”You keep your existing router/default gateway. AI traffic is steered to AgentWatch (via DNS §3‑B, a PAC/system‑proxy, or the Connect client); AgentWatch inspects and forwards to the real AI service (transparent relay — it never blackholes, and non‑AI traffic isn’t sent to it at all). “Inline” = in the HTTP path, not the L3 path.
- With an HAProxy frontend (recommended): HAProxy terminates TLS on
:443and routes by SNI to the AgentWatch container. Ships asdns-server/haproxy-mitm.cfg.example. Good for SNI‑passthrough (metadata only, no CA) and full MITM (with CA). - Without HAProxy: the AgentWatch container listens on
:443directly (single‑host). Simpler; fewer moving parts. - What happens to their existing gateway: unchanged — it remains the L3 default route. AgentWatch is upstream of the AI destinations only, and egresses to those destinations itself. Metadata‑only mode needs no CA; content inspection needs the CA (MDM/portal).
# minimal inline (no HAProxy): AgentWatch on 443. Steered AI traffic is relayed# to the real upstream automatically (transparent relay); non-AI traffic is never# routed here. Content inspection turns on once the CA is trusted on endpoints.services: agentwatch: image: iterateai/agentwatch:latest ports: ["443:8787"]7. Bulk MDM rollout — zero‑touch for the whole fleet
Section titled “7. Bulk MDM rollout — zero‑touch for the whole fleet”Two artifacts, from two different admin pages, both pushed via your MDM (JumpCloud / Intune / Jamf). Employees never configure anything and never see a prompt.
| Artifact | Downloaded from | Purpose |
|---|---|---|
.mobileconfig (root CA + DoH) |
Admin → DNS Redirector → Download .mobileconfig | Trusts the AgentWatch root CA and points device DNS at your resolver. Governs browser AI traffic; enables content inspection on the steered AI domains. This is the only artifact iOS/Android need. |
Connect installer (.dmg / .msi / .bin) |
Admin → Agent Fleet → Download | The thick MITM client for macOS / Windows / Linux desktops — full traffic capture beyond the browser. |
7a. Order of operations
Section titled “7a. Order of operations”-
Push the
.mobileconfigFIRST — to ALL devices.Admin → DNS Redirector → Download .mobileconfig. It carries the root CA + DoH/DNS steering (the server domain is taken from your browser’s address bar). Pushing it first means CA trust + DNS steering are already in place when the thick client lands — and it alone brings browser AI traffic under governance everywhere, including mobile. -
Then download the per‑OS Connect installer from Agent Fleet and push per‑OS to the matching desktop groups —
.dmg→ macOS,.msi→ Windows,.bin/.deb→ Linux. One installer per OS group. -
The thick client auto‑configures on install. It reads its MDM‑pushed managed config from the OS policy store your MDM writes — the same keys on every OS:
OS Where Connect reads it Who can write it macOS managed‑preferences payload ai.iterate.agentwatch-connect→/Library/Managed Preferences/ai.iterate.agentwatch-connect.plistthe MDM only Windows HKLM\SOFTWARE\Policies\AgentWatch\Connect(REG_SZ values)administrators / SYSTEM Linux /etc/agentwatch/connect.jsonroot — the file is ignored unless it is owned by root and not group/world‑writable Key Value ServerURLyour AgentWatch address, e.g. https://agentwatch.acme.comEnrollmentTokenAgent Fleet → Agent Connect Settings → Enrollment Token (log in as the tenant’s admin) Emailthe MDM’s per‑user variable (Intune {{mail}}/ Jamf$EMAIL) — optional, see §7eEmailDomainoptional: acme.com, used whenEmailis not availableWith the managed config present + the CA already trusted (step 1), the client auto‑enables interception on install — silent, installed as a login/service agent, no reboot (it starts on install or next login), no “unknown author” prompt. Older devices configured under
HKLM\SOFTWARE\Policies\Iterate\AgentWatchConnector/etc/agentwatch-connect/managed.jsonkeep working; new rollouts should use the paths above.
7b. iOS / Android (no thick client)
Section titled “7b. iOS / Android (no thick client)”Phones/tablets can’t run the Connect app — for them the DNS Redirector
.mobileconfig alone (or the Android managed‑config equivalent) is enough. It
steers DNS + trusts the CA, so you get browser AI traffic governed
(domain/URL metadata; content for the AI domains steered to the gateway). Native
apps on mobile aren’t intercepted — expected for the profile‑only path.
7c. What the Connect tray shows: managed vs. manual
Section titled “7c. What the Connect tray shows: managed vs. manual”- Installed via MDM (managed): the tray is locked to a minimal view — Requests Proxied, Uptime, the version number, and “🔒 Managed by your organization.” The Edit button, Server / User / Hosts Redirect rows, Show details, Enable Interception, and Check for Updates are all hidden — the config is enforced by your MDM and interception auto‑starts.
- Installed manually (an employee ran the installer themselves): the tray shows the full interactive view — Edit config, Enable/Disable interception, Show details, Check for Updates — exactly as today.
7d. Rotating the fleet key (e.g. suspected compromise)
Section titled “7d. Rotating the fleet key (e.g. suspected compromise)”The apiKey lives in the thick client’s MDM managed config (§7a step 3), not
in the .mobileconfig. To rotate: renew the org gateway key in AgentWatch
(Admin → API Key Management → renew, which invalidates the old key) → update
the apiKey value in your MDM’s managed‑config payload → re‑push it. The policy
store updates silently and the client picks up the new key on its next config
read — no employee action. (For a smaller blast radius, issue per‑device keys so a
compromise is one device, not the fleet.)
7e. How each computer is tied to ONE employee
Section titled “7e. How each computer is tied to ONE employee”The enrollment token is the same for the whole organization — it proves a computer belongs to your tenant, not which person uses it. Connect works out the person in this order, identically on macOS, Windows and Linux:
Emailfrom the MDM, when the MDM substituted a real address. A value still reading$EMAILor{{mail}}is ignored, never sent.- The signed‑in user’s directory identity — on a domain‑ or Entra‑joined
Windows PC, the user’s UPN (
jdoe@acme.com). <login name>@<EmailDomain>— only if you setEmailDomain. Connect never guesses a domain.- A sign‑in approval when none of the above gives a provisioned employee, or when your organization requires it (below).
In every case the email must belong to an employee who already exists in AgentWatch (SCIM, CSV import or Employee Management → Add); an unknown email is refused and the computer falls back to step 4. The computer always receives that employee’s own key, so everything it sends is attributed to them.
Sign‑in approval. The computer shows a short code (KQ7M‑3XTP) in the Connect
tray and opens a page in the default browser. The employee signs in with your
normal sign‑in — SSO, LDAP or password, whatever your workspace uses — checks that
the code and computer name match, and clicks Approve. The computer is enrolled
as whoever signed in, so the identity no longer depends on anything the
computer says about itself. If the approval page is opened from a different
network than the computer, the employee must type the code rather than click
a link, so a forwarded link cannot enroll someone else’s machine. On a Linux
server with no display, the link and code are printed in the log (or run
agentwatch-connect enroll --server <url> --token <token> in a terminal) and can
be approved from any device.
Require it for everyone: Agent Fleet → Agent Connect Settings → Require
sign‑in to approve each computer. With it on, the token plus a self‑reported
email is no longer accepted — every computer is approved by a sign‑in, once. It
is off by default, so turning it on is a decision rather than an upgrade
surprise. Existing enrolled computers are unaffected. Every enrollment, by either
path, is recorded in Settings → Audit Logs as agent.device_enrolled (and
agent.device_enroll_denied when someone clicks This wasn’t me).
JumpCloud, per OS:
| OS | How to push the managed config |
|---|---|
| macOS | Device Management → MDM → Custom Configuration Profile: upload the .mobileconfig from DNS Redirector → Download .mobileconfig (it already carries ServerURL + EnrollmentToken), or your own profile with payload type ai.iterate.agentwatch-connect. |
| Windows | Policy Management → Windows → Custom Registry Keys: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\AgentWatch\Connect, String values ServerURL, EnrollmentToken, and EmailDomain (or Email). |
| Linux | Commands (runs as root): write /etc/agentwatch/connect.json with {"ServerURL": "…", "EnrollmentToken": "…", "EmailDomain": "acme.com"}, then chmod 644 it. |
Whether JumpCloud substitutes a per‑user variable into a custom profile or a
registry value depends on your JumpCloud configuration — verify on one device. If
it does not, leave Email out: with EmailDomain set, Connect uses the signed‑in
user’s login name, and anything that does not match an employee goes to sign‑in
approval.
| Symptom | Cause | Fix |
|---|---|---|
| Tray says Not Configured | no managed config at the path above, or (Linux) the file is not root‑owned | check the path for your OS; sudo chown root:root /etc/agentwatch/connect.json && sudo chmod 644 … |
| Tray says Waiting for approval | Connect needs a sign‑in (no usable email, the email is not an employee, or sign‑in is required) | the employee signs in on the page that opened; Open sign‑in page in the tray reopens it |
| Approval page: set up for a different organization | the computer’s token belongs to another tenant than the signed‑in account | push the token of the employee’s own tenant |
| Approval page: no AgentWatch gateway access | the signed‑in account is not an employee (e.g. an admin login with no gateway key) | add them in Employee Management |
identity_not_provisioned in the Connect log |
the email is not an employee | provision them, or let sign‑in approval resolve it |
8. What content you can and can’t see
Section titled “8. What content you can and can’t see”- Without the CA (visibility‑only): destinations (which AI service, via DNS/SNI), volume, timing — per‑person once an identity signal is attached. No prompt/response content.
- With the CA (content governance): full prompts/responses, DLP redaction/blocking, per‑message audit.
Run visibility‑first, then enable content inspection (DLP) when ready — all per‑tenant policy, flipped without redeploy.
© Iterate.ai · AgentWatch · Dream big, build fast.