ProtectedconstructorReadonlyShutdownOptional human-readable identifier surfaced in shutdown logs and used for
de-duplication when Register is called repeatedly with the same instance
but no name. Falls back to the constructor name.
Static ReadonlyExternalThe abort reason the stop relay raises for a row cancelled with any other reason.
Static ReadonlyUserThe abort reason the stop relay raises when a run's row was marked Cancelled with
CancellationReason = 'User Request' (the Stop button). BaseAgent maps it back to the same
reason on the run it finalizes, so the row the UI wrote and the row the agent writes agree.
The tuning currently in effect (a copy).
Returns true when the heartbeat and cancellation-poll timers are currently active. Exposed for diagnostics and tests verifying idle-timer suspension.
Whether the periodic stale-run sweep timer is currently scheduled (diagnostics and tests).
Number of runs this process is currently guarding (primarily for tests/diagnostics).
StaticInstanceOverrides the default tuning. Safe to call before or after runs start tracking: timers that
are already running are restarted on the new intervals. Every value given must be a finite
number greater than zero, except sweepIntervalMs, which may also be 0 (periodic sweep off).
All-or-nothing: on an invalid value it throws, naming the field and value, and applies nothing.
undefined values are ignored.
The Global Object Store is a place to store global objects that need to be shared across the application. Depending on the execution environment, this could be the window object in a browser, or the global object in a node environment, or something else in other contexts. The key here is that in some cases static variables are not truly shared because it is possible that a given class might have copies of its code in multiple paths in a deployed application. This approach ensures that no matter how many code copies might exist, there is only one instance of the object in question by using the Global Object Store.
Whether a stop can reach this run from this process (a controller is registered for it).
Abort a run this process owns, right now, without waiting for the poll. The in-process counterpart of the row-driven relay: a caller that already knows the run was cancelled (a resolver on the same replica, a test) can fire the signal directly.
true when a controller was registered for the run and had not already fired.
IShutdownable: on graceful shutdown, mark every run this process still owns as Cancelled
(via SP_CANCEL) so it doesn't linger as a phantom Running row until the next sweep.
Idempotent and never throws — a failed cancel just falls through to the staleness sweep later.
Begin guarding a run. The owning agent calls this immediately after the run row is saved (so it has a stable ID). Idempotent per run ID. Capturing the provider/user per run lets the central heartbeat + shutdown statements run against each run's own tenant provider and user.
OptionalabortController: AbortControllerThe run's own abort controller. When supplied, the stop relay aborts
it as soon as the run's row is seen marked Cancelled by someone else (the Stop button),
with UserCancelAbortReason when the row says User Request. Without it the run
is still heart-beaten and swept, but a stop cannot reach it.
Stop guarding a run. The owner calls this as soon as the run leaves Running (any terminal
or parked state), so it is never heart-beaten again; the last run leaving stops the heartbeat
and the stop-relay poll.
A missed call is healed by the tracked-set prune, which drops runs whose row is no longer
Running. That prune is a safety net, not the normal path.
Protected StaticgetReturns the singleton instance of the class. If the instance does not exist, it is created and stored in the Global Object Store. If className is provided it will be used as part of the key in the Global Object Store, otherwise the actual class name will be used. NOTE: the class name used by default is the lowest level of the object hierarchy, so if you have a class that extends another class, the lowest level class name will be used.
OptionalclassName: stringStaticSweepForce-fail any Running agent run whose liveness heartbeat has gone stale (or that never
beat and was started long ago), via the dedicated SP_SWEEP proc. The proc does the
whole thing as one atomic, set-based UPDATE and returns the count, so it's safe to run on
every boot and on a timer, on every instance: the predicate is staleness-based (never "fail
all Running") and re-evaluated at write time, so it cannot touch a run a healthy instance is
still heart-beating. Returns the number of rows failed.
Optionalconfig: Partial<AgentRunWatchdogConfig>
Process-wide watchdog that guarantees no
AIAgentRunis left stuck inStatus='Running'after the owning process dies (restart, crash, OOM) or its terminal-state write fails.Three cooperating mechanisms, all anchored to the database clock so they remain correct across multiple MJAPI instances behind a load balancer (no instance trusts its own clock):
LastHeartbeatAtevery AgentRunWatchdogConfig.heartbeatIntervalMs via SP_HEARTBEAT.Runningrun whose heartbeat has gone stale, via SP_SWEEP (one atomic, set-basedUPDATE … WHERE Status='Running' AND <stale>inside the proc — so concurrent sweeps from multiple instances are harmless and a run another instance is still heart-beating can't be caught mid-sweep). Run once on boot (closes restart-orphans) and on a timer (closes mid-life orphans).Cancelledvia SP_CANCEL, closing the deploy case instantly.Cancelled; every AgentRunWatchdogConfig.cancellationPollIntervalMs this process reads back which of ITS runs were cancelled and aborts theAbortControllerthe owning agent registered with Track. BaseAgent already checks that signal throughout its loop and forwards it into prompts and actions, so the in-flight step ends and the run finalizes as Cancelled. Because the row is the channel, the replica that owns the run is the one that reacts, with no cross-process messaging.The heartbeat and the stop-relay poll run only while this process is guarding at least one run: the last run leaving stops them, and the next Track starts them again. The periodic sweep, once started, keeps running so it can close other instances' orphans; set AgentRunWatchdogConfig.sweepIntervalMs to
0and an idle process issues no periodic statements at all, which lets a serverless database pause.Every proc filters
Status='Running'only —PausedandAwaitingFeedbackare legitimately-not-progressing states and are never touched. The watchdog accesses the DB only through these stored procedures (writes) and the base view (reads) — never the base table — so it works as the regular runtime DB user, not just the elevated CodeGen user. Proc calls are built through the provider's Dialect.ProcedureCallSyntax, so they run on SQL Server and PostgreSQL unchanged.