NodeBase and ExecutionContext¶
The abstract base class plus the per-run Protocol every node receives.
NodeBase¶
Abstract base class for every executable graph node (FR-1). Concrete subclasses
implement async execute(state, ctx) and return a dict keyed by state-field
name; the execution loop merges each returned dict into the next state via the
field-merge registry (FR-11). Nodes never mutate state in place.
from stargraph.nodes import NodeBase
class MyNode(NodeBase):
async def execute(self, state, ctx):
return {"output_field": ...}
NodeBase itself carries no instance state, so subclasses can be plain classes,
dataclasses, or pydantic.BaseModel subclasses depending on their validation
needs. Subclasses are free to declare additional fields (e.g. model_id on
MLNode).
execute(state, ctx)¶
| Param | Type | Description |
|---|---|---|
state |
pydantic.BaseModel |
Current run state — immutable inside the call. |
ctx |
ExecutionContext |
Per-run execution context (see below). |
| returns | dict[str, Any] |
Patch keyed by state-field name; merged via FR-11. |
ExecutionContext¶
Minimal per-run context surfaced to nodes — a runtime_checkable
typing.Protocol. Phase-1 only pins run_id. Concrete contexts (the real
stargraph.graph.run.GraphRun) attach more fields (event sink, replay flag,
artifact store, capability gate); nodes that need those fields declare their
own narrower Protocol — see SubGraphContext and
WriteArtifactContext.
Why a Protocol
Structural typing keeps the contract stable as later phases attach new context fields (capabilities gate, event sink, replay flag, mirror handle, checkpointer). Nodes that don't read a context field can ignore the parameter entirely.
EchoNode¶
No-op fixture node — copies state.message straight through to the same field.
Used by tests/fixtures/sample-graph.yaml to exercise the dispatch + merge path
without depending on any tool, adapter, or external service. Missing message
raises AttributeError at runtime to surface fixture mis-configuration loudly.
State contract¶
- Reads — nothing by contract; concrete subclasses declare what they read.
- Writes — the dict returned by
execute. By convention, output keys live onself.output_field(seeMLNode,WriteArtifactNode,BrokerNode). - Merge semantics — last-write-wins on key collisions, per the field-merge registry (FR-11).
See also¶
DSPyNode,MLNode,SubGraphNode— concrete subclasses.- IR Schema —
NodeSpec.kindresolution.