Skip to content

v0.4.0

Choose a tag to compare

@chris-colinsky chris-colinsky released this 05 May 02:55
aedaf28

Spec v0.3.1 / proposal 0003: node-boundary observer hooks.

External code can now observe execution as it happens — the control-side equivalent of the data-side trace field pattern.

New public API

  • NodeEvent (frozen dataclass): node_name, namespace tuple, step, pre_state/post_state, error, parent_states. Exactly one of post_state or error is populated per event.
  • Observer Protocol: async callable receiving a NodeEvent. The parameter is positional-only so conformance isn't tied to a parameter name.
  • CompiledGraph.attach_observer(fn) -> RemoveHandle for graph-attached observers; invoke(state, observers=...) for invocation-scoped.
  • CompiledGraph.drain() — awaits delivery of every event dispatched by prior invocations of this graph. Required for short-lived processes (CLIs, scripts, serverless).

Delivery semantics

  • Strictly serial within an invocation: no two observers process the same event concurrently; no observer sees event N+1 until everyone has finished N.
  • Order: graph-attached (outermost → innermost), then invocation-scoped — both in registration order.
  • Async-from-graph: invoke() returns when the graph reaches END regardless of queue state.
  • Observer exceptions are caught and reported via warnings.warn — they don't break siblings, subsequent events, or the graph run.
  • Subgraph-internal events bubble up: the subgraph wrapper itself stays observer-transparent. Step counter spans the subgraph boundary; namespace and parent_states extend.

Other changes

  • CI workflow added at .github/workflows/ci.yml (ruff + ruff-format + pyright + pytest).
  • Spec submodule pinned at v0.3.1 (corrigendum to fixture 013's YAML syntax).

See the proposal for design rationale.