Customer agent setup
Deploy and operate a Signal Diff agent on your infrastructure for crawls that cloud workers cannot reach. No repository clone or .NET SDK required.
On this page
When to use a customer agent vs cloud crawl
| Cloud crawl (default) | Customer agent |
|---|---|
| Public sitemaps reachable from the internet | Internal, staging, VPN-only, or firewall-restricted targets |
| No extra infrastructure | Worker on a VM, build agent, or container in your network |
| Fastest path for CI on public URLs | CI or schedules that must hit URLs only visible from your network |
Cloud crawls run on Signal Diff infrastructure. A customer agent pulls work from the API, runs checks locally, and reports results over HTTPS.
Prerequisites
- Paid API access — Create an API key on Developers → API keys (for CI triggers and schedules).
- Outbound HTTPS — The agent host must reach your API origin (e.g.
https://signaldiff.dev) on port 443 for enroll, heartbeat, claim, and report endpoints. - Agent routing enabled — The API must have configuration
Features:EnableAgentRoutingset totrue. On signaldiff.dev this is enabled; self-hosted API operators must set it in app settings or environment variables. - No repository access — Install from published downloads or hosted install scripts.
Setup: enroll → install → configure → verify
1. Enroll in the UI
- Open Customer agents and sign in (requires an active paid API key).
- Under Agent management, optionally set Agent ID, name, and pool.
- Click Enroll agent. Copy the one-time credential from the install commands. Re-enrolling the same agent ID rotates the previous credential.
2. Install and configure
After enrollment, use the Windows, Linux, or Docker tab on Customer agents:
- Install — Downloads
/install/agent.ps1or/install/agent.sh. - Configure — Downloads the release zip, verifies SHA256, extracts, and writes
appsettings.json. - Start — Runs the agent in the foreground (use a service for production; see below).
Default foreground paths: Windows %LOCALAPPDATA%\SignalDiff\Agent;
Linux ~/.local/share/signaldiff/agent.
Docker image: ghcr.io/funkysi1701/signaldiff-agent with SignalDiffAgent__* environment variables.
3. Verify heartbeat
- Start the agent (foreground, service, or container).
- On Customer agents, click Send test heartbeat.
- Confirm the agent row shows a recent Last heartbeat and a semver under Version (see Version tracking).
Agent pools and CI
Pools route jobs to specific agents. Use the same agentPoolId on the enrolled agent and on the crawl (schedule, dashboard, or CI).
An empty pool on both sides uses the default pool.
curl -X POST https://signaldiff.dev/api/trigger/ci \
-H "x-ci-api-key: sck_<your-key>" \
-H "Content-Type: application/json" \
-d '{"sitemapUrl":"https://internal.example/sitemap.xml","failMode":"never","executionMode":"agent","agentPoolId":"production"}'
In Schedules, choose Customer agent as execution mode.
See the Schedules guide for pool alignment.
For GitHub Actions, set execution_mode: agent and agent_pool_id on
signal-diff-action
(CI key examples on API keys; agent routing on Customer agents).
Run as a service
Re-run the install script with elevated privileges:
- Windows (Administrator):
-InstallService— servicesignaldiff-agent, default%ProgramData%\SignalDiff\Agent - Linux (
sudo):--install-service— systemdsignaldiff-agent, default/opt/signaldiff/agent - macOS (v1): foreground or
nohupuntil launchd support is added
Credential rotation
- On Customer agents, enroll again with the same Agent ID.
- Update
appsettings.json, environment variables, or container secrets on every host. - Restart the agent process or service.
Version tracking
Each agent reports its build version on heartbeat (User-Agent: SignalDiff.Agent/<version>).
On Customer agents, the Version column shows the reported semver and a badge:
| Badge | Meaning |
|---|---|
| Up to date | Matches the latest release on downloads/agent |
| Update available | A newer release is published—open Deploy for pinned upgrade commands |
| Unknown | No version reported yet (agent offline or pre-version build) |
When updates are pending, the fleet summary shows Need update and a Latest agent release link.
Download pages list each zip with an approximate file size and a .sha256 sidecar.
Upgrades
When Update available appears, click Deploy on the agent row.
An Update available banner shows copy-paste commands pinned to the latest release
(-UpdateOnly / --update-only, optional version flag). Your credential and appsettings.json are preserved.
- Check downloads/agent or
index.jsonfor the latest release. - From Deploy wizard: use the pinned update snippet when the banner is shown (recommended).
- Manual script: re-run the install script with
-UpdateOnly/--update-onlyand-RestartService/--restart-servicefor service installs. - Manual binary: stop the agent, replace binaries, keep
appsettings.json, restart. - Docker:
docker pullwith an explicit version tag and recreate the container.
Troubleshooting
| Symptom | What to check |
|---|---|
| Heartbeat fails (401/403) | Credential expired or rotated—re-enroll and update config. Verify ApiBaseUrl. |
| Heartbeat OK, no crawls | Job executionMode must be agent. API Features:EnableAgentRouting must be true. Job tenant must match the agent owner. |
| Jobs stay Pending | Agent not running, outbound HTTPS blocked, or pool mismatch. |
| UI shows Running, agent idle | Stuck run without report; agent only claims Pending jobs. Wait for stale reconciliation or clear the job. |
| 429 Too Many Requests | Too many agents or aggressive polling; avoid duplicate processes with the same agent ID. |
| Version shows Unknown | Agent not heartbeating or on an old build. Start the agent and wait for the next heartbeat. |
| Firewall | Allow outbound HTTPS to the API host; no inbound ports on the agent. |
More scenarios (stuck Running, report chunk limits, CI pool alignment): Troubleshooting — customer agents.