Skip to content

OSSS.ai.orchestration.graph_builder

OSSS.ai.orchestration.graph_builder

Graph builder for converting OSSS agents to LangGraph structures.

This module provides utilities to build LangGraph-compatible graphs from OSSS agent definitions, including: - node creation from agents - edge routing (dependencies + custom routing) - graph validation (missing nodes, cycles, entry/exit points) - a lightweight executor to simulate graph execution (sanity testing)

Important conceptual mapping: - A OSSS "agent" becomes a LangGraph "node" - Dependencies between agents become directed edges - The result is intended to be a DAG (Directed Acyclic Graph)

EdgeType

Bases: Enum

Types of edges in a LangGraph DAG.

This enum is used to label edges so downstream logic can interpret routing: - SEQUENTIAL: always traverse from A -> B after A completes - CONDITIONAL: traverse to B only if some condition holds (not fully evaluated yet) - PARALLEL: indicates branching can happen concurrently (not implemented in executor) - AGGREGATION: indicates many-to-one merge (not implemented in executor)

GraphEdge

Bases: BaseModel

Definition of an edge between graph nodes.

Why Pydantic? - Validates node IDs early (length, types, etc.) - Allows consistent serialization for logging/debugging - Fits the wider OSSS ecosystem which is Pydantic-first

NOTE about condition: - It is typed as Callable[[AgentContext], bool] - It is allowed as an arbitrary type (Pydantic config) - It is currently NOT evaluated by GraphExecutor (placeholder for future)

to_dict()

Convert to a simple dictionary representation.

NOTE: - We serialize edge_type as its .value (string) for readability. - We do NOT serialize the actual condition callable (non-serializable).

GraphDefinition

Bases: BaseModel

Complete graph definition consisting of nodes and edges.

This is the "compiled" representation produced by GraphBuilder.

Fields: - nodes: mapping of node_id -> LangGraphNodeDefinition (from each agent) - edges: list of GraphEdge objects describing connectivity - entry_points: nodes that can start execution (no incoming edges) - exit_points: nodes that can end execution (no outgoing edges) - metadata: extra descriptive/diagnostic info

to_dict()

Convert graph definition to a JSON-friendly dict.

NOTE: - node definitions are converted via node_def.to_dict() - edges are converted via edge.to_dict()

GraphValidationError

Bases: Exception

Error raised when a graph fails structural validation.

This exception is raised by :class:GraphBuilder when one of the following conditions is detected:

  • No agents are provided.
  • Edges reference nodes that do not exist in the graph.
  • The graph contains cycles (it is not a DAG).
  • Entry or exit points are missing or invalid.

GraphBuilder

Builder for creating LangGraph-compatible graphs from OSSS agents.

High-level flow: 1) Agents are registered with the builder. 2) Each agent provides a LangGraphNodeDefinition (node definition). 3) Edges are built from: - agent dependency declarations - optional custom edges - optional custom routing declarations 4) Entry/exit points are computed. 5) Graph is validated (missing nodes, cycles, etc.)

This does NOT create an actual LangGraph object yet. It produces a GraphDefinition that can be translated later.

add_agent(agent)

Register a single agent.

Implementation detail: - Stores the agent using agent.name.lower() as the key. - This makes subsequent node lookups consistent even if original names differ in case.

Returns:

Type Description
GraphBuilder

Self (to enable fluent chaining)

add_agents(agents)

Register multiple agents.

This is convenience around add_agent().

Returns:

Type Description
GraphBuilder

Self (to enable fluent chaining)

add_edge(edge)

Add an explicit edge.

Use cases: - Override default dependency wiring - Force ordering even if dependencies aren't declared - Add conditional/parallel/aggregation semantics

NOTE: - Validation still occurs in build()

add_conditional_routing(from_node, routing_func, condition_name='custom_routing')

Register custom routing behavior for a node.

Intended behavior (future): - After from_node executes, routing_func(context) decides which node to go next. - This could implement "retry", "branching", "quality gates", etc.

Current behavior: - GraphBuilder will generate CONDITIONAL edges from from_node to all other nodes. - GraphExecutor will currently take all conditional edges (placeholder).

Parameters:

Name Type Description Default
from_node str

the node that branches

required
routing_func Callable[[AgentContext], str]

function mapping context -> next node name

required
condition_name str

descriptive label (not used directly yet)

'custom_routing'

build()

Build and validate a GraphDefinition.

Steps: - Fail fast if no agents - Ask each agent for its node definition - Build edges (dependencies + custom edges + custom routing placeholders) - Determine entry and exit points - Validate the resulting graph (node existence, cycles, entry/exit correctness)

Raises:

Type Description
GraphValidationError

If no agents are provided.

GraphValidationError

If an edge references a node that does not exist.

GraphValidationError

If the graph contains cycles.

GraphValidationError

If entry or exit points are missing or invalid.

GraphExecutor

Executor for running graphs built by GraphBuilder.

This is NOT a full LangGraph runtime. It is a lightweight simulator used to validate that: - Nodes can be executed in some order - Edges can be traversed - Context can flow through node invocations

Current limitations: - CONDITIONAL edges are not actually conditioned; all targets are taken. - PARALLEL edges are not executed concurrently. - AGGREGATION is not implemented. - Infinite-loop prevention is crude (execution_order length heuristic).

execute(initial_context) async

Execute the graph starting from entry points.

Algorithm (high level): - Start from graph_def.entry_points - For each node: - invoke the corresponding agent (if present) - add node to visited set - compute next nodes via outgoing edges - Continue until no next nodes remain or loop guard triggers

Returns:

Type Description
AgentContext

The final AgentContext after executing reachable nodes.

Side effects

Adds execution trace metadata into context.execution_state: - graph_execution_order - graph_nodes_visited