## ADDED Requirements ### Requirement: State definition via annotations The system SHALL provide an `Annotation` API for defining graph state schemas: - `Annotation(reducer?)` — creates a state key with optional reducer - `Annotation.Root({ key: Annotation })` — combines keys into a state schema - Reducers: `LastValue` (default — overwrite), `BinaryOperator` (custom merge function) #### Scenario: Annotation.Root defines typed state - **WHEN** `const State = Annotation.Root({ messages: Annotation(addMessages), step: Annotation() })` is defined - **THEN** `State` SHALL have `State`, `Update`, and `Node` type members #### Scenario: LastValue reducer replaces on each write - **WHEN** a node writes `{ step: 2 }` and then `{ step: 3 }` in the same step - **THEN** the LastValue channel SHALL throw an `InvalidUpdateError` #### Scenario: BinaryOperator reducer accumulates - **WHEN** a node returns `{ messages: ["hello"] }` and another returns `{ messages: ["world"] }` with an `addMessages` reducer - **THEN** the final state SHALL contain `messages: ["hello", "world"]` ### Requirement: StateGraph builder The system SHALL provide a `StateGraph` class for constructing stateful agent graphs. #### Scenario: StateGraph is constructed with state schema - **WHEN** `new StateGraph({ stateSchema: State })` is called - **THEN** the graph SHALL accept nodes that receive and can update the defined state #### Scenario: Nodes can read and write state - **WHEN** a node function receives state with `{ messages, step }` and returns `{ step: step + 1 }` - **THEN** the graph SHALL update `step` and preserve `messages` #### Scenario: Conditional edges route based on state - **WHEN** `addConditionalEdges("node_a", (state) => state.step > 5 ? "end" : "node_b")` is added - **THEN** execution SHALL route based on the state value at runtime