Worker Types
Dispatch has two worker types. The coordinator routes jobs based on each worker's declared capabilities.
Overview
| Property | Desktop Worker | Seeker Worker |
|---|---|---|
| Provider type | DESKTOP | SEEKER |
| Capabilities | LLM_INFER, TASK | TASK only |
| LLM inference | Yes (via Ollama) | No |
| Task execution | summarize, classify, extract_json | summarize, classify, extract_json |
| Intended device | Servers, desktops | Mobile phones, lightweight devices |
| Key storage | ./data/worker-key.json | ./data/seeker-key.json |
Desktop Worker
The desktop worker is the full-capability node. It runs LLM inference through a local Ollama instance and handles lightweight TASK jobs.
Registration
On startup, the desktop worker:
- Loads or generates an ed25519 keypair
- Connects to the coordinator via WebSocket
- Sends a
registermessage declaring its capabilities
const msg: RegisterMsg = {
type: "register",
provider_pubkey: keys.pubkeyHex,
provider_type: "DESKTOP",
capabilities: [JobType.LLM_INFER, JobType.TASK],
};- Waits for a
register_ackwith aworker_id - Starts sending heartbeats every 10 seconds
- Optionally claims a trust pairing code if
TRUST_PAIRING_CODEis set
Job execution
When the coordinator assigns a job:
- LLM_INFER: calls the local Ollama API with the prompt and max_tokens
- TASK: runs built-in logic for the specified task_type
After execution, the worker builds a receipt (SHA-256 hash of output, ed25519 signature) and sends job_complete with the output and receipt bundled together.
Seeker Worker
The seeker is a lightweight worker designed for mobile devices. It handles only TASK jobs — no LLM inference.
Registration
const regMsg: RegisterMsg = {
type: "register",
provider_pubkey: keys.pubkeyHex,
provider_type: "SEEKER",
capabilities: [JobType.TASK], // TASK only
};Supported tasks
All seekers can execute these task types:
summarize
Truncates input to 200 characters and returns a word count:
{ "summary": "Truncated text...", "word_count": 42 }classify
Performs basic sentiment analysis using keyword matching:
{ "sentiment": "positive", "confidence": 0.5 }extract_json
Extracts and parses JSON objects from free text:
{ "extracted": [{ "key": "value" }], "count": 1 }Provider Type Enum
The ProviderType enum defines the two worker types:
enum ProviderType {
DESKTOP = "DESKTOP",
SEEKER = "SEEKER",
}Sent in the register message and stored by the coordinator to track each worker's role.
How the coordinator routes jobs
When a job arrives, the coordinator's claimWorker() function finds an available worker that:
- Has the required capability (e.g.,
LLM_INFERorTASK) - Is currently online (WebSocket connected, recent heartbeat)
- Is not busy with another job
- For PRIVATE jobs: is trust-paired with the submitting user
The coordinator does not prefer desktop over seeker for TASK jobs — any worker with the capability can be assigned.
Running multiple workers
You can run multiple workers on the same machine by using different key file paths:
# Worker 1 (default path)
COORDINATOR_URL=http://localhost:4010 pnpm --filter worker-desktop start
# Worker 2 (custom key path)
COORDINATOR_URL=http://localhost:4010 \
WORKER_KEY_PATH=./data/worker-key-2.json \
pnpm --filter worker-desktop startEach worker gets its own ed25519 keypair and registers independently with the coordinator.