Skip to content

Sidecars

Scope note (2026-06-16). The steelmoth_runtime.sidecars package is a misnamed shared-infra package, not a dispatch subsystem. The Moth Dispatch Team / Kratos execution engine that originally gave this package its name has been removed from Steelmoth — dashboard surface (PR #354), runtime engine (#363), compose service (#367). It was never used in production: the Kratos executor never ran (0 rows ever in steelmoth.sidecar_runs). What remains under sidecars/ is the live infrastructure described below. See CHANGELOG.md and ADRs/RFCs 0036/0046/0038/0028/0029/0037 (all superseded).

steelmoth_runtime.sidecars is a hexagonal package (domain / application / adapters / infrastructure) that today holds live shared infrastructure that is not dispatch-specific despite the directory name:

  • Notification outbox. steelmoth.notification_outbox is the live notification queue. postgres_notification_outbox.py is its repository; the steelmoth-notifier container runs notification_worker.run_forever to drain it with PreferenceRoutingNotificationDelivery (routing_notification_delivery.py) for routing. The outbox is fed by live features — reminders and browser-task delivery — not dispatch. (RFC 0028 introduced both a Kratos run-queue half and this outbox half; only the run-queue half was removed.)
  • Workspace repository. postgres_workspace_repository.py (port: application/ports/workspace_repository.py) backs the per-owner dashboard Workspace Inbox/Outbox surfaces (ADR 0068 / ADR 0071), implemented by PostgresWorkspaceRepository.
  • Weather. weather_open_meteo.py is the Open-Meteo weather adapter used by the weather tool.
  • User settings. postgres_user_settings_profile.py (port: application/ports/user_settings_profile.py, plus an in-memory variant) backs per-owner user-settings storage.
  • Shared Postgres wiring. postgres_repositories.py exposes runtime_database_url() and the shared connection helpers the adapters reuse.

The addon registries under addons/ (registry.json and the browser_pool_orchestrator / moth_adapters addon trees) are the first source paths to inspect when addon identity, launch metadata, or addon availability changes. (The dispatch-team worker registry addons/sidecars.json was removed with the dispatch subsystem.)

Removed: the Kratos dispatch-team execution engine

Section titled “Removed: the Kratos dispatch-team execution engine”

The dispatch-team execution path — the Kratos run-queue, the worker process, the dispatch policy gate, the /v1/team/sidecars API, the dashboard /team pages, and the planner dispatch_team tool — has been removed across PRs #354 / #363 / #367 (2026-06-16). It never ran in production (sidecar_runs had 0 rows ever). Do not describe it as a current capability. A few dispatch-domain value types (domain/identifiers.py’s WorkerId / SidecarRunId, domain/execution.py) survive as inert, misnamed leftovers and should not be read as evidence the executor exists.

compose.shared.yml defines two long-lived runtime-adjacent services that inherit the run-agent-vault-proxy-session.py wrapper:

  • steelmoth-notifier (profile notifier) processes the steelmoth.notification_outbox queue via notification_worker.run_forever with PreferenceRoutingNotificationDelivery for routing.
  • steelmoth-reminder-daemon (profile reminder-daemon) ticks steelmoth_runtime.reminder_daemon.main_loop every 60s (configurable via MOTH_HYBRID_REMINDER_DAEMON_TICK_S). Each tick scans world.reminders and enqueues per-channel delivery intents into steelmoth.notification_outbox (plus synthetic steelmoth.sidecar_runs provenance rows; the table survives as the FK parent of notification_outbox). One-shot reminders are marked sent when at least one enabled channel enqueue succeeds. PRD 0032 / RFC 0067 / ADR 0087. The service remains profile-gated in compose, but the canonical startup paths (scripts/start-stack.sh and scripts/compose-up.sh) include the reminder-daemon profile so it comes up with the private runtime stack. The loop emits guardrail alerts for stale cycles (reminder_daemon.stale_cycle_alert, default threshold 120s via MOTH_HYBRID_REMINDER_DAEMON_STALE_ALERT_S) and persistent due-backlog accumulation (reminder_daemon.backlog_alert, thresholds via MOTH_HYBRID_REMINDER_DAEMON_BACKLOG_ALERT_DUE + MOTH_HYBRID_REMINDER_DAEMON_BACKLOG_ALERT_CYCLES).

Delivery is completed by steelmoth-notifier: notification_worker consumes pending outbox rows and uses PreferenceRoutingNotificationDelivery. Reminder fan-out rows preserve explicit channels (email, inbox_only, dashboard, webhook); preference auto-routing applies only to legacy default rows.

Topology rationale (ADR 0084 carried into ADR 0087): the reminder daemon runs in its own container — not as an in-process asyncio task in steelmoth-api — so DB outages or otherwise-misbehaving reminder enqueue work cannot stall the api container’s Telegram polling loop.

  • Update this page when the notification-outbox / workspace / weather / user-settings shape under the package changes, or when addon registry metadata changes.
  • Do not reintroduce dispatch-team / Kratos prose describing it as live; the executor is removed (PRs #354 / #363 / #367).
  • Do not expose raw provider secrets to package adapters; use the credential and broker boundaries documented in domain terms and ADRs.
  • This page does not describe every addon implementation.
  • The package directory name (sidecars/) is a historical misnomer; a future rename to reflect its shared-infra role is not yet scheduled.