Documentation menu
Reference
Python SDK
The ValidAnytime Python SDK is a thin, typed, MIT client for the ValidAnytime REST API: create monitors, ingest events idempotently, and read alarms back.
What’s open source
The validanytime Python package is open source (MIT): it is a thin, typed HTTP client for the ValidAnytime API. The anytime-valid engine — the detectors, fleet-wide false-discovery control, and the backtest gate — runs in the ValidAnytime cloud. Using the SDK means streaming your chosen metric values to the API and reading alarms back; the engine does not run locally, and there is no self-hosted deployment today. (Want to see the math run entirely in your browser instead? The backtest playground does exactly that on your own numbers.)
Install
pip install validanytimePreview — SDK at launch. The package publishes to PyPI at launch — start free for install instructions.
- Dashboard — create a monitor, mint an API key, watch alarms
- The REST API over HTTP (curl or any client)
- The in-browser backtest at /try — no signup
- The MCP server, run locally from a source checkout
- pip install validanytime (the Python SDK)
- The GitHub Action (offline backtest gate in CI)
- The MCP registry listing (one-line install)
Initialize
from validanytime import Client
va = Client(
api_key="va_...",
base_url="https://api.validanytime.com", # optional
)Core methods
# create / fetch monitors
monitor = va.create_monitor(name="llm-answer-quality",
config={"template": "llm_quality"})
monitor = va.get_monitor(monitor.id)
# ingest one event (event_id makes it idempotent on retry)
va.ingest(monitor.id, value=0.91, event_id="evt_1042",
ts="2026-06-24T14:02:11Z", label=1.0)
# ingest a batch
va.ingest_batch(monitor.id, events=[
{"value": 0.88, "event_id": "evt_1043"},
{"value": 0.86, "event_id": "evt_1044"},
])
# list alarms (optionally since a timestamp)
alarms = va.alarms(monitor.id, since="2026-06-01T00:00:00Z")Autoconfig & the backtest gate
Don’t hand-write detector math — bring the data and let the backtest gate (not any model) ratify a config before it goes live. This is the agent-driven path: your agent reads the metric or asks the user, then calls the API.
# Autoconfig: read the metric's shape, get a GATE-RATIFIED config.
sample = [...] # your recent metric values
s = va.suggest_config(sample, history=sample) # -> Suggestion
if s.backtest.passed: # the non-bypassable check
m = va.create_monitor("my-metric", config=s.config)
print(s.backtest.summary) # "...caught it on day X."
# Data-free matrix lookup, or re-run the gate on any config.
rows = va.use_cases() # UseCase(id, direction, config, ...)
report = va.backtest(sample, config=rows[0].config)suggest_config(sample, history=…, use_case=…)→Suggestion(config— resolved and gate-ratified — plusbacktest). It reads the sample’s shape (level, scale, direction, boundedness, drift), tunes a config, and runs the gate onhistory. Always checksuggestion.backtest.passedbefore going live.backtest(history, config=…, inject_shift=…)→BacktestReport. Graded on the page tier (passed,caught_at_seq); a warn-tier fire on the normal stretch is reported aswarned_on_normaland never fails the gate. A backtest is a replay of past data, not a forecast about a different stream.use_cases()→ a list ofUseCase— the public matrix (decision table) as a data-free lookup: each row’s resolvedconfigis create-ready, and itsidis a validuse_case=hint.
Idempotency & ordering
Pass an event_id with every event. Ingestion is an append-only log drained in strict order, so retries are de-duplicated and the anytime-valid guarantee — which depends on event order — is preserved. Re-sending the same event_id is a safe no-op.
Validation at create
create_monitor validates the config by constructing the real engine server-side: an unknown monitor family, a bad kwarg, or an unknown template id raises a 422 with the monitor menu in the message — never a 500 on your first event. A template config resolves into the full two-tier config it runs (page-tier e-processes plus a warning-tier control chart), and the Monitor.config you get back is that resolved config.
Return types
create_monitor/get_monitor→Monitor(id,name,config— the resolved config that actually runs —status).ingest/ingest_batch→IngestResult(accepted,duplicate).alarms→ a list ofAlarm(seq,fired_at,statistic,guarantee_tag,theorem_ref,e_value,discovery,message). Warning-tier alarms carryguarantee_tag="heuristic_adaptive"and always havee_value=None— they are sensitive, model-calibrated early hints, not budgeted pages.