For platform & applied-AI engineers wiring agents on top of time-series.

Typed signals. Not string alerts.

Chronos turns observation streams into structured patterns — spike, drop, stall, change_point — that downstream code can switch on. Eleven named detectors, five storage backends, one MIT-licensed Go binary. No PromQL DSL, no "AIOps platform," no cloud lock-in.

Switch on patterns, not textcase "stall": kick_worker() instead of 50 lines of NumPy or a paged human reading an alert.

Detect "level shift after deploy"In code via change_point. Not in a PagerDuty rule that nobody trusts.

Stop maintaining alert namesEleven typed patterns ship with Chronos. Add your own; consumers don't change.

Scenario

Seven flat observations. One typed signal back.

The whole product fits in one demo: ingest a stuck metric, wait one detection tick, read a structured Signal with pattern, strength, confidence, and evidence. SQLite, no setup, 30 seconds. The shape of that JSON is the pitch.

$ go install github.com/felixgeelhaar/chronos/cmd/chronos@latest
$ CHRONOS_DB_DSN="sqlite:///tmp/chronos.db" \
  CHRONOS_DETECTION_INTERVAL=5s \
  chronos serve --port 7778 &

$ ENTITY=$(uuidgen | tr A-Z a-z) SCOPE=$(uuidgen | tr A-Z a-z)

# Seven observations, all stuck at 11.0
$ for i in 1 2 3 4 5 6 7; do
    curl -s -XPOST localhost:7778/v1/ingest -d "{
      \"entity_id\":\"$ENTITY\",\"scope_id\":\"$SCOPE\",\"outcome\":11.0,
      \"timestamp\":\"2026-05-02T0$i:00:00Z\" }" > /dev/null
  done
$ sleep 6   # one detection tick

$ curl -s "localhost:7778/v1/signals?scope_id=$SCOPE&pattern=stall" | jq
{
  "signals": [
    {
      "pattern": "stall",
      "scope_id": "9d…",
      "entity_id": "1c…",
      "strength": 1.0,
      "confidence": 0.875,
      "metrics": { "normalised_stddev": 0.0, "window_n": 7 },
      "evidence": [
        { "kind": "variance_window", "window_n": 7, "stddev": 0.0 }
      ],
      "detected_at": "2026-05-02T07:00:06Z"
    }
  ],
  "count": 1
}
That's the contract. A typed Signal downstream code switches on: case "stall": kick the worker. case "spike": rate-limit. case "change_point": rollback. No NLP on alert strings, no fragile threshold tuning, no "rule engine."

How it differs

Where Chronos fits.

Threshold alerting is for humans on call. Anomaly SaaS owns your data and renders dashboards. Chronos sits in your request path, on streaming observations, and emits one row of structured Go types per detected pattern.

Tool Solves Chronos's seam
Prometheus + Alertmanager String alerts to humans on call. Chronos emits typed Signal structs (Pattern enum + Evidence + Metrics) for code to switch on.
Datadog · Anodot · DynaTrace Closed-vendor anomaly detection. Chronos is a 2 MB Go binary, MIT, your DB, your data, eleven named pattern types you import as Go constants.
Roll-your-own NumPy Bespoke detectors per project. Same eleven detectors, already typed, persisted, and stable behind a pinned wire contract.

Architecture

Adapter → Engine → Surface.

Chronos itself ships zero adapters by design — domain knowledge lives in the consumer. Inputs land via POST /v1/ingest or the streaming SDK; the engine runs detectors on every tick; signals leave via HTTP, gRPC, or SSE.

Run it

30 seconds from install to first signal.

brew install felixgeelhaar/tap/chronos
# or: go install github.com/felixgeelhaar/chronos/cmd/chronos@latest

CHRONOS_DB_DSN="sqlite:///tmp/chronos.db" \
CHRONOS_DETECTION_INTERVAL=5s \
chronos serve --port 7778

Then push observations and read signals — see the scenario above for the full Stall walkthrough. Postgres for production:

CHRONOS_DB_DSN="postgres://user:pw@host/chronos?sslmode=disable" chronos serve
What's shipped today. Eleven detectors, five backends, HTTP + gRPC + SSE, bearer auth, GoReleaser distribution, in-process detection on every tick. The only public adapter is ascend (athletes sample); the Mnemos / Nous integration adapters described in the cognitive-stack docs are illustrative — wire your own, or run Chronos standalone. No hosted UI; bring Grafana.

Cognitive stack context

Chronos works alone. Plugs into a four-system stack.

The four-system split lets each layer evolve independently: Mnemos remembers, Chronos watches time, Nous decides, Praxis executes. Olymp drives the loop. Each is independently usable.

Mnemos · memory

Evidence-linked claims with point-in-time replay and contradiction detection.

Nous · decisions

Commitment extraction, risk evaluation, intervention generation.

Praxis · execution

Three-verb action layer with idempotency and replay-from-audit.

Olymp · runtime

Drives observe → understand → decide → act → learn end-to-end.