Skip to content

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). Set AGENT1_TOKEN and AGENT1_REGION (optionally AGENT1_PROVIDER, AGENT1_ID, AGENT1_LABEL) and the hub provisions agent-1 from 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_USERNAME and STEAM_PASSWORD, and
  • STEAM_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:

bash
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:

yaml
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/data

The agent's HUB_URL defaults to http://hub:3000 (the in-compose hub).

bash
docker compose up -d

To 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:

bash
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:latest

A 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/assignment with 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_SECONDS and 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.