UAT: LangGraph conditional edge evaluation uses wrong condition key — spec requires context_value but code checks field/equals #3631

Open
opened 2026-04-05 20:58:40 +00:00 by freemo · 0 comments
Owner

Metadata

  • Branch: fix/langgraph-conditional-edge-context-value
  • Commit Message: fix(langgraph): evaluate conditional edges using context_value state field per spec
  • Milestone: v3.6.0
  • Parent Epic: #366

Background

Per docs/specification.md (lines 20975–20998), conditional edges in actor graph YAML configurations use context_value as the key to specify which state field to check:

edges:
  # Conditional edge — routes based on context value
  - source: router
    target: brainstorming
    condition:
      context_value: next_node
      equals: brainstorming

  # Conditional edge — routes based on boolean flag
  - source: passthrough
    target: auto_driver
    condition:
      context_value: auto_finish_active
      equals: true

Current Behavior

The evaluate_edge_condition() method in src/cleveragents/langgraph/nodes.py (lines 335–343) uses field as the condition key, not context_value:

def evaluate_edge_condition(self, edge: Edge, state: GraphState) -> bool:
    if not edge.condition:
        return True
    cond = edge.condition
    if "equals" in cond:
        field = cond.get("field", "content")  # ← Uses "field", not "context_value"
        if state.messages:
            return state.messages[-1].get(field) == cond["equals"]
    return True

Additionally, the method only checks state.messages[-1] (the last message), but context_value in the spec refers to a graph state context field (like next_node or auto_finish_active), not a message field.

Expected Behavior (per spec)

When a conditional edge has condition.context_value: <field_name>, the evaluation should:

  1. Look up <field_name> in the graph state's metadata (or top-level state fields)
  2. Compare it to condition.equals
  3. Return True if they match, False otherwise

Code Location

  • src/cleveragents/langgraph/nodes.py lines 335–343: evaluate_edge_condition()
  • src/cleveragents/langgraph/bridge.py lines 304–318: _create_conditional_router() also uses field instead of context_value

Steps to Reproduce

from cleveragents.langgraph.nodes import Node, NodeConfig, NodeType, Edge
from cleveragents.langgraph.state import GraphState

config = NodeConfig(name="router", type=NodeType.CONDITIONAL)
node = Node(config)

# Spec-compliant edge condition using context_value
edge = Edge(
    source="router",
    target="brainstorming",
    condition={"context_value": "next_node", "equals": "brainstorming"}
)
state = GraphState(
    messages=[],
    metadata={"next_node": "brainstorming"}
)
result = node.evaluate_edge_condition(edge, state)
# Expected: True (next_node == "brainstorming")
# Actual: True (but only because the fallback returns True — the condition is never actually evaluated)

The condition is silently ignored because "equals" in cond is True but cond.get("field", "content") returns "content" (not "next_node"), and state.messages is empty so the check is skipped, falling through to return True. This means ALL conditional edges evaluate to True regardless of state.

Impact

Conditional routing in actor graphs is completely broken. All conditional edges evaluate to True regardless of the actual graph state, meaning the routing logic is never applied. Graphs with conditional edges will always take all branches rather than the correct one.

Subtasks

  • Update evaluate_edge_condition() to check context_value key in condition dict
  • Implement correct lookup: check state.metadata.get(context_value) and state.current_node and top-level state fields
  • Update _create_conditional_router() in bridge.py to use context_value key
  • Write Behave unit tests verifying conditional edge evaluation with context_value
  • Verify all nox stages pass; coverage ≥ 97%

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • evaluate_edge_condition() correctly evaluates context_value-based conditions against graph state metadata, not message fields.
  • Unit tests (Behave) pass for conditional edge evaluation with context_value.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass; coverage ≥ 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/langgraph-conditional-edge-context-value` - **Commit Message**: `fix(langgraph): evaluate conditional edges using context_value state field per spec` - **Milestone**: v3.6.0 - **Parent Epic**: #366 ## Background Per `docs/specification.md` (lines 20975–20998), conditional edges in actor graph YAML configurations use `context_value` as the key to specify which state field to check: ```yaml edges: # Conditional edge — routes based on context value - source: router target: brainstorming condition: context_value: next_node equals: brainstorming # Conditional edge — routes based on boolean flag - source: passthrough target: auto_driver condition: context_value: auto_finish_active equals: true ``` ## Current Behavior The `evaluate_edge_condition()` method in `src/cleveragents/langgraph/nodes.py` (lines 335–343) uses `field` as the condition key, not `context_value`: ```python def evaluate_edge_condition(self, edge: Edge, state: GraphState) -> bool: if not edge.condition: return True cond = edge.condition if "equals" in cond: field = cond.get("field", "content") # ← Uses "field", not "context_value" if state.messages: return state.messages[-1].get(field) == cond["equals"] return True ``` Additionally, the method only checks `state.messages[-1]` (the last message), but `context_value` in the spec refers to a **graph state context field** (like `next_node` or `auto_finish_active`), not a message field. ## Expected Behavior (per spec) When a conditional edge has `condition.context_value: <field_name>`, the evaluation should: 1. Look up `<field_name>` in the graph state's `metadata` (or top-level state fields) 2. Compare it to `condition.equals` 3. Return `True` if they match, `False` otherwise ## Code Location - `src/cleveragents/langgraph/nodes.py` lines 335–343: `evaluate_edge_condition()` - `src/cleveragents/langgraph/bridge.py` lines 304–318: `_create_conditional_router()` also uses `field` instead of `context_value` ## Steps to Reproduce ```python from cleveragents.langgraph.nodes import Node, NodeConfig, NodeType, Edge from cleveragents.langgraph.state import GraphState config = NodeConfig(name="router", type=NodeType.CONDITIONAL) node = Node(config) # Spec-compliant edge condition using context_value edge = Edge( source="router", target="brainstorming", condition={"context_value": "next_node", "equals": "brainstorming"} ) state = GraphState( messages=[], metadata={"next_node": "brainstorming"} ) result = node.evaluate_edge_condition(edge, state) # Expected: True (next_node == "brainstorming") # Actual: True (but only because the fallback returns True — the condition is never actually evaluated) ``` The condition is silently ignored because `"equals" in cond` is True but `cond.get("field", "content")` returns `"content"` (not `"next_node"`), and `state.messages` is empty so the check is skipped, falling through to `return True`. This means ALL conditional edges evaluate to True regardless of state. ## Impact Conditional routing in actor graphs is completely broken. All conditional edges evaluate to `True` regardless of the actual graph state, meaning the routing logic is never applied. Graphs with conditional edges will always take all branches rather than the correct one. ## Subtasks - [ ] Update `evaluate_edge_condition()` to check `context_value` key in condition dict - [ ] Implement correct lookup: check `state.metadata.get(context_value)` and `state.current_node` and top-level state fields - [ ] Update `_create_conditional_router()` in `bridge.py` to use `context_value` key - [ ] Write Behave unit tests verifying conditional edge evaluation with `context_value` - [ ] Verify all nox stages pass; coverage ≥ 97% ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - `evaluate_edge_condition()` correctly evaluates `context_value`-based conditions against graph state metadata, not message fields. - Unit tests (Behave) pass for conditional edge evaluation with `context_value`. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass; coverage ≥ 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.6.0 milestone 2026-04-05 20:58:45 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#366 Epic: Post-MVP Deferred Work
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3631
No description provided.