#3773·quartznet

Agent target: a scheduler that dials out to the dashboard and answers over the connection

Author: lahmaCreated Sep 11, 2026Updated Sep 19, 2026
Labelsfeature4.x

Every product built after about 2018 for cross-machine administration has the worker dial out — Temporal, Prefect ("no inbound connections to your network"), Dagster+ ("no ingress is required"), Airflow 3's EdgeExecutor, GitHub and Azure DevOps runners, Jenkins over WebSocket, the Aspire dashboard's OTLP ingest — and markets it as a security property: one outbound HTTPS rule, no credential vault on the control plane, every node individually addressable. The HTTP target is the same-network model; this is the cross-machine one.

Shape

  • Quartz.Dashboard.Agent (references Quartz and Microsoft.AspNetCore.SignalR.Client only; no Microsoft.AspNetCore.App): q.UseDashboardAgent(o => { o.Endpoint = …; o.Token = …; }) installs a plugin that holds a SignalR client connection (WebSockets over 443, WithAutomaticReconnect), registers scheduler name, instance id, SchedulerMetadata, Quartz version and a capability list, heartbeats on a stated interval with a stated "offline after N missed" rule, streams live events and history entries up, and answers operation requests down the same connection through the operation catalogue's route table — the HTTP contract without HTTP.
  • The dashboard's AgentHub: authenticates agents (a token scheme with primary and secondary keys for rotation; the host's own authentication where it has one), is held to the same fail-closed startup guard as the API and the dashboard, raises MaximumReceiveMessageSize for 1000-row pages, and binds each connected scheduler into the repository as a Remote target keyed by the agent's target name.
  • The agent decides what it accepts: ReadOnly, IsJobTypeAllowed, an operation allow-list; a refused operation is a 403 on the tunnel.
  • Registration-token onboarding; documentation states single-instance dashboard for agent mode unless a SignalR backplane is configured.

Done means

  • An in-process test with two agent-connected schedulers and one dashboard host: every page works over each, Live Logs and History are live, an agent that stops heartbeating is Unknown after the stated interval, a ReadOnly agent refuses a pause.
  • dashboard.md gains "Fronting a scheduler on another machine"; SECURITY.md states the agent trust model.

Depends on the live-events and operation-catalogue issues.

Part of #3387 — see the design record there for how this fits the whole.