Statement Status#
The EvoFabric framework, which passes state between nodes, has the following characteristics:
During the graph execution, each node’s input is a complete
Statevariable, and the node output is the state incrementStateDelta.The incremental state will be merged with the state through the registered update mechanism, and the new state will be passed through edges to the next node.
When building the graph engine, you first need to declare the fields, data types, and update mechanisms required for the states in the graph. If you need to use a custom update mechanism, you also need to register the custom update.
State Declaration and Default Update Mechanism#
State declarations support two types, pydantic.BaseModel and TypedDict, and use Annotated to declare data types and update mechanisms.
In Annotated, the first variable is used to declare the data type, and the second variable is used to declare the update mechanism (in string format, representing the name of the update mechanism registered to StateUpdater).
We have already pre-configured two update mechanisms in StateUpdater:
append_messagesis used to record the context of the large model (only supports the list[~evofabric.core.typing.StateMessage] type), adding the large model’s output messages to the correspondingmessageslist and automatically deduplicating.overwriterepresents that the state increment of the node output will directly overwrite the existing value.
Note
If you expect to use AgentNode and UserNode and other LLM-dependent nodes, you must declare the messages field.
Status Declaration Example:
from pydantic import BaseModel
from typing import Annotated, TypedDict
from evofabric.core.typing import StateMessage
class StateSchemaBaseModelType(BaseModel):
messages: Annotated[list[StateMessage], "append_messages"]
user_name: Annotated[str, "overwrite"] = "Unknown"
class StateSchemaTypedDictType(TypedDict):
messages: Annotated[list[StateMessage], "append_messages"]
user_name: Annotated[str, "overwrite"]
Note
The state type and the node’s input type are consistent.
Namely: The state is declared as a BaseModel type, and the node’s input is also of type BaseModel; the value must be retrieved via state.messages. Conversely, the value must be retrieved via state["messages"]. If you do not wish to distinguish between the value retrieval methods, we also provide safe_get_attr() to adapt the value retrieval logic.
Register custom update mechanism#
StateUpdater is responsible for recording the state update mechanism. When you need to customize the state update mechanism, you need to register the update function using the @StateUpdater.register("update_name") decorator.
The registered update function must implement the logic that, given an old value (old) and an increment value (new), returns the new value after merging.
The following provides an update mechanism that implements list expansion:
from typing import Annotated
from pydantic import BaseModel
from evofabric.core.graph import StateUpdater
from evofabric.core.typing import MISSING
@StateUpdater.register("append_list")
def _append_list(old: list = MISSING, new: list = MISSING):
result = [] if old is MISSING else old
if new is MISSING:
return result
result.extend(new)
return result
class StateSchemaWithListAppend(BaseModel):
messages: Annotated[list, "append_message"]
trajectories: Annotated[list, "append_list"]
Dynamic creation of state declaration#
The state declaration can be dynamically created by calling the generate_state_schema() method. This method by default creates a messages field and adds other input fields to the declaration.
Note
Variable names must follow Python’s variable naming conventions.
The variable type must be one of the following: str, int, float, list, tuple, dict.
Example:
from evofabric.core.graph import generate_state_schema
DynamicStateSchema = generate_state_schema()
State Maintenance and Refactoring Mechanism#
During the operation of the graph engine, the system maintains state information through a tree structure to achieve state traceability and efficient reconstruction.
State Tree Structure
Each node’s input is a complete
Stateobject.The node’s output is not the full state, but rather the state delta (delta) of the node.
During runtime, all states are stored as a tree:
The root node represents the input state.
Each child node contains its parent node reference and the current node’s
delta.During state recovery, it will recursively merge upward from the parent node, reconstructing the complete state level by level.
State Reconstruction Logic
When nodes or edges require the complete state, the graph engine will execute the following steps:
Recursively merge all
deltaupward from the current node.Fuse states layer by layer according to the declared update strategy (update strategy).
After performing a deep copy of the complete state obtained, pass it to nodes or edges for execution.
Note
Modifications to the input state by nodes and edges will not affect the state tree maintained internally by the engine, because the passed-in state object is a deep copy.
The Impact of Special Strategies
There are two types of special strategies in the graph engine that may cause the root of the state tree to be reset:
node’s
multi_input_merge_strategyedge’s
state_filter
Since both of these are user-customizable merge logic, the engine cannot guarantee that the results are fully compatible with the original state. Therefore:
Once the above strategy is executed, the root node will be reset to the state output by the strategy.
If these strategies delete some state information, this information cannot be recovered in subsequent nodes.
Final State Output
When the graph execution ends, the
endnode collects all incoming states and builds a state queue:The states in the queue are arranged in routing order.
The engine will sequentially merge the states in the queue according to the defined update strategy.
The final output is the complete
Stateobject after merging all states.
Through this mechanism, the graph engine can ensure state consistency while achieving flexible state reconstruction and traceability.