Skip to content

Zelos Agent SDK

One Python entry point — connect() — for talking to a running Zelos Agent. Browse signals, query time-series, compute on unit-carrying series, check invariants, run actions, manage extensions, and re-open .trz files with the same handle.

What You Can Do

  • Browse Live Signals

    See what's flowing through the agent right now, with type and unit metadata.

  • Query Time-Series

    Pull a window of samples — raw or downsampled — as a frame that renders itself and charts itself.

  • Read Latest Values

    Get the most recent reading for one signal or many, with units attached.

  • Check Invariants

    Turn a queried series into a rule with a result and the evidence behind it.

  • Save and Re-Open .trz

    Capture a slice of live data, then re-open the file later with the same calls.

  • Run Actions

    Execute typed Actions exposed by the agent or its extensions.

Connect

from zelos_sdk import connect

agent = connect()
agent

connect() checks that something answers before it returns. With no argument it reads ZELOS_AGENT_URL, falling back to http://localhost:2300; a bare host or host:port gets http:// added. It is also a context manager, and agent.close() is the explicit form:

with connect("localhost:2300") as agent:
    print(agent.target)   # "http://localhost:2300"

For a long-running script or a pytest fixture, prefer the lazy Agent(target) — its channel reconnects on its own, and RPC errors surface at the call site rather than at construction.

Need more detail than a connection card?

agent.info() returns a richer snapshot — health, log and config directories, memory, settings. Anything that can't be loaded reads None and is named in info.failures.

A 60-Second Tour

One script that exercises every piece of the SDK. Each block is independent — comment out the ones you don't need. In a notebook, drop the print() and let the last line of each cell render itself.

from zelos_sdk import connect

with connect("localhost:2300") as agent:
    # 1. Discover what's live
    catalog = agent.signals()
    cells = catalog.match("bus0/BMS_message/cells.*")

    # 2. Pull the last three minutes
    frame = agent.query("bus0/BMS_message/cells.*", start="-3m")
    print(frame)                                 # rows, span, unit and nulls per column

    # 3. Compute on a column; units follow
    series = frame["bus0/BMS_message/cells.cell_0"]
    print(series.min(), series.mean())           # NamedScalar: "3.629 V 3.658 V"

    # 4. Chart it — Vega-Lite, renders offline in an export
    chart = frame.short_names().plot()

    # 5. Read the most recent value of each signal
    print(agent.latest([s.path for s in cells]))

    # 6. Check an invariant over what you just queried
    print(agent.check.that(series, ">", 3.0))

    # 7. Snapshot + change stream over a one-minute window
    replay = agent.window("bus1/inverter_status.mode", start="-1m", duration="1m")
    print(len(replay.snapshot), "opening values,", len(replay.changes), "changes")

    # 8. Watch live values, with a deadline
    for tick in agent.watch(["bus1/inverter_status.mode"], interval=1.0, until="5s"):
        print(tick)

    # 9. Save the last minute, then re-open it
    saved = agent.export("/tmp/run.trz", start="-1m", overwrite=True)
    with saved.open() as trace:
        print(trace.query("bus0/BMS_message/cells.*", start="start", end="+30s"))

    # 10. List actions and extensions
    print([a.name for a in agent.actions.list()])
    for ext in agent.extensions.list():
        print(ext.id, ext.version, ext.state)

Everything renders itself

An Agent, SignalCatalog, SignalFrame, SignalSeries, Snapshot, ReplayWindow, Trace and CheckResult all print a useful summary and render as a rich table in a notebook. You never need .to_pandas() to see something — that call is for handing data to pandas.

One glob grammar, one time grammar

* and ? expand against the catalog everywhere a path is accepted. A signed string ("-3m") is a time and an unsigned one ("3m") is a duration, in every call that takes either. See the glob grammar and time and duration grammar.

Units flow through arithmetic

Series carry their units, so voltage * current arrives as W, .integrate() over time gives J, and power / current cancels back to V. Adding mismatched units raises instead of lying.

Where to Next

  • Quick Start

    Connect to an agent and run your first query in under two minutes.

  • Query Live Data

    Catalog, globs, time windows, frames, series math, charts, cursors, watches.

  • Open Trace Files

    Re-open .trz files individually, or as runs on a shared clock.

  • Checks

    Rules with evidence behind them — live or on a recording.

  • Run Actions

    Inspect schemas, execute typed Actions, and handle results.

  • Manage Extensions

    Discover, start, stop, and configure installed extensions.

  • Manage Layouts

    List, create, update, and delete saved dashboard layouts.

  • Python reference

    Every class, method and parameter, generated from the package.

Resources