Running an agent
An agent polls a single region on a single platform and reports each reading to a hub. Anyone can run one (it doesn't matter where you live, an agent can run anywhere) and it's most useful to pick a region that has no coverage yet.
This page is the canonical agent setup guide (it's where a hub's contribute page links via AGENT_SETUP_URL).
Each agent needs its own token and its own Steam account
Don't share a token or a Steam account between two running agents. Each agent needs a dedicated Dead by Daylight account that owns the game.
1. Get an agent token
The token is how the hub recognises the agent and maps it to a region+platform. Get one in any of these ways:
- Admin UI (recommended). On your hub, open the admin UI, choose Add agent, and pick a region. The token is shown once, copy it then.
PROVISION_AGENTS: a compact string of<id>:<token>:<region>:<provider>entries, comma-separated, registered on boot:PROVISION_AGENTS=eu:tok-a:eu-central-1:steam,us1:tok-b:us-east-1:steam- Numbered
AGENTn_*env vars (what Docker Compose uses). SetAGENT1_TOKENandAGENT1_REGION(optionallyAGENT1_PROVIDER,AGENT1_ID,AGENT1_LABEL) and the hub provisionsagent-1from them. These are the same variables the agent container reads, so a token is declared once.
On someone else's hub, just ask the operator for a token. Generate a fresh token with openssl rand -base64 24.
TIP
Agents are upserted by a stable id, so re-deploys never duplicate and rotating a token or moving a region just updates the same agent.
2. Provide a dedicated Steam account
The agent logs into Steam to discover the live Dead by Daylight client build and read incentives, so it needs a Steam account that owns Dead by Daylight. Provide:
STEAM_USERNAMEandSTEAM_PASSWORD, andSTEAM_SHARED_SECRET, the Steam Guard shared secret (base64), for unattended two-factor login. Without it you'd have to enter a code by hand, which doesn't suit an always-on container.
Your Steam credentials stay on your machine
The agent's Steam credentials are never sent to the hub or to anyone else. They are used only by the agent process, on the machine you run it on, to log into Steam directly. They never leave that machine. The agent only ever sends the hub its readings and its refreshTime, authenticated by its agent token.
Only the steam provider is implemented
The provider decides the platform: a Steam agent reports Windows. epic (EGS) and grdk (Microsoft Store) are recognised by the hub but not implemented yet, so today every agent is a Steam agent.
3. Set the assignment variables
Tell the hub what this agent covers:
AGENTn_REGION: the region id, e.g.eu-central-1,us-east-1.AGENTn_PROVIDER=steam: the auth method, which also fixes the platform.
4. Run the agent
With Docker Compose
The shipped docker-compose.yml already includes an agent-1 service built from an x-agent anchor. Fill in the per-agent values in .env:
AGENT1_TOKEN=your-token
AGENT1_REGION=eu-central-1
AGENT1_PROVIDER=steam
AGENT1_STEAM_USERNAME=...
AGENT1_STEAM_PASSWORD=...
AGENT1_STEAM_SHARED_SECRET=...The compose service maps those into the agent container:
agent-1:
<<: *agent
container_name: bloodpoint-agent-1
environment:
<<: *agent-env
AGENT_KEY: ${AGENT1_TOKEN}
STEAM_USERNAME: ${AGENT1_STEAM_USERNAME:-}
STEAM_PASSWORD: ${AGENT1_STEAM_PASSWORD:-}
STEAM_SHARED_SECRET: ${AGENT1_STEAM_SHARED_SECRET:-}
volumes:
- agent-1-data:/app/dataThe agent's HUB_URL defaults to http://hub:3000 (the in-compose hub).
docker compose up -dTo add another agent: fill in the AGENT2_* variables in .env and uncomment the agent-2 service block (and its agent-2-data volume) in docker-compose.yml. The hub provisions it automatically.
With plain docker run
Against a remote hub:
docker run --rm -v bp-data:/app/data \
-e HUB_URL=https://hub.example.com \
-e AGENT_KEY=your-token \
-e STEAM_USERNAME=... -e STEAM_PASSWORD=... -e STEAM_SHARED_SECRET=... \
ghcr.io/buco7854/bloodpoint-incentives/agent:latestA bp-data volume (mounted at /app/data) persists the agent's small state file (its last-known-good client version).
What the agent does once running
- On start it calls
GET /api/v1/agent/assignmentwith its token and learns its region, platform, poll cadence, and a phase offset. - It always tracks the latest live client build from the Steam depot (never version-pinned) and reports each real reading to
POST /api/v1/agent/readings. - It obeys the hub-assigned cadence, with a hard 300-second floor. The hub will never have it poll faster than once every five minutes. The agent can also declare its own accepted range with
AGENT_MIN_POLL_SECONDS/AGENT_MAX_POLL_SECONDSand refuse, fatally, if the hub's cadence falls outside it. - It refuses to start if its credentials disagree with the assigned platform.
On an unrecoverable error (bad Steam credentials, a not-entitled account) the agent stops polling, logs off Steam, and its health endpoint returns 503 so the container is marked unhealthy instead of restart-looping into Steam. Transient errors back off and retry.
See Configuration for every agent variable, and How it works for the cadence and spacing model.