Remote Runners
Remote Runners let EvalGate dispatch prompts, scorers, tools, workflows, and agent entrypoints into infrastructure that you control. The control plane retains job identity, policy, retry, and evidence authority; the worker receives one signed, immutable execution envelope at a time. Open Remote Runners at/remote-runners to register workers, inspect capacity and heartbeats, drain or revoke identities, monitor jobs, request cancellation, and review each job’s claims, state transitions, stream custody, terminal completion, and reconciliation decisions.
A remote job binds an exact release artifact ID, version ID, SHA-256 content hash, and canonical
dev, staging, or prod environment. A runner cannot substitute another version, change the environment, or resolve “latest.”Permissions
Runner endpoints do not accept a user session or ordinary API key as worker authority. The worker first exchanges its one-time bootstrap secret for a credential that expires within ten minutes and is bound to one organization and runner identity.
Security and identity model
Each registered runner has:- A stable organization-scoped
runnerKey - A declared protocol version and content-hashed capability document
- A maximum concurrent-job count enforced in the database
- A one-time bootstrap token stored only as a SHA-256 hash
- Short-lived, revocable worker credentials with least-privilege scopes
- A derived HMAC-SHA256 job-signing key and visible key ID
- Heartbeat, capacity, last-contact, drain, loss, and revocation state
Register a runner
- Open
/remote-runnersand choose Register runner. - Enter a display name and stable runner key.
- Declare immutable runtime identifiers, such as
nodejs20orpython3.12. - Select the supported execution kinds.
- Set the maximum concurrent-job capacity.
- Review the default-deny isolation boundary and choose Register identity.
- Copy the displayed environment variables and worker start command into your deployment secret and workload configuration.
deny_all, streaming and cancellation support, one-hour CPU, 64 GiB memory, 24-hour wall time, and a 100 MiB output ceiling. The API accepts a narrower capability document when the worker has smaller limits or a reviewed HTTPS origin allowlist.
Capability negotiation
Before a claim is created, the control plane compares every job requirement with the runner declaration:
An incompatible runner simply does not receive the job. EvalGate does not silently relax a resource or network requirement to make a claim succeed.
Start a TypeScript worker
The TypeScript SDK verifies the organization binding, key ID, validity window, canonical payload hash, HMAC signature, claim identity, and nonce before returning an assignment to application code.Start a Python worker
The Python SDK implements the same canonical hashing, signing verification, replay protection, credential refresh, and endpoint contract.Enqueue an immutable job
UsePOST /api/remote-runners/jobs with a runs:write API key or authenticated session. The request contains:
- A stable idempotency key
- Subject kind, artifact ID, exact version ID, and
dev,staging, orprodenvironment - A JSON input snapshot
- Execution kind, runtime, resource limits, network policy, and streaming/cancellation requirements
Signed claim lifecycle
cancelRequested and the human cancellation rationale so the worker can stop at a safe boundary.
Stream logs and trajectories
Eachlog or trajectory chunk includes:
- Job, claim, and dispatch-attempt identity
- A zero-based contiguous sequence
- The prior chunk checksum, or
nullfor sequence zero - A deterministic payload hash
- A checksum over identity, sequence, kind, prior checksum, payload hash, and emission time
Complete with normal EvalGate evidence
A completion is accepted only for the active claim and attempt. It binds the input hash, result hash, terminal status, final stream checksum, and normal EvalGate evidence:- Evaluation run ID
- Test-result IDs
- Cost-record IDs
- Model-call ledger IDs
- Trace ID
duplicate. A different completion after acceptance returns conflict. A completion from an earlier dispatch attempt returns stale. These decisions are stored with their checksum, rationale, and reported costs rather than discarded.
Cancellation and runner loss
Queued and lost jobs cancel immediately. Claimed and running jobs entercancel_requested; the worker sees that state on heartbeat. If cancellation wins the terminal race, the job becomes cancelled while already-incurred provider or sandbox costs remain authoritative.
When a heartbeat lease expires, the reaper:
- Marks the claim and runner lost.
- Releases the runner’s active capacity.
- Appends a durable loss event.
- Requeues the job with no active claim when fewer than three attempts have been dispatched.
- Uses a new nonce and incremented attempt for the next compatible runner.
CRON_SECRET-authenticated job runner. Organization admins can also trigger the same bounded recovery from the control plane during incident response; both paths retain the durable loss and requeue events.
An older worker cannot complete the replacement attempt. Accepted results, test results, model calls, and cost records have unique custody constraints, preventing duplicate results or charges.
Operate and troubleshoot
Use the Jobs tab and Evidence action to inspect the complete state timeline and reconciliation history before retrying or rotating a worker.