Weave

Reference for Weave scheduling, callback model, dependencies, and health surfaces.

Weave is Aether's periodic execution primitive for control, synchronization, and simulation logic.

Construction

Create Weaves after Nexus and Sigils are declared, and before nexus.start().

Key parameters:

  • label: stable loop name used for introspection, logs, and tracing.
  • cycle_time: period in seconds between callback runs.
  • callback: async or sync callable executed each cycle.
  • depends_on: optional list of dependency Weaves awaited via their completion events before the callback runs.
  • description: optional operator-facing summary.

Execution model

  • Weaves are soft real-time loops.
  • A Weave transitions from PENDING to RUNNING when Nexus starts weave execution.
  • Each cycle runs the callback (async or sync), tracks cycle timing, and updates status.
  • If execution misses timing budgets, status can move to FAILED or OVERRUN.

Dependency behavior

  • Before a callback run, a Weave awaits all depends_on completion events.
  • This is event-based cycle synchronization, not a hard real-time scheduler guarantee.
  • Use dependencies to express ordering intent (for example: estimator before controller), then validate timing under realistic load.

Runtime surfaces

Each Weave registers REST and MCP read surfaces automatically.

REST endpoints (by weave id):

  • GET /weave/{id} -> label
  • GET /weave/{id}/description -> description
  • GET /weave/{id}/cycle_time -> cycle time
  • GET /weave/{id}/cycles -> completed cycle count
  • GET /weave/{id}/next_cycle -> next scheduled cycle time

MCP endpoint:

  • Read-only structured tool named from Weave {label} status
  • Returns WeaveInfo fields: label, description, status, cycle_time, next_cycle, cycles

Interaction with Sigils

A common pattern:

  1. Read writable command Sigils (setpoint, mode, thresholds).
  2. Read measured or simulated state Sigils.
  3. Compute one control/simulation step.
  4. Write outputs back to target Sigils.

This keeps operational surfaces (OPC UA/REST/MCP) and internal loop state aligned around the same Sigil values.

Minimal example

from aether.nexus import Nexus
from aether.sigil import Sigil
from aether.weave import Weave

nexus = Nexus(opc_ua_url="opc.tcp://localhost:4840")

setpoint = Sigil(node_id="ns=2;s=Loop.Setpoint", initial_value=25.0)
measurement = Sigil(node_id="ns=2;s=Loop.Measurement", initial_value=20.0, writable=False)


async def first_order_step():
    sp = float(await setpoint.read())
    pv = float(await measurement.read())
    pv += (sp - pv) * 0.02
    await measurement.write(pv)


Weave(
    label="loop_step",
    cycle_time=0.1,
    callback=first_order_step,
    description="Simple first-order process update.",
)

if __name__ == "__main__":
    nexus.start()