Understanding the Role of LangGraph in OpenMAIC: Multi-Agent Orchestration Engine
OpenMAIC relies on LangGraph as its core orchestration engine to coordinate multi-agent conversations through a deterministic state-machine workflow that manages turn-taking, real-time streaming, and state persistence across AI agents.
OpenMAIC leverages LangGraph to power its multi-agent classroom experiences, treating the framework as the central nervous system for deterministic workflow management. By implementing a state-graph architecture defined primarily in lib/orchestration/director-graph.ts, the platform orchestrates complex interactions between multiple LLM agents while maintaining clean separation between orchestration logic and underlying model providers. This integration enables OpenMAIC to handle sophisticated agent coordination without hard-coding provider-specific logic.
The State-Machine Foundation of LangGraph in OpenMAIC
LangGraph provides OpenMAIC with a state-machine abstraction through the StateGraph class. This allows the platform to define deterministic workflows where each node represents a specific computational step in the agent conversation cycle.
The orchestration topology follows a strict single-round pattern: START → director → (agent_generate) → END. As implemented in createOrchestrationGraph(), this graph guarantees that each request executes at most one director-to-agent cycle. Clients serialize multiple requests to extend conversations beyond a single turn, while the server remains stateless between invocations.
Core Components of the LangGraph Integration
State Definition and Management
All request-scoped data flows through OrchestratorState, declared in lib/orchestration/types.ts using Annotation.Root. This typed state container holds the full request payload including messages, store state, selected agents, language model configuration, and mutable fields like currentAgentId, turnCount, agentResponses, and whiteboardLedger.
LangGraph automatically carries this state between nodes, ensuring that each workflow step receives the complete context from previous steps without external database calls.
The Director Node
The director node implements the decision logic for agent selection. Located in lib/orchestration/director-graph.ts, it handles two distinct scenarios:
- Single-agent fast-path: When
state.availableAgentIds.length <= 1, the director dispatches immediately without calling an LLM. - Multi-agent orchestration: For multiple agents, the director uses
AISdkLangGraphAdapterto query an LLM via_generateand determine which agent should speak next.
The director emits streaming events—including thinking and cue_user—through LangGraph's custom stream mode, providing real-time feedback to clients before the main agent response begins.
The Agent-Generate Node
This node executes the selected agent's LLM and manages the response stream. It parses output using a custom JSON-based protocol defined in lib/orchestration/stateless-generate.ts, updates the whiteboard ledger, and returns partial state updates for turnCount, agentResponses, and totalActions.
The node receives LangGraphRunnableConfig containing a writer function that pushes StatelessEvent objects to clients via Server-Sent Events (SSE).
Streaming Integration
Both nodes leverage the writer function within LangGraphRunnableConfig to enable real-time streaming. This design allows the frontend to display partial responses as they arrive rather than waiting for complete generation, creating a responsive classroom experience where users see "thinking" indicators and text deltas immediately.
The Adapter Layer
AISdkLangGraphAdapter, defined in lib/orchestration/ai-sdk-adapter.ts, wraps any AI-SDK LanguageModel (OpenAI, Claude, Bedrock) to expose _generate and streamGenerate methods with the interface LangGraph expects. This abstraction decouples the graph logic from specific LLM providers, allowing OpenMAIC to switch models without modifying the orchestration code.
Implementing the Orchestration Workflow
Building the LangGraph workflow requires compiling the state graph and preparing the initial state before invocation.
Creating the orchestration graph:
import { createOrchestrationGraph } from '@/lib/orchestration/director-graph';
// Returns a compiled LangGraph ready to be invoked per request
const orchestrationGraph = createOrchestrationGraph();
Preparing the initial state:
import { buildInitialState } from '@/lib/orchestration/director-graph';
import { someLanguageModel } from '@/lib/models';
// `request` is a StatelessChatRequest received from the client
const initialState = buildInitialState(request, someLanguageModel, request.thinkingConfig);
Running a request through the graph:
import type { LangGraphRunnableConfig } from '@langchain/langgraph';
// `config` contains the SSE writer passed to the client
const result = await orchestrationGraph.invoke(initialState, {
writer: (event) => sse.send(event), // `sse` is an SSE helper
signal: abortController.signal,
});
Director node decision logic:
// Inside `directorNode`
if (state.availableAgentIds.length <= 1) {
// Single-agent fast-path – no LLM call
return { currentAgentId: state.availableAgentIds[0] };
}
// Multi-agent – use the adapter to ask the LLM which agent to speak next
const decision = await adapter._generate(
[new SystemMessage(prompt), new HumanMessage('Decide next speaker')],
{ signal: config.signal },
);
Agent-generate node streaming:
for await (const chunk of adapter.streamGenerate(lcMessages, { signal: config.signal })) {
if (chunk.type === 'delta') {
// Parse JSON structure, emit text deltas and actions via `write`
write({ type: 'text_delta', data: { content: parsedText, messageId } });
}
}
Stateless Design Architecture
OpenMAIC maintains a stateless server design by storing all request-scoped data—including generated agent configurations—inside the LangGraph state. The graph processes the state and returns updated versions without persisting data on the server between requests.
This approach enables horizontal scaling and simplifies deployment, as any server instance can handle any request without requiring sticky sessions or shared memory. The lib/orchestration/prompt-builder.ts module constructs system prompts dynamically based on the state contents passed through the graph.
Summary
- LangGraph serves as the core orchestration engine for OpenMAIC's multi-agent system, providing deterministic workflow management through
StateGraph. - State management occurs via typed
OrchestratorStateannotations that carry request context, agent selections, and conversation history between nodes. - Two primary nodes handle execution: the director node decides which agent speaks next, while the agent-generate node streams LLM responses and updates the whiteboard ledger.
- Real-time streaming is implemented through
LangGraphRunnableConfigwriter functions that pushStatelessEventobjects to clients via SSE. - Provider agnosticism comes from the
AISdkLangGraphAdapterlayer, which standardizes interactions with various LLM backends. - Stateless architecture allows the platform to scale horizontally by keeping all session data within the graph state rather than server memory.
Frequently Asked Questions
How does LangGraph handle state management in OpenMAIC?
LangGraph manages state through the OrchestratorState annotation declared in lib/orchestration/types.ts. This typed container holds all request data including messages, available agents, and the whiteboard ledger. LangGraph automatically passes this state between the director and agent-generate nodes, ensuring each step has access to the complete conversation context without requiring external state stores.
What is the difference between the director node and the agent-generate node?
The director node determines which agent should speak next, implementing logic for both single-agent fast-paths (no LLM call) and multi-agent scenarios (using AISdkLangGraphAdapter to query an LLM). The agent-generate node executes the selected agent's LLM, parses the JSON-based output protocol, and manages streaming responses back to the client. Together they form the complete request cycle: decision followed by execution.
How does OpenMAIC stream real-time responses using LangGraph?
OpenMAIC leverages the writer function inside LangGraphRunnableConfig to push StatelessEvent objects via Server-Sent Events (SSE). Both the director and agent-generate nodes use this mechanism to emit streaming events—such as thinking, cue_user, and text_delta—allowing the frontend to render partial responses immediately rather than waiting for complete generation.
Why does OpenMAIC use a stateless design with LangGraph?
The stateless design keeps all request-scoped data—including generated agent configurations—within the LangGraph state itself. This eliminates the need for server-side session storage, allowing any instance of the OpenMAIC server to process any request. The graph simply receives state, processes it, and returns updates, enabling horizontal scaling and simplified deployment architectures.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →